putting this in a git so i can post it
commit
13c5ca7783
|
@ -0,0 +1,51 @@
|
|||
|
||||
--[[
|
||||
env is a table with
|
||||
__p the parent env if there is one
|
||||
__t a table of strings with the same keys as the env
|
||||
entries in __t can be "special" or "macro"
|
||||
if there isnt an entry it's assumed to be normal
|
||||
--]]
|
||||
|
||||
-- todo: guard against setting / getting __t and __p ?
|
||||
|
||||
function e_create(env, sym, val, type, cont)
|
||||
if not is_sym(sym) then
|
||||
return tostr(sym) .. " is not a symbol"
|
||||
end
|
||||
|
||||
env[sym] = none
|
||||
return e_set(env, sym, val, type, cont)
|
||||
end
|
||||
|
||||
function e_set(env, sym, val, type, cont)
|
||||
if not is_sym(sym) then
|
||||
return tostr(sym) .. " is not a symbol"
|
||||
end
|
||||
|
||||
if env[sym] != nil then
|
||||
env[sym] = val
|
||||
env.__t[sym] = type
|
||||
return cont(val, type)
|
||||
elseif env.__p != nil then
|
||||
return e_set(env.__p, sym, val, type, cont)
|
||||
else
|
||||
return tostr(sym) .. " sym unbound cant set it"
|
||||
end
|
||||
end
|
||||
|
||||
function e_get(env, sym, cont)
|
||||
if not is_sym(sym) then
|
||||
return tostr(sym) .. " is not a symbol"
|
||||
end
|
||||
|
||||
if env[sym] != nil then
|
||||
return cont(env[sym], env.__t[sym])
|
||||
elseif env.__p != nil then
|
||||
return e_get(env.__p, sym, cont)
|
||||
else
|
||||
return tostr(sym) .. " sym unbound cant get it"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
-- eval.lua --
|
||||
|
||||
e_create(lib, "defmacro!", function(ast, env, cont)
|
||||
-- (defmacro! name normal-function)
|
||||
if #ast < 2 then
|
||||
return "macro needs 2 args"
|
||||
end
|
||||
return eval(ast[2], env, function(val)
|
||||
return e_create(env, ast[1], val, "macro", cont)
|
||||
end)
|
||||
end, "special", id)
|
||||
|
||||
e_create(lib, "quote", function(ast, env, cont)
|
||||
return cont(deep_copy(ast[1])) -- no mutate
|
||||
end, "special", id)
|
||||
|
||||
e_create(lib, "comma", function(ast, env, cont)
|
||||
return "comma outside of backquote"
|
||||
end, "special", id)
|
||||
|
||||
e_create(lib, "backquote", function(ast, env, cont)
|
||||
if #ast < 1 then
|
||||
return "backquote need arg"
|
||||
end
|
||||
ast = ast[1]
|
||||
--todo: implement backquote, where we iterate on the quoted thing
|
||||
--and look for invokations of (comma thing) in which we eval
|
||||
--thing and replace comma thing with it
|
||||
|
||||
--todo: could i define backquote from within lisp now that i have
|
||||
--macros ?????
|
||||
|
||||
return "nope lol oiuhre4swiuhsrgiuhjswegfoij oijerws"
|
||||
end, "special", id)
|
||||
|
||||
e_create(lib, "set!", function(ast, env, cont)
|
||||
-- (set! symbol value)
|
||||
if #ast < 2 then
|
||||
return "too few args for set!"
|
||||
end
|
||||
|
||||
return eval(ast[2], env, function(val, type)
|
||||
return e_set(env, ast[1], val, type, cont)
|
||||
end)
|
||||
end, "special", id)
|
||||
|
||||
e_create(lib, "def!", function(ast, env, cont)
|
||||
-- (def! symbol value)
|
||||
if #ast < 2 then
|
||||
return "too few args for def!"
|
||||
end
|
||||
|
||||
return eval(ast[2], env, function(val, type)
|
||||
return e_create(env, ast[1], val, type, cont)
|
||||
end)
|
||||
end, "special", id)
|
||||
|
||||
e_create(lib, "let", function(ast, env, cont)
|
||||
-- (let ((a 2) (b 4) (c 8)) ...)
|
||||
if #ast < 2 then
|
||||
return "let needs binds and body"
|
||||
end
|
||||
-- todo: check args to make sure it's a list of (bind expr)
|
||||
if not is_tab(ast[1]) then
|
||||
return "first args must be a list"
|
||||
end
|
||||
|
||||
local new_env = { __p = env, __t = {}, }
|
||||
local binds, body = ast[1], rest(ast)
|
||||
|
||||
local function do_body(idx, val)
|
||||
if idx >= #body then
|
||||
return cont(val)
|
||||
end
|
||||
return eval(body[idx + 1], new_env, bind(do_body, idx + 1))
|
||||
end
|
||||
|
||||
local function do_binds(idx, val)
|
||||
return e_create(new_env, binds[idx][1], val, nil, function()
|
||||
if idx == #binds then
|
||||
return do_body(0, nil)
|
||||
end
|
||||
return eval(binds[idx + 1][2], env, bind(do_binds, idx + 1))
|
||||
end)
|
||||
end
|
||||
|
||||
if #binds > 0 then
|
||||
return eval(binds[1][2], env, bind(do_binds, 1))
|
||||
end
|
||||
return do_body(0, nil)
|
||||
end, "special", id)
|
||||
|
||||
--todo: cond is more generic, replace this with cond ?
|
||||
e_create(lib, "if", function(ast, env, cont)
|
||||
-- (if cond a b)
|
||||
if #ast < 2 then
|
||||
return "if requires pred and body"
|
||||
end
|
||||
|
||||
return eval(ast[1], env, function(pred)
|
||||
if pred == false or pred == none then
|
||||
if ast[3] then
|
||||
return eval(ast[3], env, cont)
|
||||
end
|
||||
return cont(none)
|
||||
end
|
||||
return eval(ast[2], env, cont)
|
||||
end)
|
||||
end, "special", id)
|
||||
|
||||
e_create(lib, "\\", function(ast, env, cont)
|
||||
-- (lam (a b c...) body...)
|
||||
if #ast < 2 then
|
||||
return "lam needs args and body"
|
||||
end
|
||||
if not is_tab(ast[1]) then
|
||||
return "lam binds have to be list"
|
||||
end
|
||||
|
||||
local binds, body = ast[1], rest(ast)
|
||||
return cont(function(args, _, cont)
|
||||
local lam_env = { __p = env, __t = {}, }
|
||||
if #args < #binds then
|
||||
return "lambda needs more args"
|
||||
end
|
||||
|
||||
local function do_body(idx, val)
|
||||
if idx - 1 >= #body then
|
||||
return cont(val)
|
||||
end
|
||||
return eval(body[idx], lam_env, bind(do_body, idx + 1))
|
||||
end
|
||||
|
||||
local function do_binds(idx)
|
||||
if idx - 1 >= #binds then
|
||||
return do_body(1, nil)
|
||||
end
|
||||
return e_create(lam_env, binds[idx], args[idx], nil, bind(do_binds, idx + 1))
|
||||
end
|
||||
|
||||
return do_binds(1)
|
||||
end)
|
||||
end, "special", id)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function eval_fun_call(ast, env, cont)
|
||||
return eval(ast[1], env, function(fn)
|
||||
if not is_fun(fn) then
|
||||
return tostr(ast[1]) .. " is not a function"
|
||||
end
|
||||
|
||||
-- todo: if we can avoid cloning args
|
||||
-- and just bind args_length instead
|
||||
-- this should be faster
|
||||
local ast_args, zeroth = rest(ast), {}
|
||||
local function eval_args(args, val)
|
||||
if val != zeroth then
|
||||
args = pack(unpack(args)) -- no mutate
|
||||
if val == nil then
|
||||
args[#args + 1] = none
|
||||
else
|
||||
args[#args + 1] = val
|
||||
end
|
||||
end
|
||||
if #args == #ast_args then
|
||||
return fn(args, env, cont)
|
||||
end
|
||||
return eval(ast_args[#args + 1], env, bind(eval_args, args))
|
||||
end
|
||||
|
||||
return eval_args({}, zeroth)
|
||||
end)
|
||||
end
|
||||
|
||||
-- eval :: error : string or nil (on success)
|
||||
function eval(ast, env, cont)
|
||||
if ast == nil then
|
||||
return "error ast is nil"
|
||||
end
|
||||
|
||||
if is_num(ast) or is_bool(ast) or is_str(ast)
|
||||
or ast == none then
|
||||
return cont(ast)
|
||||
end
|
||||
|
||||
if is_sym(ast) then
|
||||
return e_get(env, ast, cont)
|
||||
end
|
||||
|
||||
if is_tab(ast) and #ast == 0 then
|
||||
return "cannot eval empty list"
|
||||
end
|
||||
|
||||
if is_tab(ast) then
|
||||
if is_tab(ast[1]) then
|
||||
return eval_fun_call(ast, env, cont)
|
||||
end
|
||||
return e_get(env, ast[1], function(val, type)
|
||||
if type == "special" then
|
||||
return val(rest(ast), env, cont)
|
||||
elseif type == "macro" then
|
||||
--todo: write macro-expand function ?
|
||||
--todo: can we write this back into the ast ? (for SPEED)
|
||||
return val(rest(ast), env, function(new_ast)
|
||||
return eval(new_ast, env, cont)
|
||||
end)
|
||||
else
|
||||
return eval_fun_call(ast, env, cont)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
return "unimplemented ast: " .. tostr(ast)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
-- 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
|
||||
|
|
@ -0,0 +1,580 @@
|
|||
pico-8 cartridge // http://www.pico-8.com
|
||||
version 32
|
||||
__lua__
|
||||
-- utils / globals
|
||||
local none = {}
|
||||
|
||||
--have to do this before i make
|
||||
--any functions
|
||||
local wraps = {}
|
||||
for k,v in pairs(_ENV) do
|
||||
if type(v)=="function" then
|
||||
wraps[#wraps + 1]={k=k, v=v,}
|
||||
end
|
||||
end
|
||||
|
||||
function is_sym(s)
|
||||
return type(s) == "string"
|
||||
and sub(s,1,1) != ";"
|
||||
end
|
||||
|
||||
function is_num(n)
|
||||
return type(n) == "number"
|
||||
end
|
||||
|
||||
function is_fun(f)
|
||||
return type(f) == "function"
|
||||
end
|
||||
|
||||
function is_tab(t)
|
||||
return type(t) == "table"
|
||||
and t != none
|
||||
end
|
||||
|
||||
function is_str(s)
|
||||
return type(s) == "string"
|
||||
and sub(s,1,1) == ";"
|
||||
end
|
||||
|
||||
function is_bool(b)
|
||||
return type(b) == "boolean"
|
||||
end
|
||||
|
||||
--todo:
|
||||
--can this be made faster ?
|
||||
function rest(t)
|
||||
local function r_1(fst, ...)
|
||||
return {...}
|
||||
end
|
||||
return r_1(unpack(t))
|
||||
end
|
||||
|
||||
function deep_copy(v)
|
||||
if not is_tab(v) then
|
||||
return v
|
||||
end
|
||||
|
||||
local c = {}
|
||||
for key = 1, #v do
|
||||
--for key in pairs(v) do
|
||||
c[key] = deep_copy(v[key])
|
||||
end
|
||||
return c
|
||||
end
|
||||
|
||||
--todo: this is limitted to 2
|
||||
--args, it's kinda missleading
|
||||
--ig, tho i doubt anyone else
|
||||
--will be using this func
|
||||
|
||||
--todo: see if this needs to /
|
||||
--can be spead up
|
||||
function bind(func, ...)
|
||||
local args = {...}
|
||||
|
||||
local function copy(t)
|
||||
return pack(unpack(t))
|
||||
end
|
||||
|
||||
return function(a, b)
|
||||
local args_2 = copy(args)
|
||||
args_2[#args + 1] = a
|
||||
args_2[#args + 2] = b
|
||||
return func(unpack(args_2))
|
||||
end
|
||||
end
|
||||
|
||||
function list_tostr(l, s)
|
||||
if l == none then
|
||||
return s .. "none"
|
||||
end
|
||||
if type(l)=="table" then
|
||||
s = s .. "("
|
||||
for i = 1, #l do
|
||||
if(i > 1) s = s .. " "
|
||||
s = list_tostr(l[i], s)
|
||||
end
|
||||
s = s .. ")"
|
||||
return s
|
||||
end
|
||||
if is_str(l) then
|
||||
return
|
||||
s.."\""..sub(l,2).."\""
|
||||
end
|
||||
return s .. tostr(l)
|
||||
end
|
||||
|
||||
function chr_size(c)
|
||||
return ord(c) < 128 and 4 or 8
|
||||
end
|
||||
|
||||
function replace(s, a, b)
|
||||
local r = ""
|
||||
for i = 1, #s do
|
||||
local c = sub(s, i, i)
|
||||
if c == a then
|
||||
c = b
|
||||
end
|
||||
r = r .. c
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
-->8
|
||||
-- tokenizer
|
||||
|
||||
--[[ todo:
|
||||
generisize token_str + com ?
|
||||
--]]
|
||||
|
||||
--::tok,rst,type
|
||||
--[[
|
||||
"pun" = puncuation
|
||||
"ws" = whitespace
|
||||
"sym" = symbol
|
||||
"num" = number
|
||||
"end" = end of input
|
||||
"str" = string
|
||||
"com" = comment
|
||||
--]]
|
||||
function token_str(s, hk)
|
||||
for i = 2, #s do
|
||||
if(hk) hk(sub(s,i,i))
|
||||
if sub(s,i,i) == "\"" then
|
||||
return sub(s, 1, i),
|
||||
sub(s,i + 1), "str"
|
||||
end
|
||||
end
|
||||
return s, "", "str" --no end
|
||||
end
|
||||
|
||||
function token_com(s, hk)
|
||||
for i = 2, #s do
|
||||
if(hk) hk(sub(s,i,i))
|
||||
if sub(s,i,i) == "\n" then
|
||||
return sub(s, 1, i),
|
||||
sub(s,i + 1), "com"
|
||||
end
|
||||
end
|
||||
return s, "", "com" --eof
|
||||
end
|
||||
|
||||
function token_1(s, hk)
|
||||
local fst,rst = sub(s,1,1),
|
||||
sub(s,2)
|
||||
|
||||
if(hk) hk(fst)
|
||||
|
||||
if(s=="")return "","","end"
|
||||
|
||||
if fst == "\"" then
|
||||
return token_str(s, hk)
|
||||
end
|
||||
if fst == ";" then
|
||||
return token_com(s, hk)
|
||||
end
|
||||
|
||||
if fst == " "
|
||||
or fst == "\n"
|
||||
or fst == "\t" then
|
||||
local t,r,tp = token_1(rst,hk)
|
||||
if tp == "ws" then
|
||||
return fst..t, r, "ws"
|
||||
end
|
||||
return fst, rst, "ws"
|
||||
end
|
||||
|
||||
if fst == "("
|
||||
or fst == ")"
|
||||
or fst == "'"
|
||||
or fst == "`"
|
||||
or fst == ","
|
||||
or fst == "@" then
|
||||
return fst, rst, "pun"
|
||||
end
|
||||
|
||||
local t,r,tp = token_1(rst,hk)
|
||||
if tp == "sym" then
|
||||
return fst..t, r, "sym"
|
||||
end
|
||||
return fst,rst,"sym"
|
||||
end
|
||||
|
||||
function token(s, hk)
|
||||
local t,r,tp = token_1(s, hk)
|
||||
|
||||
if tonum(t) != nil then
|
||||
return tonum(t),r,"num"
|
||||
end
|
||||
|
||||
return t,r,tp
|
||||
end
|
||||
|
||||
-->8
|
||||
-- parser
|
||||
|
||||
--[[ todo:
|
||||
collect line numbers ?
|
||||
--]]
|
||||
|
||||
function parse(src)
|
||||
local t, rst, tp = token(src)
|
||||
|
||||
if tp=="ws"
|
||||
or tp=="com" then
|
||||
return parse(rst) end
|
||||
|
||||
if t == "'" then
|
||||
t, rst, tp = parse(rst)
|
||||
return {"quote",t}, rst, tp
|
||||
end
|
||||
if t == "`" then
|
||||
t, rst, tp = parse(rst)
|
||||
return {"backquote",t}, rst, tp
|
||||
end
|
||||
if t == "," then
|
||||
t, rst, tp = parse(rst)
|
||||
return {"comma",t}, rst, tp
|
||||
end
|
||||
|
||||
if tp == "str" then
|
||||
return ";" .. sub(t,2,#t-1),
|
||||
rst, tp
|
||||
end
|
||||
|
||||
if t == "(" then
|
||||
local list = {}
|
||||
while true do
|
||||
t, rst, tp = parse(rst)
|
||||
if(t == ")") break
|
||||
if tp == "end" then
|
||||
print("err, unclosed paren")
|
||||
break
|
||||
end
|
||||
add(list, t)
|
||||
end
|
||||
return list, rst, tp
|
||||
end
|
||||
|
||||
return t, rst, tp
|
||||
end
|
||||
|
||||
-->8
|
||||
-- env
|
||||
#include env.lua
|
||||
|
||||
-->8
|
||||
-- lib
|
||||
#include lib.lua
|
||||
|
||||
|
||||
-->8
|
||||
-- eval
|
||||
#include eval.lua
|
||||
|
||||
eval(parse([[
|
||||
(do
|
||||
(def! push (\ (l a)
|
||||
(join l (list a))))
|
||||
|
||||
(def! bq-fold (\ (acc ast)
|
||||
(push acc
|
||||
(if (tab? ast)
|
||||
(if (= ([] ast 1) 'comma)
|
||||
([] ast 2)
|
||||
(fold bq-fold '(list) ast))
|
||||
(list 'quote ast)))))
|
||||
|
||||
(defmacro! backquote (\ (ast)
|
||||
(fold bq-fold '(list) ast))))
|
||||
]]), lib, function(val)
|
||||
--
|
||||
end)
|
||||
|
||||
-->8
|
||||
cls()
|
||||
lisp_src = [[
|
||||
|
||||
;; edit example
|
||||
(?! 69 "steamed hams") ;comment
|
||||
(do
|
||||
|
||||
(def! add-or-sub (\ (func)
|
||||
(func 10 18)))
|
||||
|
||||
(add-or-sub (\ (a b)
|
||||
(?! a b)
|
||||
(= a b))))
|
||||
|
||||
(do
|
||||
(def! add-or-sub (\ (func)
|
||||
(func 10 18)))
|
||||
|
||||
(add-or-sub (\ (a b)
|
||||
(?! a b)
|
||||
|
||||
(= a b))))
|
||||
|
||||
(do
|
||||
|
||||
(def! farts (list 69 420 666))
|
||||
|
||||
(def! combo (\ (acc l)
|
||||
(?! "combo:" acc l)
|
||||
(+ acc l)))
|
||||
|
||||
(fold combo 0 farts))
|
||||
|
||||
(do
|
||||
(def! thing 1)
|
||||
(def! adder (\ (num)
|
||||
|
||||
; unamed second function
|
||||
(\ (a)
|
||||
|
||||
; unamed third function
|
||||
(\ (b)
|
||||
(+ a b num)))
|
||||
))
|
||||
|
||||
(def! crap (adder 4))
|
||||
(def! dung (crap 2))
|
||||
(dung 1)
|
||||
;((adder 4) 2) -> dung
|
||||
|
||||
(dung 63))
|
||||
|
||||
(do
|
||||
(def! cownter (let ((c 0))
|
||||
(\ (a)
|
||||
(set! c (+ c a))
|
||||
(?! c))))
|
||||
|
||||
(cownter 1)
|
||||
(cownter 5)
|
||||
(cownter 2))
|
||||
|
||||
(do
|
||||
|
||||
(def! uwu (\ (x y)
|
||||
(set! x (- 0 x))
|
||||
(set! y (- 0 y))
|
||||
(camera x y)
|
||||
|
||||
|
||||
(color 5)
|
||||
(line 10 98 10 88)
|
||||
(line 10 98 50 98)
|
||||
(line 50 88 50 98)
|
||||
(line 50 88 40 88)
|
||||
(line 20 88 10 88)
|
||||
(line 20 88 20 60)
|
||||
(line 40 88 40 60)
|
||||
(line 40 60 20 60)
|
||||
(line 40 70 20 70)
|
||||
(line 30 65 30 60)))
|
||||
|
||||
(cls 1)
|
||||
(uwu 50 0)
|
||||
(uwu 0 0)
|
||||
(uwu 25 -48))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(do
|
||||
(defmacro! bee
|
||||
(let ((bees 0)) (\ (val)
|
||||
(set! bees (+ 1 bees))
|
||||
`(?! ,bees ,val))))
|
||||
|
||||
(def! a 6)
|
||||
(def! b "trees")
|
||||
|
||||
(bee b)
|
||||
(bee "yeet")
|
||||
(bee ((\() "yeet")))
|
||||
(bee "tank")
|
||||
(bee "yank")
|
||||
(bee "gank"))
|
||||
|
||||
|
||||
(def! draw (let ()
|
||||
(def! l (\ (c)
|
||||
(def! x (rnd 128))
|
||||
(def! y (rnd 128))
|
||||
(def! u (rnd 128))
|
||||
(def! v (rnd 128))
|
||||
(line x y u v c)
|
||||
(spr 1 (- x 4) (- y 4))
|
||||
(circ u v 4)))
|
||||
(def! jump 0)
|
||||
(\ ()
|
||||
(call/cc (\ (c)
|
||||
(set! jump c)))
|
||||
(cls 15)
|
||||
(cursor 1 1)
|
||||
(color 0)
|
||||
(?! (stat 0))
|
||||
(map 0 0)
|
||||
(if (< 0 (btn))
|
||||
(?! "hi"))
|
||||
(l 1) (l 0)
|
||||
(l 1) (l 0)
|
||||
(l 1) (l 0)
|
||||
(l 1) (l 0))))
|
||||
]]
|
||||
lisp_src = replace(lisp_src,
|
||||
"\t", " ")
|
||||
list,rst = parse(lisp_src)
|
||||
|
||||
print(list_tostr(list, ""))
|
||||
|
||||
local enviro = {
|
||||
__p = lib,
|
||||
__t = {},
|
||||
["true"] = true,
|
||||
["false"] = false,
|
||||
["none"] = none,
|
||||
}
|
||||
|
||||
local err = eval(list, enviro,
|
||||
function(v)
|
||||
print(list_tostr(v, "-> "))
|
||||
end)
|
||||
if(err) print("err: " .. tostr(err))
|
||||
|
||||
-->8
|
||||
-- edit
|
||||
|
||||
--[[
|
||||
todo:
|
||||
--]]
|
||||
|
||||
function draw_line(s, y)
|
||||
if y > 128 or y < -6 then
|
||||
return
|
||||
end
|
||||
|
||||
local x = 0
|
||||
local cols = {
|
||||
str=3, com=13, num=12, sym=6,
|
||||
bound=14, lib=11,
|
||||
}
|
||||
|
||||
local t, rst, tp = token(s)
|
||||
while tp != "end" do
|
||||
color(7)
|
||||
if cols[tp] then
|
||||
color(cols[tp])
|
||||
end
|
||||
if lib[t] then
|
||||
color(cols.lib)
|
||||
end
|
||||
if enviro[t] then
|
||||
color(cols.bound)
|
||||
end
|
||||
|
||||
x = print(t, x, y)
|
||||
t, rst, tp = token(rst)
|
||||
end
|
||||
end
|
||||
|
||||
function draw_code(y)
|
||||
cls(0)
|
||||
|
||||
local src=split(lisp_src, "\n")
|
||||
|
||||
for i = 1, #src do
|
||||
draw_line(src[i], y+ i * 6 - 6)
|
||||
--print(src[i])
|
||||
end
|
||||
end
|
||||
|
||||
-->8
|
||||
-- draw
|
||||
|
||||
if enviro.draw then
|
||||
function _draw()
|
||||
local err = enviro.draw({},
|
||||
enviro, function(v)end)
|
||||
if err then
|
||||
color(7)
|
||||
?err
|
||||
stop()
|
||||
end
|
||||
end
|
||||
else
|
||||
local scroll = 0
|
||||
function _draw()
|
||||
draw_code(scroll)
|
||||
if(btn(⬆️))scroll += 6
|
||||
if(btn(⬇️))scroll -= 6
|
||||
end
|
||||
end
|
||||
|
||||
__gfx__
|
||||
00000000008888000033330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000002200000000220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00700700002200000000220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00077000088aa8000036633000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00077000a88aa8a00636633600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00700700a88aa8a00636633600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000088888000033333000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000080080000003003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
03333330333330003333330300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
33333333333333333333333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
33333333333333333332233300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
03332223332223233333333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
03333332333233333333232300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
33333333333332333333233300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
33332333323333333333333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
33333233322333333333333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
03333323333333333333333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
03333333333333333332333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
33233333333222332333333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
33333333223333333333333000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
32323233233333333332333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
33333333333322323333333000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
33323333333332233333333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00333333333333333332333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
33333333333333333322333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
33333333333333333333333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
33333333332332333333323300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
32323322223333333332333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
33223333323333233233333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
33333333333333333332333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
03332333333333333333333000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
30333303330033300333333000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
__map__
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
0000002021220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
0000003031320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
0000004041420000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000202121212200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000404141414200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
Loading…
Reference in New Issue