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