Skip to content

Instantly share code, notes, and snippets.

@st98
Created June 14, 2017 09:04
Show Gist options
  • Save st98/57cf8c6bb8cbb653be8fb2eb04f29e03 to your computer and use it in GitHub Desktop.
Save st98/57cf8c6bb8cbb653be8fb2eb04f29e03 to your computer and use it in GitHub Desktop.
Befungeインタプリタ
import random
import sys
class Stack:
def __init__(self):
self.stack = []
def append(self, v):
self.stack.append(v)
def pop(self):
if len(self.stack) <= 0:
return 0
return self.stack.pop()
class Interpreter:
def __init__(self, program):
self.pos = (0, 0)
self.dir = (1, 0)
self.stack = Stack()
self.program = [list(line) for line in program.splitlines()]
self.running = False
def step(self):
x, y = self.pos
op = self.program[y][x]
# Befunge-93
if op == '+':
a = self.stack.pop()
b = self.stack.pop()
self.stack.append(a + b)
elif op == '-':
a = self.stack.pop()
b = self.stack.pop()
self.stack.append(b - a)
elif op == '*':
a = self.stack.pop()
b = self.stack.pop()
self.stack.append(a * b)
elif op == '/':
a = self.stack.pop()
b = self.stack.pop()
self.stack.append(b // a)
elif op == '%':
a = self.stack.pop()
b = self.stack.pop()
self.stack.append(b % a)
elif op == '!':
a = self.stack.pop()
self.stack.append(1 if a == 0 else 0)
elif op == '`':
a = self.stack.pop()
b = self.stack.pop()
self.stack.append(1 if b > a else 0)
elif op == '>':
self.dir = (1, 0)
elif op == '<':
self.dir = (-1, 0)
elif op == '^':
self.dir = (0, -1)
elif op == 'v':
self.dir = (0, 1)
elif op == '?':
self.dir = (
(1, 0),
(-1, 0),
(0, 1),
(0, -1)
)[random.randint(0, 3)]
elif op == '_':
a = self.stack.pop()
self.dir = (1, 0) if a == 0 else (-1, 0)
elif op == '|':
a = self.stack.pop()
self.dir = (0, 1) if a == 0 else (0, -1)
elif op == '"':
x, y = self.move()
while self.program[y][x] != '"':
self.stack.append(ord(self.program[y][x]))
x, y = self.move()
elif op == ':':
a = self.stack.pop()
self.stack.append(a)
self.stack.append(a)
elif op == '\\':
a = self.stack.pop()
b = self.stack.pop()
self.stack.append(a)
self.stack.append(b)
elif op == '$':
self.stack.pop()
elif op == '.':
a = self.stack.pop()
sys.stdout.write('{} '.format(a))
elif op == ',':
a = self.stack.pop()
sys.stdout.write(chr(a))
elif op == '#':
self.move()
elif op == 'g':
y = self.stack.pop()
x = self.stack.pop()
self.stack.append(ord(self.program[y][x]))
elif op == 'p':
y = self.stack.pop()
x = self.stack.pop()
v = self.stack.pop()
self.program[y][x] = chr(v)
elif op == '&':
a = ''
while not a.isdigit():
a = input('int> ')
self.stack.append(int(a))
elif op == '~':
a = input('char> ')
self.stack.append(ord(a[0]))
elif op == '@':
self.running = False
elif op.isdigit():
self.stack.append(int(op))
# Funge-98
elif op == ';':
x, y = self.move()
while self.program[y][x] != ';':
x, y = self.move()
elif 'a' <= op <= 'f':
self.stack.append(int(op, 16))
def move(self):
x, y = self.pos
dx, dy = self.dir
x += dx
if x < 0:
x = len(self.program[y]) - 1
if x >= len(self.program[y]):
x = 0
y += dy
if y < 0:
y = len(self.program) - 1
if y >= len(self.program):
y = 0
self.pos = (x, y)
return self.pos
def interpret(self):
self.running = True
while self.running:
self.step()
self.move()
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description='Befunge Interpreter')
parser.add_argument('file', nargs='?', help='file to execute')
args = parser.parse_args()
if args.file is None:
program = sys.stdin.read()
else:
with open(args.file, 'r') as f:
program = f.read()
interpreter = Interpreter(program)
interpreter.interpret()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment