Advertisement
immibis

LiL

May 27th, 2012
1,239
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 67.24 KB | None | 0 0
  1. local LIL_VERSION = "0.1"
  2.  
  3. local LUACEPTION_LEVEL = (os._LUACEPTION_LEVEL or 0) + 1
  4.  
  5. -- Yields if necessary
  6. local yield
  7.  
  8. -- pullQueuedEvent([filter]) - like os.pullEvent but can return events previously queued by yield
  9. local pullQueuedEvent
  10. do
  11.     local event_queue = {}
  12.     local lastYield
  13.     local key = "dummy "..tostring({})
  14.     local function doYield()
  15.         lastYield = os.clock()
  16.         os.queueEvent(key)
  17.         while true do
  18.             local evt = {os.pullEvent()}
  19.             if evt[1] ~= key then
  20.                 table.insert(event_queue, evt)
  21.                 while #event_queue > 100 do
  22.                     table.remove(event_queue, 1)
  23.                 end
  24.             else
  25.                 break
  26.             end
  27.         end
  28.     end
  29.     function yield()
  30.         if lastYield < os.clock() - 0.1 then
  31.             doYield()
  32.         end
  33.     end
  34.     doYield()
  35.    
  36.     function pullQueuedEvent(filter)
  37.         if filter ~= nil then
  38.             while #event_queue > 0 and event_queue[1][1] ~= filter do
  39.                 table.remove(event_queue, 1)
  40.             end
  41.         end
  42.         if #event_queue > 0 then
  43.             return table.remove(event_queue, 1)
  44.         else
  45.             return {os.pullEvent(filter)}
  46.         end
  47.     end
  48. end
  49.  
  50. local function tokenize(c, locprefix)
  51.     local tokens = {}
  52.    
  53.     locprefix = locprefix or "[string]"
  54.  
  55.     local pos = 1
  56.    
  57.     local line = 1
  58.     local char = 1
  59.  
  60.     local lasttok
  61.     local function accept(regex)
  62.         --print(regex, " ", pos)
  63.         --yield()
  64.         local r = c:match("^"..regex, pos)
  65.         if r == nil then return false end
  66.         lasttok = r
  67.         pos = pos + #lasttok
  68.        
  69.         for k=1,#r do
  70.             if r:sub(k,k) == "\n" then
  71.                 line = line + 1
  72.                 char = 1
  73.             else
  74.                 char = char + 1
  75.             end
  76.         end
  77.        
  78.         return true
  79.     end
  80.    
  81.     local function getContext()
  82.         return {prefix=locprefix, line=line, char=char}
  83.         --return c:sub(pos, pos+100)
  84.     end
  85.  
  86.     local keywords = {"do","end","function","while","repeat","until","if","then","elseif","then","else","for","in","local","return","break",
  87.     "nil","false","true",
  88.     "%.%.%.","==","~=","%.%.","<=",">=","and","or","not",
  89.     "[-+;.:+*/,=%[%]%(%)%<%>%^%%#{}]"}
  90.     local function tokenise1()
  91.         accept("[ \r\n\t]+")
  92.         if accept("%-%-%[%[") then
  93.             while not accept("%]%]") do
  94.                 if not accept("[^%]]+") then accept(".") end
  95.             end
  96.             return tokenise1()
  97.         end
  98.         if accept("%-%-[^\n]*\n") then return tokenise1() end
  99.         if accept("[a-zA-Z_][a-zA-Z_0-9]*") then
  100.             for k,v in ipairs(keywords) do
  101.                 if lasttok == v then return v end
  102.             end
  103.             return "id"
  104.         end
  105.         for k,v in ipairs(keywords) do if accept(v) then return lasttok end end
  106.         if accept("[0-9]+%.[0-9]*") or accept("[0-9]+") then return "num" end
  107.         if accept("\"") or accept("%[%[") then
  108.             local s = ""
  109.             local long = lasttok == "[["
  110.             local _end = long and "%]%]" or "\""
  111.             while not accept(_end) do
  112.                 if accept("\\") then
  113.                         if accept("a") then s=s.."\a"
  114.                     elseif accept("b") then s=s.."\b"
  115.                     elseif accept("f") then s=s.."\f"
  116.                     elseif accept("n") then s=s.."\n"
  117.                     elseif accept("r") then s=s.."\r"
  118.                     elseif accept("t") then s=s.."\t"
  119.                     elseif accept("v") then s=s.."\v"
  120.                     elseif accept("\\") then s=s.."\\"
  121.                     elseif accept("\"") then s=s.."\""
  122.                     elseif accept("'") then s=s.."\'"
  123.                     elseif accept("%[") then s=s.."["
  124.                     elseif accept("%]") then s=s.."]"
  125.                     elseif accept("[0-9][0-9][0-9]") or accept("[0-9][0-9]") or accept("[0-9]") then s=s..string.char(tonumber(lasttok))
  126.                     end
  127.                 elseif accept(long and "[^%]\\]+" or "[^\n\"\\]+") then s=s..lasttok
  128.                 else error("unfinished string")
  129.                 end
  130.             end
  131.             lasttok = s
  132.             return "str"
  133.         end
  134.         if pos > #c then lasttok="" return "<eof>" end
  135.         error("Unknown token near "..c:sub(pos-50,pos+100))
  136.         return nil
  137.     end
  138.  
  139.     while pos <= #c do
  140.         local t = tokenise1()
  141.         if t == nil then --[[print(c:sub(pos,pos+100))]] break end
  142.         table.insert(tokens, {t, lasttok, getContext()})
  143.     end
  144.    
  145.     do
  146.         local f = fs.open("tokens.txt", "w")
  147.         for k,v in ipairs(tokens) do
  148.             if v[1] == v[2] then
  149.                 f.write(v[1].."\n")
  150.             else
  151.                 f.write(v[1].." : "..v[2].."\n")
  152.             end
  153.         end
  154.         f.close()
  155.     end
  156.    
  157.     return tokens
  158. end
  159.  
  160. local function tokenizeFile(fn)
  161.     local f = fs.open(fn,"r")
  162.     local c = f.readAll()
  163.     f.close()
  164.     return tokenize(c, fn)
  165. end
  166.  
  167. local function parse(tokens)
  168.     local ntok = 1
  169.     local tdata, context = nil, tokens[1][3]
  170.     local function accept(name)
  171.         if ntok > #tokens then return false end
  172.         if tokens[ntok][1] == name then
  173.             ntok = ntok + 1
  174.             tdata = tokens[ntok-1][2]
  175.             context = tokens[ntok-1][3]
  176.             --print("accepted "..name)
  177.             return true
  178.         end
  179.         return false
  180.     end
  181.    
  182.     local function peek(name)
  183.         return ntok <= #tokens and tokens[ntok][1] == name
  184.     end
  185.    
  186.     local function expect(name)
  187.         if not accept(name) then error("expected "..name.." near "..tokens[ntok][3],2) end
  188.         return tdata
  189.     end
  190.    
  191.     local function assert(a, b)
  192.         if a == nil then error(b.." near "..tokens[ntok][3],2) end
  193.         return a
  194.     end
  195.    
  196.     local block, stat, laststat, funcname, varlist, var, namelist, explist, exp, prefixexp, functioncall, args, function_, funcbody
  197.     local parlist, tableconstructor, fieldlist, field, fieldsep, binop, unop
  198.    
  199.     function block()
  200.         local r = {}
  201.         local s
  202.         repeat
  203.             s = stat()
  204.             table.insert(r, s)
  205.             accept(";")
  206.         until s == nil
  207.         table.insert(r, laststat())
  208.         accept(";")
  209.         return r
  210.     end
  211.    
  212.     function stat()
  213.         local nt = ntok
  214.         do
  215.             local vl = varlist()
  216.             if vl ~= nil then
  217.                 expect("=")
  218.                 local al = explist()
  219.                 if al == nil then return nil end
  220.                 return {"=", vl, al, context=context}
  221.             end
  222.         end
  223.        
  224.         ntok = nt
  225.         do
  226.             local fc = prefixexp()
  227.             if fc ~= nil and (fc[1] == "call" or fc[1] == ":call") then return fc end
  228.         end
  229.        
  230.         local ctx = context
  231.        
  232.         ntok = nt
  233.         if accept("do") then
  234.             local b = assert(block(), "expected block")
  235.             expect("end")
  236.             return {"block", b}
  237.         elseif accept("while") then
  238.             local e = exp()
  239.             if e == nil then error("expected expression") end
  240.             expect("do")
  241.             local b = assert(block(), "expected block")
  242.             expect("end")
  243.             return {"while", e, b, context=ctx}
  244.         elseif accept("repeat") then
  245.             local b = block()
  246.             expect("until")
  247.             local e = exp()
  248.             if e == nil then error("expected expression") end
  249.             return {"repeat", b, e, context=ctx}
  250.         elseif accept("if") then
  251.             local r = {"if", context=ctx}
  252.             table.insert(r, assert(exp(), "expected expression"))
  253.             expect("then")
  254.             table.insert(r, block())
  255.             while accept("elseif") do
  256.                 table.insert(r, assert(exp(), "expected expression"))
  257.                 expect("then")
  258.                 table.insert(r, block())
  259.             end
  260.             if accept("else") then
  261.                 table.insert(r, block())
  262.             end
  263.             expect("end")
  264.             return r
  265.         elseif accept("for") then
  266.             nt = ntok
  267.             local nl = namelist()
  268.             if nl == nil or not accept("in") then
  269.                 ntok = nt
  270.                 -- numeric for
  271.                 expect("id")
  272.                 local id = tdata
  273.                 expect("=")
  274.                 local start = assert(exp(), "expected expression")
  275.                 expect(",")
  276.                 local stop = assert(exp(), "expected expression")
  277.                 local step = {"con", 1}
  278.                 if accept(",") then
  279.                     step = assert(exp(), "expected expression")
  280.                 end
  281.                 expect("do")
  282.                 local b = block()
  283.                 expect("end")
  284.                 return {"nfor", id, start, stop, step, b, context=ctx}
  285.             else
  286.                 -- generic for
  287.                 local el = explist()
  288.                 expect("do")
  289.                 local b = block()
  290.                 expect("end")
  291.                 return {"gfor", nl, el, b, context=ctx}
  292.             end
  293.         elseif accept("function") then
  294.             local fn = assert(funcname(), "expected funcname")
  295.             local fb = funcbody()
  296.             return {"funcst", fn, fb, context=ctx}
  297.         elseif accept("local") then
  298.             if accept("function") then
  299.                 local id = expect("id")
  300.                 local fb = funcbody()
  301.                 return {"lfunc", id, fb, context=ctx}
  302.             else
  303.                 local nl, el = assert(namelist(), "expected namelist")
  304.                 if accept("=") then
  305.                     el = assert(explist(), "expected explist")
  306.                 end
  307.                 return {"local", nl, el, context=ctx}
  308.             end
  309.         else
  310.             return nil
  311.         end
  312.     end
  313.    
  314.     function laststat()
  315.         if accept("return") then
  316.             local nt = ntok
  317.             local el = explist()
  318.             if el == nil then ntok = nt end
  319.             return {"return", el, context=context}
  320.         elseif accept("break") then
  321.             return {"break", context=context}
  322.         else
  323.             return nil
  324.         end
  325.     end
  326.    
  327.     function funcname()
  328.         local n = {".", expect("id")}
  329.         while accept(".") do
  330.             table.insert(n, expect("id"))
  331.         end
  332.         if accept(":") then
  333.             n[1] = ":"
  334.             table.insert(n, expect("id"))
  335.         end
  336.         return n
  337.     end
  338.    
  339.     function varlist()
  340.         local l = {}
  341.         repeat
  342.             local v = var()
  343.             if v == nil then
  344.                 return nil
  345.             end
  346.             table.insert(l, v)
  347.         until not accept(",")
  348.         return l
  349.     end
  350.    
  351.     function var()
  352.         local nt = ntok
  353.         local pe = prefixexp()
  354.         if pe == nil or (pe[1] ~= "[]" and pe[1] ~= "." and pe[1] ~= "var") then
  355.             ntok = nt
  356.             return nil
  357.         end
  358.         return pe
  359.     end
  360.    
  361.     function namelist()
  362.         local l = {expect("id")}
  363.         while accept(",") do
  364.             table.insert(l, expect("id"))
  365.         end
  366.         return l
  367.     end
  368.    
  369.     function explist()
  370.         local l = {exp()}
  371.         if l[1] == nil then return {} end
  372.         while accept(",") do
  373.             table.insert(l, assert(exp(), "expected expression"))
  374.         end
  375.         return l
  376.     end
  377.    
  378.     local function exp0()
  379.         if accept("nil") then return {"con", nil, context=context} end
  380.         if accept("true") then return {"con", true, context=context} end
  381.         if accept("false") then return {"con", false, context=context} end
  382.         if accept("num") then return {"con", tonumber(tdata), context=context} end
  383.         if accept("str") then return {"con", tdata, context=context} end
  384.         if accept("...") then return {"...", context=context} end
  385.         if accept("function") then return {"func", funcbody(), context=context} end
  386.         if accept("-") then return {"negate", exp0(), context=context} end
  387.         if accept("not") then return {"not", exp0(), context=context} end
  388.         if accept("#") then return {"#", exp0(), context=context} end
  389.         if peek("{") then return {"tcon", tableconstructor(), context=context} end
  390.         do
  391.             local nt = ntok
  392.             local pe = prefixexp()
  393.             if pe ~= nil then
  394.                 return pe
  395.             end
  396.             ntok = nt
  397.         end
  398.         if accept("(") then
  399.             local e = assert(exp(), "expected expression")
  400.             expect(")")
  401.             return e
  402.         end
  403.         return nil
  404.     end
  405.    
  406.     local function exp1()
  407.         local e = exp0()
  408.         if e == nil then return nil end
  409.         -- right associative
  410.         -- {"^", a, {"^", b, {"^", c, d}}}
  411.         if accept("^") then
  412.             e = {"^", e, assert(exp0(), "expected expression"), context=context}
  413.             local last = e
  414.             while accept("^") do
  415.                 last[3] = {"^", last[3], assert(exp0(), "expected expression"), context=context}
  416.                 last = last[3]
  417.             end
  418.         end
  419.         return e
  420.     end
  421.    
  422.     local function exp1_5()
  423.         local e = exp1()
  424.         if e == nil then return nil end
  425.         while accept("%") do e={"%", e, assert(exp1(), "expected expression"), context=context} end
  426.         return e
  427.     end
  428.    
  429.     local function exp2()
  430.         local e = exp1_5()
  431.         if e == nil then return nil end
  432.         while accept("/") do e={"/", e, assert(exp1_5(), "expected expression"), context=context} end
  433.         return e
  434.     end
  435.    
  436.     local function exp3()
  437.         local e = exp2()
  438.         if e == nil then return nil end
  439.         while accept("*") do e={"*", e, assert(exp2(), "expected expression"), context=context} end
  440.         return e
  441.     end
  442.    
  443.     local function exp4()
  444.         local e = exp3()
  445.         if e == nil then return nil end
  446.         while accept("-") do e={"-", e, assert(exp3(), "expected expression"), context=context} end
  447.         return e
  448.     end
  449.    
  450.     local function exp5()
  451.         local e = exp4()
  452.         if e == nil then return nil end
  453.         while accept("+") do e={"+", e, assert(exp4(), "expected expression"), context=context} end
  454.         return e
  455.     end
  456.    
  457.     local function exp6()
  458.         local e = exp5()
  459.         if e == nil then return nil end
  460.         -- right associative
  461.         -- {"^", a, {"^", b, {"^", c, d}}}
  462.         if accept("..") then
  463.             e = {"..", e, assert(exp5(), "expected expression")}
  464.             local last = e
  465.             while accept("..") do
  466.                 last[3] = {"..", last[3], assert(exp5(), "expected expression"), context=context}
  467.                 last = last[3]
  468.             end
  469.         end
  470.         return e
  471.     end
  472.    
  473.     local function exp7()
  474.         local e = exp6()
  475.         if e == nil then return nil end
  476.         while accept(">") or accept(">=") or accept("<") or accept("<=") or accept("==") or accept("~=") do
  477.             e = {tdata, e, assert(exp6(), "expected expression"), context=context}
  478.         end
  479.         return e
  480.     end
  481.    
  482.     local function exp8()
  483.         local e = exp7()
  484.         if e == nil then return nil end
  485.         while accept("and") do e={"and", e, assert(exp7(), "expected expression"), context=context} end
  486.         return e
  487.     end
  488.    
  489.     local function exp9()
  490.         local e = exp8()
  491.         if e == nil then return nil end
  492.         while accept("or") do e={"or", e, assert(exp8(), "expected expression"), context=context} end
  493.         return e
  494.     end
  495.    
  496.     function exp()
  497.         return exp9()
  498.     end
  499.    
  500.     function prefixexp()
  501.         -- prefixexp = Name | prefixexp [ exp ] | prefixexp . Name | prefixexp : Name args | prefixexp args | ( exp )
  502.         local r
  503.         if accept("id") then
  504.             r = {"var", tdata, context=context}
  505.         elseif accept("(") then
  506.             local e = assert(exp(), "expression expected")
  507.             expect(")")
  508.             r = {"()", e, context=context}
  509.         else
  510.             return nil
  511.         end
  512.         while true do
  513.             if accept(".") then
  514.                 local e = expect("id")
  515.                 r = {".", r, e, context=context}
  516.             elseif accept("[") then
  517.                 local e = assert(exp(), "expression expected")
  518.                 expect("]")
  519.                 r = {"[]", r, e, context=context}
  520.             elseif peek("(") or peek("{") or peek("str") then
  521.                 local e = args()
  522.                 r = {"call", r, e, context=context}
  523.             elseif accept(":") then
  524.                 local i = expect("id")
  525.                 local e = args()
  526.                 r = {":call", r, i, e, context=context}
  527.             else
  528.                 break
  529.             end
  530.         end
  531.         return r
  532.     end
  533.  
  534.     function funcbody()
  535.         local p, b
  536.         expect("(")
  537.         if not accept(")") then
  538.             p = parlist()
  539.             expect(")")
  540.         else
  541.             p = {}
  542.         end
  543.         b = block()
  544.         expect("end")
  545.         return {p, b}
  546.     end
  547.    
  548.     function parlist()
  549.         if accept("...") then return {"..."} end
  550.         local l = {expect("id")}
  551.         while accept(",") do
  552.             if accept("...") then
  553.                 table.insert(l, "...")
  554.                 break
  555.             else
  556.                 table.insert(l, expect("id"))
  557.             end
  558.         end
  559.         return l
  560.     end
  561.    
  562.     function tableconstructor()
  563.         expect("{")
  564.         local fl = fieldlist()
  565.         expect("}")
  566.         return fl
  567.     end
  568.    
  569.     function fieldlist()
  570.         local fl = {}
  571.         while true do
  572.             local f = field()
  573.             if f == nil then break end
  574.             table.insert(fl, f)
  575.             if not accept(";") and not accept(",") then break end
  576.         end
  577.         return fl
  578.     end
  579.    
  580.     function field()
  581.         if accept("[") then
  582.             local e = assert(exp(), "expression expected")
  583.             expect("]")
  584.             expect("=")
  585.             return {e, assert(exp(), "expression expected")}
  586.         end
  587.         local nt = ntok
  588.         if accept("id") then
  589.             local e = {"con", tdata}
  590.             if accept("=") then
  591.                 return {e, assert(exp(), "expression expected")}
  592.             else
  593.                 ntok = nt
  594.             end
  595.         end
  596.         local e = exp()
  597.         if e == nil then return nil end
  598.         return {"auto", e}
  599.     end
  600.    
  601.     function args()
  602.         if peek("{") then return {{"tcons", tableconstructor(), context=context}} end
  603.         if accept("str") then return {{"con", tdata, context=context}} end
  604.         expect("(")
  605.         local el = explist()
  606.         expect(")")
  607.         return el
  608.     end
  609.    
  610.     return block()
  611. end
  612.  
  613. local function interpret(ast_list)
  614.     local DEFAULT_GLOBAL_ENV = {} -- initialized later
  615.    
  616.     local log
  617.     local DISABLE_LOG = true
  618.     local logfile = nil
  619.     if not DISABLE_LOG then
  620.         logfile = fs.open("log.txt", "w")
  621.         log = function(s)
  622.             logfile.write(s.."\n")
  623.         end
  624.     else
  625.         log = function() end
  626.     end
  627.    
  628.     local expr, callfunc, block, stmt, funcdef
  629.    
  630.     local function assert(test, message, level)
  631.         if not test then error(message or "assertion failed!", (level or 1)+1) end
  632.         return test
  633.     end
  634.    
  635.     -- Allow throwing of non-string errors
  636.     local oldError, oldPcall = error, pcall
  637.     local error, pcall
  638.     do
  639.         local err
  640.         function error(x, level)
  641.             err = x
  642.             if (level or 1) == 0 then
  643.                 oldError("exterr", 0)
  644.             else
  645.                 if type(x) == "table" then x.lualoc = scope.context end
  646.                 oldError("exterr", (level or 1) + 1)
  647.             end
  648.         end
  649.         function pcall(f, ...)
  650.             local rv = {oldPcall(f, ...)}
  651.             if rv[1] then
  652.                 -- no error
  653.                 return unpack(rv)
  654.             end
  655.             -- error
  656.             local err2 = rv[2]
  657.             if err2 and err2:len() >= 6 and err2:sub(-6) == "exterr" then
  658.                 -- thrown with the overridden error()
  659.                 local location = err2:sub(1, -7)
  660.                 if type(err) == "string" then
  661.                     return false, location..err
  662.                 elseif type(err) == "table" then
  663.                     if location ~= "" then err.location = location end
  664.                     return false, err
  665.                 else
  666.                     return false, err
  667.                 end
  668.             else
  669.                 -- normal error
  670.                 return false, err2
  671.             end
  672.         end
  673.     end
  674.    
  675.     local scope = {env=DEFAULT_GLOBAL_ENV}
  676.     local scopeStack = {scope}
  677.     local function pushScope(sc)
  678.         scope = sc or setmetatable({context="", vars = setmetatable({}, {__index=scope.vars})}, {__index=scope})
  679.         table.insert(scopeStack, scope)
  680.         --log("pushScope "..(#scopeStack-1).." -> "..#scopeStack)
  681.     end
  682.     local function popScope()
  683.         --log("popScope "..(#scopeStack).." -> "..(#scopeStack-1))
  684.         table.remove(scopeStack, #scopeStack)
  685.         scope = scopeStack[#scopeStack]
  686.     end
  687.     local function addLocal(name, val)
  688.         if val == nil then error({"interp", "expected two arguments"}, 2) end
  689.         if val.type == nil then error({"interp", "corrupt table"}, 2) end
  690.         scope.vars[name] = {val=val}
  691.     end
  692.     -- Returns the highest scope of the (n-1)'th function call
  693.     -- Eg if scopes 5 and 12 correspond to new functions, getStackLevel(2) returns scope 11 and getStackLevel(3) returns scope 4
  694.     -- getStackLevel(1) always returns the top scope
  695.     local function getStackLevel(n)
  696.         if n ~= math.floor(n) or n < 0 then
  697.             error{"lua", "expected non-negative integer"}
  698.         end
  699.         if n == 0 then n = 1 end
  700.         local pos = #scopeStack
  701.         for k=2,n do
  702.             while not pos.fn do
  703.                 pos = pos - 1
  704.                 if pos <= 0 then
  705.                     error{"lua", "invalid level"}
  706.                 end
  707.             end
  708.             pos = pos - 1
  709.             if pos <= 0 then
  710.                 error{"lua", "invalid level"}
  711.             end
  712.         end
  713.         return scopeStack[pos]
  714.     end
  715.     local function interp_rawget(t, name)
  716.         if name == nil or name.type == "nil" then return nil end
  717.         if t.type == nil then error("corrupt table",2) end
  718.         if t.type ~= "table" then error({"lua", "attempt to index " .. t.type .. " value"}) end
  719.         if t.val[name.type] ~= nil then
  720.             local tt = t.val[name.type]
  721.             if tt[name.val] then
  722.                 return tt[name.val]
  723.             else
  724.                 return {type="nil"}
  725.             end
  726.         else
  727.             return {type="nil"}
  728.         end
  729.     end
  730.     local function interp_rawset(t, name, value)
  731.         if name == nil or name.type == "nil" then error({"lua", "expected table index; got nil"}) end
  732.         if t.type ~= "table" then error({"lua", "attempt to index " .. t.type .. " value"}, 2) end
  733.         assert(type(t.val) == "table", "corrupted table", 2)
  734.         assert(type(name) == "table", "typeof name ~= table", 2)
  735.         if t.val[name.type] == nil then t.val[name.type] = {} end
  736.         assert(type(t.val[name.type]) == "table", "corrupted table", 2)
  737.         if value.type == "nil" then
  738.             t.val[name.type][name.val] = nil
  739.             if next(t.val[name.type]) == nil then
  740.                 t.val[name.type] = nil
  741.             end
  742.         else
  743.             t.val[name.type][name.val] = value
  744.         end
  745.     end
  746.     local function getInTable(t, name, prev)
  747.         prev = prev or {}
  748.         if prev[t] then error({"lua", "loop in gettable"}) end
  749.         prev[t] = true
  750.        
  751.         if type(name) == "string" or type(name)=="number" then name = {type=type(name), val=name} end
  752.        
  753.         assert(type(t) == "table", "typeof t ~= table")
  754.         assert(type(name) == "table", "typeof name ~= table")
  755.         assert(name.type, "corrupt table", 2)
  756.        
  757.         -- try the table first
  758.         local rgr = t.type == "table" and interp_rawget(t, name)
  759.         if rgr and rgr.type ~= "nil" then return rgr end
  760.        
  761.         -- then try __index
  762.         local index = t.metatable and interp_rawget(t.metatable, {type="string",val="__index"})
  763.         if index and index.type ~= "nil" then
  764.             if index.type == "function" then
  765.                 return expr({"call", {"quote", index}, {{"quote", t}, {"quote", name}}})[1]
  766.             else
  767.                 return getInTable(index, name, prev)
  768.             end
  769.         end
  770.        
  771.         -- then return nil
  772.         return {type="nil"}
  773.     end
  774.     local function setInTable(t, name, value, prev)
  775.         prev = prev or {}
  776.         if prev[t] then error({"lua", "loop in settable"}) end
  777.         prev[t] = true
  778.        
  779.         assert(type(t) == "table", "typeof t ~= table", 2)
  780.         assert(type(name) == "table", "typeof name ~= table", 2)
  781.        
  782.         if name == nil or name.type == "nil" then error({"lua", "expected table index; got nil"}) end
  783.        
  784.         -- first, if the key already exists in the table, set it and return
  785.         if t.type == "table" and interp_rawget(t, name).type ~= "nil" then
  786.             return interp_rawset(t, name, value)
  787.         end
  788.        
  789.         -- then try __newindex
  790.         local newindex = t.metatable and interp_rawget(t.metatable, {type="string",val="__newindex"})
  791.         if newindex and newindex.type ~= "nil" then
  792.             if newindex.type == "function" then
  793.                 return expr({"call", {"quote", newindex}, {{"quote", t}, {"quote", name}, {"quote", value}}})[1]
  794.             else
  795.                 return setInTable(newindex, name, value, prev)
  796.             end
  797.         end
  798.        
  799.         -- then create a new key if it's a table
  800.         if t.type == "table" then
  801.             return interp_rawset(t, name, value)
  802.         end
  803.        
  804.         -- then fail
  805.         error({"lua", "cannot index "..t.type})
  806.     end
  807.     local function getValue(name)
  808.         if type(name) == "string" then
  809.             local v = scope.vars[name]
  810.             if v ~= nil then
  811.                 return v.val
  812.             else
  813.                 return getInTable(scope.env, {type="string",val=name})
  814.             end
  815.         elseif type(name) == "table" then
  816.             if name[1] == "." then
  817.                 if #name == 2 then
  818.                     return setValue(name[2], value)
  819.                 end
  820.                 local t = getValue(name[2])
  821.                 for k=3,#name do
  822.                     t = getInTable(t, {type="string",val=name[2]})
  823.                 end
  824.                 return t
  825.             elseif name[1] == "var" then
  826.                 return getValue(name[2])
  827.             else
  828.                 error({"interp", "invalid name operation "..name[1]})
  829.             end
  830.         else
  831.             error({"interp", "invalid name type "..type(name)})
  832.         end
  833.     end
  834.     local function setValue(name, value)
  835.         if value == nil then value = {type="nil"} end
  836.         if value.type == nil then error({"interp", "corrupt table"}, 2) end
  837.         if type(name) == "string" then
  838.             local v = scope.vars[name]
  839.             if v ~= nil then
  840.                 v.val = value
  841.             else
  842.                 setInTable(scope.env, {type="string",val=name}, value)
  843.             end
  844.         elseif type(name) == "table" then
  845.             if name[1] == "." then
  846.                 if #name == 2 then
  847.                     return setValue(name[2], value)
  848.                 end
  849.                 local t = getValue(name[2])
  850.                 for k=3,#name-1 do
  851.                     t = getInTable(t, {type="string",val=name[k]})
  852.                 end
  853.                
  854.                 setInTable(t, {type="string",val=name[#name]}, value)
  855.             elseif name[1] == "[]" then
  856.                 local tbl = expr(name[2])[1]
  857.                 local key = expr(name[3])[1]
  858.                 setInTable(tbl, key, value)
  859.             elseif name[1] == "var" then
  860.                 setValue(name[2], value)
  861.             else
  862.                 error({"interp", "invalid name operation " .. name[1]})
  863.             end
  864.         else
  865.             error({"interp", "invalid name type " .. type(name)})
  866.         end
  867.     end
  868.     local function isTrue(val)
  869.         if val.type == "nil" or (val.type == "boolean" and val.val == false) then
  870.             return false
  871.         else
  872.             return true
  873.         end
  874.     end
  875.     local function getcomphandler(a, b, event)
  876.         if a.type ~= b.type then return nil end
  877.         if a.metatable == nil or b.metatable == nil then return nil end
  878.         local af = interp_rawget(a.metatable, {type="string",val=event})
  879.         local bf = interp_rawget(b.metatable, {type="string",val=event})
  880.         if af == nil or bf == nil or af.type ~= bf.type then return nil end
  881.         if af.val == bf.val then
  882.             return af
  883.         else
  884.             return nil
  885.         end
  886.     end
  887.     local function explist(l)
  888.         local r = {}
  889.         if l == nil then error({"interp","table expected, got nil"},2) end
  890.         for k,v in ipairs(l) do
  891.             local sh = #scopeStack
  892.             for k2,v2 in ipairs(expr(v)) do
  893.                 table.insert(r, v2)
  894.             end
  895.             if sh ~= #scopeStack then error({"interp", "scope stack imbalance in expression list, type: "..v[1]}) end
  896.         end
  897.         return r
  898.     end
  899.    
  900.     local function getmetamethod(obj, name)
  901.         if obj.metatable == nil then return nil end
  902.         return obj.metatable.val.string and obj.metatable.val.string[name]
  903.     end
  904.    
  905.     local function getbinhandler(a, b, name)
  906.         return getmetamethod(a, name) or getmetamethod(b, name)
  907.     end
  908.    
  909.     local function callmetamethod(obj, name, args, default)
  910.         local mm = getmetamethod(obj, name)
  911.         if mm == nil then return default end
  912.         return callfunc(mm, args)
  913.     end
  914.    
  915.     -- initialize DEFAULT_GLOBAL_ENV
  916.     do
  917.         local env = {}
  918.        
  919.         -- helper function
  920.         -- if o.type ~= t, throw an error, then return t.val
  921.         -- if o == nil and allowNil, return nil
  922.         local function checkType(o, t, allowNil)
  923.             if t == nil then error({"interp", "expected string, got nil"}) end
  924.             if o == nil or o.type == "nil" and allowNil then return nil end
  925.             if o == nil then error({"lua", "expected "..t..", got nil"}, 2) end
  926.             if o.type == nil then error({"interp", "corrupt table"},3) end
  927.             if o.type ~= t then error({"lua", "expected "..t..", got "..o.type}, 2) end
  928.             return o.val
  929.         end
  930.        
  931.         local function wrapObj(o)
  932.             if type(o) == "number" or type(o) == "string" or type(o) == "boolean" or type(o) == "nil" then
  933.                 return {type=type(o),val=o}
  934.             else
  935.                 error({"lua", "invalid type "..type(o).." - expected number, string, boolean or nil"})
  936.             end
  937.         end
  938.         local function unwrapObj(o)
  939.             if o.type == "number" or o.type == "string" or o.type == "boolean" or o.type == "nil" then
  940.                 return o.val
  941.             else
  942.                 error({"interp", "invalid type "..o.type.." - expected number, string, boolean or nil"})
  943.             end
  944.         end
  945.        
  946.        
  947.         -- wraps a native function into a virtualized function
  948.         -- can only handle types: number, string, boolean, nil
  949.         -- eg: wrapFunc(math.pow)({type="number",val=2},{type="number",val=5}) -> {type="number",val=32}
  950.         local function wrapFunc(fn)
  951.             return function(...)
  952.                 local args = {...}
  953.                 for k,v in ipairs(args) do
  954.                     args[k] = unwrapObj(v)
  955.                 end
  956.                 local ret = {fn(unpack(args))}
  957.                 for k,v in pairs(ret) do
  958.                     ret[k] = wrapObj(v)
  959.                 end
  960.                 if #ret == 0 then ret[1] = {type="nil"} end
  961.                 return unpack(ret)
  962.             end
  963.         end
  964.        
  965.         -- like wrapFunc, for functions that return either nil or a list of wrappable types
  966.         local function wrapListReturningFunc(fn)
  967.             return function(...)
  968.                 local args = {...}
  969.                 for k,v in pairs(args) do
  970.                     args[k] = unwrapObj(v)
  971.                 end
  972.                 local ok, ret = pcall(fn, unpack(args))
  973.                 if not ok then error({"lua", ret}) end
  974.                 if ret == nil then return {type="nil"} end
  975.                 local r = {type="table",val={number={}}}
  976.                 for k,v in ipairs(ret) do
  977.                     r.val.number[k] = wrapObj(v)
  978.                 end
  979.                 return r
  980.             end
  981.         end
  982.        
  983.         env.math = {
  984.             huge = {type="number",val=math.huge},
  985.             pi = {type="number",val=math.pi},
  986.         }
  987.        
  988.         for k,v in ipairs({"abs", "acos", "asin", "atan", "atan2", "ceil", "cos", "cosh", "deg", "exp", "floor", "fmod", "frexp", "ldexp", "log", "log10", "max", "min", "modf", "pow", "rad", "random", "randomseed", "sin", "sinh", "sqrt", "tanh", "tan"}) do
  989.             env.math[v] = wrapFunc(math[v])
  990.         end
  991.        
  992.         env.string = {
  993.             byte = wrapFunc(string.byte),
  994.             char = wrapFunc(string.char),
  995.             find = wrapFunc(string.find),
  996.             format = wrapFunc(string.format),
  997.             len = wrapFunc(string.len),
  998.             lower = wrapFunc(string.lower),
  999.             match = wrapFunc(string.match),
  1000.             rep = wrapFunc(string.rep),
  1001.             reverse = wrapFunc(string.reverse),
  1002.             sub = wrapFunc(string.sub),
  1003.             upper = wrapFunc(string.upper),
  1004.            
  1005.             gmatch = function(str, ptn)
  1006.                 str = checkType(str, "string")
  1007.                 ptn = checkType(ptn, "string")
  1008.                 local f, s, v = string.gmatch(str, ptn)
  1009.                 return {type="function", val=function()
  1010.                     v = f(s, v)
  1011.                     return wrapObj(v)
  1012.                 end}
  1013.             end,
  1014.            
  1015.             -- todo: gsub
  1016.         }
  1017.        
  1018.         local event_table_map = {}
  1019.         setmetatable(event_table_map, {__mode="k"})
  1020.        
  1021.         local function native_pullEventRaw(filter)
  1022.             filter = checkType(filter, "string", true)
  1023.             local valid, t
  1024.             repeat
  1025.                 valid = true
  1026.                 t = pullQueuedEvent()
  1027.                 for k,v in ipairs(t) do
  1028.                     if type(v) == "table" then
  1029.                         if event_table_map[v] then
  1030.                             t[k] = event_table_map[v]
  1031.                         else
  1032.                             -- ignore this event
  1033.                             valid = false
  1034.                         end
  1035.                     else
  1036.                         t[k] = wrapObj(v)
  1037.                     end
  1038.                 end
  1039.             until valid
  1040.             if #t == 0 then return {type="nil"} end
  1041.             return unpack(t)
  1042.         end
  1043.    
  1044.         env.os = {
  1045.             queueEvent = wrapFunc(os.queueEvent),
  1046.             pullEventRaw = native_pullEventRaw,
  1047.             getComputerLabel = wrapFunc(os.getComputerLabel),
  1048.             shutdown = wrapFunc(os.shutdown),
  1049.             setAlarm = function(time)
  1050.                 local t = os.setAlarm(checkType(time, "number"))
  1051.                 event_table_map[t] = {type="table", val={}}
  1052.                 return event_table_map[t]
  1053.             end,
  1054.             clock = wrapFunc(os.clock),
  1055.             reboot = wrapFunc(os.reboot),
  1056.             setComputerLabel = wrapFunc(os.setComputerLabel),
  1057.             time = wrapFunc(os.time),
  1058.             startTimer = function(delay)
  1059.                 local t = os.startTimer(checkType(delay, "number"))
  1060.                 event_table_map[t] = {type="table", val={}}
  1061.                 return event_table_map[t]
  1062.             end
  1063.         }
  1064.        
  1065.         env.fs = {
  1066.             list = wrapListReturningFunc(fs.list),
  1067.             isDir = wrapFunc(fs.isDir),
  1068.             exists = wrapFunc(fs.exists),
  1069.             isReadOnly = wrapFunc(fs.isReadOnly),
  1070.             getName = wrapFunc(fs.getName),
  1071.             getSize = wrapFunc(fs.getSize),
  1072.             getDrive = wrapFunc(fs.getDrive),
  1073.             makeDir = wrapFunc(fs.makeDir),
  1074.             move = wrapFunc(fs.move),
  1075.             copy = wrapFunc(fs.copy),
  1076.             delete = wrapFunc(fs.delete),
  1077.             combine = wrapFunc(fs.combine),
  1078.             open = function(path, mode)
  1079.                 path = checkType(path, "string")
  1080.                 mode = checkType(mode, "string")
  1081.                 local native = fs.open(path, mode)
  1082.                 if native == nil then return {type="nil"} end
  1083.                
  1084.                 local rt = {type="table",val={}}
  1085.                 for k,v in pairs(native) do
  1086.                     if type(k) == "string" and type(v) == "function" then
  1087.                         setInTable(rt, wrapObj(k), {type="function",val=wrapFunc(v)})
  1088.                     end
  1089.                 end
  1090.                 return rt
  1091.             end
  1092.         }
  1093.        
  1094.         --[[env.coroutine = {
  1095.             yield = function(...)
  1096.                 local oss = scopeStack
  1097.                 local rv = {coroutine.yield(...)}
  1098.                 scopeStack = oss
  1099.                 if #rv == 0 then return {type="nil"} end
  1100.                 return unpack(rv)
  1101.             end,
  1102.             create = function(fn)
  1103.                 local cr_scopeStack = {scope}
  1104.                 local cr = coroutine.create(function(...)
  1105.                     scopeStack = cr_scopeStack
  1106.                     local rv = {pcall(callfunc, fn, ...)}
  1107.                     if table.remove(rv, 1) then
  1108.                         -- no error
  1109.                         return unpack(rv)
  1110.                     end
  1111.                     -- error
  1112.                     local err = rv[1]
  1113.                     if type(err) ~= "table" or err[1] ~= "lua" then
  1114.                         if type(err) == "table" then
  1115.                             print("Internal error in coroutine: "..err.location..err[2])
  1116.                         else
  1117.                             print("Internal error in coroutine: "..tostring(err))
  1118.                         end
  1119.                         error(err, 0)
  1120.                     end
  1121.                     print("Lua coroutine error: "..err.location..err[2])
  1122.                     error(err, 0)
  1123.                 end)
  1124.                 return {type="thread", val={cr=cr, scopeStack=cr_scopeStack}}
  1125.             end,
  1126.             resume = function(c, ...)
  1127.                 local oss = scopeStack
  1128.                 local rv = {coroutine.resume(checkType(c, "thread").cr, ...)}
  1129.                 scopeStack = oss
  1130.                 rv[1] = wrapObj(rv[1])
  1131.                 return unpack(rv)
  1132.             end,
  1133.             status = function(c)
  1134.                 return wrapObj(coroutine.status(checkType(c, "thread").cr))
  1135.             end,
  1136.         }]]
  1137.        
  1138.         env.peripheral = {
  1139.             isPresent = wrapFunc(peripheral.isPresent),
  1140.             getType = wrapFunc(peripheral.getType),
  1141.             getMethods = wrapListReturningFunc(peripheral.getMethods),
  1142.             call = wrapFunc(peripheral.call)
  1143.         }
  1144.        
  1145.         env.term = {
  1146.             setCursorBlink = wrapFunc(term.setCursorBlink),
  1147.             getSize = wrapFunc(term.getSize),
  1148.             getCursorPos = wrapFunc(term.getCursorPos),
  1149.             setCursorPos = wrapFunc(term.setCursorPos),
  1150.             write = wrapFunc(term.write),
  1151.             clear = wrapFunc(term.clear),
  1152.             clearLine = wrapFunc(term.clearLine),
  1153.             scroll = wrapFunc(term.scroll)
  1154.         }
  1155.        
  1156.         env.table = {}
  1157.        
  1158.         function env.loadstring(str, prefix)
  1159.             str = checkType(str, "string")
  1160.             prefix = checkType(prefix, "string", true) or "[string]"
  1161.             local ok, tokens, ast = pcall(tokenize, str, prefix)
  1162.             if not ok then error({"lua", tokens}, 2) end
  1163.             ok, ast = pcall(parse, tokens)
  1164.             if not ok then error({"lua", ast}, 2) end
  1165.            
  1166.             return funcdef({{"..."},ast})
  1167.         end
  1168.        
  1169.         function env.error(message, level)
  1170.             message = checkType(message, "string")
  1171.             level = checkType(level, "number", true) or 1
  1172.             if level == 0 then
  1173.                 error({"lua", message}, 0)
  1174.             else
  1175.                 local sc = getStackLevel(level)
  1176.                 error({"lua", sc.context.prefix..":"..sc.context.line..": "..message}, 0)
  1177.             end
  1178.         end
  1179.        
  1180.         function env.rawequal(a, b)
  1181.             if a == nil or b == nil then return a == b end
  1182.             return a.type == b.type and a.val == b.val
  1183.         end
  1184.        
  1185.         function env.rawget(tbl, key)
  1186.             return interp_rawget(tbl or {type="nil"}, key or {type="nil"})
  1187.         end
  1188.        
  1189.         function env.rawset(tbl, key, value)
  1190.             interp_rawset(tbl or {type="nil"}, key or {type="nil"}, value or {type="nil"})
  1191.             return {type="nil"}
  1192.         end
  1193.        
  1194.         function env.select(...)
  1195.             local args = {...}
  1196.             local n = args[1]
  1197.             if n == nil then error{"lua", "expected at least one argument"} end
  1198.             if n.type == "string" and n.val == "#" then
  1199.                 return {type="number", val=(#args-1)}
  1200.             end
  1201.             n = checkType(n, "number")
  1202.             return args[n+1] or {type="nil"}
  1203.         end
  1204.        
  1205.         function env.setfenv(fn, tbl)
  1206.             if fn == nil then fn = {type="nil"} end
  1207.             checkType(tbl, "table")
  1208.             if fn.type == "number" then
  1209.                 local scope = getStackLevel(fn.val)
  1210.                 scope.fn.val.scope.env = tbl
  1211.             else
  1212.                 checkType(fn, "function")
  1213.                 fn.val.scope.env = tbl
  1214.             end
  1215.             return fn
  1216.         end
  1217.        
  1218.         function env.getfenv(fn)
  1219.             if fn == nil then fn = {type="nil"} end
  1220.             if fn.type == "number" then
  1221.                 local scope = getStackLevel(fn.val)
  1222.                 return scope.fn.scope.env
  1223.             elseif fn.type == "nil" then
  1224.                 return scope.env
  1225.             else
  1226.                 checkType(fn, "function")
  1227.                 return fn.val.scope.env
  1228.             end
  1229.         end
  1230.        
  1231.         function env.setmetatable(tbl, meta)
  1232.             tbl = tbl or {type="nil"}
  1233.             if tbl.type ~= "table" then
  1234.                 error{"lua", "cannot set metatable of "..tbl.type.." value"}
  1235.             end
  1236.             if meta and meta.type == "nil" then meta = nil end
  1237.             tbl.metatable = meta
  1238.             return {type="nil"}
  1239.         end
  1240.        
  1241.         function env.getmetatable(tbl)
  1242.             return tbl.metatable or {type="nil"}
  1243.         end
  1244.        
  1245.         function env.unpack(tbl, start)
  1246.             checkType(tbl, "table")
  1247.             start = checkType(start, "number", true)
  1248.             if #tbl.val.number < (start or 1) then return {type="nil"} end
  1249.             return unpack(tbl.val.number, start or 1)
  1250.         end
  1251.        
  1252.         function env.xpcall(...)
  1253.             error("todo xpcall")
  1254.         end
  1255.        
  1256.         function env.pcall(fn, ...)
  1257.             local rv = {pcall(callfunc, fn, {...})}
  1258.             local ok = rv[1]
  1259.             if ok then
  1260.                 rv[1] = wrapObj(rv[1])
  1261.                 return unpack(rv)
  1262.             else
  1263.                 if type(rv[2]) ~= "table" then
  1264.                     error(rv[2], 0)
  1265.                 elseif rv[2][1] == "lua" then
  1266.                     return {type="boolean", val=false}, {type="string", val=(rv[2].lualoc or "")..rv[2][2]}
  1267.                 else
  1268.                     error(rv[2], 0)
  1269.                 end
  1270.             end
  1271.         end
  1272.        
  1273.         env.redstone = {}
  1274.         for _,k in ipairs({"setBundledOutput","getBundledInput","testBundledInput","getInput","getBundledOutput","getOutput","setOutput"}) do
  1275.             env.redstone[k] = wrapFunc(redstone[k])
  1276.         end
  1277.  
  1278. --[[
  1279. rednet = TODO ??????
  1280. coroutine = TODO NATIVE
  1281.  status = status
  1282.  resume = resume
  1283.  create = create
  1284.  yield = yield
  1285.  wrap = wrap
  1286.  running = running
  1287. string
  1288.  gsub = TODO NATIVE
  1289. ]]
  1290.        
  1291.         function env.tonumber(a)
  1292.             if a == nil or a.type ~= "string" then return wrapObj(nil) end
  1293.             return wrapObj(tonumber(a.val))
  1294.         end
  1295.        
  1296.         function env.tostring(a)
  1297.             if a == nil or a.type == "nil" then return wrapObj("nil") end
  1298.             local rv = callmetamethod(a, "__tostring", {a}, wrapObj(tostring(a.val)))
  1299.             return rv
  1300.         end
  1301.        
  1302.         function env.read(ch)
  1303.             return wrapObj(read(unwrapObj(ch)))
  1304.         end
  1305.        
  1306.         function env.print(...)
  1307.             local s = ""
  1308.             for k,v in ipairs({...}) do
  1309.                 s = s..tostring(v.val)
  1310.             end
  1311.             log(s)
  1312.             return wrapObj(print(s))
  1313.         end
  1314.        
  1315.         function env.table.insert(tbl, pos, val)
  1316.             if tbl == nil then error({"lua", "expected table, got nil"}) end
  1317.             if tbl.type ~= "table" then error({"lua", "expected table, got "..tbl.type}) end
  1318.             if val ~= nil then
  1319.                 if pos.type ~= "number" then
  1320.                     error({"lua", "expected number, got "..pos.type})
  1321.                 end
  1322.                 pos = unwrapObj(pos)
  1323.             else
  1324.                 val, pos = pos, nil
  1325.             end
  1326.             tbl.val.number = tbl.val.number or {}
  1327.             table.insert(tbl.val.number, val)
  1328.             return {type="nil"}
  1329.         end
  1330.        
  1331.         function env.table.remove(tbl, pos)
  1332.             pos = checkType(pos, "number", true)
  1333.             checkType(tbl, "table")
  1334.             table.remove(tbl.val.number, pos)
  1335.             return {type="nil"}
  1336.         end
  1337.        
  1338.         function env.next(tbl, key)
  1339.             if tbl == nil then tbl = {type="nil"} end
  1340.             if key == nil then key = {type="nil"} end
  1341.             if tbl.type == nil then error({"interp", "corrupt table"}, 2) end
  1342.             if tbl.type ~= "table" then error({"lua", "table expected, got "..tbl.type}) end
  1343.             if key.type == "nil" then
  1344.                 for k,v in pairs(tbl.val) do
  1345.                     for k2,v2 in pairs(v) do
  1346.                         return {type=k,val=k2}, v2
  1347.                     end
  1348.                 end
  1349.                 return {type="nil"}
  1350.             end
  1351.             if tbl.val[key.type] == nil then error({"lua", "invalid key to next"}) end
  1352.            
  1353.             -- try next key of the same type
  1354.             local r = next(tbl.val[key.type], key.val)
  1355.             if r ~= nil then
  1356.                 return {type=key.type,val=r}, tbl.val[key.type][r]
  1357.             end
  1358.            
  1359.             -- try next type
  1360.             local nt = next(tbl.val, key.type)
  1361.             if nt == nil then return {type="nil"},{type="nil"} end
  1362.            
  1363.             -- get first key of next type, or nil if none left
  1364.             local r = next(tbl.val[nt])
  1365.             if r == nil then return {type="nil"},{type="nil"} end
  1366.             return {type=nt, val=r}
  1367.         end
  1368.        
  1369.         function env.type(o)
  1370.             return {type="string", val=(o and o.type or "nil")}
  1371.         end
  1372.        
  1373.         -- converts a native object into a virtualized object
  1374.         -- does not wrap functions
  1375.         -- eg: wrap({"test", hi=5}) -> {type="table", val={string={hi={type="number",val=5}}, number={1={type="string",val="test"}}}}
  1376.         local function wrap(o, n)
  1377.             if type(o) == "table" then
  1378.                 local t = {type="table", val={}}
  1379.                 for k,v in pairs(o) do
  1380.                     interp_rawset(t, wrap(k), wrap(v, n.."."..k))
  1381.                 end
  1382.                 return t
  1383.             else
  1384.                 return {type=type(o), val=o, name=n}
  1385.             end
  1386.         end
  1387.        
  1388.         local new = wrap(env, "_G")
  1389.         for k,v in pairs(new) do
  1390.             DEFAULT_GLOBAL_ENV[k] = v
  1391.         end
  1392.         interp_rawset(DEFAULT_GLOBAL_ENV, {type="string", val="_G"}, DEFAULT_GLOBAL_ENV)
  1393.     end
  1394.    
  1395.     local function logicalNot(e)
  1396.         return {type="boolean", val=not isTrue(e)}
  1397.     end
  1398.    
  1399.     -- example: makeArithFunction(function(a,b) return a+b end, "__add")
  1400.     local function makeArithFunction(direct, meta)
  1401.         return function(t)
  1402.             local a = expr(t[2])[1]
  1403.             local b = expr(t[3])[1]
  1404.             if (a.type == "string" or a.type == "number") and (b.type == "string" or b.type == "number") then
  1405.                 return {type="number", val=direct(a.val,b.val)}
  1406.             end
  1407.             local mm = getbinhandler(a, b, meta)
  1408.             return mm and callfunc(mm, {a, b}) or error({"lua", "attempt to "..meta.." "..a.type.." with "..b.type})
  1409.         end
  1410.     end
  1411.    
  1412.     expr = {
  1413.         tcon = function(t)
  1414.             local r = {number={}}
  1415.             local rv = {type="table", val=r}
  1416.             local auto = 1
  1417.             for k,v in ipairs(t[2]) do
  1418.                 if v[1] == "auto" then
  1419.                     for k2,v2 in ipairs(expr(v[2])) do
  1420.                         if v2 ~= nil and v2.type ~= "nil" then
  1421.                             r.number[auto] = v2
  1422.                             auto = auto + 1
  1423.                         end
  1424.                     end
  1425.                 else
  1426.                     -- name=value or [expr]=value
  1427.                     local k2 = expr(v[1])[1]
  1428.                     r[k2.type] = r[k2.type] or {}
  1429.                     r[k2.type][k2.val] = expr(v[2])[1]
  1430.                 end
  1431.             end
  1432.             return rv
  1433.         end,
  1434.         con = function(t)
  1435.             --print(tostring(t[2]))
  1436.             return {type=type(t[2]), val=t[2]}
  1437.         end,
  1438.         quote = function(t) -- never generated by the parser
  1439.             return t[2]
  1440.         end,
  1441.         ["[]"] = function(t)
  1442.             local t2 = expr(t[2])[1]
  1443.             local i = expr(t[3])[1]
  1444.             local rv = getInTable(t2, i)
  1445.             return rv
  1446.         end,
  1447.         ["."] = function(t)
  1448.             local t2 = expr(t[2])[1]
  1449.             local rv = getInTable(t2, {type="string",val=t[3]})
  1450.             return rv
  1451.         end,
  1452.         var = function(t)
  1453.             --print("var "..t[2])
  1454.             return getValue(t[2]) or {type="nil"}
  1455.         end,
  1456.         call = function(t)
  1457.             local fn = expr(t[2])[1]
  1458.             local args = explist(t[3])
  1459.             local rv = {callfunc(fn, args)}
  1460.             return unpack(rv)
  1461.         end,
  1462.         ["=="] = function(t)
  1463.             local a = expr(t[2])[1]
  1464.             local b = expr(t[3])[1]
  1465.             local rv = true
  1466.             if a == b then
  1467.                 rv=true
  1468.             elseif a.type ~= b.type then
  1469.                 rv=false
  1470.             elseif a.val == b.val then
  1471.                 rv=true
  1472.             else
  1473.                 local ch = getcomphandler(a, b, "__eq")
  1474.                 if ch == nil then
  1475.                     rv = false
  1476.                 else
  1477.                     return callfunc(ch, {a, b})
  1478.                 end
  1479.             end
  1480.             return {type="boolean",val=rv}
  1481.         end,
  1482.         ["<="] = function(t)
  1483.             local a = expr(t[2])[1]
  1484.             local b = expr(t[3])[1]
  1485.             if a.type == "number" and b.type == "number" then
  1486.                 return {type="boolean", val=(a.val <= b.val)}
  1487.             elseif a.type == "string" and b.type == "string" then
  1488.                 return {type="boolean", val=(a.val <= b.val)}
  1489.             else
  1490.                 local f = getcomphandler(a, b, "__le")
  1491.                 if f ~= nil then
  1492.                     return callfunc(f, {a, b})
  1493.                 else
  1494.                     f = getcomphandler(a, b, "__lt")
  1495.                     if f ~= nil then
  1496.                         return logicalNot(callfunc(f, {b, a}))
  1497.                     else
  1498.                         error({"lua", "attempt to compare "..a.type.." and "..b.type})
  1499.                     end
  1500.                 end
  1501.             end
  1502.         end,
  1503.         ["<"] = function(t)
  1504.             return logicalNot(expr({"<=", t[3], t[2]})[1])
  1505.         end,
  1506.         [">="] = function(t)
  1507.             return expr({"<=", t[3], t[2]})[1]
  1508.         end,
  1509.         [">"] = function(t)
  1510.             return expr({"<", t[3], t[2]})[1]
  1511.         end,
  1512.         ["~="] = function(t)
  1513.             return expr({"not", {"==", t[2], t[3]}})[1]
  1514.         end,
  1515.         ["not"] = function(t)
  1516.             local a = expr(t[2])[1]
  1517.             return {type="boolean", val=not isTrue(a)}
  1518.         end,
  1519.         ["and"] = function(t)
  1520.             local a = expr(t[2])[1]
  1521.             if not isTrue(a) then
  1522.                 return a
  1523.             else
  1524.                 local b = expr(t[3])[1]
  1525.                 return b
  1526.             end
  1527.         end,
  1528.         ["or"] = function(t)
  1529.             local a = expr(t[2])[1]
  1530.             if isTrue(a) then
  1531.                 return a
  1532.             else
  1533.                 local b = expr(t[3])[1]
  1534.                 return b
  1535.             end
  1536.         end,
  1537.         [".."] = function(t)
  1538.             local a = expr(t[2])[1]
  1539.             local b = expr(t[3])[1]
  1540.             if (a.type == "string" or a.type == "number") and (b.type == "string" or b.type == "number") then
  1541.                 return {type="string", val=tostring(a.val)..tostring(b.val)}
  1542.             end
  1543.             local mm = getbinhandler(a, b, "__concat")
  1544.             return mm and callfunc(mm, {a, b}) or error({"lua", "attempt to concatenate "..a.type.." with "..b.type})
  1545.         end,
  1546.         ["+"] = makeArithFunction(function(a,b) return a+b end, "__add"),
  1547.         ["-"] = makeArithFunction(function(a,b) return a-b end, "__sub"),
  1548.         ["*"] = makeArithFunction(function(a,b) return a*b end, "__mul"),
  1549.         ["^"] = makeArithFunction(function(a,b) return a^b end, "__pow"),
  1550.         ["/"] = makeArithFunction(function(a,b) return a/b end, "__div"),
  1551.         ["%"] = makeArithFunction(function(a,b) return a%b end, "__mod"),
  1552.         negate = function(t)
  1553.             local a = expr(t[2])[1]
  1554.             if a.type == "number" then
  1555.                 return {type="number",val=-a.val}
  1556.             end
  1557.             local mm = getmetamethod(a, "__unm")
  1558.             if mm == nil then
  1559.                 error({"lua", "attempt to negate "..a.type})
  1560.             else
  1561.                 return callfunc(mm, {a})
  1562.             end
  1563.         end,
  1564.         ["#"] = function(t)
  1565.             local e = expr(t[2])[1]
  1566.             if e.type == "string" then
  1567.                 return {type="number", val=#e.val}
  1568.             elseif e.type == "table" then
  1569.                 local default = (e.val.number and #e.val.number or 0)
  1570.                 return callmetamethod(e, "__len", {e}, {type="number",val=default})
  1571.             else
  1572.                 error({"lua", "attempt to get length of "..e.type})
  1573.             end
  1574.         end,
  1575.         ["()"] = function(t)
  1576.             return expr(t[2])[1]
  1577.         end,
  1578.         func = function(t)
  1579.             return funcdef(t[2])
  1580.         end,
  1581.         ["..."] = function()
  1582.             if #scope.dotdotdot == 0 then return {type="nil"} end
  1583.             return unpack(scope.dotdotdot)
  1584.         end
  1585.     }
  1586.     setmetatable(expr, {__call = function(t, a)
  1587.         scope.context = a.context or scope.context
  1588.         local et = a[1]
  1589.         assert(type(et) == "string", "expected string, got "..type(et), 2)
  1590.         --print(et)
  1591.         local f = t[et]
  1592.         if f == nil then error("unimplemented expression type: " .. et) end
  1593.         --log("begin "..et)
  1594.         local rv = {f(a)}
  1595.         --log("end "..et)
  1596.         yield()
  1597.         assert(#rv > 0, "Expression type " .. et .. " returned no values")
  1598.         for k,v in ipairs(rv) do
  1599.             assert(type(v) == "table", "Expression type " .. et .. " returned " .. type(v) .. " value")
  1600.         end
  1601.         return rv
  1602.     end})
  1603.     function funcdef(t)
  1604.         pushScope()
  1605.         local f = {}
  1606.         f.argnames = t[1]
  1607.         f.body = t[2]
  1608.         f.scope = scope
  1609.         local fval = {type="function",val=f}
  1610.         f.scope.func = fval
  1611.         popScope()
  1612.         return fval
  1613.     end
  1614.    
  1615.     -- holds the return value when throwing a "return" error
  1616.     local retval
  1617.    
  1618.     -- calls block(code), catching "break" errors and returning normally
  1619.     -- return value: true if loop was broken, otherwise false
  1620.     local function catchBreak(code)
  1621.         local sh = #scopeStack
  1622.         local ok, status = pcall(block, code)
  1623.         if ok then
  1624.             if #scopeStack ~= sh then error({"interp", "Scope stack imbalance after loop!"}) end
  1625.             return false
  1626.         end
  1627.         while #scopeStack > sh do popScope() end
  1628.         if status == "break" then return true end
  1629.         error(status, 0)
  1630.     end
  1631.    
  1632.     stmt = {
  1633.         ["local"] = function(t)
  1634.             local names = t[2]
  1635.             if names[1] == "BIOS_CODE" then print(textutils.serialize(t[3])) end
  1636.             local vals = explist(t[3] or {})
  1637.             for k=1,#names do
  1638.                 addLocal(names[k], vals[k] or {type="nil"})
  1639.             end
  1640.         end,
  1641.         lfunc = function(t)
  1642.             --log("LFUNC "..t[2])
  1643.             addLocal(t[2], funcdef(t[3]))
  1644.         end,
  1645.         funcst = function(t)
  1646.             setValue(t[2], funcdef(t[3]))
  1647.         end,
  1648.         call = function(t)
  1649.             expr(t)
  1650.         end,
  1651.         ["return"] = function(t)
  1652.             retval = explist(t[2])
  1653.             if #retval == 0 then retval = {{type="nil"}} end
  1654.             error("return", -1)
  1655.         end,
  1656.         ["="] = function(t)
  1657.             local names = t[2]
  1658.             local values = explist(t[3])
  1659.             scope.context = t.context or scope.context
  1660.             for k=1,#names do
  1661.                 --log("assign "..tostring(names[k]))
  1662.                 setValue(names[k], values[k] or {type="nil"})
  1663.             end
  1664.         end,
  1665.         ["if"] = function(t)
  1666.             -- "if" {cond block} [block]
  1667.             --log("tryExit is "..getValue("tryExit").type)
  1668.             for k = 2, #t-1, 2 do
  1669.                 --print(k)
  1670.                 local test = expr(t[k])[1]
  1671.                 --print(test.type, " ", tostring(test.val))
  1672.                 if isTrue(test) then
  1673.                     block(t[k+1])
  1674.                     return
  1675.                 end
  1676.             end
  1677.             if ((#t)%2) == 0 then
  1678.                 block(t[#t])
  1679.             end
  1680.             --print(getValue("tryExit").type)
  1681.            
  1682.         end,
  1683.        
  1684.         -- generic for
  1685.         gfor = function(t)
  1686.             local el = explist(t[3]) -- expression list
  1687.             local names = t[2] -- name list
  1688.             local f, s, var = el[1], el[2], el[3]
  1689.             f = f or {type="nil"}
  1690.             s = s or {type="nil"}
  1691.             var = var or {type="nil"}
  1692.             while true do
  1693.                 local vals = {callfunc(f, {s, var})}
  1694.                 var = vals[1]
  1695.                 if var == nil or var.type == "nil" then break end
  1696.                
  1697.                 -- reset scope and assign local variables
  1698.                 pushScope()
  1699.                 -- assign local variables
  1700.                 for k=1,#names do
  1701.                     addLocal(names[k], vals[k] or {type="nil"})
  1702.                 end
  1703.                
  1704.                 if catchBreak(t[4]) then popScope() break end
  1705.                
  1706.                 popScope()
  1707.             end
  1708.         end,
  1709.        
  1710.         nfor = function(t)
  1711.             local name = t[2]
  1712.             local start = expr(t[3])[1]
  1713.             local stop = expr(t[4])[1]
  1714.             local step = expr(t[5])[1]
  1715.             if start.type ~= "number" or stop.type ~= "number" or step.type ~= "number" then
  1716.                 error({"lua","expected number"})
  1717.             end
  1718.             for var=start.val,stop.val,step.val do
  1719.                 pushScope()
  1720.                 addLocal(name, {type="number",val=var})
  1721.                
  1722.                 if catchBreak(t[6]) then popScope() break end
  1723.                
  1724.                 popScope()
  1725.             end
  1726.         end,
  1727.        
  1728.         ["while"] = function(t)
  1729.             local cond = t[2]
  1730.             local code = t[3]
  1731.            
  1732.             while isTrue(expr(cond)[1]) do
  1733.                 pushScope()
  1734. --              print(getValue("tCommandHistory").type.." test")
  1735.                 if catchBreak(code) then popScope() break end
  1736.                 popScope()
  1737.             end
  1738.         end,
  1739.        
  1740.         ["repeat"] = function(t)
  1741.             local code = t[2]
  1742.             local cond = t[3]
  1743.            
  1744.             while true do
  1745.                 pushScope()
  1746.                 if catchBreak(code) then popScope() break end
  1747.                 if not isTrue(expr(cond)[1]) then popScope() break end
  1748.                 popScope()
  1749.             end
  1750.         end,
  1751.        
  1752.         block = function(t)
  1753.             block(t[2])
  1754.         end,
  1755.        
  1756.         ["break"] = function(t)
  1757.             error("break", 0)
  1758.         end,
  1759.     }
  1760.     -- allows us to call stmt(t) to run the statement in table t
  1761.     setmetatable(stmt, {__call = function(t, a)
  1762.         if type(a) ~= "table" then error({"interp", "expected table, got "..type(a)},2) end
  1763.         local st = a[1]
  1764.         scope.context = a.context or scope.context
  1765.         --log("stmt "..st)
  1766.         yield()
  1767.         if type(st) == "table" then
  1768.             log("Statement type is table, WTF???")
  1769.             for k,v in pairs(st) do log(k," ",v) end
  1770.         end
  1771.         if t[st] == nil then error("unimplemented statement type: " .. tostring(st)) end
  1772.        
  1773.         local sh = #scopeStack
  1774.         t[st](a)
  1775.         if sh ~= #scopeStack then error({"interp", "scope stack imbalance after stmt "..st}) end
  1776.     end})
  1777.     function block(t)
  1778.         pushScope()
  1779.         for k,v in ipairs(t) do
  1780.             stmt(v)
  1781.         end
  1782.         popScope()
  1783.     end
  1784.     function callfunc(fn, args)
  1785.         if fn.type~="function" then error({"lua","attempt to call "..fn.type}) end
  1786.         local name = fn.name
  1787.         fn = fn.val
  1788.         if type(fn)=="function" then
  1789.             -- "C" function (actually written in Lua; but a native function)
  1790.             local rv = {pcall(fn, unpack(args))}
  1791.             if not table.remove(rv, 1) then
  1792.                 if type(rv[1]) == "string" then
  1793.                     error({"lua", "Native function error in "..tostring(name)..": "..tostring(rv[1])}, 2)
  1794.                 else
  1795.                     error(rv[1], 0)
  1796.                 end
  1797.             end
  1798.             if #rv == 0 then
  1799.                 error({"interp","Native function "..tostring(name).." returned no values"})
  1800.             end
  1801.             for k,v in ipairs(rv) do
  1802.                 if type(v) ~= "table" then
  1803.                     error({"interp","Native function "..tostring(name).." returned "..type(v).." value"})
  1804.                 end
  1805.             end
  1806.             return unpack(rv)
  1807.         end
  1808.         pushScope(fn.scope)
  1809.         if fn.scope.env.string and fn.scope.env.string.shell then
  1810.             print(getInTable(fn.scope.env,"shell").type)
  1811.         end
  1812.         pushScope()
  1813.         scope.allArgs = {}
  1814.         for k,v in pairs(args) do
  1815.             scope.allArgs[k]=v
  1816.         end
  1817.         assert(type(fn.argnames)=="table", "corrupt function",2)
  1818.         for k,v in ipairs(fn.argnames) do
  1819.             if v == "..." then
  1820.                 scope.dotdotdot = {}
  1821.                 for n=k,#args do
  1822.                     scope.dotdotdot[n-k+1] = args[n]
  1823.                 end
  1824.             else
  1825.                 addLocal(v, args[k] or {type="nil"})
  1826.             end
  1827.         end
  1828.        
  1829.         -- run code, catching returns and breaks
  1830.         local nScopes = #scopeStack
  1831.         local ok, status = pcall(block, fn.body)
  1832.         if not ok then
  1833.             while #scopeStack > nScopes do
  1834.                 popScope()
  1835.             end
  1836.         end
  1837.         if #scopeStack ~= nScopes then
  1838.             error({"interp", "Scope stack imbalance after function call!"})
  1839.         end
  1840.         popScope()
  1841.         popScope()
  1842.         if not ok then
  1843.             if status == "return" then
  1844.                 return unpack(retval)
  1845.             elseif status == "break" then
  1846.                 error({"lua", "break outside of loop"})
  1847.             else
  1848.                 error(status, -1)
  1849.             end
  1850.         end
  1851.        
  1852.         return {type="nil"}
  1853.     end
  1854.     for _,ast in ipairs(ast_list) do
  1855.         local ok, err = pcall(block, ast)
  1856.         if not ok then
  1857.             if err == "break" then
  1858.                 err = {"lua", "break outside of loop"}
  1859.             end
  1860.             if err == "return" then
  1861.             elseif type(err) == "string" then
  1862.                 if logfile then logfile.close() end
  1863.                 print(context)
  1864.                 oldError(err, 0)
  1865.             elseif type(err) == "table" then
  1866.                 if err[1] == "lua" then
  1867.                     print("Lua error: "..err)
  1868.                 else
  1869.                     print(context)
  1870.                     print(err.location.."Internal error: " .. table.concat(err, ": "))
  1871.                 end
  1872.                 break
  1873.             elseif err == nil then -- terminated
  1874.                 print("Terminating LiL interpreter")
  1875.             else
  1876.                 print("Caught a "..type(err).." error???")
  1877.                 break
  1878.             end
  1879.         end
  1880.     end
  1881.     if logfile then logfile.close() end
  1882. end
  1883.  
  1884. local function serializeInt(i)
  1885.     local s = ""
  1886.     repeat
  1887.         s = s .. string.char((i % 128) + ((i >= 128) and 128 or 0))
  1888.         i = math.floor(i / 128)
  1889.     until i == 0
  1890.     return s
  1891. end
  1892. -- returns int, next position
  1893. local function deserializeInt(s,pos)
  1894.     local k = pos
  1895.     local i = 0
  1896.     local m = 1
  1897.     while true do
  1898.         local b = string.byte(s:sub(k,k))
  1899.         i = i + m * (b % 128)
  1900.         m = m * 128
  1901.         k = k + 1
  1902.         if b < 128 then break end
  1903.     end
  1904.     return i, k
  1905. end
  1906.  
  1907. local nextid_key = {}
  1908. local function serializeInternal(obj, seen)
  1909.     if obj ~= nil and seen[obj] then
  1910.         return "\06" .. serializeInt(seen[obj])
  1911.     end
  1912.     if type(obj) == "table" then
  1913.         local id = seen[nextid_key]
  1914.         seen[nextid_key] = id + 1
  1915.         seen[obj] = id
  1916.  
  1917.         local s = "\05"
  1918.         local ikeys = {}
  1919.         for k,v in ipairs(obj) do
  1920.             ikeys[k] = v
  1921.             s = s .. serializeInternal(v, seen)
  1922.         end
  1923.         s = s .. serializeInternal(nil, seen)
  1924.         for k,v in pairs(obj) do
  1925.             if ikeys[k] == nil then
  1926.                 s = s .. serializeInternal(k, seen) .. serializeInternal(v, seen)
  1927.             end
  1928.         end
  1929.         s = s .. serializeInternal(nil, seen)
  1930.         return s
  1931.     elseif type(obj) == "number" then
  1932.         local ns = tostring(obj)
  1933.         return "\04" .. serializeInt(ns:len()) .. ns
  1934.     elseif type(obj) == "string" then
  1935.         return "\03" .. serializeInt(obj:len()) .. obj
  1936.     elseif type(obj) == "boolean" then
  1937.         if obj then
  1938.             return "\01"
  1939.         else
  1940.             return "\x02"
  1941.         end
  1942.     elseif type(obj) == "nil" then
  1943.         return "\00"
  1944.     elseif type(obj) == "userdata" then
  1945.         error("cannot serialize userdata")
  1946.     elseif type(obj) == "thread" then
  1947.         error("cannot serialize threads")
  1948.     elseif type(obj) == "function" then
  1949.         error("cannot serialize functions")
  1950.     else
  1951.         error("unknown type: " .. type(obj))
  1952.     end
  1953. end
  1954. function serialize(obj)
  1955.     return serializeInternal(obj, {[nextid_key] = 0})
  1956. end
  1957. function deserialize(s)
  1958.     local pos = 1
  1959.     local seen = {}
  1960.     local nextid = 0
  1961.     local function internal()
  1962.         local tch = s:sub(pos,pos)
  1963.         local len
  1964.         pos = pos + 1
  1965.         if tch == "\00" then
  1966.             return nil
  1967.         elseif tch == "\01" then
  1968.             return true
  1969.         elseif tch == "\02" then
  1970.             return false
  1971.         elseif tch == "\03" then
  1972.             len, pos = deserializeInt(s, pos)
  1973.             local rv = s:sub(pos, pos+len-1)
  1974.             pos = pos + len
  1975.             return rv
  1976.         elseif tch == "\04" then
  1977.             len, pos = deserializeInt(s, pos)
  1978.             local rv = s:sub(pos, pos+len-1)
  1979.             pos = pos + len
  1980.             return tonumber(rv)
  1981.         elseif tch == "\05" then
  1982.             local id = nextid
  1983.             nextid = id + 1
  1984.             local t = {}
  1985.             seen[id] = t
  1986.  
  1987.             local k = 1
  1988.             while true do
  1989.                 local v = internal()
  1990.                 if v == nil then break end
  1991.                 t[k] = v
  1992.                 k = k + 1
  1993.             end
  1994.  
  1995.             while true do
  1996.                 local k = internal()
  1997.                 if k == nil then break end
  1998.                 local v = internal()
  1999.                 if v == nil then break end
  2000.                 t[k] = v
  2001.             end
  2002.             return t
  2003.         elseif tch == "\06" then
  2004.             local id
  2005.             id, pos = deserializeInt(s, pos)
  2006.             return seen[id]
  2007.         else
  2008.             return nil
  2009.         end
  2010.     end
  2011.     return internal()
  2012. end
  2013.  
  2014.  
  2015. local function parseFile(filename)
  2016.     local file = fs.open(filename, "r")
  2017.     local code = file.readAll()
  2018.     file.close()
  2019.     return parse(tokenize(code))
  2020. end
  2021.  
  2022. local function cachedAST(file, cacheFile)
  2023.     if fs.exists(cacheFile) then
  2024.         local f = fs.open(cacheFile, "r")
  2025.         local s = f.readAll()
  2026.         f.close()
  2027.         return deserialize(s)
  2028.     end
  2029.     local ast = parseFile(file)
  2030.     local f = fs.open(cacheFile, "w")
  2031.     f.write(serialize(ast))
  2032.     f.close()
  2033.     return ast
  2034. end
  2035.  
  2036. local function dumpAST(code, dumpFile)
  2037.     local ast = parse(tokenize(code))
  2038.     local f = fs.open(dumpFile, "w")
  2039.     f.write(serialize(ast))
  2040.     f.close()
  2041.     return ast
  2042. end
  2043.  
  2044. local BIOS_CODE = [[
  2045. ------ Standard CC Lua functions ------
  2046. function loadfile(fn)
  2047.     local f = fs.open(fn, "r")
  2048.     if f == nil then return nil, "Failed to open file" end
  2049.     local code = f.readAll()
  2050.     f.close()
  2051.    
  2052.     return loadstring(code, fn)
  2053. end
  2054.  
  2055. function __inext(tbl, key)
  2056.     key = key + 1
  2057.     if tbl[key] ~= nil then
  2058.         return key, tbl[key]
  2059.     else
  2060.         return nil, nil
  2061.     end
  2062. end
  2063.  
  2064. function ipairs(tbl)
  2065.     return __inext, tbl, 0
  2066. end
  2067.  
  2068. function pairs(tbl)
  2069.     return next, tbl, nil
  2070. end
  2071.  
  2072. function assert(expr, message)
  2073.     if not expr then
  2074.         error(message, 2)
  2075.     else
  2076.         return expr
  2077.     end
  2078. end
  2079.  
  2080. _VERSION = "LiL ]]..LIL_VERSION..[["
  2081.  
  2082. function table.foreachi(tbl, fn)
  2083.     for k,v in ipairs(tbl) do
  2084.         -- LuaJ truncates this to one result, so emulate that
  2085.         local rv = fn(k, v)
  2086.         if rv ~= nil then
  2087.             return rv
  2088.         end
  2089.     end
  2090. end
  2091.  
  2092. function table.foreach(tbl, fn)
  2093.     for k,v in pairs(tbl) do
  2094.         -- LuaJ truncates this to one result, so emulate that
  2095.         local rv = fn(k, v)
  2096.         if rv ~= nil then
  2097.             return rv
  2098.         end
  2099.     end
  2100. end
  2101.  
  2102. function table.concat(tbl, sep)
  2103.     local s = ""
  2104.     for k,v in ipairs(tbl) do
  2105.         if k > 1 then s = s .. sep end
  2106.         s = s .. v
  2107.     end
  2108.     return s
  2109. end
  2110.  
  2111. function table.maxn(tbl)
  2112.     local k = 1
  2113.     while tbl[k] ~= nil do
  2114.         k = k + 1
  2115.     end
  2116.     return k - 1
  2117. end
  2118.  
  2119. function table.getn(tbl)
  2120.     return tbl.n or table.maxn(tbl)
  2121. end
  2122.  
  2123. -- I'm sure all these table constructors are horrible for performance.
  2124. -- Especially inside LiL.
  2125. -- Oh well. (TODO: Make table.sort a native function)
  2126. local function mergesort(tbl, start, _end, comp)
  2127.     if start == _end then return {tbl[start]} end
  2128.     if start == _end - 1 then
  2129.         if not comp(tbl[start], tbl[_end]) then
  2130.             return {tbl[_end], tbl[start]}
  2131.         else
  2132.             return {tbl[start], tbl[_end]}
  2133.         end
  2134.     end
  2135.     local midp = math.floor((_end + start)/2)
  2136.     local left = mergesort(tbl, start, midp, comp)
  2137.     local right = mergesort(tbl, midp + 1, _end, comp)
  2138.    
  2139.     -- merge left and right
  2140.     local result = {}
  2141.     while #left > 0 and #right > 0 do
  2142.         if not comp(left[1], right[1]) then
  2143.             table.insert(result, table.remove(right, 1))
  2144.         else
  2145.             table.insert(result, table.remove(left, 1))
  2146.         end
  2147.     end
  2148.     for k,v in ipairs(left) do table.insert(result, v) end
  2149.     for k,v in ipairs(right) do table.insert(result, v) end
  2150.     return result
  2151. end
  2152.  
  2153. function table.sort(tbl, comp)
  2154.     comp = comp or function(a, b)
  2155.         if a == nil then return false end
  2156.         if b == nil then return true end
  2157.         return a < b
  2158.     end
  2159.     local result = mergesort(tbl, 1, #tbl, comp)
  2160.     for k,v in ipairs(result) do
  2161.         tbl[k] = result[k]
  2162.     end
  2163. end
  2164.  
  2165.  
  2166. ------ IO library ------
  2167. io = {}
  2168. function io.write(str)
  2169.     write(str)
  2170. end
  2171. function io.read(fmt)
  2172.     if fmt ~= nil and fmt ~= "*l" then error("Unsupported format") end
  2173.     return read()
  2174. end
  2175. function io.open(fn, mode)
  2176.     local f = fs.open(fn, mode)
  2177.     if f == nil then return nil end
  2178.    
  2179.     local rv = {
  2180.         close = function(self)
  2181.             if self.bClosed then return end
  2182.             f.close()
  2183.             self.bClosed = true
  2184.             f = nil
  2185.         end,
  2186.         bFileHandle = true,
  2187.         bClosed = false
  2188.     }
  2189.    
  2190.     if mode == "r" then
  2191.         rv.read = function(self, fmt)
  2192.             if fmt == nil or fmt == "*l" then return f.readLine() end
  2193.             if fmt == "*a" then return f.readAll() end
  2194.             error("Unsupported format")
  2195.             local rv = {}
  2196.             for _,f in ipairs({...}) do
  2197.             end
  2198.             return unpack(rv)
  2199.         end
  2200.         rv.lines = function(self)
  2201.             return function()
  2202.                 local line = self:read()
  2203.                 if line == nil then self:close() end
  2204.                 return line
  2205.             end
  2206.         end
  2207.     elseif mode == "rb" then
  2208.         rv.read = function(self)
  2209.             return f.read()
  2210.         end
  2211.     elseif mode == "w" or mode == "a" or mode == "wb" or mode == "ab" then
  2212.         rv.write = function(self, data)
  2213.             return f.write(data)
  2214.         end
  2215.     else
  2216.         f.close()
  2217.         error("Unsupported mode")
  2218.     end
  2219.    
  2220.     return rv
  2221. end
  2222. function io.type(f)
  2223.     if type(f) == "table" and f.bFileHandle == true then
  2224.         return f.bClosed and "closed file" or "file"
  2225.     end
  2226.     return nil
  2227. end
  2228.  
  2229.  
  2230. ------ Standard CC functions ------
  2231. function redstone.getSides()
  2232.     return {"top","bottom","front","back","left","right"}
  2233. end
  2234.  
  2235. function os.computerID()
  2236.     return ]]..os.computerID()..[[
  2237. end
  2238. os.getComputerID = os.computerID
  2239. os.computerLabel = os.getComputerLabel
  2240.  
  2241. function os.version()
  2242.     if turtle then
  2243.         return "LiL ]]..LIL_VERSION..[[/TurtleOS 1.3"
  2244.     end
  2245.     return "LiL ]]..LIL_VERSION..[[/CraftOS 1.3"
  2246. end
  2247.  
  2248. function os.pullEvent(filter)
  2249.     -- bios.lua limits this to 5 arguments, so we do too
  2250.     local evt, a, b, c, d, e = os.pullEventRaw(filter)
  2251.     if evt == "terminate" then
  2252.         print("Terminated")
  2253.         error()
  2254.     end
  2255.     return evt, a, b, c, d, e
  2256. end
  2257.  
  2258. function sleep(seconds)
  2259.     local timer = os.startTimer(seconds)
  2260.     repeat
  2261.         local sEvent, param = os.pullEvent( "timer" )
  2262.     until param == timer
  2263. end
  2264.  
  2265. -- From bios.lua
  2266. function write( sText )
  2267.     local w,h = term.getSize()     
  2268.     local x,y = term.getCursorPos()
  2269.    
  2270.     local nLinesPrinted = 0
  2271.     local function newLine()
  2272.         if y + 1 <= h then
  2273.             term.setCursorPos(1, y + 1)
  2274.         else
  2275.             term.scroll(1)
  2276.             term.setCursorPos(1, h)
  2277.         end
  2278.         x, y = term.getCursorPos()
  2279.         nLinesPrinted = nLinesPrinted + 1
  2280.     end
  2281.    
  2282.     -- Print the line with proper word wrapping
  2283.     while string.len(sText) > 0 do
  2284.         local whitespace = string.match( sText, "^[ \t]+" )
  2285.         if whitespace then
  2286.             -- Print whitespace
  2287.             term.write( whitespace )
  2288.             x,y = term.getCursorPos()
  2289.             sText = string.sub( sText, string.len(whitespace) + 1 )
  2290.         end
  2291.        
  2292.         local newline = string.match( sText, "^\n" )
  2293.         if newline then
  2294.             -- Print newlines
  2295.             newLine()
  2296.             sText = string.sub( sText, 2 )
  2297.         end
  2298.        
  2299.         local text = string.match( sText, "^[^ \t\n]+" )
  2300.         if text then
  2301.             sText = string.sub( sText, string.len(text) + 1 )
  2302.             if string.len(text) > w then
  2303.                 -- Print a multiline word              
  2304.                 while string.len( text ) > 0 do
  2305.                     if x > w then
  2306.                         newLine()
  2307.                     end
  2308.                     term.write( text )
  2309.                     text = string.sub( text, (w-x) + 2 )
  2310.                     x,y = term.getCursorPos()
  2311.                 end
  2312.             else
  2313.                 -- Print a word normally
  2314.                 if x + string.len(text) > w then
  2315.                     newLine()
  2316.                 end
  2317.                 term.write( text )
  2318.                 x,y = term.getCursorPos()
  2319.             end
  2320.         end
  2321.     end
  2322.    
  2323.     return nLinesPrinted
  2324. end
  2325.  
  2326. os._LUACEPTION_LEVEL = ]]..LUACEPTION_LEVEL..[[
  2327.  
  2328. function print(...)
  2329.     local s = ""
  2330.     for k,v in ipairs({...}) do
  2331.         s = s .. tostring(v)
  2332.     end
  2333.     return write(s .. "\n")
  2334. end
  2335.  
  2336. -- From bios.lua
  2337. function read( _sReplaceChar, _tHistory )  
  2338.     term.setCursorBlink( true )
  2339.  
  2340.     local sLine = ""
  2341.     local nHistoryPos = nil
  2342.     local nPos = 0
  2343.     if _sReplaceChar then
  2344.         _sReplaceChar = string.sub( _sReplaceChar, 1, 1 )
  2345.     end
  2346.    
  2347.     local w, h = term.getSize()
  2348.     local sx, sy = term.getCursorPos() 
  2349.     local function redraw()
  2350.         local nScroll = 0
  2351.         if sx + nPos >= w then
  2352.             nScroll = (sx + nPos) - w
  2353.         end
  2354.            
  2355.         term.setCursorPos( sx, sy )
  2356.         term.write( string.rep(" ", w - sx + 1) )
  2357.         term.setCursorPos( sx, sy )
  2358.         if _sReplaceChar then
  2359.             term.write( string.rep(_sReplaceChar, string.len(sLine) - nScroll) )
  2360.         else
  2361.             term.write( string.sub( sLine, nScroll + 1 ) )
  2362.         end
  2363.         term.setCursorPos( sx + nPos - nScroll, sy )
  2364.     end
  2365.    
  2366.     while true do
  2367.         local sEvent, param = os.pullEvent()
  2368.         if sEvent == "char" then
  2369.             sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
  2370.             nPos = nPos + 1
  2371.             redraw()
  2372.            
  2373.         elseif sEvent == "key" then
  2374.             if param == 28 then
  2375.                 -- Enter
  2376.                 break
  2377.                
  2378.             elseif param == 203 then
  2379.                 -- Left
  2380.                 if nPos > 0 then
  2381.                     nPos = nPos - 1
  2382.                     redraw()
  2383.                 end
  2384.                
  2385.             elseif param == 205 then
  2386.                 -- Right               
  2387.                 if nPos < string.len(sLine) then
  2388.                     nPos = nPos + 1
  2389.                     redraw()
  2390.                 end
  2391.            
  2392.             elseif param == 200 or param == 208 then
  2393.                 -- Up or down
  2394.                 if _tHistory then
  2395.                     if param == 200 then
  2396.                         -- Up
  2397.                         if nHistoryPos == nil then
  2398.                             if #_tHistory > 0 then
  2399.                                 nHistoryPos = #_tHistory
  2400.                             end
  2401.                         elseif nHistoryPos > 1 then
  2402.                             nHistoryPos = nHistoryPos - 1
  2403.                         end
  2404.                     else
  2405.                         -- Down
  2406.                         if nHistoryPos == #_tHistory then
  2407.                             nHistoryPos = nil
  2408.                         elseif nHistoryPos ~= nil then
  2409.                             nHistoryPos = nHistoryPos + 1
  2410.                         end                    
  2411.                     end
  2412.                    
  2413.                     if nHistoryPos then
  2414.                         sLine = _tHistory[nHistoryPos]
  2415.                         nPos = string.len( sLine )
  2416.                     else
  2417.                         sLine = ""
  2418.                         nPos = 0
  2419.                     end
  2420.                     redraw()
  2421.                 end
  2422.             elseif param == 14 then
  2423.                 -- Backspace
  2424.                 if nPos > 0 then
  2425.                     sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )
  2426.                     nPos = nPos - 1                
  2427.                     redraw()
  2428.                 end
  2429.             end
  2430.         end
  2431.     end
  2432.    
  2433.     term.setCursorBlink( false )
  2434.     term.setCursorPos( w + 1, sy )
  2435.     print()
  2436.    
  2437.     return sLine
  2438. end
  2439.  
  2440. dofile = function(path)
  2441.     local func, err = loadfile(path)
  2442.     if func ~= nil then
  2443.         setfenv(f, getfenv(2))
  2444.         func() -- and bios.lua doesn't return the result? we can't either for compatibility
  2445.     else
  2446.         error(err)
  2447.     end
  2448. end
  2449.  
  2450. -- Install the rest of the OS api
  2451. function os.run( _tEnv, _sPath, ... )
  2452.     local tArgs = { ... }
  2453.     local fnFile, err = loadfile( _sPath )
  2454.     if fnFile then
  2455.         local tEnv = _tEnv
  2456.         setmetatable( tEnv, { __index = _G } )
  2457.         setfenv( fnFile, tEnv )
  2458.         local ok, err = pcall( function()
  2459.             fnFile( unpack( tArgs ) )
  2460.         end )
  2461.         if not ok then
  2462.             if err and err ~= "" then
  2463.                 print( err )
  2464.             end
  2465.             return false
  2466.         end
  2467.         return true
  2468.     end
  2469.     if err and err ~= "" then
  2470.         print( err )
  2471.     end
  2472.     return false
  2473. end
  2474.  
  2475. local bProtected = true
  2476. local function protect( _t )
  2477.     local meta = getmetatable( _t )
  2478.     if meta == "Protected" then
  2479.         -- already protected
  2480.         return
  2481.     end
  2482.    
  2483.     setmetatable( _t, {
  2484.         __newindex = function( t, k, v )
  2485.             if bProtected then
  2486.                 error( "Attempt to write to global" )
  2487.             else
  2488.                 rawset( t, k, v )
  2489.             end
  2490.         end,
  2491.         __metatable = "Protected",
  2492.     } )
  2493. end
  2494.  
  2495. local tAPIsLoading = {}
  2496. function os.loadAPI( _sPath )
  2497.     local sName = fs.getName( _sPath )
  2498.     if tAPIsLoading[sName] == true then
  2499.         print( "API "..sName.." is already being loaded" )
  2500.         return false
  2501.     end
  2502.     tAPIsLoading[sName] = true
  2503.        
  2504.     local tEnv = {}
  2505.     setmetatable( tEnv, { __index = _G } )
  2506.     local fnAPI, err = loadfile( _sPath )
  2507.     if fnAPI then
  2508.         setfenv( fnAPI, tEnv )
  2509.         fnAPI()
  2510.     else
  2511.         print( err )
  2512.         return false
  2513.     end
  2514.    
  2515.     local tAPI = {}
  2516.     for k,v in pairs( tEnv ) do
  2517.         tAPI[k] =  v
  2518.     end
  2519.     protect( tAPI )
  2520.    
  2521.     bProtected = false
  2522.     _G[sName] = tAPI
  2523.     bProtected = true
  2524.    
  2525.     tAPIsLoading[sName] = nil
  2526.     return true
  2527. end
  2528.  
  2529. function os.unloadAPI( _sName )
  2530.     if _sName ~= "_G" and type(_G[_sName] == "table") then
  2531.         bProtected = false
  2532.         _G[sName] = nil
  2533.         bProtected = true
  2534.     end
  2535. end
  2536.  
  2537. os.sleep = sleep
  2538.  
  2539. -- Install the lua part of the HTTP api (if enabled)
  2540. if http then
  2541.     http.get = function( _url )
  2542.         local requestID = http.request( _url )
  2543.         while true do
  2544.             local event, param1, param2 = os.pullEvent()
  2545.             if event == "http_success" and param1 == _url then
  2546.                 return param2
  2547.             elseif event == "http_failure" and param1 == _url then
  2548.                 return nil
  2549.             end
  2550.         end
  2551.     end
  2552. end
  2553.  
  2554. -- Install the lua part of the peripheral api
  2555. peripheral.wrap = function( _sSide )
  2556.     if peripheral.isPresent( _sSide ) then
  2557.         local tMethods = peripheral.getMethods( _sSide )
  2558.         local tResult = {}
  2559.         for n,sMethod in ipairs( tMethods ) do
  2560.             tResult[sMethod] = function( ... )
  2561.                 return peripheral.call( _sSide, sMethod, ... )
  2562.             end
  2563.         end
  2564.         return tResult
  2565.     end
  2566.     return nil
  2567. end
  2568.  
  2569. -- Protect the global table against modifications
  2570. protect( _G )
  2571. for k,v in pairs( _G ) do
  2572.     if type(v) == "table" then
  2573.         protect( v )
  2574.     end
  2575. end
  2576.  
  2577. -- Load APIs
  2578. local tApis = fs.list( "rom/apis" )
  2579. for n,sFile in ipairs( tApis ) do
  2580.     if string.sub( sFile, 1, 1 ) ~= "." then
  2581.         local sPath = fs.combine( "rom/apis", sFile )
  2582.         if not fs.isDir( sPath ) and (sFile ~= "parallel" or coroutine) then
  2583.             print("Loading API "..sFile)
  2584.             os.loadAPI( sPath )
  2585.         end
  2586.     end
  2587. end
  2588.  
  2589. -- don't allow programs to shut down or reboot the computer
  2590. os.shutdown = function() end
  2591. os.reboot = function() end
  2592.  
  2593. if turtle then
  2594.     local tApis = fs.list( "rom/apis/turtle" )
  2595.     for n,sFile in ipairs( tApis ) do
  2596.         if string.sub( sFile, 1, 1 ) ~= "." then
  2597.             local sPath = fs.combine( "rom/apis/turtle", sFile )
  2598.             if not fs.isDir( sPath ) then
  2599.                 print("Loading API "..sFile)
  2600.                 os.loadAPI( sPath )
  2601.             end
  2602.         end
  2603.     end
  2604. end
  2605. ]]
  2606.  
  2607. local MAIN_CODE = [[
  2608. local ok, err = pcall(os.run, {}, "rom/programs/shell")
  2609. if not ok then print(err) end
  2610. ]]
  2611.  
  2612. print(">>> LUACEPTION LEVEL "..(LUACEPTION_LEVEL))
  2613.  
  2614. local astList = {
  2615.     dumpAST(BIOS_CODE, "bios.ast.txt"),
  2616.     --cachedAST("lil", "lil.ast.txt"),
  2617.     parse(tokenize(MAIN_CODE)),
  2618.     --cachedAST("/rom/programs/computer/adventure", "ast.txt")
  2619. }
  2620.  
  2621. local status, err = pcall(interpret, astList)
  2622. if not status and type(err) == "table" then
  2623.     print(err[1], ": ", err[2])
  2624. else
  2625.     print(err)
  2626. end
  2627.  
  2628. print("<<< LUACEPTION LEVEL "..(LUACEPTION_LEVEL - 1))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement