changeset 9:526bec3b2090

Function call and lambda expression support. Fix ABI for main function. Use main definition for number of args rather than assuming 2 of them.
author Michael Pavone <pavone@retrodev.com>
date Fri, 25 Jul 2014 14:45:55 -0700
parents 494ef2e3a756
children 66d0858692a9
files code/lmc.tp
diffstat 1 files changed, 79 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/code/lmc.tp	Fri Jul 25 13:59:43 2014 -0700
+++ b/code/lmc.tp	Fri Jul 25 14:45:55 2014 -0700
@@ -176,14 +176,22 @@
 	
 	_exprHandlers set: (ast call) :expr syms {
 		tc <- (expr tocall)
+		normal <- true
 		if: (tc nodeType) = (ast sym) {
 			_funHandlers ifget: (tc name) :handler {
 				handler: (expr args) syms
+				normal <- false
 			} else: {
-				error: "function calls not implemented yet"
 			}
-		} else: {
-			error: "call expression to value not implemented yet - " . tc
+		}
+		if: normal {
+			compileExpr: tc syms: syms
+			num <- 0
+			foreach: (expr args) :idx arg {
+				compileExpr: arg syms: syms
+				num <- num + 1
+			}
+			prog add: (inst: "AP" #[num])
 		}
 	}
 	
@@ -212,6 +220,58 @@
 			error: "symbol " . (sym name) . " is not defined"
 		}
 	}
+	
+	compileLambda:syms <- :fname fun :syms {
+		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 {
+			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" #[])
+	}
+	
+	_exprHandlers set: (ast lambda) :expr syms {
+		fname <- prog makeLabel: "lambda"
+		end <- prog makeLabel: "lambda_end"
+		prog add: (inst: "LDC" #[1])
+		prog add: (inst: "TSEL" #[
+			end
+			end
+		])
+		compileLambda: fname expr syms: syms
+		prog setLabel: end
+	}
 	#{
 		compile <- :code {
 			res <- parser top: code
@@ -224,6 +284,7 @@
 				
 				prog add: (inst: "DUM" #[num])
 				slot <- 0
+				mainArgs <- 0
 				foreach: (outer messages) :idx msg {
 					if: (msg nodeType) = (ast assignment) {
 						def <- msg assign
@@ -232,6 +293,9 @@
 						if: (def nodeType) = (ast lambda) {
 							prog add: (inst: "LDF" #[sym])
 							functions set: sym def
+							if: sym = "main" {
+								mainArgs <- (def args) length
+							}
 						} else: {
 							compileExpr: def syms: syms
 						}
@@ -245,47 +309,21 @@
 				prog add: (inst: "LDF" #[after_env])
 				prog add: (inst: "TRAP" #[num])
 				prog setLabel: after_env
+				
+				i <- 0
+				while: { i < mainArgs } do: {
+					prog add: (inst: "LD" #[
+						0
+						i
+					])
+					i <- i + 1
+				}
+				
 				prog add: (inst: "LDF" #["main"])
-				prog add: (inst: "TAP" #[2])
+				prog add: (inst: "TAP" #[mainArgs])
 				
 				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 {
-						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" #[])
+					compileLambda: fname fun syms: syms
 				}
 				print: prog
 			} else: {