From 65a1c1f8820425e5a531a1bd4d652390489d4f9c Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Wed, 21 Feb 2024 22:20:45 -0600 Subject: Fix weird eval problem Don't do things ya don't get, kids --- eval.lua | 95 ++++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 54 insertions(+), 41 deletions(-) (limited to 'eval.lua') diff --git a/eval.lua b/eval.lua index 3decded..d441859 100644 --- a/eval.lua +++ b/eval.lua @@ -2,36 +2,53 @@ local eval = {} local read = require "read" -local types = require "types" local util = require "util" local pp = require "pp" -Env = types.Object:new { - __type = "Environment", - __extend = - function(self, parms, args, outer) - for _, p in ipairs(parms) do - for _, a in ipairs(args) do - self[p] = a - end - end - getmetatable(self).__index = outer - end, -} +local function Type (x) + if type(x) == "string" then + return "Symbol" + elseif type(x) == "number" then + return "Number" + elseif getmetatable(x) and getmetatable(x).__type then + return x.__type + elseif type(x) == "table" then + return "List" + else + return type(x) + end +end -Proc = types.Object:new { - __type = "Procedure", - __call = - function (self, args) - local e = Env:new() - e:__extend(self.parms, - util.table(args), - self.env) - return eval(self.body[1], e) - end -} +local Symbol = tostring +local Number = tonumber + +local function Env(inner, outer) + return setmetatable(inner, { __type = "Environment", __index = outer, }) +end + +local function Proc(params, body, env) + local p = { + params = params, + body = body, + env = env, + } + local mt = { + __type = "Procedure", + __call = + function (self, ...) + local inner = {} + for _, p in ipairs(self.params) do + for _, a in ipairs({...}) do + inner[p] = a + end + end + return eval(self.body, Env(inner, self.env)) + end, + } + return setmetatable(p, mt) +end -global_env = Env:new { +local global_env = { -- constants ["#t"] = true, ["#f"] = false, @@ -56,11 +73,11 @@ global_env = Env:new { end, ["number?"] = function(x) - return types.Type(x) == "Number" + return Type(x) == "Number" end, ["symbol?"] = function(x) - return types.Type(x) == "Symbol" + return Type(x) == "Symbol" end, -- scheme functions ["apply"] = @@ -95,9 +112,9 @@ end function eval.eval (x, env) env = env or global_env - if types.Type(x) == "Symbol" then + if Type(x) == "Symbol" then return env[x] - elseif types.Type(x) ~= "List" then + elseif type(x) ~= "table" then return x else local op = util.car(x) @@ -107,19 +124,15 @@ function eval.eval (x, env) elseif op == "define" then local sym, exp = table.unpack(args) env[sym] = eval(exp, env) - elseif op == "set!" then - local sym, exp = table.unpack(args) - env[sym] = eval(exp, env) + --[[ + elseif op == "set!" then + local sym, exp = table.unpack(args) + env[sym] = eval(exp, env) --]] elseif op == "lambda" then - local parms = util.car(args) - local body = util.cdr(args) - return Proc:new { - parms = parms, - body = body, - env = env, - } + local params = util.car(args) + local body = util.cdr(args)[1] + return Proc(params, body, env) else -- procedure call - pp(op) local proc = eval(op, env) local vals = util.map( function(v) return eval(v, env) end, @@ -142,4 +155,4 @@ return setmetatable(eval, { __call = --[[ (begin (define sq (lambda (x) (* x x))) (define rep (lambda (f) (lambda (x) (f (f x)))))) --- ]] + -- ]] -- cgit 1.4.1-21-gabe81