# HG changeset patch # User Michael Pavone # Date 1406543105 25200 # Node ID 4438054a183cde539d51af6f96ffe552d425c5b0 # Parent dcfa9797607125be7fd135f32e900a83c0310090# Parent 8f6ade456edfaea21ea4482fc33a5c3d6d613e63 Merge diff -r 8f6ade456edf -r 4438054a183c code/dotScanner.lm --- a/code/dotScanner.lm Mon Jul 28 03:14:50 2014 -0700 +++ b/code/dotScanner.lm Mon Jul 28 03:25:05 2014 -0700 @@ -29,11 +29,13 @@ gridMaxY gridArea grid:inBounds? - grid:get:withDefault calcPos ] from: (module: "grid.lm") visited <- 0 + badGhostCount <- 0 + edibleGhosts <- 0 + totalGhosts <- 0 advancer <- :continuations { notdone <- 1 @@ -65,6 +67,11 @@ } continuations } + + target0 <- 2 + target1 <- 3 + target2 <- 4 + target3 <- 7 makeContClos <- :grid myLoc path { { @@ -75,7 +82,7 @@ if: (grid: visited get: myLoc) { } else: { atpos <- grid: grid get: myLoc - if: (atpos = 2) + (atpos = 3) + (atpos = 4) { + if: (atpos = target0) + (atpos = target1) + (atpos = target2) + (atpos = target3) { //pellet, power pellet, fruit ret <- #[1 (reverse: path)] } else: { @@ -99,6 +106,7 @@ step <- :myState world { lmState <- (world tail) value + myVitality <- lmState value myLoc <- (lmState tail) value ghostState <- ((world tail) tail) value fruitState <- ((world tail) tail) tail @@ -116,23 +124,49 @@ } makeTree: row }) + badGhostCount <- 0 + edibleGhosts <- 0 + totalGhosts <- 0 grid <- fold: ghostState grid with: :acc ghost { + totalGhosts <- totalGhosts + 1 vitality <- ghost value loc <- (ghost tail) value dir <- (ghost tail) tail nextloc <- 0 move <- 0 + manHatDist <- 0 if: vitality = 1 { - //treat fright mode ghosts as a pellet for now - acc <- grid: acc set: loc to: 2 + + if: (myLoc value) > (loc value) { + manHatDist <- (myLoc value) - (loc value) + } else: { + manHatDist <- (loc value) - (myLoc value) + } + if: (myLoc tail) > (loc tail) { + manHatDist <- manHatDist + (myLoc tail) - (loc tail) + } else: { + manHatDist <- manHatDist + (loc tail) - (myLoc tail) + } + if: myVitality > (manHatDist * 254) { + edibleGhosts <- edibleGhosts + 1 + } else: {} + //mark fright mode ghosts + acc <- grid: acc set: loc to: 7 } else: { if: vitality = 0 { + badGhostCount <- badGhostCount + 1 //treat normal mode ghosts as a wall for now acc <- grid: acc set: loc to: 0 while: { move < 4 } do: { nextloc <- calcPos: move loc if: (grid: acc inBounds?: nextloc) { - acc <- grid: acc set: nextloc to: 0 + acc <- grid: acc update: nextloc with: :oldval { + if: oldval = 3 { + } else: { + oldval <- 0 + } + oldval + } } else: {} move <- move + 1 } @@ -140,6 +174,24 @@ } acc } + //default behavior, target all yummy things + target0 <- 2 + target1 <- 3 + target2 <- 4 + target3 <- 7 + if: badGhostCount > 0 { + } else: { + if: totalGhosts > 0 { + //ignore power pellets when there are no ghosts in normal mode + target1 <- 2 + if: edibleGhosts > 0 { + //ignore anything except edible ghosts when some are in range + target0 <- 7 + target1 <- 7 + target2 <- 7 + } else: {} + } else: {} + } //make sure my location is marked clear even if there is a ghost nearby grid <- grid: grid set: myLoc to: 1 visited <- treeMap: grid :row { diff -r 8f6ade456edf -r 4438054a183c code/ghost0.gq --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/code/ghost0.gq Mon Jul 28 03:25:05 2014 -0700 @@ -0,0 +1,140 @@ +#{ + up <- 0 + right <- 1 + down <- 2 + left <- 3 + + getDirX <- :dir startX { + if: dir = right { + startX <- startX + 1 + } else: { + if: dir = left { + startX <- startX - 1 + } + } + startX + } + + getDirY <- :dir startY { + if: dir = up { + startY <- startY - 1 + } else: { + if: dir = down { + startY <- startY + 1 + } + } + startY + } + + opDir <- :dir { + if: dir < 2 { + dir <- dir + 2 + } else: { + dir <- dir - 2 + } + dir + } + + goTowardsX:Y <- :targetX targetY { + myIdx <- (me: ) + myX <- ghostPos: myIdx + myY <- yCoord + myVit <- ghostStatus: myIdx + myDir <- direction + + + firstChoice <- 0 + secondChoice <- 0 + + if: myX > targetX { + //ghost is to the right of target + if: myY > targetY { + //ghost is below target + if: (myX - targetX) > (myY - targetY) { + //target is more left than up + firstChoice <- left + secondChoice <- up + } else: { + firstChoice <- up + secondChoice <- left + } + } else: { + //ghost is above or directly to the right of target + if: (myX - targetX) > (targetY - myY) { + //target is more left than down + firstChoice <- left + secondChoice <- down + } else: { + //target is more down than left + firstChoice <- down + secondChoice <- left + } + } + } else: { + //ghost is to the left of or directly above/below target + if: myY > targetY { + //ghost is below target + if: (targetX - myX) > (myY - targetY) { + //target is more right than up + firstChoice <- right + secondChoice <- up + } else: { + firstChoice <- up + secondChoice <- right + } + } else: { + //ghost is above or directly to the left of target + if: (targetX - myX) > (targetY - myY) { + //target is more right than down + firstChoice <- right + secondChoice <- down + } else: { + //target is more down than right + firstChoice <- down + secondChoice <- right + } + } + } + if: myVit = 1 { + //currently in fright mode, try to run away + firstChoice <- opDir: firstChoice + secondChoice <- opDir: secondChoice + } + + + + tmp <- 0 + i <- 0 + while: { i < 3} do: { + targetX <- getDirX: firstChoice myX + targetY <- getDirY: firstChoice myY + + if: (mapContentsAt: targetX targetY) - 1 > 4 { + //first choice is a wall or ghost start pos + tmp <- firstChoice + firstChoice <- secondChoice + secondChoice <- opDir: firstChoice + i <- i + 1 + } else: { + if: firstChoice = (opDir: myDir) { + //first choice is backwards + tmp <- firstChoice + firstChoice <- secondChoice + secondChoice <- opDir: firstChoice + i <- i + 1 + } else: { + i <- 3 + } + } + } + direction!: firstChoice + + 0 + } + + //chases lambda man + main <- { + lambdamanPos: + goTowardsX: xCoord Y: yCoord + } +} \ No newline at end of file diff -r 8f6ade456edf -r 4438054a183c code/ghost1.gq --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/code/ghost1.gq Mon Jul 28 03:25:05 2014 -0700 @@ -0,0 +1,158 @@ +#{ + up <- 0 + right <- 1 + down <- 2 + left <- 3 + lastX <- 0 + lastY <- 0 + + getDirX <- :dir startX { + if: dir = right { + startX <- startX + 1 + } else: { + if: dir = left { + startX <- startX - 1 + } + } + startX + } + + getDirY <- :dir startY { + if: dir = up { + startY <- startY - 1 + } else: { + if: dir = down { + startY <- startY + 1 + } + } + startY + } + + opDir <- :dir { + if: dir < 2 { + dir <- dir + 2 + } else: { + dir <- dir - 2 + } + dir + } + + goTowardsX:Y <- :targetX targetY { + myIdx <- (me: ) + myX <- ghostPos: myIdx + myY <- yCoord + myVit <- ghostStatus: myIdx + myDir <- direction + + + firstChoice <- 0 + secondChoice <- 0 + + if: myX > targetX { + //ghost is to the right of target + if: myY > targetY { + //ghost is below target + if: (myX - targetX) > (myY - targetY) { + //target is more left than up + firstChoice <- left + secondChoice <- up + } else: { + firstChoice <- up + secondChoice <- left + } + } else: { + //ghost is above or directly to the right of target + if: (myX - targetX) > (targetY - myY) { + //target is more left than down + firstChoice <- left + secondChoice <- down + } else: { + //target is more down than left + firstChoice <- down + secondChoice <- left + } + } + } else: { + //ghost is to the left of or directly above/below target + if: myY > targetY { + //ghost is below target + if: (targetX - myX) > (myY - targetY) { + //target is more right than up + firstChoice <- right + secondChoice <- up + } else: { + firstChoice <- up + secondChoice <- right + } + } else: { + //ghost is above or directly to the left of target + if: (targetX - myX) > (targetY - myY) { + //target is more right than down + firstChoice <- right + secondChoice <- down + } else: { + //target is more down than right + firstChoice <- down + secondChoice <- right + } + } + } + if: myVit = 1 { + //currently in fright mode, try to run away + firstChoice <- opDir: firstChoice + secondChoice <- opDir: secondChoice + } + + + + tmp <- 0 + i <- 0 + while: { i < 3} do: { + targetX <- getDirX: firstChoice myX + targetY <- getDirY: firstChoice myY + + if: (mapContentsAt: targetX targetY) - 1 > 4 { + //first choice is a wall or ghost start pos + tmp <- firstChoice + firstChoice <- secondChoice + secondChoice <- opDir: firstChoice + i <- i + 1 + } else: { + if: firstChoice = (opDir: myDir) { + //first choice is backwards + tmp <- firstChoice + firstChoice <- secondChoice + secondChoice <- opDir: firstChoice + i <- i + 1 + } else: { + i <- 3 + } + } + } + direction!: firstChoice + + 0 + } + + //tries to intercept lambda man by targeting a + //position two cells ahead of his current position + main <- { + lmX <- lambdamanPos: + lmY <- yCoord + diffX <- 0 + diffY <- 0 + + if: notFirst? = 1 { + diffX <- lmX - lastX + diffY <- lmY - lastY + } + lastX <- lmX + lastY <- lmY + + lmX <- (lmX + diffX) + diffX + lmY <- (lmY + diffY) + diffY + + goTowardsX: lmX Y: lmY + + } +} \ No newline at end of file diff -r 8f6ade456edf -r 4438054a183c code/ghost2.gq --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/code/ghost2.gq Mon Jul 28 03:25:05 2014 -0700 @@ -0,0 +1,177 @@ +#{ + up <- 0 + right <- 1 + down <- 2 + left <- 3 + myIdx <- (me: ) + lastX <- 0 + lastY <- 0 + myX <- 0 + myY <- 0 + dist <- 0 + distX <- 0 + distY <- 0 + + getDirX <- :dir startX { + if: dir = right { + startX <- startX + 1 + } else: { + if: dir = left { + startX <- startX - 1 + } + } + startX + } + + getDirY <- :dir startY { + if: dir = up { + startY <- startY - 1 + } else: { + if: dir = down { + startY <- startY + 1 + } + } + startY + } + + /* + opDir <- :dir { + (dir + 2) and: 3 + } + */ + + goTowardsX:Y <- :targetX targetY { + myVit <- ghostStatus: myIdx + myDir <- direction + + + firstChoice <- 0 + secondChoice <- 0 + + if: myX > targetX { + //ghost is to the right of target + if: myY > targetY { + //ghost is below target + if: distX > distY { + //target is more left than up + firstChoice <- left + secondChoice <- up + } else: { + firstChoice <- up + secondChoice <- left + } + } else: { + //ghost is above or directly to the right of target + if: distX > distY { + //target is more left than down + firstChoice <- left + secondChoice <- down + } else: { + //target is more down than left + firstChoice <- down + secondChoice <- left + } + } + } else: { + //ghost is to the left of or directly above/below target + if: myY > targetY { + //ghost is below target + if: distX > distY { + //target is more right than up + firstChoice <- right + secondChoice <- up + } else: { + firstChoice <- up + secondChoice <- right + } + } else: { + //ghost is above or directly to the left of target + if: distX > distY { + //target is more right than down + firstChoice <- right + secondChoice <- down + } else: { + //target is more down than right + firstChoice <- down + secondChoice <- right + } + } + } + if: myVit = 1 { + //currently in fright mode, try to run away if we are close to LM + if: dist < 16 { + firstChoice <- (firstChoice + 2) and: 3 //opDir: firstChoice + secondChoice <- (secondChoice + 2) and: 3 //opDir: secondChoice + } + } + + + + tmp <- 0 + i <- 0 + fail <- 0 + while: { i < 3} do: { + targetX <- getDirX: firstChoice myX + targetY <- getDirY: firstChoice myY + + if: (mapContentsAt: targetX targetY) - 1 > 4 { + //first choice is a wall or ghost start pos + tmp <- firstChoice + firstChoice <- secondChoice + secondChoice <- (firstChoice + 2) and: 3 //opDir: firstChoice + i <- i + 1 + } else: { + if: firstChoice = ( (myDir + 2) and: 3 /*opDir: myDir*/) { + //first choice is backwards + tmp <- firstChoice + firstChoice <- secondChoice + secondChoice <- (firstChoice + 2) and: 3 //opDir: firstChoice + i <- i + 1 + } else: { + i <- 3 + } + } + } + direction!: firstChoice + + 0 + } + + //"wingman" - tries to surround lambda man + //by picking a position sideways of his current direction + main <- { + lmX <- lambdamanPos: + lmY <- yCoord + myX <- ghostPos: myIdx + myY <- yCoord + diffX <- 0 + diffY <- 0 + + if: notFirst? = 1 { + diffX <- lmX - lastX + diffY <- lmY - lastY + } + lastX <- lmX + lastY <- lmY + + distX <- myX - lmX + if: distX < 0 { + distX <- 0 - distX + } + distY <- myY - lmY + if: distY < 0 { + distY <- 0 - distX + } + dist <- distX + distY + if: dist < 8 { + diffX <- 0 + diffY <- 0 + } + + lmX <- (lmX + diffY) + diffY + lmY <- (lmY + diffX) + diffX + + goTowardsX: lmX Y: lmY + + } +} \ No newline at end of file diff -r 8f6ade456edf -r 4438054a183c code/gqc.tp --- a/code/gqc.tp Mon Jul 28 03:14:50 2014 -0700 +++ b/code/gqc.tp Mon Jul 28 03:25:05 2014 -0700 @@ -1,14 +1,20 @@ { + reg? <- :val { + (object does: val understand?: "isReg?") && (val isReg?) + } + mem? <- :val { + (object does: val understand?: "isMem?") && (val isMem?) + } + mem <- :_addr { #{ addr <- { _addr } string <- { "[" . _addr . "]" } isReg? <- { false } + != <- :other { (not: (mem?: other)) || _addr != (other addr) } + = <- :other { (mem?: other) && _addr = (other addr) } } } - reg? <- :val { - (object does: val understand?: "isReg?") && (val isReg?) - } reg <- :_num { #{ num <- { _num } @@ -82,7 +88,8 @@ error <- :msg { (file stderr) write: "Error - " . msg . "\n" } - _nextVar <- 0 + //0 is used for the special notFirst? variable + _nextVar <- 1 //a and b are reserved for int/return values //h is reserved as a stack pointer _allTemp <- [ @@ -94,6 +101,26 @@ ] _tempRegs <- _allTemp + getTemp <- { + if: (_tempRegs empty?) { + //out of regs, use memory + loc <- _nextVar + _nextVar <- _nextVar + 1 + mem: loc + } else: { + r <- _tempRegs value + _tempRegs <- _tempRegs tail + r + } + } + + preserveTemps <- :fun { + saveTempRegs <- _tempRegs + res <- fun: + _tempRegs <- saveTempRegs + res + } + _exprHandlers <- dict hash compileExpr:syms <- :expr :syms { @@ -118,19 +145,22 @@ _opNames set: "xor" "XOR" _exprHandlers set: (ast binary) :expr syms { - startTempRegs <- _tempRegs - l <- compileExpr: (expr left) syms: syms - r <- compileExpr: (expr right) syms: syms + l <- 0 + r <- preserveTemps: { + l <- compileExpr: (expr left) syms: syms + compileExpr: (expr right) syms: syms + } dest <- l if: (reg?: l) { - _tempRegs <- startTempRegs filter: :r { r != l } + //reallocate temp register used by l + //not always safe, needs work + _tempRegs <- _tempRegs filter: :r { r != l } } else: { - dest <- startTempRegs value + dest <- getTemp: prog add: (inst: "MOV" #[ dest l ]) - _tempRegs <- startTempRegs tail } _opNames ifget: (expr op) :i { prog add: (inst: i #[ @@ -161,14 +191,16 @@ info <- syms find: (sym name) else: { error: "this should never happen!" } - startTempRegs <- _tempRegs - v <- compileExpr: (expr assign) syms: syms - _tempRegs <- startTempRegs + v <- preserveTemps: { + compileExpr: (expr assign) syms: syms + } dest <- info def - prog add: (inst: "MOV" #[ - dest - v - ]) + if: dest != v { + prog add: (inst: "MOV" #[ + dest + v + ]) + } dest } @@ -180,9 +212,9 @@ } _funHandlers set: "direction!" :args syms { dir <- args value - startTempRegs <- _tempRegs - v <- compileExpr: dir syms: syms - _tempRegs <- startTempRegs + v <- preserveTemps: { + compileExpr: dir syms: syms + } if: (reg: 0) != v { prog add: (inst: "MOV" #[ reg: 0 @@ -208,9 +240,9 @@ intNum <- idx + 4 _funHandlers set: name :args syms { ghostIdx <- args value - startTempRegs <- _tempRegs - v <- compileExpr: ghostIdx syms: syms - _tempRegs <- startTempRegs + v <- preserveTemps: { + compileExpr: ghostIdx syms: syms + } if: (reg: 0) != v { prog add: (inst: "MOV" #[ reg: 0 @@ -224,10 +256,10 @@ _funHandlers set: "mapContentsAt" :args syms { x <- args value y <- (args tail) value - startTempRegs <- _tempRegs - x <- compileExpr: x syms: syms - y <- compileExpr: y syms: syms - _tempRegs <- startTempRegs + preserveTemps: { + x <- compileExpr: x syms: syms + y <- compileExpr: y syms: syms + } if: (reg: 0) != x { prog add: (inst: "MOV" #[ reg: 0 @@ -243,12 +275,33 @@ prog add: (inst: "INT" #[7]) reg: 0 } + //new Quiche parser doesn't support and/or/xor operators yet :( + _funHandlers set: "and" :args syms { + l <- 0 + r <- preserveTemps: { + l <- compileExpr: (args value) syms: syms + compileExpr: ((args tail) value) syms: syms + } + dest <- getTemp: + if: dest != l { + prog add: (inst: "MOV" #[ + dest + l + ]) + } + prog add: (inst: "AND" #[ + dest + r + ]) + dest + } //allow access to raw instructions foreach: #["MOV" "INC" "DEC" "ADD" "SUB" "MUL" "DIV" "AND" "OR" "XOR" "JLT" "JEQ" "JGT" "HLT"] :idx instName { _funHandlers set: instName :args syms { - saveTempRegs <- _tempRegs - args <- args map: :arg { compileExpr: arg syms: syms } + preserveTemps: { + args <- args map: :arg { compileExpr: arg syms: syms } + } prog add: (inst: instName args) } } @@ -262,10 +315,11 @@ end <- prog makeLabel: "loop_end" prog setLabel: top - saveTempRegs <- _tempRegs - l <- compileExpr: (cond left) syms: syms - r <- compileExpr: (cond right) syms: syms - _tempRegs <- saveTempRegs + l <- 0 + r <- preserveTemps: { + l <- compileExpr: (cond left) syms: syms + compileExpr: (cond right) syms: syms + } ok <- true //we need the inverse check in the instruction since a true condition @@ -347,9 +401,9 @@ prog setLabel: lbl syms define: (expr name) lbl } else: { - saveTempRegsExpr <- _tempRegs - v <- compileExpr: expr syms: syms - _tempRegs <- saveTempRegsExpr + v <- preserveTemps: { + compileExpr: expr syms: syms + } } } prog add: (inst: "MOV" #[ @@ -375,10 +429,11 @@ falseLbl <- prog makeLabel: "false" endLbl <- prog makeLabel: "end" - saveTempRegs <- _tempRegs - l <- compileExpr: (cond left) syms: syms - r <- compileExpr: (cond right) syms: syms - _tempRegs <- saveTempRegs + l <- 0 + r <- preserveTemps: { + l <- compileExpr: (cond left) syms: syms + compileExpr: (cond right) syms: syms + } ok <- true @@ -454,9 +509,9 @@ prog setLabel: lbl syms define: (expr name) lbl } else: { - saveTempRegsExpr <- _tempRegs - v <- compileExpr: expr syms: syms - _tempRegs <- saveTempRegsExpr + v <- preserveTemps: { + compileExpr: expr syms: syms + } } } prog add: (inst: "MOV" #[ @@ -472,9 +527,9 @@ prog setLabel: lbl syms define: (expr name) lbl } else: { - saveTempRegsExpr <- _tempRegs - v <- compileExpr: expr syms: syms - _tempRegs <- saveTempRegsExpr + v <- preserveTemps: { + compileExpr: expr syms: syms + } } } prog setLabel: endLbl @@ -486,6 +541,108 @@ } } + _funHandlers set: "if" :args syms { + cond <- (args value) + trueBody <- ((args tail) value) expressions + + if: (cond nodeType) = (ast binary) { + trueLbl <- prog makeLabel: "true" + endLbl <- prog makeLabel: "end" + + l <- 0 + r <- preserveTemps: { + l <- compileExpr: (cond left) syms: syms + compileExpr: (cond right) syms: syms + } + + ok <- true + + if: (cond op) = ">=" { + prog add: (inst: "JLT" #[ + endLbl + l + r + ]) + } else: { + if: (cond op) = "<=" { + prog add: (inst: "JGT" #[ + endLbl + l + r + ]) + } else: { + if: (cond op) = "!=" { + prog add: (inst: "JEQ" #[ + endLbl + l + r + ]) + } else: { + if: (cond op) = ">" { + prog add: (inst: "JGT" #[ + trueLbl + l + r + ]) + prog add: (inst: "MOV" #[ + reg: 8 + endLbl + ]) + } else: { + if: (cond op) = "<" { + prog add: (inst: "JLT" #[ + trueLbl + l + r + ]) + prog add: (inst: "MOV" #[ + reg: 8 + endLbl + ]) + } else: { + bodyLbl <- prog makeLabel: "loop_body" + if: (cond op) = "=" { + prog add: (inst: "JEQ" #[ + trueLbl + l + r + ]) + prog add: (inst: "MOV" #[ + reg: 8 + endLbl + ]) + } else: { + ok <- false + } + } + } + } + } + } + if: ok { + prog setLabel: trueLbl + //TODO: do 2 passes for labels to allow forward references + foreach: trueBody :idx expr { + if: (expr nodeType) = (ast sym) { + //allow using bare symbols to define labels + lbl <- prog makeLabel: (expr name) + prog setLabel: lbl + syms define: (expr name) lbl + } else: { + v <- preserveTemps: { + compileExpr: expr syms: syms + } + } + } + prog setLabel: endLbl + } else: { + error: "Condition parameter to if must be a comparison operator expression" + } + } else: { + error: "Condition parameter to if must be a comparison operator expression" + } + } + _exprHandlers set: (ast call) :expr syms { tc <- (expr tocall) if: (tc nodeType) = (ast sym) { @@ -493,9 +650,9 @@ handler: (expr args) syms } else: { syms ifDefined: (tc name) :info { - saveTempRegs <- _tempRegs - funArgs <- (expr args) map: :arg { compileExpr: arg syms: syms} - _tempRegs <- saveTempRegs + funArgs <- preserveTemps: { + (expr args) map: :arg { compileExpr: arg syms: syms} + } //save registers that need it needSave <- _allTemp filter: :r { @@ -562,41 +719,40 @@ _compileFun <- :fName fun globsyms { syms <- symbols tableWithParent: globsyms - saveTempRegs <- _tempRegs - foreach: (fun args) :idx arg { - argname <- (if: (arg startsWith?: ":") { arg from: 1 } else: { arg }) - r <- _tempRegs value - _tempRegs <- _tempRegs tail - syms define: argname r - } - - lastexpr <- ((fun expressions) length) - 1 - - //TODO: do 2 passes for labels to allow forward references - foreach: (fun expressions) :idx expr { - if: idx != lastexpr && (expr nodeType) = (ast sym) { - //allow using bare symbols to define labels - prog setLabel: (expr name) - syms define: (expr name) (expr name) - } else: { - saveTempRegsExpr <- _tempRegs - v <- compileExpr: expr syms: syms - _tempRegs <- saveTempRegsExpr - if: idx = lastexpr && (fName != "main") { - //move result to a register - prog add: (inst: "MOV" #[ - reg: 0 - v - ]) - //return instruction - prog add: (inst: "MOV" #[ - reg: 8 - mem: (reg: 7) - ]) + preserveTemps: { + foreach: (fun args) :idx arg { + argname <- (if: (arg startsWith?: ":") { arg from: 1 } else: { arg }) + r <- getTemp: + syms define: argname r + } + + lastexpr <- ((fun expressions) length) - 1 + + //TODO: do 2 passes for labels to allow forward references + foreach: (fun expressions) :idx expr { + if: idx != lastexpr && (expr nodeType) = (ast sym) { + //allow using bare symbols to define labels + prog setLabel: (expr name) + syms define: (expr name) (expr name) + } else: { + v <- preserveTemps: { + compileExpr: expr syms: syms + } + if: idx = lastexpr && (fName != "main") { + //move result to a register + prog add: (inst: "MOV" #[ + reg: 0 + v + ]) + //return instruction + prog add: (inst: "MOV" #[ + reg: 8 + mem: (reg: 7) + ]) + } } } } - saveTempRegs <- _tempRegs } #{ @@ -606,6 +762,20 @@ outer <- res yield functions <- dict hash syms <- symbols table + + //define symbols for the special notFirst? variable + syms define: "notFirst?" (mem: 0) + //use it to skip global init on subsequent runthroughs + prog add: (inst: "JEQ" #[ + "main" + (mem: 0) + 1 + ]) + prog add: (inst: "MOV" #[ + (mem: 0) + 1 + ]) + //define symbols for all registers //for low level shenanigans i <- 0 @@ -630,7 +800,14 @@ functions set: sym def syms define: sym sym } else: { - compileExpr: msg syms: syms + if: (def nodeType) != (ast intlit) || (def val) != 0{ + preserveTemps: { + compileExpr: msg syms: syms + } + } else: { + syms define: sym (mem: _nextVar) + _nextVar <- _nextVar + 1 + } } } else: { error: "Only assignments are allowed at the top level"