Advertisement
thisismysignup

pico8 repl v35

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