view code/lmc.tp @ 2:71e8d638da5c

Add operator support to lmc
author Michael Pavone <pavone@retrodev.com>
date Fri, 25 Jul 2014 09:32:12 -0700
parents 68d1447bfdbe
children a9a2ad99adfb
line wrap: on
line source

{
	error <- :msg {
		(file stderr) write: "Error - " . msg . "\n"
	}

	_exprHandlers <- dict hash
	
	compileExpr <- :expr {
		_exprHandlers ifget: (expr nodeType) :handler {
			handler: expr
		} else: {
			error: "Unhandled node type " . (expr nodeType)
		}
	}
	
	_exprHandlers set: (ast intlit) :expr {
		print: "  LDC " . (expr val) . "\n"
	}
	
	_exprHandlers set: (ast sequence) :expr {
		count <- 0
		foreach: (expr els) :idx el {
			compileExpr: el
			count <- count + 1
		}
		if: (expr array?) {
			count <- count - 1
		} else: {
			print: "  LDC 0\n"
		}
		while: { count > 0} do: {
			print: "  CONS\n"
			count <- count - 1
		}
	}
	
	_opNames <- dict hash
	_opNames set: "+" "ADD"
	_opNames set: "-" "SUB"
	_opNames set: "*" "MUL"
	_opNames set: "/" "DIV"
	_opNames set: "|" "CONS"
	_opNames set: "=" "CEQ"
	_opNames set: ">" "CGT"
	_opNames set: ">=" "CGTE"
	
	_exprHandlers set: (ast binary) :expr {
		if: (expr op) = "|" {
			compileExpr: (expr left)
			compileExpr: (expr right)
		} else: {
			compileExpr: (expr right)
			compileExpr: (expr left)
		}
		_opNames ifget: (expr op) :inst {
			print: "  " . inst . "\n"
		} else: {
			error: "operator " . (expr op) . " is not supported"
		}
	}
	#{
		compile <- :code {
			res <- parser top: code
			if: res {
				outer <- res yield
				main_fun <- false
				others <- dict hash
				foreach: (outer messages) :idx msg {
					if: ((msg to) name) = "main" {
						main_fun <- msg assign
					} else: {
						others set: ((msg to) name) (msg assign)
					}
				}
				foreach: (main_fun expressions) :idx expr {
					compileExpr: expr
				}
				foreach: others :name fun {
					print: ";" . name . "\n"
					foreach: (fun expressions) :idx expr {
						compileExpr: expr
					}
				}
			} else: {
				error: "Parse failed!"
			}
		}

		compileFile <- :filename {
			f <- file open: filename
			compile: (f readAll)
		}
		
		main <- :args {
			if: (args length) > 1 {
				compileFile: (args get: 1)
			} else: {
				print: "Usage lmc FILE\n"
			}
		}
	}
}