From 4fb6e90474c8e9292df1a6210b8de260dd253ccb Mon Sep 17 00:00:00 2001
From: Case Duckworth
Date: Sat, 23 Mar 2024 15:51:07 -0500
Subject: Break special forms out into their own table

---
 eval.lua | 53 ++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 36 insertions(+), 17 deletions(-)

diff --git a/eval.lua b/eval.lua
index 9b1c315..610b902 100644
--- a/eval.lua
+++ b/eval.lua
@@ -53,6 +53,40 @@ function eval.Proc (params, body, env)
 	return setmetatable(v, mt)
 end
 
+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,
+	-- TODO: include, import, define-syntax, define-values(?) ...
+}
+-- Aliases
+specials.lam = specials.lambda
+specials.def = specials.define
+
 function eval.eval (x, env)
 	env = env or base.env
 	if isa(x, "Symbol") then
@@ -61,23 +95,8 @@ 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 params = {}
-- 
cgit 1.4.1-21-gabe81