lis.p8/lib.lua

184 lines
3.7 KiB
Lua

-- lib.lua --
local lib = { __p = nil, __t = {}, }
-- todo: we can set these directly when we know that e_create works right
function id(a) return a end
e_create(lib, "call/cc", function(args, env, cont)
if not is_fun(args[1]) then
return "call/cc takes a function"
end
local function escape(args, env, _cont)
if args[1] == nil then
return cont("no value passed")
end
return cont(args[1])
end
return args[1]({escape}, env, cont)
end, nil, id)
e_create(lib, "do", function(args, env, cont)
return cont(args[#args])
end, nil, id)
-- todo: error on wrong arg type
e_create(lib, "+", function(args, env, cont)
local acc = 0
for i = 1, #args do
acc += args[i]
end
return cont(acc)
end, nil, id)
e_create(lib, "*", function(args, env, cont)
local acc = args[1]
for i = 2, #args do
acc *= args[i]
end
return cont(acc)
end, nil, id)
e_create(lib, "-", function(args, env, cont)
-- todo: return errors for bad types
-- todo: unary minus
local acc = args[1] or 0
for i = 2, #args do
acc -= args[i]
end
return cont(acc)
end, nil, id)
e_create(lib, "/", function(args, env, cont)
local acc = args[1] or 0
for i = 2, #args do
acc /= args[i]
end
return cont(acc)
end, nil, id)
e_create(lib, "even?", function(args, env, cont)
return cont(args[1] % 2 == 0)
end, nil, id)
e_create(lib, "?!", function(args, env, cont)
local s = ""
for i = 1, #args do
if is_str(args[i]) then
s = s .. sub(args[i], 2) .. " "
elseif args[i] == none then
s = s .. "[none] "
else
s = s .. tostr(args[i]) .. " "
end
end
print(s)
return cont(";" .. s)
end, nil, id)
e_create(lib, "<", function(args, env, cont)
local acc = -32768 -- lowest pico-8 value i think
for i = 1, #args do
if not (args[i] > acc) then
return cont(false)
end
acc = args[i]
end
return cont(true)
end, nil, id)
e_create(lib, "=", function(args, env, cont)
local acc = args[1]
for i = 2, #args do
if args[i] != acc then
return cont(false)
end
end
return cont(true)
end, nil, id)
e_create(lib, "list", function(args, env, cont)
return cont(args)
end, nil, id)
e_create(lib, "[]", function(args, env, cont)
if not is_tab(args[1]) then
return "[] 1st arg must be table"
end
return cont(args[1][args[2]])
end, nil, id)
e_create(lib, "len", function(args, env, cont)
if not is_tab(args[1]) then
return "len arg must be table"
end
return cont(#(args[1]))
end, nil, id)
e_create(lib, "join", function(args, env, cont)
local new, len = {}, 0
for i = 1, #args do
local arg = args[i]
if not is_tab(arg) then
len += 1
new[len] = arg
goto next
end
for j = 1, #arg do
new[len + j] = arg[j]
end
len += #arg
::next::
end
return cont(new)
end, nil, id)
e_create(lib, "fold", function(args, env, cont)
if not is_fun(args[1]) then
return "1st arg should be func"
elseif args[2] == nil then
return "2nd arg should be start val"
elseif not is_tab(args[3]) then
return "3rd arg should be table"
end
local fn, acc, list = args[1], args[2], args[3]
local len = #list
if len < 1 then
return "cant fold empty list"
end
local function do_fold(idx, val)
if idx == len then
return cont(val)
end
return fn({val, list[idx + 1]}, env, bind(do_fold, idx + 1))
end
return fn({acc, list[1]}, env, bind(do_fold, 1))
end, nil, id)
function wrap_fn(fn, name)
e_create(lib, name, function(args, env, cont)
return cont(fn(unpack(args)))
end, nil, id)
end
for i = 1, #wraps do
-- todo: should i / do i need to prefix these ??
-- todo: post these with ! since almost all of them can mutate
wrap_fn(wraps[i].v, wraps[i].k)
end
wraps = nil -- let there be garbage collection
for k, v in pairs({
["sym?"] = is_sym,
["num?"] = is_num,
["fun?"] = is_fun,
["tab?"] = is_tab,
["str?"] = is_str,
["bool?"] = is_bool,
}) do
wrap_fn(v, k)
end