# Brainfox: A brainf*ck interpreter for microbit.
# (C) 2017 Alynna Trypnotk, GPL3
# Be selective here to save RAM
from microbit import uart, display, button_a, button_b, sleep, Image, reset
from gc import collect, mem_free
from os import remove
collect() # DEFPROG is Hello World. These strings are defined here to get them in flash, not RAM.
DEFPROG = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."
PROGNAME = "prog.bf"
INPUTNAME = "input.bf"
PRIMS = "+-<>[],.#|"
PRAGMA = "FX" # Default PRAGMA and DELAY.
DELAY = 100 # You can set these freely.
CELLS = 256 # CELLS available. This is configurabale
# and will cost its value in bytes.
def receive():
global PRAGMA
print("* Enter program, [/ ENTER] to submit *")
DC = 0
getProg = 2
while True:
AC = str(input())
if getProg == 2: # Prevents null programs.
file = open(PROGNAME, "wt")
getProg = 1
if AC[0] == '/':
PRAGMA = AC[1:].upper() if len(AC)>1 else PRAGMA
break
if AC[0] == '_':
getProg = 0
file.close()
file = open(INPUTNAME, "wt")
DC = 0
continue
if getProg: AC = ''.join([x for x in AC if x in PRIMS])
DC += len(AC)
file.write(str(AC))
print(DC)
collect()
file.close()
if button_a.is_pressed():
try:
remove(PROGNAME)
remove(INPUTNAME)
except: pass
display.show(Image.PACMAN, wait=False)
receive()
reset()
def get_input():
if "R" in PRAGMA:
while not uart.any(): sleep(1)
return str(uart.read(1),"ascii");
else:
x = file.read(1)
return '\0' if x == "" else x
def bfprint(c):
print(chr(c),sep='',end='')
if not "T" in PRAGMA:
display.show(chr(c) if c>32 else " ")
sleep(DELAY)
def leppard():
try:
print("CP:",repr(cell[0:CP+8])[11:-1])
except:
print("CP:",repr(cell[CP-8:CP+8])[11:-1])
def debug():
print("{0}PC={1} CP={2} [CP]={3} LV={4} {5}#{6}: {7}"
.format("["*len(stack), PC, CP, cell[CP], LEVEL, repr(stack),
len(stack), "END OF LINE" if PC>=len(prog) else prog[PC]))
if "C" in PRAGMA: leppard()
def crash(text):
global CRASHED
CRASHED = True
print("\n[ERROR]",text,"... Debugging.")
display.show(Image.HEART,wait=False)
try:
prog = open(PROGNAME).read()
except Exception as e:
prog = DEFPROG
with open(PROGNAME,"wt") as f: f.write(prog)
print("{0}. Using Hello World.\n".format(e))
reset()
CRASHED = False # Semaphore indicating an interpreter error.
LEVEL = 0 # When zero, we are executing primitives.
# When non-zero, we are seeking our matching ]
PC = 0 # Program Counter
CP = 0 # Cell Pointer
cell = bytearray(CELLS) # Fixed memory of byte sized cells.
stack = [] # [] stack. Allocate last because it grows and shrinks.
uart.init(115200)
print("Brainfox Initalized.")
if button_b.is_pressed():
PRAGMA = input("Pragmas: ").upper()
if not "R" in PRAGMA:
try:
file = open(INPUTNAME)
except:
PRAGMA += "R"
DEBUG = "D" in PRAGMA
if "F" in PRAGMA: DELAY = 0
display.show(Image.HAPPY, wait=False)
collect()
print("Prog size: {0}; Free: {1}B ({2} stk)".format(len(prog),mem_free(),int(mem_free()/4)))
while True:
if PC >= len(prog):
if LEVEL: crash("Unbalanced [")
break
if DEBUG or button_a.is_pressed(): debug()
if "T" in PRAGMA:
display.show(prog[PC])
sleep(DELAY)
if prog[PC] in "[]":
if prog[PC] == "[":
stack += [PC]
if cell[CP] == 0 and not LEVEL:
LEVEL = len(stack)
else:
if not (cell[CP] == 0) and not LEVEL:
PC = stack[-1]+1
continue
if stack == []:
crash("Unbalanced ]")
break
else:
stack = stack[:-1]
if len(stack) < LEVEL: LEVEL = 0
if DEBUG: debug()
if not LEVEL:
if prog[PC] == ">":
CP +=1
if CP+1 >= CELLS: CP = 0
elif prog[PC] == "<":
CP -= 1
if CP < 0: CP = CELLS - 1
elif prog[PC] == "+":
cell[CP] = cell[CP] + 1
elif prog[PC] == "-":
cell[CP] = cell[CP] - 1
elif prog[PC] == ",":
cell[CP] = ord(get_input())
elif prog[PC] == ".":
bfprint(cell[CP])
elif "X" in PRAGMA and prog[PC] == "#":
DEBUG = not DEBUG
elif "X" in PRAGMA and prog[PC] == "|":
sleep(DELAY)
if CRASHED or button_b.is_pressed():
break
else:
PC+=1
try: file.close()
except: pass
print("\n--")
debug()
leppard()
print("* Game Over. Hold A to upload or press B to reset *")
while not button_a.is_pressed() and not button_b.is_pressed(): sleep(10)
reset()
Comments