melzneni

quarry_lib

Mar 19th, 2020 (edited)
310
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 42.55 KB | None | 0 0
  1. local args = { ... }
  2.  
  3. local test = false
  4. if args[2] ~= nil then
  5.     if args[2] == "test" then
  6.         print("test")
  7.         test = true
  8.     elseif args[2] == "noTest" then
  9.     else
  10.         error("unknwon first argument: '" .. args[2] .. "'")
  11.     end
  12. end
  13.  
  14. local TYPE_FUNCTION = 1
  15. local TYPE_VALUE = 2
  16. local TYPE_VAR = 3
  17. local TYPE_USER_FUNCTION = 4
  18. local TYPE_DEFAULT_FUNCTION = 5
  19. local TYPE_ARR = 6
  20. local TYPE_ADD = 7
  21. local TYPE_SUB = 8
  22. local TYPE_CONSTANT = 9
  23. local TYPE_DECLARATION = 10
  24. local TYPE_CMP = 11
  25. local TYPE_CONTROL_FLOW = 12
  26. local TYPE_OR = 13
  27. local TYPE_COMP = 14
  28.  
  29. local TYPE_COMP_EQUAL = 1
  30.  
  31. local TYPE_CF_WHILE = 1
  32. local TYPE_CF_IF = 2
  33. local TYPE_CF_FOR = 3
  34.  
  35. local storage
  36.  
  37. local defaultFunctions
  38. local fctSetStorageData
  39. local initToContinue
  40. if test then
  41.     local data = require("defaultFunctions")
  42.     data[1](true)
  43.     fctSetStorageData = data[2]
  44.     defaultFunctions = data[3]
  45.     initToContinue = data[4]
  46. else
  47.     os.loadAPI("lib_defaultFunctions")
  48.     lib_defaultFunctions.setTest(false, { shell = shell, turtle = turtle })
  49.     defaultFunctions = lib_defaultFunctions.getDefaultFunctions()
  50.     fctSetStorageData = lib_defaultFunctions.setStorageData
  51.     initToContinue = lib_defaultFunctions.initToContinue
  52. end
  53.  
  54. function readAll(file)
  55.     local f = assert(io.open(file, "rb"))
  56.     local content = f:read("*all")
  57.     f:close()
  58.     return content
  59. end
  60.  
  61. function splitText(source, letters)
  62.     local parts = {}
  63.     local akt = "";
  64.     local qM1 = 0;
  65.     local qM2 = 0;
  66.     local b1 = 0;
  67.     local b2 = 0;
  68.     local b3 = 0;
  69.     for i = 1, #source do
  70.         local z = string.sub(source, i, i)
  71.         if z == "'" and qM2 == 0 then
  72.             qM1 = 1 - qM1;
  73.         elseif z == "\"" and qM1 == 0 then
  74.             qM2 = 1 - qM2;
  75.         elseif qM1 == 0 and qM2 == 0 then
  76.             if z == "(" then
  77.                 b1 = b1 + 1
  78.             elseif z == ")" then
  79.                 b1 = b1 - 1
  80.             elseif z == "[" then
  81.                 b2 = b2 + 1
  82.             elseif z == "]" then
  83.                 b2 = b2 - 1
  84.             elseif z == "{" then
  85.                 b3 = b3 + 1
  86.             elseif z == "}" then
  87.                 b3 = b3 - 1
  88.             end
  89.         end
  90.         local split = false
  91.         if b1 == 0 and b2 == 0 and b3 == 0 and qM1 == 0 and qM2 == 0 then
  92.             for j = 1, #letters do
  93.                 if z == string.sub(letters, j, j) then
  94.                     split = true
  95.                     break
  96.                 end
  97.             end
  98.         end
  99.         if split then
  100.             if akt ~= "" then
  101.                 table.insert(parts, akt)
  102.                 akt = ""
  103.             end
  104.         else
  105.             akt = akt .. z
  106.         end
  107.     end
  108.     if akt ~= "" then
  109.         table.insert(parts, akt)
  110.     end
  111.     return parts
  112. end
  113.  
  114. function splitTextPattern(source, letters)
  115.     local parts = {}
  116.     local akt = "";
  117.     local qM1 = 0;
  118.     local qM2 = 0;
  119.     local b1 = 0;
  120.     local b2 = 0;
  121.     local b3 = 0;
  122.     local i = 1
  123.     while (i <= #source) do
  124.         local z = string.sub(source, i, i)
  125.         if z == "'" and qM2 == 0 then
  126.             qM1 = 1 - qM1;
  127.         elseif z == "\"" and qM1 == 0 then
  128.             qM2 = 1 - qM2;
  129.         elseif qM1 == 0 and qM2 == 0 then
  130.             if z == "(" then
  131.                 b1 = b1 + 1
  132.             elseif z == ")" then
  133.                 b1 = b1 - 1
  134.             elseif z == "[" then
  135.                 b2 = b2 + 1
  136.             elseif z == "]" then
  137.                 b2 = b2 - 1
  138.             elseif z == "{" then
  139.                 b3 = b3 + 1
  140.             elseif z == "}" then
  141.                 b3 = b3 - 1
  142.             end
  143.         end
  144.         local split = false
  145.         if b1 == 0 and b2 == 0 and b3 == 0 and qM1 == 0 and qM2 == 0 then
  146.             split = true
  147.             for j = 1, #letters do
  148.                 if string.sub(source, i + j - 1, i + j - 1) ~= string.sub(letters, j, j) then
  149.                     split = false
  150.                     break
  151.                 end
  152.             end
  153.         end
  154.         if split then
  155.             if akt ~= "" then
  156.                 table.insert(parts, akt)
  157.                 akt = ""
  158.                 i = i + #letters - 1
  159.             end
  160.         else
  161.             akt = akt .. z
  162.         end
  163.         i = i + 1
  164.     end
  165.     if akt ~= "" then
  166.         table.insert(parts, akt)
  167.     end
  168.     return parts
  169. end
  170.  
  171. function removeLetters(source, letters)
  172.     local target = ""
  173.     for i = 1, #source do
  174.         local valid = true
  175.         for j = 1, #letters do
  176.             if string.sub(source, i, i) == string.sub(letters, j, j) then
  177.                 valid = false
  178.             end
  179.         end
  180.         if valid then
  181.             target = target .. string.sub(source, i, i)
  182.         end
  183.     end
  184.     return target
  185. end
  186.  
  187. function readFileText(file)
  188.     if test then
  189.         return readAll(file)
  190.     else
  191.         local f = fs.open(file, "r")
  192.         local text = f.readAll()
  193.         f.close()
  194.         return text
  195.     end
  196. end
  197.  
  198. function analyseCommands(source)
  199.     local cmdsSource = splitText(source, ";")
  200.     local cmds = {}
  201.     for i, v in ipairs(cmdsSource) do
  202.         if v ~= "" then
  203.             if string.sub(v, 1, 2) ~= "//" then
  204.                 table.insert(cmds, loadCommand(v))
  205.             end
  206.         end
  207.     end
  208.     return cmds
  209. end
  210.  
  211. function nextCloseIndex(source, chOpen, chClose)
  212.     local a = 0;
  213.     local qM1 = 0;
  214.     local qM2 = 0
  215.     for i = 1, #source do
  216.         local z = string.sub(source, i, i)
  217.         if z == "\"" and qM2 == 0 then
  218.             qM1 = 1 - qM1
  219.         elseif z == "'" and qM1 == 0 then
  220.             qM2 = 1 - qM2
  221.         elseif z == chOpen and qM1 == 0 and qM2 == 0 then
  222.             a = a + 1
  223.         elseif z == chClose and qM1 == 0 and qM2 == 0 then
  224.             a = a - 1
  225.             if a == 0 then
  226.                 return i
  227.             end
  228.         end
  229.     end
  230.     return -1
  231. end
  232.  
  233. function loadCommand(source)
  234.     if string.find(source, "%(") ~= nil and string.find(source, "){") ~= nil then
  235.         local ind = string.find(source, "%(")
  236.         local name = string.sub(source, 1, ind - 1)
  237.         if name == "while" then
  238.             local ind1 = string.find(source, "){")
  239.             local body = analyseCommands(string.sub(source, ind1 + 2, #source - 1))
  240.             local cmdCondition = loadCommand(string.sub(source, ind + 1, ind1 - 1))
  241.             return { type = TYPE_CONTROL_FLOW, cond = cmdCondition, body = body, id = newCFId(), typeCF = TYPE_CF_WHILE }
  242.         elseif name == "for" then
  243.             local ind1 = string.find(source, "){")
  244.             local body = analyseCommands(string.sub(source, ind1 + 2, #source - 1))
  245.             local headPts = splitText(string.sub(source, ind + 1, ind1 - 1), ";")
  246.             if #headPts ~= 3 then
  247.                 error("invalid for-head: " .. string.sub(source, ind + 1, ind1 - 1))
  248.             end
  249.             local firstCommand = loadCommand(headPts[1])
  250.             local secondCondition = loadCommand(headPts[2])
  251.             local thirdCommand = loadCommand(headPts[3])
  252.             return { type = TYPE_CONTROL_FLOW, first = firstCommand, second = secondCondition, third = thirdCommand, body = body, id = newCFId(), typeCF = TYPE_CF_FOR }
  253.         elseif name == "if" then
  254.             local pts = splitText(source, "else")
  255.             local data = { type = TYPE_CONTROL_FLOW, typeCF = TYPE_CF_IF, id = newCFId(), ifCmdBlocks = {} }
  256.  
  257.             for i = 1, #pts do
  258.                 local pt = pts[i]
  259.                 local ind = string.find(pt, "%(")
  260.                 local ind1 = string.find(pt, "{")
  261.                 local body = analyseCommands(string.sub(pt, ind1 + 1, #pt - 1))
  262.                 if ind1 == 1 then
  263.                     if i ~= #pts then
  264.                         error("'else' statement needs to be at end of 'if'-block (source: " .. source .. ")")
  265.                     end
  266.                     table.insert(data.ifCmdBlocks, { body = body })
  267.                 else
  268.                     local name = string.sub(pt, 1, ind - 1)
  269.                     if name ~= "if" then
  270.                         error("invalid keyword: [else]" .. name)
  271.                     end
  272.                     local cond = loadCommand(string.sub(pt, ind + 1, ind1 - 2))
  273.                     table.insert(data.ifCmdBlocks, { body = body, cond = cond })
  274.                 end
  275.             end
  276.             return data
  277.         else
  278.             error("unknown keyword '" .. name .. "'")
  279.         end
  280.     end
  281.  
  282.     local ptsSources = splitTextPattern(source, "||")
  283.     if #ptsSources > 1 then
  284.         local values = {};
  285.         for i = 1, #ptsSources do
  286.             print(ptsSources[i])
  287.             values[i] = loadCommand(ptsSources[i])
  288.         end
  289.         return { type = TYPE_OR, values = values }
  290.     end
  291.     for i, ch in ipairs({ ">=", "<=", "<", ">", "==", "!=" }) do
  292.         local ptsSources = splitTextPattern(source, ch)
  293.         if #ptsSources > 1 then
  294.             if #ptsSources > 2 then
  295.                 error("only 2 arguments allowed for '" .. ch .. "'")
  296.             end
  297.             local pts = {}
  298.             for i, v in ipairs(ptsSources) do
  299.                 table.insert(pts, loadCommand(v))
  300.             end
  301.             return { type = TYPE_CMP, ch = ch, pts = pts }
  302.         end
  303.     end
  304.  
  305.     local ptsSources = splitText(source, "=")
  306.     if #ptsSources > 1 then
  307.         local name = ptsSources[1]
  308.         if #ptsSources > 2 then
  309.             error("there is only one '=' allowed in a declaration")
  310.         end
  311.         if string.match(name, "%$[A-Za-z_][A-Za-z0-9_]*%$") == name or
  312.                 string.match(name, "[A-Za-z_][A-Za-z0-9_]*") == name then
  313.             return { type = TYPE_DECLARATION, name = name, value = loadCommand(ptsSources[2]) }
  314.         else
  315.             error("invalid declaration variable: " .. name)
  316.         end
  317.     end
  318.  
  319.     local ptsSources = splitText(source, "+")
  320.     if #ptsSources > 1 then
  321.         local pts = {}
  322.         for i, v in ipairs(ptsSources) do
  323.             table.insert(pts, loadCommand(v))
  324.         end
  325.         return { type = TYPE_ADD, pts = pts }
  326.     end
  327.     local ptsSources = splitText(source, "-")
  328.     if #ptsSources > 1 then
  329.         local pts = {}
  330.         for i, v in ipairs(ptsSources) do
  331.             table.insert(pts, loadCommand(v))
  332.         end
  333.         return { type = TYPE_SUB, pts = pts }
  334.     end
  335.  
  336.     local i = string.find(source, "%(")
  337.     if i ~= nil and nextCloseIndex(source, "(", ")") == #source then
  338.         local funcName = string.sub(source, 1, i - 1)
  339.         if string.match(funcName, "[a-zA-Z_][a-zA-Z_0-9]*") ~= funcName then
  340.             error("invalid funcName: " .. funcName)
  341.         end
  342.         local pars = {}
  343.         local parSources = splitText(string.sub(source, i + 1, -2), ",")
  344.         for i, par in ipairs(parSources) do
  345.             table.insert(pars, loadCommand(par))
  346.         end
  347.         return { type = TYPE_FUNCTION, name = funcName, pars = pars }
  348.     else
  349.         if tonumber(source) ~= nil then
  350.             return { type = TYPE_VALUE, value = tonumber(source) }
  351.         elseif string.match(source, "%$[A-Za-z_][A-Za-z0-9_]*%$") == source then
  352.             local key = string.sub(source, 2, #source - 1)
  353.             return { type = TYPE_CONSTANT, key = key }
  354.         elseif source == "true" or source == "false" then
  355.             return { type = TYPE_VALUE, value = source == "true" }
  356.         elseif string.match(source, "[A-Za-z_][A-Za-z0-9_]*") == source then
  357.             return { type = TYPE_VAR, name = source }
  358.         elseif string.sub(source, 1, 1) == "[" and string.sub(source, #source) == "]" then
  359.             local parts = splitText(string.sub(source, 2, #source - 1), ",")
  360.             local vars = {}
  361.             for i, v in ipairs(parts) do
  362.                 table.insert(vars, loadCommand(v))
  363.             end
  364.             return { type = TYPE_ARR, vars = vars }
  365.         elseif string.sub(source, 1, 1) == "\"" and string.sub(source, #source) == "\"" then
  366.             return { type = TYPE_VALUE, value = string.sub(source, 2, #source - 1) }
  367.         else
  368.             error("unknown value: " .. source)
  369.         end
  370.     end
  371.     return nil
  372. end
  373.  
  374. local currentCFId = 0
  375. function newCFId()
  376.     local id = currentCFId
  377.     currentCFId = currentCFId + 1
  378.     return id
  379. end
  380.  
  381. function analyseStack(source)
  382.     local values = {}
  383.     for i, v in ipairs(splitText(source, ",")) do
  384.         if v ~= "" then
  385.             table.insert(values, tonumber(v))
  386.         end
  387.     end
  388.     return values
  389. end
  390.  
  391. function combineArr(table1, table2)
  392.     local table = {}
  393.     for i = 1, #table1 do
  394.         table[i] = table1[i]
  395.     end
  396.     for i = 1, #table2 do
  397.         table[i + #table1] = table2[i]
  398.     end
  399.     return table
  400. end
  401.  
  402. function getTableFromSaveText(source)
  403.     local tableSources = splitText(source, ";")
  404.     local tables = {}
  405.     for i = 1, #tableSources do
  406.         table.insert(tables, {})
  407.     end
  408.     for i, v in ipairs(tableSources) do
  409.         local tbl = tables[i]
  410.         getTableFromSaveTextInd(tbl, v, tables)
  411.     end
  412.  
  413.     return tables[1]
  414. end
  415.  
  416. function getTableFromSaveTextInd(tbl, tblSource, tables)
  417.     if string.sub(tblSource, 1, 1) ~= "{" or string.sub(tblSource, #tblSource) ~= "}" then
  418.         error("invalid source (braces arround table): " .. tblSource)
  419.     end
  420.     local pts = splitText(string.sub(tblSource, 2, #tblSource - 1), ",")
  421.     for i, pt in ipairs(pts) do
  422.         local i = string.find(pt, "=")
  423.         local vKey = getValueFromSaveText(string.sub(pt, 1, i - 1), tables)
  424.         local vValue = getValueFromSaveText(string.sub(pt, i + 1), tables)
  425.         tbl[vKey] = vValue
  426.     end
  427. end
  428.  
  429. function getValueFromSaveText(source, tables)
  430.     if string.sub(source, 1, 1) == "\"" and string.sub(source, #source) == "\"" then
  431.         return string.sub(source, 2, #source - 1)
  432.     elseif tonumber(source) ~= nil then
  433.         return tonumber(source)
  434.     elseif string.sub(source, 1, 4) == "tbl:" then
  435.         return tables[tonumber(string.sub(source, 5))]
  436.     elseif source == "false" then
  437.         return false
  438.     elseif source == "true" then
  439.         return true
  440.     else
  441.         error("invalid source (getValueAnalysis): " .. source)
  442.     end
  443. end
  444.  
  445. function getTableSaveText(sourceTable)
  446.     local alreadyUsed = {}
  447.     local sources = {}
  448.     getTableSaveTextInd(sourceTable, alreadyUsed, sources)
  449.     local txt = ""
  450.     for i, v in pairs(sources) do
  451.         txt = txt .. v .. ";"
  452.     end
  453.     return txt
  454. end
  455.  
  456. function getTableSaveTextInd(sourceTable, alreadyUsed, sources)
  457.     local index
  458.     for i, v in ipairs(alreadyUsed) do
  459.         if v == sourceTable then
  460.             index = i
  461.             break
  462.         end
  463.     end
  464.  
  465.     if index ~= nil then
  466.         return "tbl:" .. index
  467.     else
  468.         table.insert(alreadyUsed, sourceTable)
  469.         local sourceString = ""
  470.         local ind = #alreadyUsed
  471.         for k, v in pairs(sourceTable) do
  472.             sourceString = sourceString .. getSaveValueString(k, alreadyUsed, sources) .. "=" .. getSaveValueString(v, alreadyUsed, sources) .. ","
  473.         end
  474.         sources[ind] = "{" .. sourceString .. "}"
  475.         return "tbl:" .. ind
  476.     end
  477. end
  478.  
  479. function getSaveValueString(obj, alreadyUsed, sources)
  480.     local t = type(obj)
  481.     if t == "string" then
  482.         return "\"" .. obj .. "\""
  483.     elseif t == "number" then
  484.         return obj
  485.     elseif t == "table" then
  486.         return getTableSaveTextInd(obj, alreadyUsed, sources)
  487.     elseif t == "boolean" then
  488.         if obj then
  489.             return "true"
  490.         else
  491.             return "false"
  492.         end
  493.     else
  494.         error("unknown type: " .. t)
  495.     end
  496. end
  497.  
  498. function finished()
  499.     deleteFile(storage.stackFileName)
  500.     deleteFile(storage.dataFileName)
  501. end
  502.  
  503. function deleteFile(fileName)
  504.     if test then
  505.         os.remove(fileName)
  506.     else
  507.         shell.run("delete", fileName)
  508.     end
  509. end
  510.  
  511. function save()
  512.     if storage.dfData.save then
  513.         local txt = getTableSaveText(storage)
  514.         writeToFile(storage.stackFileName .. "1", txt)
  515.         writeToFile(storage.stackFileName, txt)
  516.     end
  517. end
  518.  
  519. function writeToFile(fileName, data)
  520.     if test then
  521.         local f = io.open(fileName, "w")
  522.         io.output(f)
  523.         io.write(data)
  524.         io.close(f)
  525.     else
  526.         local f = fs.open(fileName, "w")
  527.         f.write(data)
  528.         f.close()
  529.     end
  530. end
  531.  
  532. function fileExists(fileName)
  533.     if test then
  534.         local f = io.open(fileName)
  535.         if f ~= nil then
  536.             io.close(f)
  537.             return true
  538.         end
  539.         return false
  540.     else
  541.         return fs.exists(fileName)
  542.     end
  543. end
  544.  
  545. function tryLoadStorage(fileName, stackFileName, dataFileName, currentFileData)
  546.     print(stackFileName)
  547.     if fileExists(stackFileName) then
  548.         if isSameFileData(currentFileData, readFileText(dataFileName)) then
  549.             print("loading storage")
  550.             local data
  551.             local state, msg = pcall(function()
  552.                 data = getTableFromSaveText(readFileText(stackFileName))
  553.             end)
  554.             if state then
  555.                 return true, data
  556.             else
  557.                 return true, getTableFromSaveText(readFileText(stackFileName .. "1"))
  558.             end
  559.         else
  560.             print("source file has changed, restarting program")
  561.             deleteFile(stackFileName)
  562.             deleteFile(dataFileName)
  563.         end
  564.     end
  565.  
  566.     return false, {
  567.         stack = nil,
  568.         fileName = fileName,
  569.         stackFileName = stackFileName,
  570.         dataFileName = dataFileName,
  571.         dfData = {save = true},
  572.         diedLast = 0,
  573.         constants = {}
  574.     }
  575. end
  576.  
  577. function isSameFileData(data1, data2)
  578.  
  579.     local pts1 = getLengthFormatedParts(data1)
  580.     local pts2 = getLengthFormatedParts(data2)
  581.  
  582.     while #pts1 > 0 do
  583.         local data = pts1[1]
  584.         local success = false
  585.         for j, data2 in ipairs(pts2) do
  586.             if data2 == data then
  587.                 table.remove(pts1, 1)
  588.                 table.remove(pts2, j)
  589.                 success = true
  590.                 break
  591.             end
  592.         end
  593.         if not success then
  594.             return false
  595.         end
  596.     end
  597.     return #pts2 == 0
  598. end
  599.  
  600. function getLengthFormatedParts(data)
  601.     local pts = {}
  602.     while #data > 0 do
  603.         local i = string.find(data, "|")
  604.         local len = tonumber(string.sub(data, 1, i - 1))
  605.         data = string.sub(data, i + 1)
  606.         table.insert(pts, string.sub(data, 1, len))
  607.         data = string.sub(data, len + 1)
  608.     end
  609.     return pts
  610. end
  611.  
  612. function loadProgram(file, stackFile, dataFile, cFCount)
  613.  
  614.     local source = readFileText(file)
  615.     source = string.gsub(source, "/%*[^%*]*%*/", "")
  616.     source = string.gsub(source, "//[^\n]*", "")
  617.  
  618.     source = removeLetters(source, "\n\r\t ")
  619.     local methods = {}
  620.     for i, v in ipairs(splitText(source, ";")) do
  621.         local m = string.find(v, ":{")
  622.         local name = string.sub(v, 1, m - 1)
  623.         local fct = {}
  624.         fct.pars = {}
  625.         if string.find(name, "%(") ~= nil and string.sub(name, #name, #name) == ")" then
  626.             local i = string.find(name, "%(")
  627.             local parSource = string.sub(name, i + 1, -2)
  628.             name = string.sub(name, 1, i - 1)
  629.             local parNames = splitText(parSource, ",")
  630.             for i, n in ipairs(parNames) do
  631.                 if string.match(n, "[A-Za-z_][A-Za-z0-9_]*") ~= n then
  632.                     error("invalid parameter-name: " .. n)
  633.                 end
  634.                 table.insert(fct.pars, n)
  635.             end
  636.         end
  637.         if string.match(name, "[A-Za-z_][A-Za-z0-9_]*") ~= name then
  638.             error("invalid function-name: " .. name)
  639.         end
  640.         local srcCommands = string.sub(v, m + 2, -2)
  641.         fct.cmds = analyseCommands(srcCommands)
  642.         methods[name] = fct
  643.     end
  644.  
  645.     local validMethods = {}
  646.     for name, fct in pairs(methods) do
  647.         table.insert(validMethods, { type = TYPE_USER_FUNCTION, pars = { #fct.pars }, name = name, fct = fct, cmds = fct.cmds })
  648.     end
  649.  
  650.     checkMethodValidity(combineArr(validMethods, defaultFunctions))
  651.  
  652.     if methods["main"] == nil then
  653.         error("function 'main' needs to be defined in commands-source")
  654.     end
  655.     if #methods["main"]["pars"] ~= 0 then
  656.         error("function 'main' doesn't take any arguments (" .. #methods["main"]["pars"] .. " given)")
  657.     end
  658.  
  659.     local currentFileData = getFileData(methods)
  660.  
  661.     local success
  662.     success, storage = tryLoadStorage(file, stackFile, dataFile, currentFileData)
  663.     storage.dfData.save = true
  664.  
  665.     fctSetStorageData(storage.dfData, save)
  666.     if success then
  667.         initToContinue()
  668.     end
  669.  
  670.     writeToFile(dataFile, currentFileData)
  671.  
  672.     if storage.stack == nil then
  673.         local stack = {}
  674.         table.insert(stack, { name = "main", offset = 1, executed = false, localVars = { {} }, cFStack = {} })
  675.         if methods["init"] ~= nil then
  676.             if #methods["init"]["pars"] ~= 0 then
  677.                 error("function 'init' doesn't take any arguments (" .. #methods["init"]["pars"] .. " given)")
  678.             end
  679.             table.insert(stack, { name = "init", offset = 1, executed = false, localVars = { {} }, cFStack = {} })
  680.         end
  681.         storage.stack = stack
  682.     else
  683.         if methods["onRestart"] ~= nil then
  684.             if #methods["onRestart"]["pars"] ~= 0 then
  685.                 error("function 'onRestart' doesn't take any arguments (" .. #methods["onRestart"]["pars"] .. " given)")
  686.             end
  687.             table.insert(storage.stack, { name = "onRestart", offset = 1, executed = false, localVars = { {} }, cFStack = {} })
  688.         end
  689.     end
  690.  
  691.     save()
  692.  
  693.     execute(methods, true, cFCount)
  694.  
  695.     finished()
  696. end
  697.  
  698. function getFileData(methods)
  699.     local data = ""
  700.     for methodName, v in pairs(methods) do
  701.         if countKeys(v) > 2 then
  702.             error("fail")
  703.         end
  704.         local pars = v.pars
  705.         local cmds = v.cmds
  706.         local methodString = methodName .. "("
  707.         for i, par in ipairs(pars) do
  708.             if i ~= 1 then
  709.                 methodString = methodString .. ","
  710.             end
  711.             methodString = methodString .. par
  712.         end
  713.         methodString = methodString .. ")|" .. getFileDataCmds(cmds)
  714.         data = data .. #methodString .. "|" .. methodString
  715.     end
  716.     return data
  717. end
  718.  
  719. function getFileDataCmds(cmds)
  720.     local txt = ""
  721.     for i, cmd in ipairs(cmds) do
  722.         if i ~= 1 then
  723.             txt = txt .. ";"
  724.         end
  725.         txt = txt .. getFileDataCmd(cmd)
  726.     end
  727.     return txt
  728. end
  729.  
  730. function getFileDataCmd(cmd)
  731.     if cmd.type == TYPE_VALUE then
  732.         if cmd.value == "nil" then
  733.             return "nil"
  734.         elseif type(cmd.value) == "string" then
  735.             return "\"" .. cmd.value .. "\""
  736.         elseif type(cmd.value) == "boolean" then
  737.             return "\"" .. ((cmd.value and "true") or "false") .. "\""
  738.         else
  739.             return "" .. cmd.value
  740.         end
  741.         --elseif cmd.type == TYPE_DECLARATION then
  742.  
  743.     elseif cmd.type == TYPE_FUNCTION then
  744.         local txtPars = ""
  745.         for i, par in ipairs(cmd.pars) do
  746.             if i ~= 1 then
  747.                 txtPars = txtPars .. ","
  748.             end
  749.             txtPars = txtPars .. getFileDataCmd(par)
  750.         end
  751.         return cmd.name .. "(" .. txtPars .. ")"
  752.     elseif cmd.type == TYPE_CONSTANT then
  753.         return "$" .. cmd.key .. "$"
  754.     elseif cmd.type == TYPE_ARR then
  755.         local txt = ""
  756.         for i, v in ipairs(cmd.vars) do
  757.             if i ~= 1 then
  758.                 txt = txt .. ","
  759.             end
  760.             txt = txt .. getFileDataCmd(v)
  761.         end
  762.         return "[" .. txt .. "]"
  763.     elseif cmd.type == TYPE_VAR then
  764.         return cmd.name
  765.     elseif cmd.type == TYPE_ADD then
  766.         local txt = ""
  767.         for i, v in ipairs(cmd.pts) do
  768.             if i ~= 1 then
  769.                 txt = txt .. "+"
  770.             end
  771.             txt = txt .. getFileDataCmd(v)
  772.         end
  773.         return txt
  774.     elseif cmd.type == TYPE_SUB then
  775.         local txt = ""
  776.         for i, v in ipairs(cmd.pts) do
  777.             if i ~= 1 then
  778.                 txt = txt .. "-"
  779.             end
  780.             if v.type == TYPE_ADD then
  781.                 txt = txt .. "(" .. getFileDataCmd(v) .. ")"
  782.             else
  783.                 txt = txt .. getFileDataCmd(v)
  784.             end
  785.         end
  786.         return txt
  787.     elseif cmd.type == TYPE_DECLARATION then
  788.         return cmd.name .. "=" .. getFileDataCmd(cmd.value)
  789.     elseif cmd.type == TYPE_CONTROL_FLOW then
  790.         if cmd.typeCF == TYPE_CF_WHILE then
  791.             return "while(" .. getFileDataCmd(cmd.cond) .. "){" .. getFileDataCmds(cmd.body) .. "}"
  792.         elseif cmd.typeCF == TYPE_CF_FOR then
  793.             return "for(" .. getFileDataCmd(cmd.first) .. ";" .. getFileDataCmd(cmd.second) .. ";" .. getFileDataCmd(cmd.third) .. "){" .. getFileDataCmds(cmd.body) .. "}"
  794.         elseif cmd.typeCF == TYPE_CF_IF then
  795.             local txt = "";
  796.             for i, block in pairs(cmd.ifCmdBlocks) do
  797.                 if i ~= 1 then
  798.                     txt = txt .. "else"
  799.                 end
  800.                 if block.cond ~= nil then
  801.                     txt = txt .. "if(" .. getFileDataCmd(block.cond) .. ")"
  802.                 end
  803.                 txt = txt .. "{" .. getFileDataCmds(block.body) .. "}"
  804.             end
  805.             return txt
  806.         else
  807.             error("fail: " .. cmd.typeCF)
  808.         end
  809.     elseif cmd.type == TYPE_CMP then
  810.         return getFileDataCmd(cmd.pts[1]) .. cmd.ch .. getFileDataCmd(cmd.pts[2])
  811.     elseif cmd.type == TYPE_OR then
  812.         local txt = ""
  813.         for i = 1, #cmd.values do
  814.             if txt ~= "" then
  815.                 txt = txt .. "||"
  816.             end
  817.             txt = txt .. getFileDataCmd(cmd.values[i])
  818.         end
  819.         return txt
  820.     else
  821.         printKeys(cmd)
  822.         error("unknown type: " .. cmd.type)
  823.     end
  824. end
  825.  
  826. function printKeys(t)
  827.     local keys = ""
  828.     local c = 0
  829.     for i, v in pairs(t) do
  830.         keys = keys .. ((c ~= 0 and ",") or "") .. i
  831.         c = 1
  832.     end
  833.     print(keys)
  834. end
  835.  
  836. function countKeys(t)
  837.     local c = 0
  838.     for i, v in pairs(t) do
  839.         c = c + 1
  840.     end
  841.     return c
  842. end
  843.  
  844. function execute(methods, isStartThread, cFCount)
  845.     local methodName = storage.stack[#storage.stack].name
  846.     local methodOffset = storage.stack[#storage.stack].offset
  847.     local methodExecuted = storage.stack[#storage.stack].executed --TODO check pos or anything else when executed=false
  848.     local currentMethod = methods[methodName]
  849.     local cmds = currentMethod.cmds
  850.     local localVars = storage.stack[#storage.stack].localVars
  851.  
  852.     if methodExecuted then
  853.         storage.stack[#storage.stack].offset = storage.stack[#storage.stack].offset + 1
  854.     end
  855.     executeCommands(storage.stack[#storage.stack], cmds, methods, localVars, cFCount)
  856.  
  857.     if isStartThread and #storage.stack > 1 then
  858.         table.remove(storage.stack)
  859.         save()
  860.         execute(methods, true, cFCount)
  861.     end
  862. end
  863.  
  864. function executeCommand(cmd, methods, localVars, cFCount)
  865.     if cmd.type == TYPE_FUNCTION then
  866.         local pars = {}
  867.         for i, p in pairs(cmd.pars) do
  868.             table.insert(pars, executeGetValue(p, localVars, methods, cFCount))
  869.         end
  870.         --default function
  871.         for i, f in pairs(defaultFunctions) do
  872.             if f.name == cmd.name then
  873.                 return f.fct(pars)
  874.             end
  875.         end
  876.         --user function
  877.         local method = methods[cmd.name]
  878.         local newLocalVars = { {} }
  879.         for i, p in pairs(pars) do
  880.             newLocalVars[1][method.pars[i]] = p
  881.         end
  882.         table.insert(storage.stack, { name = cmd.name, offset = 1, executed = false, localVars = newLocalVars, cFStack = {} })
  883.         save()
  884.         execute(methods, false, cFCount)
  885.         table.remove(storage.stack)
  886.         save()
  887.     elseif cmd.type == TYPE_DECLARATION then
  888.         local name = cmd.name
  889.         if string.sub(name, 1, 1) == "$" then
  890.             local v = executeGetValue(cmd.value, localVars, methods, cFCount)
  891.             name = string.sub(name, 2, #name - 1)
  892.             if storage.constants[name] ~= nil then
  893.                 error("constant '" + name + "' is already defined")
  894.             end
  895.             storage.constants[name] = v
  896.         else
  897.             local v = executeGetValue(cmd.value, localVars, methods, cFCount)
  898.  
  899.             for i = 1, cFCount do
  900.                 for n, v1 in pairs(localVars[i]) do
  901.                     if n == name then
  902.                         localVars[i][name] = v
  903.                         return
  904.                     end
  905.                 end
  906.             end
  907.             if not localVars[cFCount+1] then
  908.                 localVars[cFCount+1]={}
  909.             end
  910.             localVars[cFCount+1][name] = v
  911.         end
  912.     elseif cmd.type == TYPE_CONTROL_FLOW then
  913.         if cmd.typeCF == TYPE_CF_IF then
  914.             local id = cmd.id
  915.             local data
  916.             if #storage.stack[#storage.stack].cFStack <= cFCount then
  917.                 data = { cmd = cmd, condExecuted = false, offset = 1, ifOffset = 1, executed = false, condResult = false }
  918.                 table.insert(localVars, {})
  919.                 table.insert(storage.stack[#storage.stack].cFStack, data)
  920.                 save()
  921.             else
  922.                 data = storage.stack[#storage.stack].cFStack[cFCount + 1]
  923.                 if data.cmd.id ~= cmd.id then
  924.                     print("fail")
  925.                 end
  926.             end
  927.             print(cFCount, #storage.stack[#storage.stack].cFStack)
  928.             for i = data.ifOffset, #cmd.ifCmdBlocks do
  929.                 local cond = cmd.ifCmdBlocks[i].cond
  930.                 local body = cmd.ifCmdBlocks[i].body
  931.  
  932.                 if not data.condExecuted then
  933.                     local v
  934.                     if cond ~= nil then
  935.                         v = executeGetValue(cond, localVars, methods, cFCount)
  936.                         if v == nil or type(v) ~= "boolean" then
  937.                             error("type of condition needs to be 'boolean' (type '" .. type(v) .. "' given)")
  938.                         end
  939.                     else
  940.                         v = true
  941.                     end
  942.                     data.condExecuted = true
  943.                     data.condResult = v
  944.                     save()
  945.                 end
  946.  
  947.                 if data.condResult then
  948.                     if data.executed then
  949.                         data.offset = data.offset + 1
  950.                     end
  951.                     save()
  952.                     executeCommands(data, body, methods, localVars, cFCount + 1)
  953.                 end
  954.  
  955.                 data.ifOffset = i + 1
  956.                 data.condExecuted = false
  957.                 data.executed = false
  958.                 data.offset = 1
  959.                 save()
  960.  
  961.                 if data.condResult then
  962.                     break
  963.                 end
  964.             end
  965.  
  966.             table.remove(storage.stack[#storage.stack].cFStack)
  967.             table.remove(localVars)
  968.         elseif cmd.typeCF == TYPE_CF_FOR then
  969.             local id = cmd.id
  970.             local data
  971.             if #storage.stack[#storage.stack].cFStack <= cFCount then
  972.                 data = { cmd = cmd, firstExecuted = false, offset = 1, condExecuted = false, lastExecuted = false, condResult = false }
  973.                 table.insert(localVars, {})
  974.                 table.insert(storage.stack[#storage.stack].cFStack, data)
  975.                 save()
  976.             else
  977.                 data = storage.stack[#storage.stack].cFStack[cFCount + 1]
  978.                 if data.cmd.id ~= cmd.id then
  979.                     print("fail")
  980.                 end
  981.             end
  982.             if not data.firstExecuted then
  983.                 executeCommand(data.cmd.first, methods, localVars, cFCount - 1)
  984.                 data.firstExecuted = true
  985.                 save()
  986.             end
  987.             while true do
  988.                 if not data.condExecuted then
  989.                     local v = executeGetValue(data.cmd.second, localVars, methods, cFCount)
  990.                     if v == nil or type(v) ~= "boolean" then
  991.                         error("type of condition needs to be 'boolean' (type '" .. type(v) .. "' given)")
  992.                     end
  993.                     data.condExecuted = true
  994.                     data.condResult = v
  995.                     save()
  996.                     if not v then
  997.                         break
  998.                     end
  999.                 end
  1000.                 if data.executed then
  1001.                     data.offset = data.offset + 1
  1002.                     save()
  1003.                 end
  1004.  
  1005.                 executeCommands(data, data.cmd.body, methods, localVars, cFCount + 1)
  1006.  
  1007.                 if not data.lastExecuted then
  1008.                     executeCommand(data.cmd.third, methods, localVars, cFCount)
  1009.                     data.lastExecuted = true
  1010.                     save()
  1011.                 end
  1012.  
  1013.                 data.lastExecuted = false
  1014.                 data.condExecuted = false
  1015.                 data.executed = false
  1016.                 data.offset = 1
  1017.                 save()
  1018.             end
  1019.             table.remove(storage.stack[#storage.stack].cFStack)
  1020.             table.remove(localVars)
  1021.         elseif cmd.typeCF == TYPE_CF_WHILE then
  1022.             local id = cmd.id
  1023.             local data
  1024.             if #storage.stack[#storage.stack].cFStack <= cFCount then
  1025.                 data = { cmd = cmd, condExecuted = false, offset = 1, executed = false, condResult = false }
  1026.                 table.insert(localVars, {})
  1027.                 table.insert(storage.stack[#storage.stack].cFStack, data)
  1028.                 save()
  1029.             else
  1030.                 data = storage.stack[#storage.stack].cFStack[cFCount + 1]
  1031.                 if data.cmd.id ~= cmd.id then
  1032.                     print("fail")
  1033.                 end
  1034.             end
  1035.  
  1036.             while true do
  1037.                 if not data.condExecuted then
  1038.                     local v = executeGetValue(data.cmd.cond, localVars, methods, cFCount)
  1039.                     if v == nil or type(v) ~= "boolean" then
  1040.                         error("type of condition needs to be 'boolean' (type '" .. type(v) .. "' given)")
  1041.                     end
  1042.                     data.condExecuted = true
  1043.                     data.condResult = v
  1044.                     save()
  1045.                     if not v then
  1046.                         break
  1047.                     end
  1048.                 end
  1049.                 if data.executed then
  1050.                     data.offset = data.offset + 1
  1051.                 end
  1052.                 save()
  1053.                 executeCommands(data, data.cmd.body, methods, localVars, cFCount + 1)
  1054.  
  1055.                 data.condExecuted = false
  1056.                 data.executed = false
  1057.                 data.offset = 1
  1058.                 save()
  1059.             end
  1060.  
  1061.             table.remove(storage.stack[#storage.stack].cFStack)
  1062.             table.remove(localVars)
  1063.         else
  1064.             error("unknown typeCF: " .. cmd.typeCF .. "")
  1065.         end
  1066.     else
  1067.         error("unknown type: " .. cmd.type)
  1068.     end
  1069. end
  1070.  
  1071. function executeCommands(data, cmds, methods, localVars, cFCount)
  1072.     for i = data.offset, #cmds do
  1073.         local cmd = cmds[i]
  1074.         data.offset = i
  1075.         data.executed = false
  1076.         if cmd.type == TYPE_FUNCTION then
  1077.             local isDefault = false
  1078.             for i, f in pairs(defaultFunctions) do
  1079.                 if f.name == cmd.name then
  1080.                     isDefault = true
  1081.                 end
  1082.             end
  1083.             data.executed = not isDefault
  1084.         end
  1085.  
  1086.         --data.executed = cmd.type == TYPE_FUNCTION
  1087.         save()
  1088.         executeCommand(cmd, methods, localVars, cFCount)
  1089.         data.executed = true
  1090.         save()
  1091.     end
  1092. end
  1093.  
  1094. function executeGetValue(value, localVars, methods, cFCount)
  1095.     if value.type == TYPE_VALUE then
  1096.         return value.value
  1097.     elseif value.type == TYPE_ARR then
  1098.         local vars = {}
  1099.         for i = 1, #value.vars do
  1100.             vars[i] = executeGetValue(value.vars[i], localVars, methods, cFCount);
  1101.         end
  1102.         return vars
  1103.     elseif value.type == TYPE_VAR then
  1104.         for i = 1, #localVars do
  1105.             for n, v in pairs(localVars[#localVars - i + 1]) do
  1106.                 if value.name == n then
  1107.                     return v
  1108.                 end
  1109.             end
  1110.         end
  1111.         error("var '" .. value.name .. "' isn't defined yet")
  1112.     elseif value.type == TYPE_FUNCTION then
  1113.         return executeCommand(value, methods, localVars, cFCount)
  1114.     elseif value.type == TYPE_ADD then
  1115.         local v = executeGetValue(value.pts[1], localVars, methods, cFCount)
  1116.         for i = 2, #value.pts do
  1117.             local v1 = executeGetValue(value.pts[i], localVars, methods, cFCount)
  1118.             if type(v) == "string" or type(v1) == "string" then
  1119.                 v = v .. v1
  1120.             else
  1121.                 v = v + v1
  1122.             end
  1123.         end
  1124.         return v
  1125.     elseif value.type == TYPE_SUB then
  1126.         local v = executeGetValue(value.pts[1], localVars, methods, cFCount)
  1127.         for i = 2, #value.pts do
  1128.             v = v - executeGetValue(value.pts[i], localVars, methods, cFCount)
  1129.         end
  1130.         return v
  1131.     elseif value.type == TYPE_CONSTANT then
  1132.         for k, val in pairs(storage.constants) do
  1133.             if (k == value.key) then
  1134.                 return val
  1135.             end
  1136.         end
  1137.         error("constant '" .. value.key .. "' isn't defined yet")
  1138.     elseif value.type == TYPE_CMP then
  1139.         local v = executeGetValue(value.pts[1], localVars, methods, cFCount)
  1140.         local v1 = executeGetValue(value.pts[2], localVars, methods, cFCount)
  1141.  
  1142.         if value.ch == ">" then
  1143.             return v > v1
  1144.         elseif value.ch == "<" then
  1145.             return v < v1
  1146.         elseif value.ch == ">=" then
  1147.             return v >= v1
  1148.         elseif value.ch == "<=" then
  1149.             return v <= v1
  1150.         elseif value.ch == "==" then
  1151.             return v == v1
  1152.         elseif value.ch == "!=" then
  1153.             return v ~= v1
  1154.         else
  1155.             error("unknown char: '" .. value.ch .. "'")
  1156.         end
  1157.     elseif value.type == TYPE_OR then
  1158.         for i = 1, #value.values do
  1159.             if executeGetValue(value.values[i], localVars, methods, cFCount) then
  1160.                 return true
  1161.             end
  1162.         end
  1163.         return false
  1164.     elseif value.type == TYPE_COMP then
  1165.         if value.mode == TYPE_COMP_EQUAL then
  1166.             printTable(value.values[1])
  1167.             return executeGetValue(value.values[1], localVars, methods, cFCount) == executeGetValue(value.values[2], localVars, methods, cFCount)
  1168.         else
  1169.             error("unsupported mode: " .. value.mode)
  1170.         end
  1171.     else
  1172.         error("unknown type: " .. value.type)
  1173.     end
  1174. end
  1175.  
  1176. function checkMethodValidity(methods)
  1177.     local definedNames = {}
  1178.     for i, v in pairs(methods) do
  1179.         definedNames[v.name] = v.pars
  1180.     end
  1181.     for i, v in pairs(methods) do
  1182.         if v.type == TYPE_USER_FUNCTION then
  1183.             checkCmdsValidity(v.cmds, definedNames)
  1184.         end
  1185.     end
  1186. end
  1187.  
  1188. function checkCmdsValidity(cmds, definedNames)
  1189.     for i, cmd in pairs(cmds) do
  1190.         if cmd.type == TYPE_FUNCTION then
  1191.             if definedNames[cmd.name] == nil then
  1192.                 error("function '" .. cmd.name .. "' isn't defined")
  1193.             end
  1194.             local args = definedNames[cmd.name]
  1195.             local cStart = args[1]
  1196.             local cEnd = cStart
  1197.             if #args > 1 then
  1198.                 cEnd = args[2]
  1199.             end
  1200.             local count = #cmd.pars
  1201.             if count < cStart or count > cEnd then
  1202.                 error("function '" .. cmd.name .. "' takes between " .. cStart .. " and " .. cEnd .. " argument(s) (" .. count .. " given)")
  1203.             end
  1204.             checkCmdsValidity(cmd.pars, definedNames)
  1205.         elseif cmd.type == TYPE_CONTROL_FLOW then
  1206.             if cmd.typeCF == TYPE_CF_WHILE then
  1207.                 checkCmdsValidity(cmd.body, definedNames)
  1208.             elseif cmd.typeCF == TYPE_CF_FOR then
  1209.                 checkCmdsValidity({ cmd.first, cmd.second, cmd.third }, definedNames)
  1210.                 checkCmdsValidity(cmd.body, definedNames)
  1211.             elseif cmd.typeCF == TYPE_CF_IF then
  1212.                 for i, block in ipairs(cmd.ifCmdBlocks) do
  1213.                     if cmd.cond ~= nil then
  1214.                         checkCmdsValidity({ block.cond }, definedNames)
  1215.                     end
  1216.                     checkCmdsValidity(block.body, definedNames)
  1217.                 end
  1218.             else
  1219.                 error("unknown typeCF: " .. cmd.typeCF)
  1220.             end
  1221.         elseif cmd.type == TYPE_ARR then
  1222.             checkCmdsValidity(cmd.vars, definedNames)
  1223.         elseif cmd.type == TYPE_ADD or cmd.type == TYPE_SUB then
  1224.             checkCmdsValidity(cmd.pts, definedNames)
  1225.         elseif cmd.type == TYPE_DECLARATION then
  1226.             checkCmdsValidity({ cmd.value }, definedNames)
  1227.         elseif cmd.type ~= TYPE_CONSTANT and cmd.type ~= TYPE_VAR and cmd.type ~= TYPE_VALUE and cmd.type ~= TYPE_CMP then
  1228.             printKeys(cmd)
  1229.             error("unknown type: " .. cmd.type)
  1230.         end
  1231.     end
  1232. end
  1233.  
  1234. function printTable(tbl)
  1235.     printTableIndex(tbl, "", {})
  1236. end
  1237.  
  1238. function printTableIndex(tbl, before, alreadyUsed)
  1239.     for i, v in pairs(tbl) do
  1240.         if type(v) == "table" then
  1241.             if tableContainsValue(alreadyUsed, v) then
  1242.                 print(before .. i .. ":", "alreadyUsed");
  1243.             else
  1244.                 print(before .. i .. ": [");
  1245.                 table.insert(alreadyUsed, v)
  1246.                 printTableIndex(v, before .. "\t", alreadyUsed)
  1247.                 print(before .. "]")
  1248.             end
  1249.         else
  1250.             print(before .. i .. ":", v);
  1251.         end
  1252.     end
  1253. end
  1254.  
  1255. function tableContainsValue(table, value)
  1256.     for i, v in pairs(table) do
  1257.         if v == value then
  1258.             return true
  1259.         end
  1260.     end
  1261.     return false
  1262. end
  1263.  
  1264. local fileName = args[1]
  1265. local stackFileName = fileName .. ".stack"
  1266. local dataFileName = fileName .. ".id"
  1267. if args[3] ~= nil then
  1268.     if args[3] == "restart" then
  1269.         print("restart")
  1270.         if test then
  1271.             os.remove(stackFileName)
  1272.         else
  1273.             fs.delete(stackFileName)
  1274.         end
  1275.     else
  1276.         error("unknown second argument: '" .. args[3] .. "'")
  1277.     end
  1278. end
  1279.  
  1280. while true do
  1281.     local status, err = pcall(loadProgram, fileName, stackFileName, dataFileName, 0)
  1282.     if not status then
  1283.         if storage ~= nil then
  1284.             print(storage.diedLast, os.clock())
  1285.             print("err: ", err)
  1286.             if err ~= "Terminated" and (storage.diedLast == nil or os.clock() > 300) then
  1287.                 storage.diedLast = 0
  1288.                 save()
  1289.                 os.reboot()
  1290.                 return
  1291.             end
  1292.         else
  1293.             print("err: ", err)
  1294.         end
  1295.         return
  1296.     else
  1297.         return
  1298.     end
  1299. end
  1300.  
  1301.  
  1302.  
  1303.  
Add Comment
Please, Sign In to add comment