Created
May 24, 2015 18:05
-
-
Save wolfiestyle/6cffc155250bddd19939 to your computer and use it in GitHub Desktop.
my first attempt at implementing Lisp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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