changeset 7:afd55b32549b

Implement support for local variables and top level functions
author Michael Pavone <pavone@retrodev.com>
date Fri, 25 Jul 2014 13:47:21 -0700
parents 0ab6eb5f0190
children 494ef2e3a756
files code/lmc.tp code/test.lm
diffstat 2 files changed, 118 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- 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: {
--- 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]
 	}
 }