Advertisement
Imgoodisher

Befunge Interpreter

Feb 3rd, 2013
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.05 KB | None | 0 0
  1. function run(tbl, name, debug, limitx, limity)
  2.     w, h = term.getSize()
  3.     limitx, limity = limitx or w, limity or h
  4.    
  5.     for _x=0, limitx do
  6.         if not tbl[_x] then tbl[_x] = {} end
  7.         for _y=0, limity do
  8.             if not tbl[_x][_y] then
  9.                 tbl[_x][_y] = " "
  10.             end
  11.         end
  12.     end
  13.    
  14.     local x, y = 0, 0
  15.     local vx, vy = 1, 0
  16.     local stringmode = false
  17.     local stack = {}
  18.     local bExit = false
  19.    
  20.     local function push(n)
  21.         table.insert(stack, n)
  22.     end
  23.     local function pop()
  24.         if stack[#stack] then
  25.             return table.remove(stack, #stack)
  26.         else
  27.             error((name or "befunge")..": ("..x..", "..y..") Stack is empty!", 0)
  28.         end
  29.     end
  30.    
  31.     local lastchar = " "
  32.     local lastx, lasty = 1, 1
  33.     local first = true
  34.     local function draw()
  35.         if debug then
  36.            
  37.             for _x,v in pairs(tbl) do
  38.                 for _y,char in pairs(v) do
  39.                     if _x == x and _y == y then
  40.                         term.setBackgroundColor(colors.yellow)
  41.                         lastchar = char
  42.                         lastx, lasty = _x, _y
  43.                     else
  44.                         term.setBackgroundColor(colors.black)
  45.                     end
  46.                     if ((char ~= " ") and first) or (_x==x and _y==y)then
  47.                         term.setCursorPos(_x+1, _y+1)
  48.                         write(char)
  49.                     end
  50.                 end
  51.             end
  52.            
  53.             sleep(0.1)
  54.             term.setBackgroundColor(colors.black)
  55.             term.setCursorPos(lastx+1, lasty+1)
  56.             term.write(lastchar)
  57.            
  58.             first = false
  59.         end
  60.     end
  61.    
  62.     local cmds = {
  63.         -- Befunge-93 Instruction List from http://en.wikipedia.org/wiki/Befunge
  64.         ["+"] = function() a = pop() b = pop() push(a+b) end, -- Addition: Pop a and b, then push a+b
  65.         ["-"] = function() a = pop() b = pop() push(a-b) end, -- Subtraction: Pop a and b, then push b-a
  66.         ["*"] = function() a = pop() b = pop() push(a*b) end, -- Multiplication: Pop a and b, then push a*b
  67.         ["/"] = function() a = pop() b = pop() push(a/b) end, -- Integer division: Pop a and b, then push b/a, rounded down. If a is zero, ask the user what result they want
  68.         ["%"] = function() a = pop() b = pop() push(a%b) end, -- Modulo: Pop a and b, then push the remainder of the integer division of b/a. If a is zero, ask the user what result they want
  69.         ["!"] = function() a = pop() if a == 0 then push(1) else push(0) end end, -- Logical NOT: Pop a value. If the value is zero, push 1; otherwise, push zero
  70.         ["`"] = function() a = pop() b = pop() if b>a then push(1) else push(0) end end, -- Greater than: Pop a and b, then push 1 if b>a, otherwise zero
  71.         [">"] = function() vx, vy = 1, 0 end, -- Start moving right
  72.         ["<"] = function() vx, vy = -1, 0 end, -- Start moving left
  73.         ["^"] = function() vx, vy = 0, -1 end, -- Start moving up
  74.         ["v"] = function() vx, vy = 0, 1 end, -- Start moving down
  75.         ["?"] = function() -- Start moving in a random cardinal direction
  76.             local dir = math.random(1, 4)
  77.             if dir == 1 then vx, vy = 1, 0
  78.             elseif dir == 2 then vx, vy = -1, 0
  79.             elseif dir == 3 then vx, vy = 0, -1
  80.             elseif dir == 4 then vx, vy = 0, 1
  81.             end
  82.         end,
  83.         ["_"] = function() a = pop() -- Pop a value; move right if value=0, left otherwise
  84.             if a == 0 then
  85.                 vx, vy = 1, 0
  86.             else
  87.                 vx, vy = -1, 0
  88.             end
  89.         end,
  90.         ["|"] = function() a = pop() -- Pop a value; move down if value=0, up otherwise
  91.             if a == 0 then
  92.                 vx, vy = 0, 1
  93.             else
  94.                 vx, vy = 0, -1
  95.             end
  96.         end,  
  97.         ['"'] = function() stringmode = not stringmode end, -- Start string mode: push each character's ASCII value all the way up to the next "
  98.         [":"] = function() push(stack[#stack]) end, -- Duplicate value on top of the stack
  99.        ["\\"] = function() a = pop() b = pop() push(a) push(b) end, -- Swap two values on top of the stack
  100.         ["$"] = function() pop() end, -- Pop value from the stack
  101.         ["."] = function()  -- Pop value and output as an integer
  102.             if debug then term.setCursorPos(1, h) end
  103.             write(pop())
  104.             if debug then sleep(0.1) end
  105.         end,
  106.         [","] = function() -- Pop value and output as ASCII character
  107.             if debug then term.setCursorPos(1, h) end
  108.             write(string.char(pop()))
  109.             if debug then sleep(0.1) end
  110.         end,
  111.         ["#"] = function() x, y = x+vx, y+vy end, -- Trampoline: Skip next cell
  112.         ["p"] = function() -- A "put" call (a way to store a value for later use). Pop y, x and v, then change the character at the position (x,y) in the program to the character with ASCII value v
  113.             local _y, _x, v = pop(), pop(), pop()
  114.             tbl[_x][_y] = string.char(v)
  115.             first = true
  116.         end,
  117.         ["g"] = function()  
  118.             local _y, _x = pop(), pop()
  119.             push(string.byte(tbl[_x][_y]))
  120.         end, -- A "get" call (a way to retrieve data in storage). Pop y and x, then push ASCII value of the character at that position in the program
  121.         ["&"] = function()  -- Ask user for a number and push it
  122.             if debug then term.setCursorPos(1, h) end
  123.             num = read()
  124.             push(tonumber(num) or 0)
  125.             term.clear()
  126.             first = true
  127.         end,
  128.         ["~"] = function() -- Ask user for a character and push its ASCII value
  129.             if debug then term.setCursorPos(1, h) end
  130.             char = read()
  131.             push(string.byte(string.sub(char, 1, 1)))
  132.             term.clear()
  133.             first = true
  134.         end,
  135.         ["@"] = function() bExit = true end, -- End program
  136.         [" "] = function() end, -- No-op. Does nothing
  137.        
  138.         ["s"] = function() sleep(0) end -- Sleep, add to avoid "Too Long without Yielding" error
  139.     }
  140.    
  141.     term.clear()
  142.     while not bExit do
  143.         draw()
  144.         --if not tbl[x] or not tbl[x][y]then
  145.         --  error((name or "befunge")..": ("..x..", "..y..") Instruction does not exist!", 0)
  146.         --end
  147.         local cmd
  148.         if tbl[x] then
  149.             cmd = tbl[x][y] or " "
  150.         else
  151.             cmd = " "
  152.         end
  153.         if stringmode and cmd ~= '"' then -- within ""
  154.             push(string.byte(cmd))
  155.         elseif string.match(cmd, "%d") then -- a number
  156.             push(tonumber(cmd))
  157.         else -- a command
  158.             if cmds[cmd] then
  159.                 cmds[cmd]()
  160.             else
  161.                 error((name or "befunge")..": ("..x..", "..y..") Unknown instruction!", 0)
  162.             end
  163.         end
  164.        
  165.         x, y = (x+vx)%80, (y+vy)%20
  166.     end
  167.     print("")
  168. end
  169.  
  170. function load(path)
  171.     local file = io.open(path, "r")
  172.     local tbl = {}
  173.     local y = 0
  174.    
  175.     for line in file:lines() do
  176.         for x=1, line:len() do
  177.             if not tbl[x-1] then tbl[x-1] = {} end
  178.             tbl[x-1][y] = string.sub(line, x, x)
  179.         end
  180.         y = y + 1
  181.     end
  182.    
  183.     return tbl
  184. end
  185.  
  186. tArgs = {...}
  187. run(load(tArgs[1]), tArgs[1], tArgs[2])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement