Skip to content

Instantly share code, notes, and snippets.

@wolfiestyle
Created May 24, 2015 18:05
Show Gist options
  • Save wolfiestyle/6cffc155250bddd19939 to your computer and use it in GitHub Desktop.
Save wolfiestyle/6cffc155250bddd19939 to your computer and use it in GitHub Desktop.
my first attempt at implementing Lisp
#!/usr/bin/env lua
local eval
local global = {
["+"] = function(args)
local acc = 0
for i = 1, #args do
acc = acc + args[i]
end
return acc
end,
["*"] = function(args)
local acc = 1
for i = 1, #args do
acc = acc * args[i]
end
return acc
end,
define = function(args, env)
local name, val = unpack(args)
env[name] = val
return val
end,
lambda = function(args, env)
local arg_names = args[1]
local env_mt = { __index = env }
return function(arg_list)
local _local = setmetatable({}, env_mt)
for i, val in ipairs(arg_list) do
_local[arg_names[i]] = val
end
local res
for i = 2, #args do
res = eval(args[i], _local)
end
return res
end
end,
map = function(args, env)
local fn, list = unpack(args)
local res = {}
for i = 1, #list do
res[i] = fn({ list[i] }, env)
end
return res
end,
}
function eval(code, env)
env = env or global
if type(code) == "string" then
return env[code] or code --FIXME: strings are identifiers AND strings
elseif type(code) ~= "table" then
return code
elseif code.quote then
code.quote = nil
return code
end
local list = {}
local no_eval = code[1] == "lambda"
for i, item in ipairs(code) do
if no_eval and i > 1 then
list[i] = item
else
list[i] = eval(item, env)
end
end
local fn = table.remove(list, 1)
return fn(list, env)
end
local function quote(list)
list.quote = true
return list
end
eval{ "define", "double", { "lambda", { "x" }, { "*", "x", 2 } } }
print(eval{ "double", { "*", { "+", 1, 2 }, 4 } })
eval{ "define", "i", "6" }
eval{ "define", "test", { "lambda", {},
{ "define", "i", 33 },
{ "lambda", {}, "i" }
}
}
eval{ "define", "fn", { "test" } }
print(eval{ "fn" })
print(eval("i"))
eval{ "define", "stuff", { "map", "double", quote{ 1, 2, 3, 4, 5 } }}
print(unpack(eval("stuff")))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment