From fc8989a2019922208c1e054a7a08a44ed7db1a35 Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Sun, 31 Mar 2024 22:14:22 -0500 Subject: Add quasiquote --- eval.lua | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/eval.lua b/eval.lua index e13fb97..714c67e 100644 --- a/eval.lua +++ b/eval.lua @@ -48,17 +48,43 @@ function m.procedure (params, body, env) return setmetatable(t, mt) end -local specials = { m.specials = { -- each of these takes R (a list of args) and E (an environment) - quote = - function (r, e) return r[1] end, - define = - function (r, e) rawset(e, r[1], m.eval(r[2][1], e)) end, - lambda = - function (r, e) return m.procedure(r[1], r[2], e) end, - ["set!"] = - function (r, e) e[r[1]] = m.eval(r[2][1], e) end, + quote = function (r, e) return r[1] end, + quasiquote = + function (r, e) + local x = r[1] + if not type.islist(x) or x == type.null then + return x + end + local QQ, fin = {}, nil + local car, cdr = x[1], x[2] + while cdr do + if type.islist(car) then + if car[1] == "unquote" then + table.insert(QQ, + m.eval(car[2][1], e)) + elseif car[1] == "unquote-splicing" then + local usl = m.eval(car[2][1], e) + if not type.islist(usl) then + fin = usl + break + end + while usl[2] do + table.insert(QQ, usl[1]) + usl = usl[2] + end + end + else + table.insert(QQ, car) + end + car, cdr = cdr[1], cdr[2] + end + return type.list(QQ, fin) + end, + define = function (r, e) rawset(e, r[1], m.eval(r[2][1], e)) end, + lambda = function (r, e) return m.procedure(r[1], r[2], e) end, + ["set!"] = function (r, e) e[r[1]] = m.eval(r[2][1], e) end, ["if"] = function (r, e) local test, conseq, alt = -- cgit 1.4.1-21-gabe81