# HG changeset patch # User Michael Pavone # Date 1406321241 25200 # Node ID afd55b32549bbd337e350c0b7163f054dc690545 # Parent 0ab6eb5f0190f36325c5bc4f2690d39cf07019a5 Implement support for local variables and top level functions diff -r 0ab6eb5f0190 -r afd55b32549b code/lmc.tp --- a/code/lmc.tp Fri Jul 25 11:46:34 2014 -0700 +++ b/code/lmc.tp Fri Jul 25 13:47:21 2014 -0700 @@ -63,22 +63,22 @@ _exprHandlers <- dict hash - compileExpr <- :expr { + compileExpr:syms <- :expr :syms { _exprHandlers ifget: (expr nodeType) :handler { - handler: expr + handler: expr syms } else: { error: "Unhandled node type " . (expr nodeType) } } - _exprHandlers set: (ast intlit) :expr { + _exprHandlers set: (ast intlit) :expr syms { prog add: (inst: "LDC" #[(expr val)]) } - _exprHandlers set: (ast sequence) :expr { + _exprHandlers set: (ast sequence) :expr syms { count <- 0 foreach: (expr els) :idx el { - compileExpr: el + compileExpr: el syms: syms count <- count + 1 } if: (expr array?) { @@ -102,13 +102,13 @@ _opNames set: ">" "CGT" _opNames set: ">=" "CGTE" - _exprHandlers set: (ast binary) :expr { + _exprHandlers set: (ast binary) :expr syms { if: (expr op) = "|" { - compileExpr: (expr left) - compileExpr: (expr right) + compileExpr: (expr left) syms: syms + compileExpr: (expr right) syms: syms } else: { - compileExpr: (expr right) - compileExpr: (expr left) + compileExpr: (expr right) syms: syms + compileExpr: (expr left) syms: syms } _opNames ifget: (expr op) :i { prog add: (inst: i #[]) @@ -130,8 +130,8 @@ } _funHandlers <- dict hash - _funHandlers set: "if:else" :args { - compileExpr: (args value) + _funHandlers set: "if:else" :args syms { + compileExpr: (args value) syms: syms args <- args tail tlabel <- prog makeLabel: "true" flabel <- prog makeLabel: "false" @@ -142,7 +142,7 @@ ]) prog setLabel: tlabel foreach: ((args value) expressions) :idx expr { - compileExpr: expr + compileExpr: expr syms: syms } prog add: (inst: "LDC" #[1]) prog add: (inst: "TSEL" #[ @@ -152,33 +152,33 @@ args <- args tail prog setLabel: flabel foreach: ((args value) expressions) :idx expr { - compileExpr: expr + compileExpr: expr syms: syms } prog setLabel: elabel } - _funHandlers set: "isInteger?" :args { - compileExpr: (args value) + _funHandlers set: "isInteger?" :args syms { + compileExpr: (args value) syms: syms prog add: (inst: "ATOM" #[]) } - _funHandlers set: "value" :args { - compileExpr: (args value) + _funHandlers set: "value" :args syms { + compileExpr: (args value) syms: syms prog add: (inst: "CAR" #[]) } - _funHandlers set: "tail" :args { - compileExpr: (args value) + _funHandlers set: "tail" :args syms { + compileExpr: (args value) syms: syms prog add: (inst: "CDR" #[]) } - _funHandlers set: "not" :args { - compileExpr: (args value) + _funHandlers set: "not" :args syms { + compileExpr: (args value) syms: syms prog add: (inst: "LDC" #[0]) prog add: (inst: "CEQ" #[]) } - _exprHandlers set: (ast call) :expr { + _exprHandlers set: (ast call) :expr syms { tc <- (expr tocall) if: (tc nodeType) = (ast sym) { _funHandlers ifget: (tc name) :handler { - handler: (expr args) + handler: (expr args) syms } else: { error: "function calls not implemented yet" } @@ -186,28 +186,102 @@ error: "call expression to value not implemented yet - " . tc } } + + _exprHandlers set: (ast sym) :expr syms { + syms ifDefined: (expr name) :info { + frame <- if: (info isLocal?) { 0 } else: { info depth } + prog add: (inst: "LD" #[ + frame + (info def) + ]) + } else: { + error: "symbol " . (expr name) . " is not defined" + } + } + + _exprHandlers set: (ast assignment) :expr syms { + sym <- expr to + syms ifDefined: (sym name) :info { + frame <- if: (info isLocal?) { 0 } else: { info depth } + compileExpr: (expr assign) syms: syms + prog add: (inst: "ST" #[ + frame + (info def) + ]) + } else: { + error: "symbol " . (sym name) . " is not defined" + } + } #{ compile <- :code { res <- parser top: code if: res { outer <- res yield - main_fun <- false - others <- dict hash + functions <- dict hash + + num <- (outer messages) length + syms <- symbols table + + prog add: (inst: "DUM" #[num]) + slot <- 0 foreach: (outer messages) :idx msg { - if: ((msg to) name) = "main" { - main_fun <- msg assign + if: (msg nodeType) = (ast assignment) { + def <- msg assign + sym <- (msg to) name + + if: (def nodeType) = (ast lambda) { + prog add: (inst: "LDF" #[sym]) + functions set: sym def + } else: { + compileExpr: def syms: syms + } + syms define: sym slot + slot <- slot + 1 } else: { - others set: ((msg to) name) (msg assign) + error: "Only assignments are allowed at the top level" } } - foreach: (main_fun expressions) :idx expr { - compileExpr: expr - } - foreach: others :name fun { - prog setLabel: name + prog add: (inst: "LDF" #["main"]) + prog add: (inst: "TRAP" #[num]) + + foreach: functions :fname fun { + prog setLabel: fname + argsyms <- symbols tableWithParent: syms + foreach: (fun args) :idx el { + argsyms define: (if: (el startsWith?: ":") { el from: 1 } else: { el }) idx + } + + slot <- 0 + locsyms <- symbols tableWithParent: argsyms foreach: (fun expressions) :idx expr { - compileExpr: expr + if: (expr nodeType) = (ast assignment) { + locsyms ifDefined: ((expr to) name) :sym { + //already defined, nothing to do here + } else: { + locsyms define: ((expr to) name) slot + slot <- slot + 1 + } + } } + fsyms <- if: slot > 0 { + //allocate frame for locals + prog add: (inst: "DUM" #[slot]) + i <- 0 + while: { i < slot } do: { + prog add: (inst: "LDC" #[0]) + i <- i + 1 + } + prologue_end <- prog makeLabel: fname . "_real" + prog add: (inst: "LDF" #[prologue_end]) + prog add: (inst: "TRAP" #[slot]) + prog setLabel: prologue_end + locsyms + } else: { argsyms } + + foreach: (fun expressions) :idx expr { + compileExpr: expr syms: fsyms + } + prog add: (inst: "RTN" #[]) } print: prog } else: { diff -r 0ab6eb5f0190 -r afd55b32549b code/test.lm --- a/code/test.lm Fri Jul 25 11:46:34 2014 -0700 +++ b/code/test.lm Fri Jul 25 13:47:21 2014 -0700 @@ -1,13 +1,15 @@ #{ - init <- { - #[1 2 3 4] + step <- :myState :world { + foo <- 1234 + if: (isInteger?: 1 | [(2 + 32 * 8) 3 4]) { + myState <- 42 + } else: { + myState <- 24 + } + #[myState 1] } main <- { - if: (isInteger?: 1 | [(2 + 32 * 8) 3 4]) { - 42 - } else: { - 24 - } + #[0 step] } }