Advertisement
TangentFox

Terminal WIP v2 (for minetest luacontrollers)

May 26th, 2019 (edited)
263
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.21 KB | None | 0 0
  1. local DISPLAY = "lcd"
  2. local INPUT = "kbd"
  3.  
  4. local run, fns
  5. if not event then
  6.   -- running outside of minetest
  7.   local _print = print
  8.   print = function(...)
  9.     local args = {...}
  10.     if #args == 1 and type(args[1]) == "table" then
  11.       _print(run(args[1]))
  12.     else
  13.       _print(...)
  14.     end
  15.   end
  16.   digiline_send = function(c, ...) print("digiline_send -> " .. c, ...) end
  17.   event = { type = "program" }
  18. else
  19.   -- running inside minetest
  20.   print = function(...)
  21.     local args = {...}
  22.     if #args > 1 then
  23.       digiline_send(DISPLAY, table.concat(args, "\t"))
  24.     elseif #args == 1 then
  25.       if "table" == type(args[1]) then
  26.         digiline_send(DISPLAY, run(args[1]))
  27.       else
  28.         digiline_send(DISPLAY, tostring(args[1]))
  29.       end
  30.     end
  31.   end
  32.   string.rep = function(str, c)
  33.     local out = ""
  34.     while c > 0 do
  35.       out = out .. str
  36.       c = c - 1
  37.     end
  38.     return out
  39.   end
  40. end
  41.  
  42. local tokenize -- translate string into tokens of parenthesis & sequences of non-space characters
  43. tokenize = function(str)
  44.   local tokens = {}
  45.   local currentToken = ""
  46.   while #str > 0 do
  47.     local t = str:sub(1, 1)
  48.     if t == " " then
  49.       if #currentToken > 0 then
  50.         table.insert(tokens, currentToken)
  51.         currentToken = ""
  52.       end
  53.     elseif t == "(" then
  54.       if #currentToken > 0 then
  55.         table.insert(tokens, currentToken)
  56.         currentToken = ""
  57.       end
  58.       table.insert(tokens, "(")
  59.     elseif t == ")" then
  60.       if #currentToken > 0 then
  61.         table.insert(tokens, currentToken)
  62.         currentToken = ""
  63.       end
  64.       table.insert(tokens, ")")
  65.     else
  66.       currentToken = currentToken .. t
  67.     end
  68.     str = str:sub(2)
  69.   end
  70.   if #currentToken > 0 then
  71.     table.insert(tokens, currentToken)
  72.   end
  73.   return tokens
  74. end
  75.  
  76. local store -- store tokens into an abstract syntax tree
  77. store = function(tokens)
  78.   local ast = {}
  79.   local ret
  80.   while #tokens > 0 do
  81.     if tokens[1] == "(" then
  82.       table.remove(tokens, 1)
  83.       ret, tokens = store(tokens)
  84.       table.insert(ast, ret)
  85.     elseif tokens[1] == ")" then
  86.       table.remove(tokens, 1)
  87.       return ast, tokens
  88.     else
  89.       table.insert(ast, table.remove(tokens, 1))
  90.     end
  91.   end
  92.   if #ast == 1 then
  93.     return ast[1]
  94.   else
  95.     return ast
  96.   end
  97. end
  98.  
  99. run = function(str_or_ast, args)
  100.   local program, fn
  101.   if "string" == type(str_or_ast) then
  102.     program = store(tokenize(str_or_ast))
  103.   else
  104.     program = str_or_ast
  105.   end
  106.   if "string" == type(program) then
  107.     fn = program
  108.     program = {}
  109.   else
  110.     fn = table.remove(program, 1)
  111.   end
  112.   if "string" == type(fn) then
  113.     if fns[fn] then
  114.       if args then
  115.         return fns[fn](args, unpack(program))
  116.       else
  117.         return fns[fn](unpack(program))
  118.       end
  119.     elseif _G[fn] then
  120.       if args then
  121.         return _G[fn](args, unpack(program))
  122.       else
  123.         return _G[fn](unpack(program))
  124.       end
  125.     else
  126.       print("error! function '"..tostring(fn).."' doesn't exist")
  127.     end
  128.   else
  129.     return run(fn, args)
  130.   end
  131. end
  132.  
  133. local show_table -- basic debug output / pretty print for objects
  134. show_table = function(t,d)
  135.   if type(t) ~= "table" then return tostring(t) end
  136.   local str = ""
  137.   d = d or 0
  138.   for k,v in pairs(t) do
  139.     str = str .. string.rep(" ", d) .. tostring(k) .. " = " .. tostring(v) .. "\n"
  140.     if type(v) == "table" then str = str .. show_table(v,d+1) end
  141.   end
  142.   return str
  143. end
  144.  
  145. local function _if(condition, codeT, codeF)
  146.   if run(condition) then
  147.     return run(codeT)
  148.   elseif codeF then
  149.     return run(codeF)
  150.   end
  151. end
  152.  
  153. local function _while(condition, loop)
  154.   while run(condition) do
  155.     run(loop)
  156.   end
  157. end
  158.  
  159. local function set_env(name, ...)
  160.   if type(name) == "table" then name = run(name) end
  161.  
  162.   local args = {...}
  163.   local value
  164.   if #args > 1 then
  165.     value = table.concat(args, " ")
  166.   elseif #args == 1 then
  167.     if "table" == type(args[1]) then
  168.       value = run(args[1])
  169.     else
  170.       value = args[1]
  171.     end
  172.   end
  173.  
  174.   value = tonumber(value) or value
  175.   mem.env[name] = value
  176. end
  177.  
  178. local function get_env(name)
  179.   if type(name) == "table" then name = run(name) end
  180.   return mem.env[name]
  181. end
  182.  
  183. local function send(channel, ...)
  184.   if type(channel) == "table" then channel = run(channel) end
  185.  
  186.   local args = {...}
  187.   if #args > 1 then
  188.     digiline_send(channel, table.concat(args, " "))
  189.   elseif #args == 1 then
  190.     if "table" == type(args[1]) then
  191.       digiline_send(channel, run(args[1]))
  192.     else
  193.       digiline_send(channel, args[1])
  194.     end
  195.   end
  196. end
  197.  
  198. fns = { -- available to custom code
  199.   echo = print,
  200.   show_table = show_table,
  201.   ["if"] = _if,
  202.   ["while"] = _while,
  203.   ["="] = set_env,
  204.   ["$"] = get_env,
  205.   ["true"] = function() return true end,
  206.   ["false"] = function() return false end,
  207.   -- ["`"] = function(...) return table.concat({...}, " ") end,
  208.   digiline_send = send,
  209. }
  210.  
  211. -- local example_code = "digiline_send lcd Hello!"
  212. -- local example_code = "print Hello world!"
  213. -- local example_code = "if false (print This is true.) (print This is false.)"
  214.  
  215. if event.type == "digiline" then
  216.   if event.channel == INPUT then
  217.     run(event.msg)
  218.   end
  219.  
  220. elseif event.type == "program" then
  221.   mem.env = {}
  222.   print("Ready.")
  223. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement