thisismysignup

pico8 repl v36

Dec 23rd, 2025
353
0
Never
13
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 74.45 KB | Source Code | 0 0
  1.  
  2. ------------------------
  3. -- Prepare globals
  4. ------------------------
  5.  
  6. local g_ENV, my_ENV, globfuncs = _ENV, {}, {}
  7. for k,v in pairs(_ENV) do
  8.     my_ENV[k] = v
  9.     if (type(v) == "function") globfuncs[k] = true
  10. end
  11.  
  12. local _ENV = my_ENV -- with this, we segregate ourselves from the running code (all global accesses below use _ENV automagically)
  13.  
  14. g_enable_repl, g_last_value = true
  15.  
  16.  
  17. ------------------------
  18. -- Utils
  19. ------------------------
  20.  
  21. -- is elem inside seq (a sequence or string)? (if so, returns index)
  22. function isoneof(elem, seq)
  23.     for i=1,#seq do
  24.         if (seq[i] == elem) return i
  25.     end
  26. end
  27.  
  28. ------------------------
  29. -- Tokenize
  30. ------------------------
  31.  
  32. -- escape sequences in strings (e.g. \n -> new line)
  33. local esc_keys, esc_values = split "a,b,f,n,r,t,v,\\,\",',\n,*,#,-,|,+,^", split "\a,\b,\f,\n,\r,\t,\v,\\,\",',\n,\*,\#,\-,\|,\+,\^"
  34. local escapes = {}
  35. for i=1,#esc_keys do escapes[esc_keys[i]] = esc_values[i] end
  36.  
  37. -- is ch a digit char?
  38. function isdigit(ch)
  39.     return ch and ch >= '0' and ch <= '9'
  40. end
  41. -- is ch a valid identifier char?
  42. function isalnum(ch)
  43.     return ch and (ch >= 'A' and ch <= 'Z' or ch >= 'a' and ch <= 'z' or isoneof(ch, '_\x1e\x1f') or ch >= '\x80' or isdigit(ch))
  44. end
  45.  
  46.  
  47. -- extarct string value from quoted string
  48. -- returns value, end index
  49. function dequote(str, i, strlen, quote, fail)
  50.     local rawstr = ''
  51.     while i <= strlen do
  52.         local ch = str[i]
  53.         if (ch == quote) break
  54.         if ch == '\\' then -- handle escape sequences
  55.             i += 1
  56.             local esch = str[i]
  57.             ch = escapes[esch] -- handle normal escapes
  58.             -- hex escape (e.g. \xff)
  59.             if esch == 'x' then
  60.                 esch = tonum('0x'..sub(str,i+1,i+2))
  61.                 if (esch) i += 2 else fail "bad hex escape"
  62.                 ch = chr(esch)
  63.             -- decimal escape (e.g. \014)
  64.             elseif isdigit(esch) then
  65.                 local start = i
  66.                 while isdigit(esch) and i < start + 3 do i += 1; esch = str[i] end
  67.                 i -= 1
  68.                 esch = tonum(sub(str,start,i))
  69.                 if (not esch or esch >= 256) fail "bad decimal escape"
  70.                 ch = chr(esch)
  71.             -- ignore subsequent whitespace
  72.             elseif esch == 'z' then
  73.                 repeat i += 1; esch = str[i] until not isoneof(esch, ' \r\t\f\v\n')
  74.                 if (not esch) fail()
  75.                 ch = ''
  76.                 i -= 1
  77.             elseif not esch then fail() ch='' end
  78.             if (not ch) fail("bad escape: " .. esch) ch=''
  79.         elseif ch == '\n' then
  80.             fail "unterminated string"
  81.             break
  82.         end
  83.         rawstr ..= ch
  84.         i += 1
  85.     end
  86.     if (i > strlen) fail("unterminated string", true)
  87.     return rawstr, i+1
  88. end
  89.  
  90. -- extracts string value from long bracketed string (e.g. [[string]])
  91. -- returns value, end index
  92. function delongbracket(str, i, strlen, fail)
  93.     if str[i] == '[' then
  94.         i += 1
  95.         local eq_start = i
  96.         while (str[i] == '=') i += 1
  97.         local end_delim = ']' .. sub(str,eq_start,i-1) .. ']'
  98.         local j = #end_delim
  99.  
  100.         if str[i] == '[' then
  101.             i += 1
  102.             if (str[i] == '\n') i += 1
  103.             local start = i
  104.             while (i <= strlen and sub(str,i,i+j-1) != end_delim) i += 1
  105.             if (i >= strlen) fail()
  106.             return sub(str,start,i-1), i+j
  107.         end
  108.     end
  109.     return nil, i
  110. end
  111.  
  112. -- converts a string into tokens.
  113. --   if strict is set, errors are thrown if invalid, and comments are ignored
  114. -- returns:
  115. --   array of tokens
  116. --   array of the line each token is found at (for if/while shorthand parsing only)
  117. --   array of token start indices
  118. --   array of token end indices
  119. -- A token is:
  120. --   false for invalid
  121. --   true for comment (unless strict)
  122. --   number for numeric literal
  123. --   string for identifier, keyword, or punctuation
  124. --   table for string literal (table contains a single string at position [1])
  125. function tokenize(str, strict)
  126.     local i, line, start = 1, 1
  127.     local tokens, tlines, tstarts, tends, err = {}, {}, {}, {}
  128.  
  129.     local function fail(v, ok)
  130.         if (strict) on_compile_fail(v, start)
  131.         err = v and not ok
  132.     end
  133.  
  134.     -- we support unindexable huge strings up to 64KB (at least as long as pico8 can handle them)
  135.     -- we do this via the below hacks (though it doesn't handle huge tokens over 16KB...)
  136.     local strlen = #str >= 0 and #str or 0x7fff
  137.     while i <= strlen do
  138.         if (i >= 0x4001 and strlen >= 0x7fff) str = sub(str, 0x4001); i -= 0x4000; strlen = #str >= 0 and #str or 0x7fff
  139.        
  140.         start = i
  141.         local ch = str[i]
  142.         local ws, token
  143.         -- whitespace
  144.         if isoneof(ch, ' \r\t\f\v\n') then
  145.             i += 1; ws = true
  146.             if (ch == '\n') line += 1
  147.         -- comment
  148.         elseif isoneof(ch, '-/') and str[i+1] == ch then
  149.             i += 2
  150.             if (ch == '-' and str[i] == '[') token, i = delongbracket(str, i, strlen, fail)
  151.             if not token then
  152.                 while (i <= strlen and str[i] != '\n') i += 1
  153.             end
  154.             if (strict) ws = true else add(tokens, true)
  155.         -- number
  156.         elseif isdigit(ch) or (ch == '.' and isdigit(str[i+1])) then
  157.             local digits, dot = "0123456789", true
  158.             -- hex. number (0x...)
  159.             if ch == '0' and isoneof(str[i+1], 'xX') then digits ..= "AaBbCcDdEeFf"; i += 2
  160.             -- binary number (0b...)
  161.             elseif ch == '0' and isoneof(str[i+1], 'bB') then digits = "01"; i += 2
  162.             end
  163.             while true do
  164.                 ch = str[i]
  165.                 if ch == '.' and dot then dot = false
  166.                 elseif not isoneof(ch, digits) then break end
  167.                 i += 1
  168.             end
  169.             token = sub(str,start,i-1)
  170.             if (not tonum(token)) fail "bad number"; token="0"
  171.             add(tokens, tonum(token))
  172.         -- identifier
  173.         elseif isalnum(ch) then
  174.             while isalnum(str[i]) do i += 1 end
  175.             add(tokens, sub(str,start,i-1))
  176.         -- string
  177.         elseif ch == "'" or ch == '"' then
  178.             token, i = dequote(str, i+1, strlen, ch, fail)
  179.             add(tokens, {token})
  180.         -- long-bracket string
  181.         elseif ch == '[' and isoneof(str[i+1], "=[") then
  182.             token, i = delongbracket(str, i, strlen, fail)
  183.             if (not token) fail "invalid long brackets"
  184.             add(tokens, {token})
  185.         -- punctuation
  186.         else
  187.             i += 1
  188.             local ch2,ch3,ch4 = unpack(split(sub(str,i,i+2),""))
  189.             if ch2 == ch and ch3 == ch and isoneof(ch,'.>') then
  190.                 i += 2
  191.                 if (ch4 == "=" and isoneof(ch,'>')) i += 1
  192.             elseif ch2 == ch and ch3 != ch and isoneof(ch,'<>') and isoneof(ch3,'<>') then
  193.                 i += 2
  194.                 if (ch4 == "=") i += 1
  195.             elseif ch2 == ch and isoneof(ch,'.:^<>') then
  196.                 i += 1
  197.                 if (ch3 == "=" and isoneof(ch,'.^<>')) i += 1
  198.             elseif ch2 == '=' and isoneof(ch,'+-*/\\%^&|<>=~!') then i += 1
  199.             elseif isoneof(ch,'+-*/\\%^&|<>=~#(){}[];,?@$.:') then
  200.             else fail("bad char: " .. ch) end
  201.             add(tokens, sub(str,start,i-1))
  202.         end
  203.         if (not ws) add(tlines, line); add(tstarts, start); add(tends, i-1)
  204.         if (err) tokens[#tokens], err = false, false
  205.     end
  206.     return tokens, tlines, tstarts, tends
  207. end
  208. ------------------------
  209. -- More Utils
  210. ------------------------
  211.  
  212. -- similar to unpack, except depack(pack(...)) is always ...
  213. function depack(t)
  214.     return unpack(t,1,t.n) -- (unpack defaults to t,1,#t instead)
  215. end
  216.  
  217. -- copy a table
  218. function copy(t)
  219.     local ct = {}
  220.     for k, v in next, t do ct[k] = v end
  221.     return ct
  222. end
  223.  
  224. ------------------------
  225. -- Parse & Eval
  226. ------------------------
  227.  
  228. -- General information:
  229. -- As we parse lua's grammar, we build nodes, which are merely
  230. -- functions that take e (an environment) as the first arg.
  231. -- Parent nodes call their children nodes, thus forming a sort of tree.
  232.  
  233. -- An environment (e) is an array of scope tables
  234. -- the scope table at index 0 contains top-level upvalues like _ENV
  235. -- other scope tables contain locals defined within a local statement (*)
  236. -- Thus, upvalues and locals are accessed the same way
  237.  
  238. -- Expression (expr) parsing returns a (node, setnode, tailcallnode) tuple.
  239. -- node returns the expression's value
  240. -- setnode returns a tuple of the table and key to use for the assignment (**)
  241. -- tailcallnode returns a tuple of the function and args to use for a tail-call
  242. -- setnode and/or tailcallnode are nil if assignment/call is not available
  243.  
  244. -- Note that functions called from within parse_expr instead return a
  245. -- (node, is_prefix, setnode, tailcallnode) tuple, where is_prefix
  246. -- says whether the node can be used as a prefix for calls/etc.
  247.  
  248. -- Statement (stmt) parsing returns a (node, is_end) tuple
  249. -- node returns either:
  250. --   nil to continue execution
  251. --   true to break from loop
  252. --   (0, label object) to goto the label object
  253. --   table to return its depack() from the function
  254. --   function to tail-call it as we return from the function
  255. -- node may also be nil for empty statements
  256. -- is_end is true if the statement must end the block
  257.  
  258. -- (*) We create a table per local statement, instead of per block
  259. --     because by using goto, you can execute a local statement multiple
  260. --     times without leaving a block, each time resulting in a different
  261. --     local (that can be independently captured)
  262.  
  263. -- (**) It would be much simpler for setnode to do the assignment itself,
  264. --      but it would prevent us from mimicking lua's observable left-to-right
  265. --      evaluation behaviour,  where the assignment targets are evaluated
  266. --      before the assignment values.
  267.  
  268. -- On that note, we generally mimic lua's observable left-to-right evaluation
  269. -- behaviour, except that we do true left-to-right evaluation, while lua
  270. -- usually evaluates locals (only!) right before the operation that uses them.
  271. -- This difference can be observed if the local is captured by a closure,
  272. --  e.g: local a=1; print(a + (function() a = 3; return 0 end)())
  273.  
  274. -- anyway:
  275.  
  276. -- identifiers to treat as keywords instead
  277. local keywords = split "and,break,do,else,elseif,end,false,for,function,goto,if,in,local,nil,not,or,repeat,return,then,true,until,while"
  278.  
  279. keyword_map = {}
  280. for kw in all(keywords) do keyword_map[kw] = true end
  281.  
  282. -- is token an assign op (e.g. +=)?
  283. local function is_op_assign(token)
  284.     return type(token) == "string" and token[-1] == '='
  285. end
  286.  
  287. -- tokens that terminate a block
  288. end_tokens = split 'end,else,elseif,until'
  289.  
  290.  
  291.  
  292. -- parses a string, returning a function
  293. -- that receives a global environment (e.g. _ENV) and executes the code
  294. function parse(str )
  295.     -- tokenize the string first
  296.     local tokens, tlines, tstarts = tokenize(str, true)
  297.     -- ti: the token index we're at
  298.     -- e_len: how many environments deep we are
  299.     -- depth: how many blocks deep we are
  300.     local ti, e_len, depth, func_e_len, loop_depth, func_depth = 1, 0, 0 , 0
  301.     local parse_expr, parse_block
  302.     -- gotos: array of functions to evaluate in order to finalize gotos
  303.     -- locals: maps names of locals to the environment array index where
  304.     --         they're defined
  305.     -- labels: maps names of labels to label objects
  306.     --
  307.     -- both locals and labels use a metatable to simulate a sort-of stack
  308.     -- where pushed maps inherit from all previous maps in the stack and
  309.     -- can be easily popped.
  310.     --
  311.     -- endcb: specifies when to stop shorthand parsing
  312.     local gotos, locals, labels, endcb = {}
  313.  
  314.     local function fail(err)
  315.         on_compile_fail(err, tstarts[ti-1] or 1)
  316.     end
  317.  
  318.     -- return a node that returns a constant
  319.     local function const_node(value)
  320.         return function() return value end
  321.     end
  322.     -- return a node that returns the value of a variable
  323.     local function var_node(name)
  324.         local e_i = locals[name]
  325.         if e_i then return function(e) return e[e_i][name] end -- local/upvalue
  326.         else e_i = locals._ENV return function(e) return e[e_i]._ENV[name] end -- global
  327.         end
  328.     end
  329.     -- return a node that returns the values of the vararg arguments
  330.     -- of the current function.
  331.     local function vararg_node()
  332.         local e_i = locals['...']
  333.         if (not e_i or e_i != func_e_len) fail "unexpected '...'"
  334.         return function(e) return depack(e[e_i]["..."]) end
  335.     end
  336.     -- return a setnode that allows assigning to the value of a variable
  337.     local function assign_node(name)
  338.         local e_i = locals[name]
  339.         if e_i then return function(e) return e[e_i], name end -- local/upvalue
  340.         else e_i = locals._ENV return function(e) return e[e_i]._ENV, name end -- global
  341.         end
  342.     end
  343.  
  344.     -- consume the next token, requiring it to be 'expect'
  345.     local function require(expect)
  346.         local token = tokens[ti]; ti += 1
  347.         if (token == expect) return
  348.         if (token == nil) fail()
  349.         fail("expected: " .. expect)
  350.     end
  351.  
  352.     -- consume the next token, requiring it to be an identifier
  353.     -- returns the identifier
  354.     local function require_ident(token)
  355.         if (not token) token = tokens[ti]; ti += 1
  356.         if (token == nil) fail()
  357.         if (type(token) == 'string' and isalnum(token[1]) and not keyword_map[token]) return token
  358.         if (type(token) == 'string') fail("invalid identifier: " .. token)
  359.         fail "identifier expected"
  360.     end
  361.  
  362.     -- if the next token is 'expect', consumes it and returns true
  363.     local function accept(expect)
  364.         if (tokens[ti] == expect) ti += 1; return true
  365.     end
  366.  
  367.     -- return whether we're at the end of a statement
  368.     local function at_stmt_end()
  369.         return isoneof(tokens[ti], end_tokens) or (endcb and endcb(ti))
  370.     end
  371.  
  372.     -- push a new locals map to the locals 'stack'
  373.     local function push_locals()
  374.         locals = setmetatable({}, {__index=locals})
  375.         e_len += 1
  376.     end
  377.  
  378.     -- pop a locals map from the 'stack'
  379.     local function pop_locals()
  380.         locals = getmetatable(locals).__index
  381.         e_len -= 1
  382.     end
  383.  
  384.     -- evaluate an array of nodes, returning a pack of results
  385.     -- the last node in the array may return an arbitrary number of results,
  386.     -- all of which are packed.
  387.     local function eval_nodes(e, nodes)
  388.         local results = {}
  389.         local n = #nodes
  390.         for i=1,n-1 do
  391.             results[i] = nodes[i](e)
  392.         end
  393.         if n > 0 then
  394.             local values = pack(nodes[n](e))
  395.             if values.n != 1 then
  396.                 for i=1,values.n do
  397.                     results[n + i - 1] = values[i]
  398.                 end
  399.                 n += values.n - 1
  400.             else
  401.                 results[n] = values[1]
  402.             end
  403.         end
  404.         results.n = n
  405.         return results
  406.     end
  407.  
  408.     -- parses a comma-separated list of elements, each parsed via 'parser'
  409.     local function parse_list(parser)
  410.         local list = {}
  411.         add(list, (parser()))
  412.         while accept ',' do
  413.             add(list, (parser()))
  414.         end
  415.         return list
  416.     end
  417.  
  418.     -- parse a call expression
  419.     --   node : call target node
  420.     --   method : method to call for method call expression (e.g. a:b())
  421.     --   arg : single argument node (e.g. for a"b" and a{b})
  422.     -- returns (node, is_prefix (true), setnode (nil), tailcallnode, is_call (true))
  423.     local function parse_call(node, method, arg)
  424.         -- parse the arguments
  425.         local args = {}
  426.         if arg then
  427.             add(args, arg)
  428.         elseif not accept ')' then
  429.             while true do
  430.                 add(args, (parse_expr()))
  431.                 if (accept ')') break
  432.                 require ','
  433.             end
  434.         end
  435.  
  436.         if method then
  437.             return function(e)
  438.                 -- call method
  439.                 local obj = node(e)
  440.                 return obj[method](obj, depack(eval_nodes(e, args)))
  441.             end, true, nil, function(e)
  442.                 -- return ingredients for a method tail-call
  443.                 local obj = node(e)
  444.                 return obj[method], pack(obj, depack(eval_nodes(e, args)))
  445.             end, true
  446.         else
  447.             return function(e)
  448.                 -- call function
  449.                 return node(e)(depack(eval_nodes(e, args)))
  450.             end, true, nil, function(e)
  451.                 -- return ingredients for a function tail-call
  452.                 return node(e), eval_nodes(e, args)
  453.             end, true
  454.         end
  455.     end
  456.  
  457.     -- parse a table construction expression (e.g. {1,2,3})
  458.     local function parse_table()
  459.         -- key/value nodes
  460.         local keys, values = {}, {}
  461.         -- splat_i : either #keys if the last item in the table is array-style
  462.         --   (and thus may fill multiple array values), or nil otherwise
  463.         local index, splat_i = 1
  464.         while not accept '}' do
  465.             splat_i = nil
  466.  
  467.             local key, value
  468.             -- e.g. [a]=b
  469.             if accept '[' then
  470.                 key = parse_expr(); require ']'; require '='; value = parse_expr()
  471.             -- e.g. a=b
  472.             elseif tokens[ti+1] == '=' then
  473.                 key = const_node(require_ident()); require '='; value = parse_expr()
  474.             -- e.g. b
  475.             else
  476.                 key = const_node(index); value = parse_expr(); index += 1; splat_i = #keys + 1
  477.             end
  478.  
  479.             add(keys, key); add(values, value)
  480.  
  481.             if (accept '}') break
  482.             if (not accept ';') require ','
  483.         end
  484.  
  485.         return function(e)
  486.             -- constuct table
  487.             -- note: exact behaviour of # may differ from natively created tables
  488.             local table = {}
  489.             for i=1,#keys do
  490.                 if i == splat_i then
  491.                     -- set multiple table elements (e.g. {f()})
  492.                     local key, value = keys[i](e), pack(values[i](e))
  493.                     for j=1,value.n do
  494.                         table[key + j - 1] = value[j]
  495.                     end
  496.                 else
  497.                     -- set table element
  498.                     table[keys[i](e)] = values[i](e)
  499.                 end
  500.             end
  501.             return table
  502.         end
  503.     end
  504.  
  505.     -- parse a function expression or statement
  506.     -- is_stmt : true if statement
  507.     -- is_local: true if local function statement
  508.     local function parse_function(is_stmt, is_local)
  509.        
  510.         -- has_self : function has implicit self arg
  511.         -- setnode : for statements, how to assign the function to a variable
  512.         local name, has_self, setnode
  513.  
  514.         if is_stmt then
  515.             if is_local then
  516.                 -- local function statement
  517.                 push_locals()
  518.                 name = require_ident()
  519.                 locals[name] = e_len
  520.                 setnode = assign_node(name)
  521.                
  522.             else
  523.                 -- function statement
  524.                 name = {require_ident()}
  525.                 -- function name may include multiple .-seprated parts
  526.                 while (accept '.') add(name, require_ident())
  527.                 -- and may include a final :-separated part
  528.                 if (accept ':') add(name, require_ident()); has_self = true
  529.  
  530.                 if #name == 1 then setnode = assign_node(name[1])
  531.                 else
  532.                     local node = var_node(name[1])
  533.                     for i=2,#name-1 do
  534.                         local node_i = node -- capture
  535.                         node = function(e) return node_i(e)[name[i]] end
  536.                     end
  537.                     setnode = function(e) return node(e), name[#name] end
  538.                 end
  539.                
  540.             end
  541.         end
  542.  
  543.         -- parse function params
  544.         local params, vararg = {}
  545.         if (has_self) add(params, 'self')
  546.         require "("
  547.         if not accept ')' then
  548.             while true do
  549.                 if (accept '...') vararg = true; else add(params, require_ident())
  550.                 if (accept ')') break
  551.                 require ','
  552.                 if (vararg) fail "unexpected param after '...'"
  553.             end
  554.         end
  555.  
  556.         -- add function params as locals
  557.         push_locals()
  558.         for param in all(params) do locals[param] = e_len end
  559.         if (vararg) locals['...'] = e_len
  560.  
  561.         -- parse function's body
  562.         local old_gotos, old_depth, old_e_len = gotos, func_depth, func_e_len
  563.         gotos, func_depth, func_e_len = {}, depth + 1, e_len
  564.         local body = parse_block()
  565.         for g in all(gotos) do g() end -- handle gotos
  566.         gotos, func_depth, func_e_len = old_gotos, old_depth, old_e_len
  567.         require 'end'
  568.         pop_locals()
  569.  
  570.         return function(e)
  571.             if (is_local) add(e, {})
  572.  
  573.             -- create the function's environment
  574.             -- note: this is a shallow copy of the environment array,
  575.             --   not of the tables within.
  576.             local func_e = copy(e)
  577.             local expected_e_len = #func_e
  578.  
  579.             -- this is the actual function created
  580.             local func = function(...)
  581.                 local args = pack(...) -- pack args
  582.                
  583.                
  584.  
  585.                 -- normally, when a function exits, its environment
  586.                 -- ends up the same as it started, so it can be reused
  587.                 -- however, if the function didn't exit yet (e.g. recursion)
  588.                 -- we create a copy of the environment to use for this call
  589.                 local my_e = func_e
  590.                 if #my_e != expected_e_len then
  591.                     local new_e = {}
  592.                     for i=0, expected_e_len do new_e[i] = my_e[i] end
  593.                     my_e = new_e
  594.                 end
  595.  
  596.                 -- add scope for params
  597.                 local scope = {}
  598.                 for i=1,#params do scope[params[i]] = args[i] end
  599.  
  600.                 if (vararg) scope['...'] = pack(unpack(args, #params+1, args.n))
  601.  
  602.                 -- evaluate function body
  603.                 add(my_e, scope)
  604.                 local retval = body(my_e)
  605.                 deli(my_e)
  606.  
  607.                
  608.                
  609.                 -- return function result
  610.                 if retval then
  611.                     if (type(retval) == "table") return depack(retval) -- return
  612.                     return retval() -- tailcall
  613.                 end
  614.             end
  615.  
  616.             -- assign or return the function
  617.             if (is_stmt) local d,k = setnode(e); d[k] = func else return func
  618.         end
  619.     end
  620.  
  621.     -- parse a core expression, aka an expression without any suffixes
  622.     -- returns (node, is_prefix, setnode, tailcallnode, is_call)
  623.     local function parse_core()
  624.         local token = tokens[ti]; ti += 1
  625.         local arg
  626.         if (token == nil) fail()
  627.         -- nil constant
  628.         if (token == "nil") return const_node()
  629.         -- true constant
  630.         if (token == "true") return const_node(true)
  631.         -- false constant
  632.         if (token == "false") return const_node(false)
  633.         -- number constant
  634.         if (type(token) == "number") return const_node(token)
  635.         -- string constant
  636.         if (type(token) == "table") return const_node(token[1])
  637.         -- table
  638.         if (token == "{") return parse_table()
  639.         -- parentheses (this is NOT an no-op, unlike in most
  640.         --   languages - as it forces the expression to return 1 result)
  641.         if (token == "(") arg = parse_expr(); require ')'; return function(e) return (arg(e)) end, true
  642.         -- unary ops
  643.         if (token == "-") arg = parse_expr(11); return function(e) return -arg(e) end
  644.         if (token == "~") arg = parse_expr(11); return function(e) return ~arg(e) end
  645.         if (token == "not") arg = parse_expr(11); return function(e) return not arg(e) end
  646.         if (token == "#") arg = parse_expr(11); return function(e) return #arg(e) end
  647.         if (token == "@") arg = parse_expr(11); return function(e) return @arg(e) end
  648.         if (token == "%") arg = parse_expr(11); return function(e) return %arg(e) end
  649.         if (token == "$") arg = parse_expr(11); return function(e) return $arg(e) end
  650.         -- function creation
  651.         if (token == 'function') return parse_function()
  652.         -- vararg
  653.         if (token == "...") return vararg_node()
  654.         -- print shorthand
  655.         if token == '?' then
  656.             local print_node, nodes = var_node 'print', parse_list(parse_expr);
  657.             return function (e) return (print_node(e)(depack(eval_nodes(e, nodes)))) end, false, nil, nil, true
  658.         end
  659.         -- special repl-specific commands
  660.         if (token == "\\") arg = require_ident() return function() return cmd_exec(arg) end, true, function() return cmd_assign(arg) end
  661.         -- identifiers
  662.         if (require_ident(token)) return var_node(token), true, assign_node(token)
  663.         fail("unexpected token: " .. token)
  664.     end
  665.  
  666.     -- parse a binary operation expression
  667.     -- the extra 'v' argument is used only by op-assignment statements
  668.     local function parse_binary_op(token, prec, left, right_expr)
  669.         local right
  670.         if (token == "^" and prec <= 12) right = right_expr(12); return function(e,v) return left(e,v) ^ right(e) end
  671.         if (token == "*" and prec < 10) right = right_expr(10); return function(e,v) return left(e,v) * right(e) end
  672.         if (token == "/" and prec < 10) right = right_expr(10); return function(e,v) return left(e,v) / right(e) end
  673.         if (token == "\\" and prec < 10) right = right_expr(10); return function(e,v) return left(e,v) \ right(e) end
  674.         if (token == "%" and prec < 10) right = right_expr(10); return function(e,v) return left(e,v) % right(e) end
  675.         if (token == "+" and prec < 9) right = right_expr(9); return function(e,v) return left(e,v) + right(e) end
  676.         if (token == "-" and prec < 9) right = right_expr(9); return function(e,v) return left(e,v) - right(e) end
  677.         if (token == ".." and prec <= 8) right = right_expr(8); return function(e,v) return left(e,v) .. right(e) end
  678.         if (token == "<<" and prec < 7) right = right_expr(7); return function(e,v) return left(e,v) << right(e) end
  679.         if (token == ">>" and prec < 7) right = right_expr(7); return function(e,v) return left(e,v) >> right(e) end
  680.         if (token == ">>>" and prec < 7) right = right_expr(7); return function(e,v) return left(e,v) >>> right(e) end
  681.         if (token == "<<>" and prec < 7) right = right_expr(7); return function(e,v) return left(e,v) <<> right(e) end
  682.         if (token == ">><" and prec < 7) right = right_expr(7); return function(e,v) return left(e,v) >>< right(e) end
  683.         if (token == "&" and prec < 6) right = right_expr(6); return function(e,v) return left(e,v) & right(e) end
  684.         if ((token == "^^" or token == "~") and prec < 5) right = right_expr(5); return function(e,v) return left(e,v) ^^ right(e) end
  685.         if (token == "|" and prec < 4) right = right_expr(4); return function(e,v) return left(e,v) | right(e) end
  686.         if (token == "<" and prec < 3) right = right_expr(3); return function(e,v) return left(e,v) < right(e) end
  687.         if (token == ">" and prec < 3) right = right_expr(3); return function(e,v) return left(e,v) > right(e) end
  688.         if (token == "<=" and prec < 3) right = right_expr(3); return function(e,v) return left(e,v) <= right(e) end
  689.         if (token == ">=" and prec < 3) right = right_expr(3); return function(e,v) return left(e,v) >= right(e) end
  690.         if (token == "==" and prec < 3) right = right_expr(3); return function(e,v) return left(e,v) == right(e) end
  691.         if ((token == "~=" or token == "!=") and prec < 3) right = right_expr(3); return function(e,v) return left(e,v) ~= right(e) end
  692.         if (token == "and" and prec < 2) right = right_expr(2); return function(e,v) return left(e,v) and right(e) end
  693.         if (token == "or" and prec < 1) right = right_expr(1); return function(e,v) return left(e,v) or right(e) end
  694.     end
  695.  
  696.     -- given an expression, parses a suffix for this expression, if possible
  697.     -- prec : precedence to not go beyond when parsing
  698.     -- isprefix : true to allow calls/etc. (lua disallows it for certain
  699.     --            expression unless parentheses are used, not sure why)
  700.     -- returns (node, is_prefix, setnode, tailcallnode, is_call)
  701.     local function parse_expr_more(prec, left, isprefix)
  702.         local token = tokens[ti]; ti += 1
  703.         local right, arg
  704.         if isprefix then
  705.             -- table index by name
  706.             if (token == '.') right = require_ident(); return function(e) return left(e)[right] end, true, function(e) return left(e), right end
  707.             -- table index
  708.             if (token == '[') right = parse_expr(); require ']'; return function(e) return left(e)[right(e)] end, true, function(e) return left(e), right(e) end
  709.             -- call
  710.             if (token == "(") return parse_call(left)
  711.             -- call with table or string argument
  712.             if (token == "{" or type(token) == "table") ti -= 1; arg = parse_core(); return parse_call(left, nil, arg)
  713.             -- method call
  714.             if token == ":" then
  715.                 right = require_ident();
  716.                 -- ... with table or string argument
  717.                 if (tokens[ti] == "{" or type(tokens[ti]) == "table") arg = parse_core(); return parse_call(left, right, arg)
  718.                 require '('; return parse_call(left, right)
  719.             end
  720.         end
  721.        
  722.         -- binary op
  723.         local node = parse_binary_op(token, prec, left, parse_expr)
  724.         if (not node) ti -= 1
  725.         return node
  726.     end
  727.  
  728.     -- parse an arbitrary expression
  729.     -- prec : precedence to not go beyond when parsing
  730.     -- returns (node, setnode, tailcallnode, is_call)
  731.     parse_expr = function(prec)
  732.         local node, isprefix, setnode, callnode, iscall = parse_core()
  733.         while true do
  734.             local newnode, newisprefix, newsetnode, newcallnode, newiscall = parse_expr_more(prec or 0, node, isprefix)
  735.             if (not newnode) break
  736.             node, isprefix, setnode, callnode, iscall = newnode, newisprefix, newsetnode, newcallnode, newiscall
  737.         end
  738.         return node, setnode, callnode, iscall
  739.     end
  740.  
  741.     -- parse an assignment expression, returning its setnode
  742.     local function parse_assign_expr()
  743.         local _, assign_expr = parse_expr()
  744.         if (not assign_expr) fail "cannot assign to value"
  745.         return assign_expr
  746.     end
  747.  
  748.     -- parse assignment statement
  749.     local function parse_assign()
  750.         local targets = parse_list(parse_assign_expr)
  751.         require "="
  752.         local sources = parse_list(parse_expr)
  753.  
  754.         if #targets == 1 and #sources == 1 then return function(e)
  755.             -- single assignment (for performance)
  756.             local d,k = targets[1](e); d[k] = sources[1](e)
  757.         end else return function(e)
  758.             -- multiple assignment (e.g. a,b=c,d)
  759.             local dests, keys = {}, {}
  760.             for i=1,#targets do local d,k = targets[i](e); add(dests,d) add(keys,k) end
  761.             local values = eval_nodes(e, sources)
  762.             -- assign from last to first, per observable lua behaviour
  763.             for i=#targets,1,-1 do dests[i][keys[i]] = values[i] end
  764.         end end
  765.     end
  766.  
  767.     -- parse op-assignment statement (e.g. +=)
  768.     -- receives the setnode of the assignment target, and uses it to both get and set the value
  769.     -- (this is to ensure the node is evaluated only once)
  770.     local function parse_op_assign(setnode)
  771.         local token = tokens[ti]; ti += 1
  772.         local op = sub(token,1,-2)
  773.         local node = function(e, v) return v end -- parse_binary_op propagates the value as an extra arg to us
  774.         local op_node = parse_binary_op(op, 0, node, function() return parse_expr() end) -- ignore precedence
  775.         if (not op_node) fail "invalid compound assignment"
  776.         return function(e) local d,k = setnode(e); d[k] = op_node(e, d[k]) end
  777.     end
  778.  
  779.     -- parse local statement
  780.     local function parse_local()
  781.         if accept 'function' then
  782.             -- local function statement
  783.             return parse_function(true, true)
  784.         else
  785.             local targets = parse_list(require_ident)
  786.             local sources = accept '=' and parse_list(parse_expr) or {}
  787.  
  788.             push_locals()
  789.             for i=1,#targets do locals[targets[i]] = e_len end
  790.  
  791.             if #targets == 1 and #sources == 1 then return function(e)
  792.                 -- single local (for performance)
  793.                 add(e, {[targets[1]] = sources[1](e)})
  794.             end else return function(e)
  795.                 -- multiple locals
  796.                 local scope = {}
  797.                 local values = eval_nodes(e, sources)
  798.                 for i=1,#targets do scope[targets[i]] = values[i] end
  799.                 add(e, scope)
  800.             end end
  801.         end
  802.     end
  803.  
  804.     -- start if/while shorthand parsing
  805.     -- allows terminating the parsing of a block at the end of the line
  806.     local function start_shorthand(allowed)
  807.         local line = tlines[ti - 1]
  808.         local prev_endcb = endcb
  809.         endcb = function(i) return line != tlines[i] end
  810.         if (not allowed or endcb(ti)) fail(ti <= #tokens and "unterminated shorthand" or nil)
  811.         return prev_endcb
  812.     end
  813.  
  814.     -- end shorthand parsing, and verify we haven't exceeded the line
  815.     local function end_shorthand(prev_endcb)
  816.         if (endcb(ti-1)) fail("unterminated shorthand")
  817.         endcb = prev_endcb
  818.     end
  819.  
  820.     -- parse an 'if' statement
  821.     local function parse_ifstmt()
  822.         local short = tokens[ti] == '('
  823.         local cond = parse_expr()
  824.         local then_b, else_b
  825.         if accept 'then' or accept 'do' then
  826.             -- normal if statement
  827.             then_b, else_b = parse_block()
  828.             if accept 'else' then else_b = parse_block(); require "end" -- else
  829.             elseif accept 'elseif' then else_b = parse_ifstmt() -- elseif
  830.             else require "end" end
  831.         else
  832.             -- shorthand if
  833.             local prev = start_shorthand(short)
  834.             then_b = parse_block()
  835.             if (not endcb(ti) and accept 'else') else_b = parse_block() -- shorhand if/else
  836.             end_shorthand(prev)
  837.         end
  838.  
  839.         return function(e)
  840.             -- execute the if
  841.             if cond(e) then return then_b(e)
  842.             elseif else_b then return else_b(e)
  843.             end
  844.         end
  845.     end
  846.  
  847.     -- parse a loop block, updating loop_depth (for break purposes)
  848.     local function parse_loop_block(...)
  849.         local old_depth = loop_depth
  850.         loop_depth = depth + 1
  851.         local result = parse_block(...)
  852.         loop_depth = old_depth
  853.         return result
  854.     end
  855.  
  856.     -- if retval denotes a break, do not propagate it further
  857.     -- useful when returning from loop blocks
  858.     local function handle_break(retval, label)
  859.         if (retval == true) return -- break
  860.         return retval, label
  861.     end
  862.  
  863.     -- parse a 'while' block
  864.     local function parse_while()
  865.         local short = tokens[ti] == '('
  866.         local cond = parse_expr()
  867.         local body
  868.         if accept 'do' then
  869.             -- normal while statement
  870.             body = parse_loop_block()
  871.             require 'end'
  872.         else
  873.             -- shorthand while statement
  874.             local prev = start_shorthand(short)
  875.             body = parse_loop_block()
  876.             end_shorthand(prev)
  877.         end
  878.  
  879.         return function(e)
  880.             -- execute the while
  881.             while cond(e) do
  882.                 if (stat(1)>=1) yield_execute()
  883.                 local retval, label = body(e)
  884.                 if (retval) return handle_break(retval, label)
  885.             end
  886.         end
  887.     end
  888.  
  889.     -- parse a repeat/until statement
  890.     local function parse_repeat()
  891.         -- note that the until part can reference
  892.         -- locals declared inside the repeat body, thus
  893.         -- we pop the locals/scopes ourselves
  894.         local block_e_len = e_len
  895.         local body = parse_loop_block(true)
  896.         require 'until'
  897.         local cond = parse_expr()
  898.         while (e_len > block_e_len) pop_locals()
  899.  
  900.         return function(e)
  901.             -- execute the repeat/until
  902.             repeat
  903.                 if (stat(1)>=1) yield_execute()
  904.                 local retval, label = body(e)
  905.                 if (not retval) label = cond(e) -- reuse label as the end cond
  906.  
  907.                 while (#e > block_e_len) deli(e) -- pop scopes ourselves
  908.                 if (retval) return handle_break(retval, label)
  909.             until label -- actually the end cond
  910.         end
  911.     end
  912.  
  913.     -- parse a 'for' statement
  914.     local function parse_for()
  915.         if tokens[ti + 1] == '=' then
  916.             -- numeric for statement
  917.             local varb = require_ident()
  918.             require '='
  919.             local min = parse_expr()
  920.             require ','
  921.             local max = parse_expr()
  922.             local step = accept ',' and parse_expr() or const_node(1)
  923.             require 'do'
  924.  
  925.             -- push 'for' local, and parse the body
  926.             push_locals()
  927.             locals[varb] = e_len
  928.             local body = parse_loop_block()
  929.             require 'end'
  930.             pop_locals()
  931.  
  932.             return function(e)
  933.                 -- execute the numeric 'for'
  934.                 for i=min(e),max(e),step(e) do
  935.                     if (stat(1)>=1) yield_execute()
  936.                     add(e, {[varb]=i})
  937.                     local retval, label = body(e)
  938.                     deli(e)
  939.                     if (retval) return handle_break(retval, label)
  940.                 end
  941.             end
  942.         else
  943.             -- generic 'for' block
  944.             local targets = parse_list(require_ident)
  945.             require "in"
  946.             local sources = parse_list(parse_expr)
  947.             require 'do'
  948.  
  949.             -- push 'for' locals, and parse the body
  950.             push_locals()
  951.             for target in all(targets) do locals[target] = e_len end
  952.  
  953.             local body = parse_loop_block()
  954.             require 'end'
  955.             pop_locals()
  956.  
  957.             return function(e)
  958.                 -- execute the generic 'for'
  959.                 -- (must synthesize it ourselves, as a generic for's
  960.                 --  number of vars is fixed)
  961.                 local exps = eval_nodes(e, sources)
  962.                 while true do
  963.                     local scope = {}
  964.  
  965.                     local vars = {exps[1](exps[2], exps[3])}
  966.                     if (vars[1] == nil) break
  967.                     exps[3] = vars[1]
  968.                     for i=1,#targets do scope[targets[i]] = vars[i] end
  969.  
  970.                     if (stat(1)>=1) yield_execute()
  971.                     add(e, scope)
  972.                     local retval, label = body(e)
  973.                     deli(e)
  974.                     if (retval) return handle_break(retval, label)
  975.                 end
  976.             end
  977.         end
  978.     end
  979.  
  980.     -- parse a break statement
  981.     local function parse_break()
  982.         if (not loop_depth or func_depth and loop_depth < func_depth) fail "break outside of loop"
  983.         return function() return true end
  984.     end
  985.  
  986.     -- parse a return statement
  987.     -- N.B. lua actually allows return (and vararg) outside of functions.
  988.     --      this kinda completely breaks repuzzle, so the repl code in it disallows it.
  989.     local function parse_return()
  990.  
  991.         if tokens[ti] == ';' or at_stmt_end() then
  992.             -- return no values (represented by us as an empty pack)
  993.             return function() return pack() end
  994.         else
  995.             local node, _, callnode = parse_expr()
  996.             local nodes = {node}
  997.             while (accept ',') add(nodes, (parse_expr()))
  998.  
  999.             if #nodes == 1 and callnode and func_depth then
  1000.                 -- tail-call (aka jump into other function instead of returning)
  1001.                 return function(e) local func, args = callnode(e);
  1002.                     if (stat(1)>=1) yield_execute()
  1003.                     return function() return func(depack(args)) end
  1004.                 end
  1005.             else
  1006.                 -- normal return
  1007.                 return function(e) return eval_nodes(e, nodes) end
  1008.             end
  1009.         end
  1010.     end
  1011.  
  1012.     -- parse label statement
  1013.     local function parse_label(parent)
  1014.         local label = require_ident()
  1015.         require '::'
  1016.         if (labels[label] and labels[label].depth == depth) fail "label already defined"
  1017.         -- store label object
  1018.         labels[label] = {e_len=e_len, depth=depth, block=parent, i=#parent}
  1019.     end
  1020.  
  1021.     -- parse goto statement
  1022.     local function parse_goto()
  1023.         local label = require_ident()
  1024.         local labels_c, e_len_c, value = labels, e_len -- capture labels
  1025.  
  1026.         -- the label may be defined after the goto, so process the goto
  1027.         -- at function end
  1028.         add(gotos, function ()
  1029.             value = labels_c[label]
  1030.             if (not value) fail "label not found"
  1031.             if (func_depth and value.depth < func_depth) fail "goto outside of function"
  1032.             -- goto cannot enter a scope
  1033.             -- (empty statements at the end of a scope aren't considered a
  1034.             --  part of the scope for this purpose)
  1035.             local goto_e_len = labels_c[value.depth] or e_len_c
  1036.             if (value.e_len > goto_e_len and value.i < #value.block) fail "goto past local"
  1037.         end)
  1038.  
  1039.         return function()
  1040.             if (stat(1)>=1) yield_execute()
  1041.             return 0, value
  1042.         end
  1043.     end
  1044.  
  1045.     -- parse any statement
  1046.     local function parse_stmt(parent)
  1047.         local token = tokens[ti]; ti += 1
  1048.         -- empty semicolon
  1049.         if (token == ';') return
  1050.         -- do-end block
  1051.         if (token == 'do') local node = parse_block(); require 'end'; return node
  1052.         -- if
  1053.         if (token == 'if') return parse_ifstmt()
  1054.         -- while loop
  1055.         if (token == 'while') return parse_while()
  1056.         -- repeat/until loop
  1057.         if (token == 'repeat') return parse_repeat()
  1058.         -- for loop
  1059.         if (token == 'for') return parse_for()
  1060.         -- break
  1061.         if (token == 'break') return parse_break()
  1062.         -- return
  1063.         if (token == 'return') return parse_return(), true
  1064.         -- local
  1065.         if (token == 'local') return parse_local()
  1066.         -- goto
  1067.         if (token == 'goto') return parse_goto()
  1068.         -- label
  1069.         if (token == '::') return parse_label(parent)
  1070.         -- function
  1071.         if (token == 'function' and tokens[ti] != '(') return parse_function(true)
  1072.  
  1073.         -- handle assignments and expressions
  1074.         ti -= 1
  1075.         local start = ti -- allow reparse
  1076.         local node, setnode, tailcall, iscall = parse_expr()
  1077.  
  1078.         -- assignment
  1079.         if accept ',' or accept '=' then
  1080.             ti = start; return parse_assign()
  1081.         -- op-assignment
  1082.         elseif is_op_assign(tokens[ti]) then
  1083.             return parse_op_assign(setnode)
  1084.         -- repl-specific print of top-level expression
  1085.         elseif depth <= 1 and g_enable_repl then
  1086.             return function (e)
  1087.                 local results = pack(node(e))
  1088.                 -- iscall and not tailcall == node is a '?'
  1089.                 if (not (iscall and (results.n == 0 or not tailcall))) add(g_results, results)
  1090.                 g_last_value = results[1]
  1091.             end
  1092.         -- regular expression statements (must be call)
  1093.         else
  1094.             if (not iscall) fail "statement has no effect"
  1095.             return function(e) node(e) end
  1096.         end
  1097.     end
  1098.  
  1099.     -- parse a block of statements
  1100.     -- keep_locals: true to let the caller exit the block themselves
  1101.     parse_block = function(keep_locals)
  1102.         -- push a new labels map in the labels 'stack'
  1103.         labels = setmetatable({}, {__index=labels})
  1104.         labels[depth] = e_len
  1105.  
  1106.         -- increase depth
  1107.         depth += 1
  1108.         local block_depth = depth
  1109.         local block_e_len = keep_locals and 0x7fff or e_len
  1110.  
  1111.         -- parse block statements
  1112.         local block = {}
  1113.         while ti <= #tokens and not at_stmt_end() do
  1114.             local  stmt, need_end =  parse_stmt(block)
  1115.             if (stmt) add(block, stmt)
  1116.             if (need_end) accept ';'; break
  1117.         end
  1118.  
  1119.         -- pop any locals pushed inside the block
  1120.         while (e_len > block_e_len) pop_locals()
  1121.         depth -= 1
  1122.         labels = getmetatable(labels).__index
  1123.  
  1124.         return function (e)
  1125.             -- execute the block's statements
  1126.             local retval, label
  1127.             local i,n = 1,#block
  1128.             while i <= n do
  1129.                
  1130.                 retval, label = block[i](e)
  1131.                 if retval then
  1132.                     -- handle returns & breaks
  1133.                     if (type(retval) != "number") break
  1134.                     -- handle goto to parent block
  1135.                     if (label.depth != block_depth) break
  1136.                     -- handle goto to this block
  1137.                     i = label.i
  1138.                     while (#e > label.e_len) deli(e)
  1139.                     retval, label = nil
  1140.                 end
  1141.                 i += 1
  1142.             end
  1143.             while (#e > block_e_len) deli(e)
  1144.             return retval, label
  1145.         end
  1146.     end
  1147.    
  1148.     -- create top-level upvalues
  1149.     locals = g_enable_repl and {_ENV=0, _env=0, _=0} or {_ENV=0}
  1150.     locals['...'] = 0
  1151.     -- parse top-level block
  1152.     local root = parse_block()
  1153.     if (ti <= #tokens) fail "unexpected end"
  1154.     -- handle top-level gotos
  1155.     for g in all(gotos) do g() end
  1156.  
  1157.     return function(env, ...)
  1158.         -- create top-level scope
  1159.         local scope = g_enable_repl and {_ENV=env, _env=env, _=g_last_value} or {_ENV=env}
  1160.         scope['...'] = pack(...)
  1161.        
  1162.         -- execute
  1163.                
  1164.         local retval = root{[0]=scope}
  1165.        
  1166.         if (retval) return depack(retval)
  1167.     end
  1168. end
  1169. ------------------------
  1170. -- Output
  1171. ------------------------
  1172.  
  1173. g_show_max_items, g_hex_output, g_precise_output = 10, false, false
  1174.  
  1175.  
  1176. -- reverse mapping of escapes
  1177. local unescapes = {["\0"]="000",["\014"]="014",["\015"]="015"}
  1178. for k, v in pairs(escapes) do
  1179.     if (not isoneof(k, "'\n")) unescapes[v] = k
  1180. end
  1181.  
  1182. -- create quoted string from a string value
  1183. function requote(str)
  1184.     local i = 1
  1185.     while i <= #str do
  1186.         local ch = str[i]
  1187.         local nch = unescapes[ch]
  1188.         if (nch) str = sub(str,1,i-1) .. '\\' .. nch .. sub(str,i+1); i += #nch
  1189.         i += 1
  1190.     end
  1191.     return '"' .. str .. '"'
  1192. end
  1193.  
  1194. -- is 'key' representable as an identifier?
  1195. function is_identifier(key)
  1196.     if (type(key) != 'string') return false
  1197.     if (keyword_map[key]) return false
  1198.     if (#key == 0 or isdigit(key[1])) return false
  1199.     for i=1,#key do
  1200.         if (not isalnum(key[i])) return false
  1201.     end
  1202.     return true
  1203. end
  1204.  
  1205. -- convert value as a string
  1206. -- (more featured than tostr)
  1207. function value_to_str(val, depth)
  1208.     local ty = type(val)
  1209.     -- nil
  1210.     if (ty == 'nil') then
  1211.         return 'nil'
  1212.     -- boolean
  1213.     elseif (ty == 'boolean') then
  1214.         return val and 'true' or 'false'
  1215.     -- number (optionally hex)
  1216.     elseif (ty == 'number') then
  1217.         if (not g_precise_output) return tostr(val, g_hex_output)
  1218.         local str = tostr(val)
  1219.         return tonum(str) == val and str or tostr(val,1)
  1220.     -- string (with quotes)
  1221.     elseif (ty == 'string') then
  1222.         return requote(val)
  1223.     -- table contents
  1224.     elseif (ty == 'table' and not depth) then
  1225.         local res = '{'
  1226.         local i = 0
  1227.         local prev = 0
  1228.         -- avoid pairs, as it uses metamethods
  1229.         for k,v in next, val do
  1230.             if (i == g_show_max_items) res ..= ',<...>' break
  1231.             if (i > 0) res ..= ','
  1232.            
  1233.             local vstr = value_to_str(v,1)
  1234.             if k == prev + 1 then res ..= vstr; prev = k
  1235.             elseif is_identifier(k) then res ..= k .. '=' .. vstr
  1236.             else res ..= '[' .. value_to_str(k,1) ..']=' .. vstr end
  1237.             i += 1
  1238.         end
  1239.        
  1240.         return res .. '}'
  1241.     -- other
  1242.     else
  1243.         return '<' .. tostr(ty) .. '>'
  1244.     end
  1245. end
  1246. -- convert more results into a string
  1247. function results_to_str(str, results)
  1248.     if (results == nil) return str -- no new results
  1249.     if (not str) str = ''
  1250.  
  1251.     local count = min(21,#results)
  1252.     for ir=1, count do
  1253.         if (#str > 0) str ..= '\n'
  1254.  
  1255.         local result = results[ir]
  1256.         if type(result) == 'table' then
  1257.             local line = ''
  1258.             for i=1,result.n do
  1259.                 if (#line > 0) line ..= ', '
  1260.                 line ..= value_to_str(result[i])
  1261.             end
  1262.             str ..= line
  1263.         else
  1264.             str ..= result
  1265.         end
  1266.     end
  1267.  
  1268.     local new_results = {}
  1269.     for i=count+1, #results do new_results[i - count] = results[i] end
  1270.     return str, new_results
  1271. end
  1272.  
  1273. ------------------------
  1274. -- Console output
  1275. ------------------------
  1276.  
  1277. poke(0x5f2d,1) -- enable keyboard
  1278. cls()
  1279.  
  1280. g_prompt = "> " -- currently must be valid token!
  1281. g_input, g_input_lines, g_input_start = "", 1, 0
  1282. g_cursor_pos, g_cursor_time = 1, 20
  1283. --lint: g_str_output, g_error_output
  1284. g_history, g_history_i = {''}, 1
  1285. --lint: g_interrupt, g_notice, g_notice_time
  1286. g_abort = false
  1287. g_num_output_lines, g_line = 0, 1
  1288.  
  1289. g_enable_interrupt, g_enable_autoflip = true, true
  1290. g_pal = split "7,4,3,5,6,8,5,12,14,7,11,5"
  1291.  
  1292. -- override print for better output
  1293. g_ENV.print = function(value, ...)
  1294.     if (not g_enable_interrupt or select('#', ...) != 0) return print(value, ...)
  1295.  
  1296.     add(g_results, tostr(value))
  1297.     local resx, resy = print(value, 1000, 1000) -- offscreen print for result and side-effects
  1298.     return resx - 1000, resy - 1000 -- kinda
  1299. end
  1300.  
  1301. -- suppress pause (e.g. from p, etc.)
  1302. function unpause()
  1303.     poke(0x5f30,1)
  1304. end
  1305.  
  1306. -- an iterator over pressed keys
  1307. function get_keys()
  1308.     return function()
  1309.         if (stat(30)) return stat(31)
  1310.     end
  1311. end
  1312.  
  1313. -- walk over a string, calling a callback on its chars
  1314. function walk_str(str, cb)
  1315.     local i = 1
  1316.     local x, y = 0, 0
  1317.     if (not str) return i, x, y
  1318.     while i <= #str do
  1319.         local ch = str[i]
  1320.         local spch = ch >= '\x80'
  1321.         if (x >= (spch and 31 or 32)) y += 1; x = 0
  1322.         if (cb) cb(i,ch,x,y)
  1323.  
  1324.         if ch == '\n' then y += 1; x = 0
  1325.         else x += (spch and 2 or 1) end
  1326.         i += 1
  1327.     end
  1328.     return i, x, y
  1329. end
  1330.  
  1331. -- given string and index, return x,y at index
  1332. function str_i2xy(str, ci)
  1333.     local cx, cy = 0, 0
  1334.     local ei, ex, ey = walk_str(str, function(i,ch,x,y)
  1335.         if (ci == i) cx, cy = x, y
  1336.     end)
  1337.     if (ci >= ei) cx, cy = ex, ey
  1338.     if (ex > 0) ey += 1
  1339.     return cx, cy, ey
  1340. end
  1341.  
  1342. -- given string and x,y - return index at x,y
  1343. function str_xy2i(str, cx, cy)
  1344.     local ci = 1
  1345.     local found = false
  1346.     local ei, ex, ey = walk_str(str, function(i,ch,x,y)
  1347.         if (cy == y and cx == x and not found) ci = i; found = true
  1348.         if ((cy < y or cy == y and cx < x) and not found) ci = i - 1; found = true
  1349.     end)
  1350.     if (not found) ci = cy >= ey and ei or ei - 1
  1351.     if (ex > 0) ey += 1
  1352.     return ci, ey
  1353. end
  1354.  
  1355. -- print string at position, using color value or function
  1356. function str_print(str, xpos, ypos, color)
  1357.     if type(color) == "function" then
  1358.         walk_str(str, function(i,ch,x,y)
  1359.             print(ch, xpos + x*4, ypos + y*6, color(i))
  1360.         end)
  1361.     else
  1362.         print(str and "\^rw" .. str, xpos, ypos, color)
  1363.     end
  1364. end
  1365.  
  1366. -- print code, using syntax highlighting
  1367. function str_print_input(input, xpos, ypos)
  1368.     local tokens, _, tstarts, tends = tokenize(input) -- tlines not reliable!
  1369.     local ti = 1
  1370.     str_print(input, xpos, ypos, function(i)
  1371.         while ti <= #tends and tends[ti] < i do ti += 1 end
  1372.  
  1373.         local token
  1374.         if (ti <= #tends and tstarts[ti] <= i) token = tokens[ti]
  1375.  
  1376.         local c = g_pal[5]
  1377.         if token == false then c = g_pal[6] -- error
  1378.         elseif token == true then c = g_pal[7] -- comment
  1379.         elseif type(token) != 'string' or isoneof(token, split"nil,true,false") then c = g_pal[8]
  1380.         elseif keyword_map[token] then c = g_pal[9]
  1381.         elseif not isalnum(token[1]) then c = g_pal[10]
  1382.         elseif globfuncs[token] then c = g_pal[11] end
  1383.  
  1384.         return c
  1385.     end)
  1386. end
  1387.  
  1388. -- draw (messy...)
  1389. function _draw()
  1390.     local old_color = peek(0x5f25)
  1391.     local old_camx, old_camy = peek2(0x5f28), peek2(0x5f2a)
  1392.     camera()
  1393.  
  1394.     local function scroll(count)
  1395.         cursor(0,127)
  1396.         for _=1,count do
  1397.             rectfill(0,g_line*6,127,(g_line+1)*6-1,0)
  1398.             if g_line < 21 then
  1399.                 g_line += 1
  1400.             else
  1401.                 print ""
  1402.             end
  1403.         end
  1404.     end
  1405.  
  1406.     local function unscroll(count, minline)
  1407.         for _=1,count do
  1408.             if (g_line > minline) g_line -= 1
  1409.             rectfill(0,g_line*6,127,(g_line+1)*6-1,0)
  1410.         end
  1411.     end
  1412.  
  1413.     local function draw_cursor(x, y)
  1414.         for i=0,2 do
  1415.             local c = pget(x+i,y+5)
  1416.             pset(x+i,y+5,c==0 and g_pal[12] or 0)
  1417.         end
  1418.     end
  1419.  
  1420.     local function draw_input(cursor)
  1421.         local input = g_prompt .. g_input .. ' '
  1422.         local cx, cy, ilines = str_i2xy(input, #g_prompt + g_cursor_pos) -- ' ' is cursor placeholder
  1423.  
  1424.         if ilines > g_input_lines then
  1425.             scroll(ilines - g_input_lines)
  1426.         elseif ilines < g_input_lines then
  1427.             unscroll(g_input_lines - ilines, ilines)
  1428.         end
  1429.         g_input_lines = ilines
  1430.  
  1431.         g_input_start = mid(g_input_start, 0, max(g_input_lines - 21, 0))
  1432.  
  1433.         ::again::
  1434.         local sy = g_line - g_input_lines + g_input_start
  1435.         if (sy+cy < 0) g_input_start += 1; goto again
  1436.         if (sy+cy >= 21) g_input_start -= 1; goto again
  1437.  
  1438.         local y = sy*6
  1439.         rectfill(0,y,127,y+g_input_lines*6-1,0)
  1440.         if (g_input_lines>21) rectfill(0,126,127,127,0) -- clear partial line
  1441.         str_print_input(input,0,y)
  1442.         print(g_prompt,0,y,g_pal[4])
  1443.  
  1444.         if (g_cursor_time >= 10 and cursor != false and not g_interrupt) draw_cursor(cx*4, y + cy*6)
  1445.     end
  1446.  
  1447.     -- require pressing enter to view more results
  1448.     local function page_interrupt(page_olines)
  1449.         scroll(1)
  1450.         g_line -= 1
  1451.         print("[enter] ('esc' to abort)",0,g_line*6,g_pal[3])
  1452.  
  1453.         while true do
  1454.             flip(); unpause()
  1455.             for key in get_keys() do
  1456.                 if (key == '\x1b') g_abort = true; g_str_output = ''; g_results = {}; return false
  1457.                 if (key == '\r' or key == '\n') g_num_output_lines += page_olines; return true
  1458.             end
  1459.         end
  1460.     end
  1461.  
  1462.     ::restart::
  1463.     local ostart, olines
  1464.     if g_results or g_str_output then
  1465.         ostart, olines = str_xy2i(g_str_output, 0, g_num_output_lines)
  1466.         if olines - g_num_output_lines <= 20 and g_results then -- add more output
  1467.             g_str_output, g_results = results_to_str(g_str_output, g_results)
  1468.             ostart, olines = str_xy2i(g_str_output, 0, g_num_output_lines)
  1469.             if (#g_results == 0 and not g_interrupt) g_results = nil
  1470.         end
  1471.     end
  1472.  
  1473.     if (not g_interrupt) camera()
  1474.  
  1475.     if (g_num_output_lines == 0 and not g_interrupt) draw_input(not g_str_output)
  1476.  
  1477.     if g_str_output then
  1478.         local output = sub(g_str_output, ostart)
  1479.         local page_olines = min(olines - g_num_output_lines, 20)
  1480.  
  1481.         scroll(page_olines)
  1482.         str_print(output,0,(g_line - page_olines)*6,g_pal[1])
  1483.  
  1484.         if page_olines < olines - g_num_output_lines then
  1485.             if (page_interrupt(page_olines)) goto restart
  1486.         else
  1487.             local _, _, elines = str_i2xy(g_error_output, 0)
  1488.             scroll(elines)
  1489.             str_print(g_error_output,0,(g_line - elines)*6,g_pal[2])
  1490.  
  1491.             if g_interrupt then
  1492.                 g_num_output_lines += page_olines
  1493.             else
  1494.                 g_input, g_input_lines, g_input_start, g_cursor_pos, g_num_output_lines, g_str_output, g_error_output =
  1495.                     '', 0, 0, 1, 0
  1496.                 draw_input()
  1497.             end
  1498.         end
  1499.     end
  1500.  
  1501.     if g_interrupt then
  1502.         scroll(1)
  1503.         g_line -= 1
  1504.         print(g_interrupt,0,g_line*6,g_pal[3])
  1505.     end
  1506.  
  1507.     if g_notice then
  1508.         scroll(1)
  1509.         g_line -= 1
  1510.         print(g_notice,0,g_line*6,g_pal[3])
  1511.         g_notice = nil
  1512.     end
  1513.  
  1514.     if g_notice_time then
  1515.         g_notice_time -= 1
  1516.         if (g_notice_time == 0) g_notice, g_notice_time = ''
  1517.     end
  1518.  
  1519.     g_cursor_time -= 1
  1520.     if (g_cursor_time == 0) g_cursor_time = 20
  1521.  
  1522.     color(old_color)
  1523.     camera(old_camx, old_camy)
  1524.     if (g_line <= 20) cursor(0, g_line * 6)
  1525. end
  1526.  
  1527. ------------------------
  1528. --- Execution loop
  1529. ------------------------
  1530.  
  1531. g_in_execute_yield, g_in_mainloop, g_from_flip = false, false, false
  1532. g_pending_keys = {}
  1533. --lint: g_results, g_error, g_error_idx
  1534.  
  1535. -- report compilation error
  1536. -- an error of nil means code is likely incomplete
  1537. function on_compile_fail(err, idx)
  1538.     g_error, g_error_idx = err, idx
  1539.     assert(false, err)
  1540. end
  1541.  
  1542. -- execute code
  1543. function execute_raw(line, env, ...)
  1544.     return parse(line)(env or g_ENV, ...)
  1545. end
  1546.  
  1547. -- evaluate code
  1548. function eval_raw(expr, env, ...)
  1549.     return execute_raw("return " .. expr, env, ...)
  1550. end
  1551.  
  1552. -- try parse code
  1553. function try_parse(line)
  1554.     local cc = cocreate(parse)
  1555.     ::_::
  1556.     local ok, result = coresume(cc, line)
  1557.     if (ok and not result) goto _ -- this shouldn't happen anymore, but does (pico bug?)
  1558.     if (not ok) result, g_error = g_error, false
  1559.     return ok, result
  1560. end
  1561.  
  1562. function pos_to_str(line, idx)
  1563.     local x, y = str_i2xy(line, idx)
  1564.     return "line " .. y+1 .. " col " .. x+1
  1565. end
  1566.  
  1567. -- execute code
  1568. function execute(line, complete)
  1569.     g_results, g_abort, g_error = {}, false, false
  1570.     g_in_execute_yield, g_in_mainloop, g_from_flip = false, false, false
  1571.  
  1572.     -- create a coroutine to allow the code to yield to us periodically
  1573.     local coro = cocreate(function ()
  1574.         local results = pack(execute_raw(line))
  1575.         if (results.n != 0) add(g_results, results)
  1576.     end)
  1577.     local _ok, error
  1578.     while true do
  1579.         _ok, error = coresume(coro)
  1580.         if (costatus(coro) == 'dead') break
  1581.  
  1582.         -- handle yields (due to yield/flip or periodic)
  1583.         if g_enable_interrupt and not g_in_mainloop then
  1584.             g_interrupt = "running, press 'esc' to abort"
  1585.             _draw(); flip()
  1586.             g_interrupt = nil
  1587.         else
  1588.             if (g_enable_autoflip and not g_in_mainloop and not g_from_flip) flip()
  1589.             if (not g_enable_autoflip and holdframe) holdframe()
  1590.             g_from_flip = false
  1591.         end
  1592.  
  1593.         for key in get_keys() do
  1594.             if key == '\x1b' then g_abort = true
  1595.             else add(g_pending_keys, key) end
  1596.         end
  1597.  
  1598.         -- abort execution if needed
  1599.         if (g_abort) error = 'computation aborted'; break
  1600.     end
  1601.  
  1602.     if g_error == nil then -- code is incomplete
  1603.         if (complete) error = "unexpected end of code" else error, g_results = nil
  1604.     end
  1605.     if (g_error) error, g_error = g_error .. "\nat " .. pos_to_str(line, g_error_idx)
  1606.     g_error_output = error
  1607.     g_pending_keys = {}
  1608.     return not error
  1609. end
  1610.  
  1611. -- called periodically during execution
  1612. yield_execute = function ()
  1613.     -- yield all the way back to us
  1614.     g_in_execute_yield = true
  1615.     yield()
  1616.     g_in_execute_yield = false
  1617. end
  1618.  
  1619. -- override flip to force a yield_execute
  1620. g_ENV.flip = function(...)
  1621.     local results = pack(flip(...))
  1622.     g_from_flip = true
  1623.     yield_execute()
  1624.     return depack(results)
  1625. end
  1626.  
  1627. -- override coresume to handle yield_execute in coroutines
  1628. g_ENV.coresume = function(co, ...)
  1629.     local results = pack(coresume(co, ...))
  1630.     -- propagate yields from yield_execute
  1631.     while g_in_execute_yield do
  1632.         yield()
  1633.         results = pack(coresume(co)) -- and resume
  1634.     end
  1635.     g_error = false -- discard inner compilation errors (via \x)
  1636.     return depack(results)
  1637. end
  1638.  
  1639. -- override stat so we can handle keys ourselves
  1640. g_ENV.stat = function(i, ...)
  1641.     if i == 30 then
  1642.         return #g_pending_keys > 0 or stat(i, ...)
  1643.     elseif i == 31 then
  1644.         if #g_pending_keys > 0 then
  1645.             return deli(g_pending_keys, 1)
  1646.         else
  1647.             local key = stat(i, ...)
  1648.             if (key == '\x1b') g_abort = true
  1649.             return key
  1650.         end
  1651.     else
  1652.         return stat(i, ...)
  1653.     end
  1654. end
  1655.  
  1656. -- simulate a mainloop.
  1657. -- NOTE:
  1658. --   real mainloop disables time/btnp updates, and also can't be recursed into/quit legally.
  1659. --   the below doesn't disable time/btnp updates at all - but that's not important enough for us.
  1660. function do_mainloop(env, continue)
  1661.     if not continue then
  1662.         if (_set_fps) _set_fps(env._update60 and 60 or 30)
  1663.         if (env._init) env._init()
  1664.     end
  1665.     g_in_mainloop = true
  1666.     while env._draw or env._update or env._update60 do
  1667.         -- if (_update_buttons) _update_buttons() -- this breaks btnp in its current form
  1668.         if (holdframe) holdframe()
  1669.         if env._update60 then env._update60() elseif env._update then env._update() end
  1670.         if (env._draw) env._draw()
  1671.         flip()
  1672.         g_from_flip = true
  1673.         yield_execute()
  1674.     end
  1675.     g_in_mainloop = false
  1676. end
  1677.  
  1678. ------------------------
  1679. -- Cart decompression
  1680. ------------------------
  1681.  
  1682. k_old_code_table = "\n 0123456789abcdefghijklmnopqrstuvwxyz!#%(){}[]<>+=/*:;.,~_"
  1683.  
  1684. -- Old code compression scheme - encodes offset+count for repeated code
  1685. function uncompress_code_old(comp)
  1686.     local code, i = "", 9
  1687.     while true do
  1688.         local ch = ord(comp, i); i += 1
  1689.         if ch == 0 then
  1690.             -- any pico8 char
  1691.             local ch2 = comp[i]; i += 1
  1692.             if (ch2 == '\0') break -- end
  1693.             code ..= ch2
  1694.         elseif ch <= 0x3b then
  1695.             -- quick char from table
  1696.             code ..= k_old_code_table[ch]
  1697.         else
  1698.             -- copy previous code
  1699.             local ch2 = ord(comp, i); i += 1
  1700.             local count = (ch2 >> 4) + 2
  1701.             local offset = ((ch - 0x3c) << 4) + (ch2 & 0xf)
  1702.             for _=1,count do
  1703.                 code ..= code[-offset]
  1704.             end
  1705.         end
  1706.     end
  1707.     return code
  1708. end
  1709.  
  1710. -- New code compression scheme - also uses move-to-front (mtf) and bit reading
  1711. function uncompress_code_new(comp)
  1712.     local code, i, shift, mtf = "", 9, 0, {}
  1713.     comp..="\0\0\0" -- since we don't check for end the legal way
  1714.  
  1715.     for idx=0,0xff do mtf[idx] = chr(idx) end
  1716.  
  1717.     local function getbit()
  1718.         local bit = (ord(comp, i) >> shift) & 1
  1719.         shift += 1
  1720.         if (shift == 8) i += 1; shift = 0
  1721.         return bit == 1
  1722.     end
  1723.     local function getbits(n)
  1724.         local value = 0
  1725.         for bit=0,n-1 do -- NOT fast
  1726.             value |= tonum(getbit()) << bit
  1727.         end
  1728.         return value
  1729.     end
  1730.  
  1731.     while true do
  1732.         if getbit() then
  1733.             -- literal char
  1734.             local nbits, idx = 4, 0
  1735.             while (getbit()) idx |= 1 << nbits; nbits += 1
  1736.             idx += getbits(nbits)
  1737.  
  1738.             local ch = mtf[idx]
  1739.             code ..= ch
  1740.  
  1741.             -- update mtf
  1742.             for j=idx,1,-1 do
  1743.                 mtf[j] = mtf[j-1]
  1744.             end
  1745.             mtf[0] = ch
  1746.         else
  1747.             -- copy previous code (usually)
  1748.             local obits = getbit() and (getbit() and 5 or 10) or 15
  1749.             local offset = getbits(obits) + 1
  1750.  
  1751.             if offset == 1 and obits == 15 then
  1752.                 break -- not an official way to recognize end, but works
  1753.             elseif offset == 1 and obits == 10 then
  1754.                 -- raw block
  1755.                 while true do
  1756.                     local ch = getbits(8)
  1757.                     if (ch == 0) break else code ..= chr(ch)
  1758.                 end
  1759.             else
  1760.                 local count = 3
  1761.                 repeat
  1762.                     local part = getbits(3)
  1763.                     count += part
  1764.                 until part != 7
  1765.  
  1766.                 for _=1,count do
  1767.                     -- we assume 0x8000 isn't a valid offset (pico8 doesn't produce it)
  1768.                     code ..= code[-offset]
  1769.                 end
  1770.             end
  1771.         end
  1772.     end
  1773.     return code
  1774. end
  1775.  
  1776. ------------------------
  1777. -- Console input
  1778. ------------------------
  1779.  
  1780. --lint: g_ideal_x, g_key_code
  1781. g_prev_paste = stat(4)
  1782. g_key_time, g_lower = 0, false
  1783.  
  1784. poke(0x5f5c,10,2) -- faster btnp
  1785.  
  1786. -- return if keyboard key is pressed, using btnp-like logic
  1787. function keyp(code)
  1788.     if stat(28,code) then
  1789.         if (code != g_key_code) g_key_code, g_key_time = code, 0
  1790.         return g_key_time == 0 or (g_key_time >= 10 and g_key_time % 2 == 0)
  1791.     elseif g_key_code == code then
  1792.         g_key_code = nil
  1793.     end
  1794. end
  1795.  
  1796. -- update console input
  1797. function _update()
  1798.     local input = false
  1799.  
  1800.     local function go_line(dy)
  1801.         local cx, cy, h = str_i2xy(g_prompt .. g_input, #g_prompt + g_cursor_pos)
  1802.         if (g_ideal_x) cx = g_ideal_x
  1803.         cy += dy
  1804.         if (not (cy >= 0 and cy < h)) return false
  1805.         g_cursor_pos = max(str_xy2i(g_prompt .. g_input, cx, cy) - #g_prompt, 1)
  1806.         g_ideal_x = cx
  1807.         g_cursor_time = 20 -- setting input clears ideal x
  1808.         return true
  1809.     end
  1810.  
  1811.     local function go_edge(dx)
  1812.         local cx, cy = str_i2xy(g_prompt .. g_input, #g_prompt + g_cursor_pos)
  1813.         cx = dx > 0 and 100 or 0
  1814.         g_cursor_pos = max(str_xy2i(g_prompt .. g_input, cx, cy) - #g_prompt, 1)
  1815.         input = true
  1816.     end
  1817.  
  1818.     local function go_history(di)
  1819.         g_history[g_history_i] = g_input
  1820.         g_history_i += di
  1821.         g_input = g_history[g_history_i]
  1822.         if di < 0 then
  1823.             g_cursor_pos = #g_input + 1
  1824.         else
  1825.             g_cursor_pos = max(str_xy2i(g_prompt .. g_input, 32, 0) - #g_prompt, 1) -- end of first line
  1826.             local ch = g_input[g_cursor_pos]
  1827.             if (ch and ch != '\n') g_cursor_pos -= 1
  1828.         end
  1829.         input = true
  1830.     end
  1831.  
  1832.     local function push_history()
  1833.         if #g_input > 0 then
  1834.             if (#g_history > 50) del(g_history, g_history[1])
  1835.             g_history[#g_history] = g_input
  1836.             add(g_history, '')
  1837.             g_history_i = #g_history
  1838.             input = true
  1839.         end
  1840.     end
  1841.  
  1842.     local function delchar(offset)
  1843.         if (g_cursor_pos+offset > 0) then
  1844.             g_input = sub(g_input,1,g_cursor_pos+offset-1) .. sub(g_input,g_cursor_pos+offset+1)
  1845.             g_cursor_pos += offset
  1846.             input = true
  1847.         end
  1848.     end
  1849.  
  1850.     local function inschar(key)
  1851.         g_input = sub(g_input,1,g_cursor_pos-1) .. key .. sub(g_input,g_cursor_pos)
  1852.         g_cursor_pos += #key
  1853.         input = true
  1854.     end
  1855.  
  1856.     local ctrl = stat(28,224) or stat(28,228)
  1857.     local shift = stat(28,225) or stat(28,229)
  1858.  
  1859.     local keycode = -1
  1860.     if keyp(80) then -- left
  1861.         if (g_cursor_pos > 1) g_cursor_pos -= 1; input = true
  1862.     elseif keyp(79) then -- right
  1863.         if (g_cursor_pos <= #g_input) g_cursor_pos += 1; input = true
  1864.     elseif keyp(82) then -- up
  1865.         if ((ctrl or not go_line(-1)) and g_history_i > 1) go_history(-1)
  1866.     elseif keyp(81) then -- down
  1867.         if ((ctrl or not go_line(1)) and g_history_i < #g_history) go_history(1)
  1868.     else
  1869.         local key = stat(31)
  1870.         keycode = ord(key)
  1871.  
  1872.         if key == '\x1b' then -- escape
  1873.             if #g_input == 0 then extcmd "pause"
  1874.             else g_results, g_error_output = {}; push_history() end
  1875.         elseif key == '\r' or key == '\n' then -- enter
  1876.             if shift then
  1877.                 inschar '\n'
  1878.             else
  1879.                 execute(g_input) -- sets g_results/g_error_output
  1880.                 if (not g_results) inschar '\n' else push_history()
  1881.             end
  1882.         elseif ctrl and keyp(40) then -- ctrl+enter
  1883.             execute(g_input, true); push_history()
  1884.         elseif key != '' and keycode >= 0x20 and keycode < 0x9a then -- ignore ctrl-junk
  1885.             if (g_lower and keycode >= 0x80) key = chr(keycode - 63)
  1886.             inschar(key)
  1887.         elseif keycode == 193 then -- ctrl+b
  1888.             inschar '\n'
  1889.         elseif keycode == 192 then -- ctrl+a
  1890.             go_edge(-1)
  1891.         elseif keycode == 196 then -- ctrl+e
  1892.             go_edge(1)
  1893.         elseif keycode == 203 then -- ctrl+l
  1894.             g_lower = not g_lower
  1895.             g_notice, g_notice_time = "shift now selects " .. (g_lower and "punycase" or "symbols"), 40
  1896.         elseif keyp(74) then -- home
  1897.             if (ctrl) g_cursor_pos = 1; input = true else go_edge(-1);
  1898.         elseif keyp(77) then -- end
  1899.             if (ctrl) g_cursor_pos = #g_input + 1; input = true else go_edge(1);        
  1900.         elseif keyp(42) then delchar(-1) -- backspace
  1901.         elseif keyp(76) then delchar(0) -- del
  1902.         end
  1903.     end
  1904.  
  1905.     local paste = stat(4)
  1906.     if (paste != g_prev_paste or keycode == 213) inschar(paste); g_prev_paste = paste -- ctrl+v
  1907.  
  1908.     if keycode == 194 or keycode == 215 then -- ctrl+x/c
  1909.         if g_input != '' and g_input != g_prev_paste then
  1910.             g_prev_paste = g_input; printh(g_input, "@clip");
  1911.             if (keycode == 215) g_input = ''; g_cursor_pos = 1;
  1912.             g_notice = "press again to put in clipboard"
  1913.         else
  1914.             g_notice = ''
  1915.         end
  1916.     end
  1917.  
  1918.     if stat(120) then -- file drop
  1919.         local str, count = ""
  1920.         repeat
  1921.             count = serial(0x800,0x5f80,0x80)
  1922.             str ..= chr(peek(0x5f80,count))
  1923.         until count == 0
  1924.         if (not load_cart(str)) inschar(str)
  1925.     end
  1926.  
  1927.     if (input) g_cursor_time, g_ideal_x = 20
  1928.     g_key_time += 1
  1929.  
  1930.     unpause()
  1931. end
  1932.  
  1933. ------------------------
  1934. -- Main
  1935. ------------------------
  1936.  
  1937. -- my own crummy mainloop, since time() does not seem to update if the regular mainloop goes "rogue" and flips.
  1938. function toplevel_main()
  1939.     while true do
  1940.         if (holdframe) holdframe()
  1941.         _update()
  1942.         _draw()
  1943.         flip()
  1944.     end
  1945. end
  1946.  
  1947. -- Self-test
  1948. -- (so I can more easily see if something got regressed in the future (esp. due to pico8 changes))
  1949.  
  1950. function selftest(i, cb)
  1951.     local ok, error = coresume(cocreate(cb))
  1952.     if not ok then
  1953.         printh("error #" .. i .. ": " .. error)
  1954.         print("error #" .. i .. "\npico8 broke something again,\nthis cart may not work.\npress any button to ignore")
  1955.         while (btnp() == 0) flip()
  1956.         cls()
  1957.     end
  1958. end
  1959.  
  1960. selftest(1, function() assert(pack(eval_raw "(function (...) return ... end)(1,2,nil,nil)" ).n == 4) end)
  1961. selftest(2, function() assert(eval_raw "function() local temp, temp2 = {max(1,3)}, -20;return temp[1] + temp2; end" () == -17) end)
  1962.  
  1963. -------------------------------------------------------
  1964. -- We're running out of tokens!
  1965. -- What to do? Well, we already have an interpreter above,
  1966. -- so we might as well as interpret the rest of our code!
  1967. --
  1968. -- But looking at code inside strings isn't fun, so I'm automatically moving
  1969. -- all the below code (after the count::stop) into the $$BELOW$$ string
  1970. -- when creating the cart.
  1971. -------------------------------------------------------
  1972.  
  1973. _ENV.g_ENV = g_ENV -- make g_ENV a global, so it can be accessed by below code
  1974. execute_raw("$$BELOW$$", _ENV)
  1975. --lint: count::stop
  1976.  
  1977. ------------------------
  1978. -- Special \-commands
  1979. ------------------------
  1980.  
  1981. -- execute a repl-specific command
  1982. function cmd_exec(name)
  1983.     if isoneof(name, {"i","interrupt"}) then
  1984.         return g_enable_interrupt
  1985.     elseif isoneof(name, {"f","flip"}) then
  1986.         return g_enable_autoflip
  1987.     elseif isoneof(name, {"r","repl"}) then
  1988.         return g_enable_repl
  1989.     elseif isoneof(name, {"mi","max_items"}) then
  1990.         return g_show_max_items
  1991.     elseif isoneof(name, {"h","hex"}) then
  1992.         return g_hex_output
  1993.     elseif isoneof(name, {"pr","precise"}) then
  1994.         return g_precise_output
  1995.     elseif isoneof(name, {"cl","colors"}) then
  1996.         return g_pal
  1997.     elseif isoneof(name, {"c","code"}) then
  1998.         local code = {[0]=g_input}
  1999.         for i=1,#g_history-1 do code[i] = g_history[#g_history-i] end
  2000.         return code
  2001.     elseif isoneof(name, {"cm","compile"}) then
  2002.         return function(str) return try_parse(str) end
  2003.     elseif isoneof(name, {"x","exec"}) then
  2004.         return function(str, env, ...) execute_raw(str, env, ...) end
  2005.     elseif isoneof(name, {"v","eval"}) then
  2006.         return function(str, env, ...) return eval_raw(str, env, ...) end
  2007.     elseif isoneof(name, {"p","print"}) then
  2008.         return function(str, ...) g_ENV.print(value_to_str(str), ...) end
  2009.     elseif isoneof(name, {"ts","tostr"}) then
  2010.         return function(str) return value_to_str(str) end
  2011.     elseif isoneof(name, {"rst","reset"}) then
  2012.         run() -- full pico8 reset
  2013.     elseif isoneof(name, {"run"}) then
  2014.         do_mainloop(g_ENV)
  2015.     elseif isoneof(name, {"cont"}) then
  2016.         do_mainloop(g_ENV, true)
  2017.     else
  2018.         assert(false, "unknown \\-command")
  2019.     end
  2020. end
  2021.  
  2022. -- assign to a repl-specific command
  2023. function cmd_assign(name)
  2024.     local function trueish(t)
  2025.         return (t and t != 0) and true or false
  2026.     end
  2027.  
  2028.     local func
  2029.     if isoneof(name, {"i","interrupt"}) then
  2030.         func = function(v) g_enable_interrupt = trueish(v) end
  2031.     elseif isoneof(name, {"f","flip"}) then
  2032.         func = function(v) g_enable_autoflip = trueish(v) end
  2033.     elseif isoneof(name, {"r","repl"}) then
  2034.         func = function(v) g_enable_repl = trueish(v) end
  2035.     elseif isoneof(name, {"mi","max_items"}) then
  2036.         func = function(v) g_show_max_items = tonum(v) or -1 end
  2037.     elseif isoneof(name, {"h","hex"}) then
  2038.         func = function(v) g_hex_output = trueish(v) end
  2039.     elseif isoneof(name, {"pr","precise"}) then
  2040.         func = function(v) g_precise_output = trueish(v) end
  2041.     elseif isoneof(name, {"cl","colors"}) then
  2042.         func = function(v) g_pal = v end
  2043.     else
  2044.         assert(false, "unknown \\-command assign")
  2045.     end
  2046.  
  2047.     -- do some trickery to allow calling func upon assignment
  2048.     -- (as we're expected to return the assignment target)
  2049.     local obj = {
  2050.         __newindex=function(t,k,v) func(v) end,
  2051.         __index=function() return cmd_exec(name) end, -- op-assign needs this
  2052.     }
  2053.     return setmetatable(obj, obj), 0
  2054. end
  2055.  
  2056. ------------------------
  2057. -- Misc.
  2058. ------------------------
  2059.  
  2060. function load_cart(str)
  2061.     -- is this a full rom? (I'm assuming nobody will drop exactly-32kb text files here!)
  2062.     local code, full = sub(str, 0x4301)
  2063.     if #code == 0x3d00 then
  2064.         full = true
  2065.         poke(0, ord(str, 1, 0x4300)) -- load rom
  2066.     else
  2067.         code = str -- else, either tiny-rom or plaintext
  2068.     end
  2069.  
  2070.     local header = sub(code, 1, 4)
  2071.     if header == ":c:\0" then
  2072.         code = uncompress_code_old(code)
  2073.     elseif header == "\0pxa" then
  2074.         code = uncompress_code_new(code)
  2075.     elseif full then
  2076.         code = split(code, '\0')[1]
  2077.     else
  2078.         -- either plaintext or a tiny/uncompressed tiny-rom (indistinguishable)
  2079.         return
  2080.     end
  2081.  
  2082.     -- run in ideal execution environment
  2083.     g_enable_interrupt, g_enable_repl = false, false
  2084.     local ok = execute(code, true)
  2085.     g_enable_repl = true
  2086.     if (ok) execute("\\run") -- we need to call do_mainloop from within execute, this is the easiest way
  2087.     return true
  2088. end
  2089.  
  2090. toplevel_main()
Tags: pico8 repl
Advertisement
Comments
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • Gelnevor
    137 days
    # CSS 0.85 KB | 0 0
    1. ✅ Leaked Exploit Documentation:
    2.  
    3. https://docs.google.com/document/d/1dOCZEHS5JtM51RITOJzbS4o3hZ-__wTTRXQkV1MexNQ/edit?usp=sharing
    4.  
    5. This made me $13,000 in 2 days.
    6.  
    7. Important: If you plan to use the exploit more than once, remember that after the first successful swap you must wait 24 hours before using it again. Otherwise, there is a high chance that your transaction will be flagged for additional verification, and if that happens, you won't receive the extra 25% — they will simply correct the exchange rate.
    8. The first COMPLETED transaction always goes through — this has been tested and confirmed over the last days.
    9.  
    10. Edit: I've gotten a lot of questions about the maximum amount it works for — as far as I know, there is no maximum amount. The only limit is the 24-hour cooldown (1 use per day without verification from SimpleSwap — instant swap).
  • User was banned
Add Comment
Please, Sign In to add comment