Mercurial > repos > icfp2014
changeset 58:d35601d47db1
Implement if:else in gqc
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 27 Jul 2014 20:03:34 -0700 |
parents | a3e4d2833301 |
children | 428c1daefca9 2a5d7308e1df |
files | code/gqc.tp |
diffstat | 1 files changed, 121 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/code/gqc.tp Sun Jul 27 19:53:08 2014 -0700 +++ b/code/gqc.tp Sun Jul 27 20:03:34 2014 -0700 @@ -365,6 +365,127 @@ } } + _funHandlers set: "if:else" :args syms { + cond <- (args value) + trueBody <- ((args tail) value) expressions + falseBody <- (((args tail) tail) value) expressions + + if: (cond nodeType) = (ast binary) { + trueLbl <- prog makeLabel: "true" + falseLbl <- prog makeLabel: "false" + endLbl <- prog makeLabel: "end" + + saveTempRegs <- _tempRegs + l <- compileExpr: (cond left) syms: syms + r <- compileExpr: (cond right) syms: syms + _tempRegs <- saveTempRegs + + ok <- true + + if: (cond op) = ">=" { + prog add: (inst: "JLT" #[ + falseLbl + l + r + ]) + } else: { + if: (cond op) = "<=" { + prog add: (inst: "JGT" #[ + falseLbl + l + r + ]) + } else: { + if: (cond op) = "!=" { + prog add: (inst: "JEQ" #[ + falseLbl + l + r + ]) + } else: { + if: (cond op) = ">" { + prog add: (inst: "JGT" #[ + trueLbl + l + r + ]) + prog add: (inst: "MOV" #[ + reg: 8 + falseLbl + ]) + } else: { + if: (cond op) = "<" { + prog add: (inst: "JLT" #[ + trueLbl + l + r + ]) + prog add: (inst: "MOV" #[ + reg: 8 + falseLbl + ]) + } else: { + bodyLbl <- prog makeLabel: "loop_body" + if: (cond op) = "=" { + prog add: (inst: "JEQ" #[ + trueLbl + l + r + ]) + prog add: (inst: "MOV" #[ + reg: 8 + falseLbl + ]) + } 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: { + saveTempRegsExpr <- _tempRegs + v <- compileExpr: expr syms: syms + _tempRegs <- saveTempRegsExpr + } + } + prog add: (inst: "MOV" #[ + reg: 8 + endLbl + ]) + prog setLabel: falseLbl + //TODO: do 2 passes for labels to allow forward references + foreach: falseBody :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: { + saveTempRegsExpr <- _tempRegs + v <- compileExpr: expr syms: syms + _tempRegs <- saveTempRegsExpr + } + } + prog setLabel: endLbl + } else: { + error: "Condition parameter to if:else must be a comparison operator expression" + } + } else: { + error: "Condition parameter to if:else must be a comparison operator expression" + } + } + _exprHandlers set: (ast call) :expr syms { tc <- (expr tocall) if: (tc nodeType) = (ast sym) {