--- lam.eval local eval = {} local read = require "read" local type = require "type" local util = require "util" local unpack = table.unpack or unpack function eval.Env (inner, outer) local mt = { __type = "Environment", __index = outer, } return setmetatable(inner, mt) end function eval.Proc (params, body, env) local v = { params = params, body = body, env = env, } local mt = { __type = "Procedure", __call = function (self, args) local inner = {} local p, a = self.params, args while p.cdr and a.cdr do inner[p.car] = a.car p, a = p.cdr, a.cdr end -- pp.pp(self.body) return eval.eval( self.body, eval.Env(inner, self.env)) end, } return setmetatable(v, mt) end local global = { begin = function (args) local a = args while not type.isNull(a.cdr) do a = a.cdr end return a.car end, ["+"] = function (args) local acc = 0 local car, cdr = args.car, args.cdr while cdr do acc = acc + car car, cdr = cdr.car, cdr.cdr end return acc end, ["-"] = function (args) return args.car - args.cdr.car end, } function eval.eval (x, env) env = env or global if type.isa(x, "Symbol") then return env[x] elseif not type.isList(x) then return x else local op, args = x.car, x.cdr if op == "quote" then return args elseif op == "define" then env[args.car] = eval.eval(args.cdr.car, env) return nil elseif op == "lambda" then return eval.Proc( args.car, type.Cons("begin", args.cdr), env) else -- procedure local proc = eval.eval(op, env) local params = {} local a = args while a.cdr do table.insert(params, eval.eval(a.car, env)) a = a.cdr end return proc(type.List(params)) end end end --- return eval