aboutsummaryrefslogtreecommitdiff
path: root/lua/step2_eval.lua
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2015-01-08 23:25:40 -0600
committerJoel Martin <github@martintribe.org>2015-01-08 23:25:40 -0600
commit9d42904e47c50c5ff2306da04993b2a32bc9cd16 (patch)
treee1b2d46a232e6573dc2c185967ebe988be3db973 /lua/step2_eval.lua
parentfd888612ca589d7e1a46c36fc3fe12aed126f6a8 (diff)
downloadmal-9d42904e47c50c5ff2306da04993b2a32bc9cd16.tar.gz
mal-9d42904e47c50c5ff2306da04993b2a32bc9cd16.zip
Lua: all steps and self-hosting.
Also some misc docs/TODO updates.
Diffstat (limited to 'lua/step2_eval.lua')
-rwxr-xr-xlua/step2_eval.lua75
1 files changed, 75 insertions, 0 deletions
diff --git a/lua/step2_eval.lua b/lua/step2_eval.lua
new file mode 100755
index 0000000..7487064
--- /dev/null
+++ b/lua/step2_eval.lua
@@ -0,0 +1,75 @@
+#!/usr/bin/env lua
+
+local table = require('table')
+
+local readline = require('readline')
+local utils = require('utils')
+local types = require('types')
+local reader = require('reader')
+local printer = require('printer')
+local List, Vector, HashMap = types.List, types.Vector, types.HashMap
+
+-- read
+function READ(str)
+ return reader.read_str(str)
+end
+
+-- eval
+function eval_ast(ast, env)
+ if types._symbol_Q(ast) then
+ if env[ast.val] == nil then
+ types.throw("'"..ast.val.."' not found")
+ end
+ return env[ast.val]
+ elseif types._list_Q(ast) then
+ return List:new(utils.map(function(x) return EVAL(x,env) end,ast))
+ elseif types._vector_Q(ast) then
+ return Vector:new(utils.map(function(x) return EVAL(x,env) end,ast))
+ elseif types._hash_map_Q(ast) then
+ local new_hm = {}
+ for k,v in pairs(ast) do
+ new_hm[EVAL(k, env)] = EVAL(v, env)
+ end
+ return HashMap:new(new_hm)
+ else
+ return ast
+ end
+end
+
+function EVAL(ast, env)
+ --print("EVAL: "..printer._pr_str(ast,true))
+ if not types._list_Q(ast) then return eval_ast(ast, env) end
+ local args = eval_ast(ast, env)
+ local f = table.remove(args, 1)
+ return f(unpack(args))
+end
+
+-- print
+function PRINT(exp)
+ return printer._pr_str(exp, true)
+end
+
+-- repl
+local repl_env = {['+'] = function(a,b) return a+b end,
+ ['-'] = function(a,b) return a-b end,
+ ['*'] = function(a,b) return a*b end,
+ ['/'] = function(a,b) return math.floor(a/b) end}
+function rep(str)
+ return PRINT(EVAL(READ(str),repl_env))
+end
+
+while true do
+ line = readline.readline("user> ")
+ if not line then break end
+ xpcall(function()
+ print(rep(line))
+ end, function(exc)
+ if exc then
+ if types._malexception_Q(exc) then
+ exc = printer._pr_str(exc.val, true)
+ end
+ print("Error: " .. exc)
+ print(debug.traceback())
+ end
+ end)
+end