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) {