# 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()