From 1d5041ff7bf92458d6d07ac6a03f2747dce9b9b1 Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Thu, 21 Mar 2024 22:34:12 -0500 Subject: Refactor eval Localize stuff and also break out specials --- eval.lua | 75 +++++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 27 deletions(-) diff --git a/eval.lua b/eval.lua index 9b1c315..39a5bbe 100644 --- a/eval.lua +++ b/eval.lua @@ -1,13 +1,12 @@ --- lam.eval -local eval = {} local base = require "base" local type = require "type" local isNull, isList, isa, List, Cons = type.isNull, type.isList, type.isa, type.List, type.Cons local unpack = table.unpack or unpack -function eval.Env (inner, outer) +local function Env (inner, outer) local mt = { __type = "Environment", __index = outer, @@ -25,7 +24,7 @@ function eval.Env (inner, outer) return setmetatable(inner, mt) end -function eval.Proc (params, body, env) +local function Proc (params, body, env) local v = { params = params, body = body, @@ -42,18 +41,51 @@ function eval.Proc (params, body, env) p, a = p.cdr, a.cdr end local b = self.body - local e = eval.Env(inner, self.env) + local e = Env(inner, self.env) while not isNull(b.cdr) do - eval.eval(b.car, e) + eval(b.car, e) b = b.cdr end - return eval.eval(b.car, e) + return eval(b.car, e) end, } return setmetatable(v, mt) end -function eval.eval (x, env) +local specials = { + quote = + function (args, env) + return args.car + end, + define = + function (args, env) + rawset(env, args.car, eval(args.cdr.car, env)) + return nil + end, + lambda = + function (args, env) + return Proc(args.car, args.cdr, env) + end, + ["set!"] = + function (args, env) + env[args.car] = eval(args.cdr.car, env) + return nil + end, + ["if"] = + function (args, env) + local test, conseq, alt = + args.car, args.cdr.car, args.cdr.cdr.car + if eval(test) + then return eval(conseq) + else return eval(alt) + end + end, +} +-- Aliases +specials.lam = specials.lambda +specials.def = specials.define + +local function eval (x, env) env = env or base.env if isa(x, "Symbol") then return env[x] @@ -61,29 +93,14 @@ function eval.eval (x, env) return x else local op, args = x.car, x.cdr - if op == "quote" then - return args.car - elseif op == "define" or op == "def" then - rawset(env, args.car, eval.eval(args.cdr.car, env)) - return nil - elseif op == "set!" then - env[args.car] = eval.eval(args.cdr.car, env) - elseif op == "lambda" or op == "lam" then - return eval.Proc(args.car, args.cdr, env) - elseif op == "if" then - assert(not isNull(args.cdr), "Malformed 'if'") - local test, conseq, alt = - args.car, args.cdr.car, args.cdr.cdr.car - if eval.eval(test) - then return eval.eval(conseq) - else return eval.eval(alt) - end + if specials[op] then + return specials[op](args, env) else -- procedure - local proc = eval.eval(op, env) + local proc = eval(op, env) local params = {} local a = args while a.cdr do - table.insert(params, eval.eval(a.car, env)) + table.insert(params, eval(a.car, env)) a = a.cdr end return proc(List(params)) @@ -92,4 +109,8 @@ function eval.eval (x, env) end --- -return eval +return { + Env = Env, + Proc = Proc, + eval = eval, +} -- cgit 1.4.1-21-gabe81