immibis

NextBASIC

Sep 11th, 2013
242
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 19.65 KB | None | 0 0
  1. local filename = (...) or error("Usage: "..shell.getRunningProgram().." FILENAME", 0)
  2.  
  3. local function isStringVar(var)
  4.     return var:sub(#var,#var) == "$"
  5. end
  6.  
  7. local functions = {
  8.     -- {#params, function}
  9.     int = {1, math.floor},
  10.     rnd = {0, math.random},
  11.     --abs = {1, math.abs},
  12.     --sqr = {1, math.sqrt},
  13.     --exp = {1, math.exp},
  14.     --log = {1, math.log},
  15.     --max = {2, math.max},
  16.     --min = {2, math.min},
  17.     --acos = {1, math.acos},
  18.     --asin = {1, math.asin},
  19.     --atan = {1, math.atan},
  20.     --cos = {1, math.cos},
  21.     --sin = {1, math.sin},
  22.     --tan = {1, math.tan},
  23.     val = {1, tonumber},
  24.     ["str$"] = {1, tostring},
  25.     --["chr$"] = {1, string.char},
  26.     --asc = {1, string.byte},
  27.     len = {1, string.len},
  28.     ["left$"] = {2, function(s, n) return s:sub(1, n) end},
  29.     ["right$"] = {2, function(s, n) return s:sub(s:len() - n + 1) end},
  30.     ["mid$"] = {3, function(s, start, num) return s:sub(start, start+num-1) end},
  31.     ["lower$"] = {1, string.lower},
  32.     ["upper$"] = {1, string.upper},
  33.     ["trim$"] = {1, function(s) return s:gsub("^ +", ""):gsub(" +$", "") end},
  34.     ["space$"] = {1, function(n) return string.rep(" ", n) end},
  35.     instr = {3, function(s, what, start) return string.find(s, what, start, true) or -1 end},
  36.    
  37. }
  38.    
  39. local function parse(fn)
  40.     local f = fs.open(fn, "r") or error("Failed to open "..fn, 0)
  41.     local code = f.readAll()
  42.     f.close()
  43.    
  44.     code = code .. "\n"
  45.    
  46.     local curLine = 1
  47.     local curChar = 1
  48.     local function updateCurrentPosition(matched)
  49.         for k=1,#matched do
  50.             if matched:sub(k,k) == "\n" then
  51.                 curLine = curLine+1
  52.                 curChar = 1
  53.             else
  54.                 curChar = curChar+1
  55.             end
  56.         end
  57.     end
  58.    
  59.     local function whereami()
  60.         return "line "..curLine..", position "..curChar
  61.     end
  62.    
  63.     local pos = 1
  64.     local function accept(pattern)
  65.         local startpos, endpos = code:find("^" .. pattern, pos)
  66.         if not startpos then return nil end
  67.        
  68.         local matched = code:sub(startpos, endpos)
  69.         pos = endpos + 1
  70.         updateCurrentPosition(matched)
  71.         return matched
  72.     end
  73.    
  74.     local function mark()
  75.         return {pos, curLine, curChar}
  76.     end
  77.     local function reset(x)
  78.         pos = x[1]
  79.         curLine = x[2]
  80.         curChar = x[3]
  81.     end
  82.  
  83.     local function skipWhitespace()
  84.         accept(" *")
  85.     end
  86.    
  87.     local function synerr(message)
  88.         error(message.." at "..whereami()..", just before: "..accept(string.rep(".?", 30)), 0)
  89.     end
  90.    
  91.     local compiled = {}
  92.     local function emit(inst)
  93.         compiled[#compiled+1] = inst
  94.         --print(textutils.serialize(inst))
  95.     end
  96.    
  97.     --[[ No, varnames with spaces don't work in this syntax at least
  98.     local function acceptVarName()
  99.         local s = accept(" *[a-zA-Z][a-zA-Z0-9 ]*%$?")
  100.         if not s then return nil end
  101.         s = s:gsub("^ +", ""):gsub(" +$", "") -- trim
  102.         s = s:gsub("  +", " ") -- merge consecutive spaces
  103.         s = s:gsub(" %$", "$") -- no space immediately before $
  104.         return s
  105.     end]]
  106.     local function acceptVarName()
  107.         local s = accept("[a-zA-Z][a-zA-Z0-9]*%$?")
  108.         if s then s = s:lower() end
  109.         return s
  110.     end
  111.    
  112.     local function acceptSide()
  113.         local s = accept("[lL][eE][fF][tT]") or accept("[rR][iI][gG][hH][tT]") or accept("[tT][oO][pP]") or accept("[bB][oO][tT][tT][oO][mM]") or accept("[fF][rR][oO][nN][tT]") or accept("[bB][aA][cC][kK]")
  114.         if s then s = s:lower() end
  115.         return s
  116.     end
  117.    
  118.     local function acceptColour()
  119.         if accept("[bB][lL][aA][cC][kK]") then return colours.black end
  120.         if accept("[rR][eE][dD]") then return colours.red end
  121.         if accept("[gG][rR][eE][eE][nN]") then return colours.green end
  122.         if accept("[bB][rR][oO][wW][nN]") then return colours.brown end
  123.         if accept("[bB][lL][uU][eE]") then return colours.blue end
  124.         if accept("[pP][uU][rR][pP][lL][eE]") then return colours.purple end
  125.         if accept("[cC][yY][aA][nN]") then return colours.cyan end
  126.         if accept("[lL][iI][gG][hH][tT] *[gG][rR][eEaA][yY]") then return colours.lightGrey end
  127.         if accept("[gG][rR][eEaA][yY]") then return colours.grey end
  128.         if accept("[pP][iI][nN][kK]") then return colours.pink end
  129.         if accept("[lL][iI][mM][eE]") then return colours.lime end
  130.         if accept("[yY][eE][lL][lL][oO][wW]") then return colours.yellow end
  131.         if accept("[lL][iI][gG][hH][tT] *[bB][lL][uU][eE]") then return colours.lightBlue end
  132.         if accept("[mM][aA][gG][eE][nN][tT][aA]") then return colours.magenta end
  133.         if accept("[oO][rR][aA][nN][gG][eE]") then return colours.orange end
  134.         if accept("[wW][hH][iI][tT][eE]") then return colours.white end
  135.     end
  136.    
  137.     local function getColourName(c)
  138.         for k,v in pairs(colour) do
  139.             if v == c then return k end
  140.         end
  141.         return "unknown"
  142.     end
  143.    
  144.     -- allowed operators in precedence order (= means same precedence):
  145.     -- ()
  146.     -- **
  147.     -- * and /
  148.     -- + and -
  149.    
  150.     -- returns true (ok) or false (no expression) or raises syntax error
  151.     local acceptExpr
  152.     local function acceptExpr4()
  153.         skipWhitespace()
  154.         if accept("\"") then
  155.             local content = accept("[^\"]*")
  156.             if not accept("\"") then synerr("No \" to end string") end
  157.             emit({"string", content})
  158.             return true
  159.         end
  160.         local var = acceptVarName()
  161.         if var then
  162.             if accept("%(") then
  163.                 if not functions[var] then
  164.                     synerr("No such function: "..var)
  165.                 end
  166.                 local p1 = acceptExpr()
  167.                 local params
  168.                 if not p1 then
  169.                     _= accept("%)") or synerr("Expected ) after "..var.."(")
  170.                     params = 0
  171.                 else
  172.                     params = 1
  173.                     while accept(",") do
  174.                         local p = acceptExpr()
  175.                         if not p then synerr("Expected expression after , (in "..var..")") end
  176.                         params = params + 1
  177.                     end
  178.                     _= accept("%)") or synerr("Expected ) after "..var.."( and expression list")
  179.                 end
  180.                 if params ~= functions[var][1] then
  181.                     synerr("Wrong number of parameters to "..var.." - need "..functions[var][1]..", but you wrote "..params)
  182.                 end
  183.                 emit({"call", var})
  184.                 return true
  185.             else
  186.                 emit({"getvar", var})
  187.                 return true
  188.             end
  189.         end
  190.         local num = accept("-?[0-9]+")
  191.         if num then
  192.             if accept("%.") then
  193.                 local decimal = accept("[0-9]+") or synerr("Expected decimal part after .")
  194.                 num = num .. "." .. decimal
  195.             end
  196.             emit({"num", tonumber(num)})
  197.             return true
  198.         end
  199.         return false
  200.     end
  201.     local function acceptExpr3()
  202.         skipWhitespace()
  203.         if not acceptExpr4() then return false end
  204.         skipWhitespace()
  205.         while accept("%*%*") do
  206.             if not acceptExpr4() then return synerr("Expected expression after **") end
  207.             emit({"pow"})
  208.             skipWhitespace()
  209.         end
  210.         return true
  211.     end
  212.     local function acceptExpr2()
  213.         skipWhitespace()
  214.         if not acceptExpr3() then return false end
  215.         while true do
  216.             skipWhitespace()
  217.             if accept("%*") then
  218.                 if not acceptExpr3() then synerr("Expected expression after * sign") end
  219.                 emit({"mul"})
  220.             elseif accept("/") then
  221.                 if not acceptExpr3() then synerr("Expected expression after / sign") end
  222.                 emit({"div"})
  223.             else
  224.                 return true
  225.             end
  226.         end
  227.     end
  228.     local function acceptExpr1()
  229.         skipWhitespace()
  230.         if not acceptExpr2() then return false end
  231.         while true do
  232.             skipWhitespace()
  233.             if accept("%+") then
  234.                 if not acceptExpr2() then synerr("Expected expression after + sign") end
  235.                 emit({"add"})
  236.             elseif accept("%-") then
  237.                 if not acceptExpr2() then synerr("Expected expression after - sign") end
  238.                 emit({"sub"})
  239.             else
  240.                 return true
  241.             end
  242.         end
  243.     end
  244.     acceptExpr = acceptExpr1
  245.    
  246.     local function acceptLabel()
  247.         return accept("%[[^%]\n]+%]")
  248.     end
  249.    
  250.     -- Condition precedence: ()/comparisons > NOT > AND > OR
  251.     local acceptCondition
  252.     local function acceptCondition3()
  253.         skipWhitespace()
  254.         if accept("%(") then
  255.             if not acceptCondition() or not accept("%)") then synerr("Error understanding condition") end
  256.             return true
  257.         end
  258.         if accept("[nN][oO][tT]") then
  259.             skipWhitespace()
  260.             if not acceptCondition3() then synerr("Expected valid condition after NOT") end
  261.             emit({"not"})
  262.             return true
  263.         end
  264.         if accept("[rR][eE][dD][sS][tT][oO][nN][eE] *[sS][iI][gG][nN][aA][lL]") then
  265.             skipWhitespace()
  266.             local side = acceptSide() or synerr("Expected side after REDSTONE SIGNAL")
  267.             skipWhitespace()
  268.             local col = acceptColour()
  269.             skipWhitespace()
  270.             if col then
  271.                 emit({"io-bundled-in", side, col})
  272.             else
  273.                 emit({"io-redstone-in", side})
  274.             end
  275.             return true
  276.         end
  277.         local e = acceptExpr()
  278.         if e then
  279.             skipWhitespace()
  280.             local operator = accept("=") or accept(">=") or accept("<=") or accept("<>") or accept("<") or accept(">") or synerr("Error understanding condition (invalid comparison operator?)")
  281.             if not acceptExpr() then synerr("Expected valid expression after "..operator.." (need something to compare with)") end
  282.             emit({operator})
  283.             return true
  284.         end
  285.         return false
  286.     end
  287.     local function acceptCondition2()
  288.         skipWhitespace()
  289.         if not acceptCondition3() then return false end
  290.         skipWhitespace()
  291.         while accept("[aA][nN][dD]") do
  292.             skipWhitespace()
  293.             if not acceptCondition3() then synerr("Expected condition after AND") end
  294.             emit({"and"})
  295.         end
  296.         return true
  297.     end
  298.     local function acceptCondition1()
  299.         skipWhitespace()
  300.         if not acceptCondition2() then return false end
  301.         skipWhitespace()
  302.         while accept("[oO][rR]") do
  303.             skipWhitespace()
  304.             if not acceptCondition2() then synerr("Expected condition after OR") end
  305.             emit({"or"})
  306.         end
  307.         return true
  308.     end
  309.     acceptCondition = acceptCondition1
  310.    
  311.     local function acceptStatement()
  312.         skipWhitespace()
  313.         if accept("[lL][eE][tT]") then
  314.             skipWhitespace()
  315.             local var = acceptVarName() or synerr("Expected variable name after LET")
  316.             skipWhitespace()
  317.             _= accept("=") or synerr("Expected = after LET "..var)
  318.             skipWhitespace()
  319.             _= acceptExpr() or synerr("Expected valid expression after LET "..var.." =")
  320.             emit({"setvar", var})
  321.         elseif accept("[pP][rR][iI][nN][tT]") then
  322.             skipWhitespace()
  323.             local overrideNewline = false
  324.             if accept("\n") then
  325.             else
  326.                 while acceptExpr() do
  327.                     overrideNewline = false
  328.                     if accept(";") then
  329.                         emit({"print"})
  330.                         overrideNewline = true
  331.                     elseif accept(",") then
  332.                         emit({"print-with-comma"})
  333.                         overrideNewline = true
  334.                     else
  335.                         emit({"print"})
  336.                         break
  337.                     end
  338.                 end
  339.             end
  340.             if not overrideNewline then
  341.                 emit({"print-newline"})
  342.             end
  343.             return true
  344.         elseif accept("[iI][nN][pP][uU][tT]") then
  345.             skipWhitespace()
  346.             local var = acceptVarName() or synerr("There must be a valid variable name after INPUT, and nothing else.")
  347.             emit({isStringVar(var) and "input-string" or "input-number", var})
  348.         elseif accept("[iI][fF]") then
  349.             _= acceptCondition() or synerr("There must be a valid condition after IF, followed by THEN.")
  350.             skipWhitespace()
  351.             _= accept("[tT][hH][eE][nN]") or synerr("There must be a valid condition after IF, followed by THEN.")
  352.             emit({"if"})
  353.             _= acceptStatement() or synerr("There must be a statement after THEN.")
  354.             emit({"endif"})
  355.             return true
  356.         elseif accept("[gG][oO][tT][oO]") then
  357.             skipWhitespace()
  358.             local m = mark()
  359.             local label = acceptLabel() or synerr("Expected label after GOTO")
  360.             emit({"goto", label, m})
  361.         elseif accept("[cC][lL][sS]") then
  362.             emit({"cls"})
  363.         elseif accept("[sS][eE][tT] *[rR][eE][dD][sS][tT][oO][nN][eE] *[sS][iI][gG][nN][aA][lL]") then
  364.             skipWhitespace()
  365.             local side = acceptSide() or synerr("There must be a valid side after SET REDSTONE SIGNAL")
  366.             skipWhitespace()
  367.             local colour = acceptColour()
  368.             skipWhitespace()
  369.             local onoff
  370.             if accept("[oO][nN]") then
  371.                 onoff = true
  372.             elseif accept("[oO][fF][fF]") then
  373.                 onoff = false
  374.             else
  375.                 synerr("After SET REDSTONE SIGNAL "..side:upper()..(colour and " "..getColourName(colour):upper() or "").." must be ON or OFF.")
  376.             end
  377.             if colour then
  378.                 emit({onoff and "io-bundled-on" or "io-bundled-off", side, colour})
  379.             else
  380.                 emit({"io-redstone", side, onoff})
  381.             end
  382.         elseif accept("[wW][aA][iI][tT]") then
  383.             skipWhitespace()
  384.             if accept("[fF][oO][rR]") then
  385.                 skipWhitespace()
  386.                 if accept("[rR][eE][dD][sS][tT][oO][nN][eE] *[sS][iI][gG][nN][aA][lL]") then
  387.                     skipWhitespace()
  388.                     if accept("[cC][hH][aA][nN][gG][eE]") then
  389.                         emit({"io-redstone-wait-any"})
  390.                     else
  391.                         local side = acceptSide() or synerr("There must be a valid side after WAIT FOR REDSTONE SIGNAL")
  392.                         skipWhitespace()
  393.                         local colour = acceptColour()
  394.                         skipWhitespace()
  395.                         local onoff
  396.                         if accept("[oO][nN]") then
  397.                             onoff = true
  398.                         elseif accept("[oO][fF][fF]") then
  399.                             onoff = false
  400.                         else
  401.                             synerr("After WAIT FOR REDSTONE SIGNAL "..side:upper()..(colour and " "..getColourName(colour):upper() or "").." must be ON or OFF.")
  402.                         end
  403.                         if colour then
  404.                             emit({"io-bundled-wait", side, colour, onoff})
  405.                         else
  406.                             emit({"io-redstone-wait", side, onoff})
  407.                         end
  408.                     end
  409.                 else
  410.                     synerr("I don't know how to wait for that.")
  411.                 end
  412.             else
  413.                 _= acceptExpr() or synerr("Expected expression or FOR after WAIT")
  414.                 skipWhitespace()
  415.                 if accept("[sS][eE][cC][oO][nN][dD][sS]?") then
  416.                     emit({"wait-seconds"})
  417.                 else
  418.                     synerr("Expected SECOND or SECONDS after WAIT expression")
  419.                 end
  420.             end
  421.         else
  422.             return false
  423.         end
  424.        
  425.         if accept("\n") then
  426.             return true
  427.         elseif accept(":") then
  428.             acceptStatement()
  429.             return true
  430.         else
  431.             synerr("I got confused")
  432.         end
  433.     end
  434.    
  435.     local seenLabels = {}
  436.    
  437.     while pos < #code do
  438.         local m = mark()
  439.         local label = acceptLabel()
  440.         if label then
  441.             emit({"label", label})
  442.             if seenLabels[label] then
  443.                 reset(m)
  444.                 synerr("You can't have two labels with the same name ("+label+")")
  445.             else
  446.                 seenLabels[label] = true
  447.             end
  448.             _= accept("\n") or synerr("There can't be anything after a label on the same line")
  449.         elseif accept("\n") then
  450.         elseif accept("[rR][eE][mM][^\n]*") then
  451.         elseif acceptStatement() then
  452.         else
  453.             synerr("I got confused")
  454.         end
  455.     end
  456.    
  457.     -- resolve labels
  458.     local labels = {}
  459.     for pos,line in ipairs(compiled) do
  460.         if line[1] == "label" then
  461.             labels[line[2]] = pos
  462.         end
  463.     end
  464.     for pos,line in ipairs(compiled) do
  465.         if line[1] == "goto" then
  466.             local lname = line[2]
  467.             line[2] = labels[lname]
  468.             if not line[2] then
  469.                 reset(line[3])
  470.                 synerr("No such label: "..lname)
  471.             end
  472.             line[3] = nil
  473.         end
  474.     end
  475.    
  476.     return compiled
  477. end
  478.  
  479. local parsed = parse(filename)
  480.  
  481.  
  482. local function runerr(msg)
  483.     error(msg, 0)
  484. end
  485.  
  486. local function interr(msg, level)
  487.     error("Internal error: "..msg, (level or 1) + 1)
  488. end
  489.  
  490. local stack = {}
  491. local function push(val)
  492.     stack[#stack+1] = val
  493. end
  494. local function pop()
  495.     local v = stack[#stack]
  496.     if v == nil then interr("empty operand stack", 2) end
  497.     stack[#stack] = nil
  498.     return v
  499. end
  500.  
  501.  
  502. local function checkvartype(varname, object)
  503.     if isStringVar(varname) then
  504.         if type(object) ~= "string" then
  505.             runerr("Can't assign "..type(object).." to string variable "..varname)
  506.         end
  507.     else
  508.         if type(object) ~= "number" then
  509.             runerr("Can't assign "..type(object).." to number varaible "..varname)
  510.         end
  511.     end
  512. end
  513.  
  514. local realvars = {}
  515. local vars = setmetatable({}, {
  516.     __index = function(t, n)
  517.         return realvars[n] or (isStringVar(n) and "" or 0)
  518.     end,
  519.     __newindex = function(t, n, v)
  520.         checkvartype(n, v)
  521.         realvars[n] = v
  522.     end
  523. })
  524.  
  525. local programCounter = 1
  526.  
  527. local function exec(line)
  528.     local cmd = line[1]
  529.     if cmd == "label" then
  530.         -- nothing to do
  531.     elseif cmd == "num" or cmd == "string" then
  532.         push(line[2])
  533.     elseif cmd == "setvar" then
  534.         vars[line[2]] = pop()
  535.     elseif cmd == "print" then
  536.         write(pop())
  537.     elseif cmd == "print-with-comma" then
  538.         write(pop())
  539.         write(" ")
  540.     elseif cmd == "print-newline" then
  541.         write("\n")
  542.     elseif cmd == "input-number" then
  543.         local value = tonumber(read())
  544.         while not value do
  545.             write("Not a number, try again: ")
  546.             value = tonumber(read())
  547.         end
  548.         vars[line[2]] = value
  549.     elseif cmd == "input-string" then
  550.         vars[line[2]] = read()
  551.     elseif cmd == "getvar" then
  552.         push(vars[line[2]])
  553.     elseif cmd == "add" then
  554.         local b = pop()
  555.         local a = pop()
  556.         if type(a) == "number" and type(b) == "number" then
  557.             push(a+b)
  558.         else
  559.             push(tostring(a)..tostring(b))
  560.         end
  561.     elseif cmd == "sub" then
  562.         local b = pop()
  563.         local a = pop()
  564.         if type(a) ~= "number" or type(b) ~= "number" then runerr("Not a number") end
  565.         push(a - b)
  566.     elseif cmd == "mul" then
  567.         local b = pop()
  568.         local a = pop()
  569.         if type(a) ~= "number" or type(b) ~= "number" then runerr("Not a number") end
  570.         push(a * b)
  571.     elseif cmd == "div" then
  572.         local b = pop()
  573.         local a = pop()
  574.         if type(a) ~= "number" or type(b) ~= "number" then runerr("Not a number") end
  575.         push(a / b)
  576.     elseif cmd == "pow" then
  577.         local b = pop()
  578.         local a = pop()
  579.         if type(a) ~= "number" or type(b) ~= "number" then runerr("Not a number") end
  580.         push(a ^ b)
  581.     elseif cmd == "and" then
  582.         local a, b = pop(), pop()
  583.         if type(a) ~= "boolean" then interr("condition resulted in "..type(a)..": "..tostring(a)) end
  584.         if type(b) ~= "boolean" then interr("condition resulted in "..type(b)..": "..tostring(b)) end
  585.         push(a and b)
  586.     elseif cmd == "or" then
  587.         local a, b = pop(), pop()
  588.         if type(a) ~= "boolean" then interr("condition resulted in "..type(a)..": "..tostring(a)) end
  589.         if type(b) ~= "boolean" then interr("condition resulted in "..type(b)..": "..tostring(b)) end
  590.         push(a or b)
  591.     elseif cmd == "not" then
  592.         local a = pop()
  593.         if type(a) ~= "boolean" then interr("condition resulted in "..type(a)..": "..tostring(a)) end
  594.         push(not a)
  595.     elseif cmd == "call" then
  596.         local params = {}
  597.         local npar = functions[line[2]][1]
  598.         local func = functions[line[2]][2]
  599.         for k = 1, npar do
  600.             params[npar+1-k] = pop()
  601.         end
  602.         push(func(unpack(params)))
  603.     elseif cmd == "<" then
  604.         local b = pop()
  605.         push(pop() < b)
  606.     elseif cmd == ">" then
  607.         local b = pop()
  608.         push(pop() > b)
  609.     elseif cmd == "<=" then
  610.         local b = pop()
  611.         push(pop() <= b)
  612.     elseif cmd == ">=" then
  613.         local b = pop()
  614.         push(pop() >= b)
  615.     elseif cmd == "=" then
  616.         local b = pop()
  617.         push(pop() == b)
  618.     elseif cmd == "<>" then
  619.         local b = pop()
  620.         push(pop() ~= b)
  621.     elseif cmd == "if" then
  622.         local s = pop()
  623.         if type(s) ~= "boolean" then interr("condition resulted in "..type(s)..": "..tostring(s)) end
  624.         if not s then
  625.             -- skip to matching endif
  626.             local level = 1
  627.             programCounter = programCounter + 1
  628.             while programCounter <= #parsed and level > 0 do
  629.                 if parsed[programCounter][1] == "if" then
  630.                     level = level + 1
  631.                 elseif parsed[programCounter][1] == "endif" then
  632.                     level = level - 1
  633.                 end
  634.                 programCounter = programCounter + 1
  635.             end
  636.             programCounter = programCounter - 1
  637.             if level ~= 0 then interr("no matching endif") end
  638.         end
  639.     elseif cmd == "goto" then
  640.         programCounter = line[2] - 1
  641.     elseif cmd == "cls" then
  642.         term.clear()
  643.         term.setCursorPos(1, 1)
  644.     elseif cmd == "endif" then
  645.         -- do nothing
  646.     elseif cmd == "io-bundled-on" then
  647.         rs.setBundledOutput(line[2], colours.combine(rs.getBundledOutput(line[2]), line[3]))
  648.     elseif cmd == "io-bundled-off" then
  649.         rs.setBundledOutput(line[2], colours.subtract(rs.getBundledOutput(line[2]), line[3]))
  650.     elseif cmd == "io-redstone" then
  651.         rs.setOutput(line[2], line[3])
  652.     elseif cmd == "wait-seconds" then
  653.         local n = pop()
  654.         if type(n) ~= "number" then runerr("Expected number in WAIT command") end
  655.         sleep(n)
  656.     elseif cmd == "io-bundled-in" then
  657.         push(colours.test(rs.getBundledInput(line[2]), line[3]))
  658.     elseif cmd == "io-redstone-in" then
  659.         push(rs.getInput(line[2]) and true or false)
  660.     elseif cmd == "io-redstone-wait" then
  661.         while rs.getInput(line[2]) ~= line[3] do
  662.             os.pullEvent("redstone")
  663.         end
  664.     elseif cmd == "io-redstone-wait-any" then
  665.         os.pullEvent("redstone")
  666.     elseif cmd == "io-bundled-wait" then
  667.         while colours.test(rs.getBundledInput(line[2]), line[3]) ~= line[4] do
  668.             os.pullEvent("redstone")
  669.         end
  670.     else
  671.         interr("unsupported: "..cmd)
  672.     end
  673. end
  674.  
  675. --f = fs.open("temp", "w")
  676. --for _,v in ipairs(parsed) do f.writeLine(textutils.serialize(v)) end
  677. --f.close()
  678.  
  679. while programCounter <= #parsed do
  680.     exec(parsed[programCounter])
  681.     programCounter = programCounter + 1
  682. end
Advertisement
Add Comment
Please, Sign In to add comment