Created
January 7, 2015 14:21
-
-
Save 9point6/500155218210d1aa4607 to your computer and use it in GitHub Desktop.
Basic CoffeeScript Befunge Interpreter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
numberize = (fn) -> (a, b) -> fn Number(a), Number(b) | |
changeDirection = (pos, direction) -> | |
if direction is '?' then direction = '^v<>'[parseInt Math.random() * 4] | |
[pos.dx, pos.dy] = {'^': [0,-1], 'v': [0,1], '<': [-1,0], '>': [1,0]}[direction] | |
pos | |
operations = | |
'+': numberize (a, b) -> a + b | |
'-': numberize (a, b) -> b - a | |
'*': numberize (a, b) -> a * b | |
'/': numberize (a, b) -> ~~(a / b) | |
'%': numberize (a, b) -> ~~(b % a) | |
'!': (a ) -> Number !a | |
'`': (a, b) -> Number b > a | |
'_': (a ) -> if a is 0 then '>' else '<' | |
'|': (a ) -> if a is 0 then 'v' else '^' | |
':': (a ) -> [a, a] | |
'\\':(a, b) -> [a, b] | |
'$': (a ) -> [] | |
doOp = (stack, ins, pushResult = true) -> | |
args = [] | |
args.push stack.pop() ? 0 for i in [0...operations[ins].length] | |
result = operations[ins].apply null, args | |
if pushResult then stack.concat result else [stack, result] | |
doMove = (code, pos) -> | |
pos.x = (pos.x + pos.dx) % code[pos.y].length | |
pos.y = (pos.y + pos.dy) % code.length | |
pos | |
interpret = (code) -> | |
output = "" | |
stack = [] | |
code = code.split('\n').map (x) -> x.split '' | |
pos = x: 0, y: 0, dx: 1, dy: 0 | |
asciiMode = false | |
while (instruction = code[pos.y][pos.x]) isnt '@' | |
if instruction is '"' then asciiMode = asciiMode is false | |
else if asciiMode isnt false then stack.push instruction.charCodeAt 0 | |
else if /[0-9]/.test instruction then stack.push Number instruction | |
else if /[<>^v\?]/.test instruction then pos = changeDirection pos, instruction | |
else if /[|_]/.test instruction | |
[stack, res] = doOp stack, instruction, false | |
pos = changeDirection pos, res | |
else if instruction is '.' then output += stack.pop() | |
else if instruction is ',' then output += String.fromCharCode stack.pop() | |
else if instruction is '#' then pos = doMove code, pos | |
else if /[pg]/.test instruction | |
[y, x] = [stack.pop(), stack.pop()] | |
if instruction is 'p' then code[y][x] = stack.pop() | |
else stack.push code[y][x].charCodeAt?(0) ? code[y][x] | |
else if instruction isnt ' ' then stack = doOp stack, instruction | |
pos = doMove code, pos | |
output |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Missing the commands requiring user input for the time being.