Advertisement
alynna

Brainfox: Brainf*ck interpreter for Microbit

Aug 18th, 2017
292
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.13 KB | None | 0 0
  1. # Brainfox: A brainf*ck interpreter for microbit.
  2. # (C) 2017 Alynna Trypnotk, GPL3
  3. # Be selective here to save RAM
  4. from microbit import uart, display, button_a, button_b, sleep, Image, reset
  5. from gc import collect, mem_free
  6. from os import remove
  7. collect() # DEFPROG is Hello World.  These strings are defined here to get them in flash, not RAM.
  8. DEFPROG = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."
  9. PROGNAME = "prog.bf"
  10. INPUTNAME = "input.bf"
  11. PRIMS = "+-<>[],.#|"
  12. PRAGMA = "FX"          # Default PRAGMA and DELAY.
  13. DELAY = 100             # You can set these freely.
  14. CELLS = 256             # CELLS available. This is configurabale
  15.                         # and will cost its value in bytes.
  16. def receive():
  17.     global PRAGMA
  18.     print("* Enter program, [/ ENTER] to submit *")
  19.     DC = 0
  20.     getProg = 2
  21.     while True:
  22.         AC = str(input())
  23.         if getProg == 2:    # Prevents null programs.
  24.             file = open(PROGNAME, "wt")
  25.             getProg = 1
  26.         if AC[0] == '/':
  27.             PRAGMA = AC[1:].upper() if len(AC)>1 else PRAGMA
  28.             break
  29.         if AC[0] == '_':
  30.             getProg = 0
  31.             file.close()
  32.             file = open(INPUTNAME, "wt")
  33.             DC = 0
  34.             continue
  35.         if getProg: AC = ''.join([x for x in AC if x in PRIMS])
  36.         DC += len(AC)
  37.         file.write(str(AC))
  38.         print(DC)
  39.         collect()
  40.     file.close()
  41. if button_a.is_pressed():
  42.     try:
  43.         remove(PROGNAME)
  44.         remove(INPUTNAME)
  45.     except: pass
  46.     display.show(Image.PACMAN, wait=False)
  47.     receive()
  48.     reset()
  49. def get_input():
  50.     if "R" in PRAGMA:
  51.         while not uart.any(): sleep(1)
  52.         return str(uart.read(1),"ascii");
  53.     else:
  54.         x = file.read(1)
  55.         return '\0' if x == "" else x
  56. def bfprint(c):
  57.     print(chr(c),sep='',end='')
  58.     if not "T" in PRAGMA:
  59.         display.show(chr(c) if c>32 else " ")
  60.         sleep(DELAY)
  61. def leppard():
  62.     try:
  63.         print("CP:",repr(cell[0:CP+8])[11:-1])
  64.     except:
  65.         print("CP:",repr(cell[CP-8:CP+8])[11:-1])
  66. def debug():
  67.     print("{0}PC={1} CP={2} [CP]={3} LV={4} {5}#{6}: {7}"
  68.         .format("["*len(stack), PC, CP, cell[CP], LEVEL, repr(stack),
  69.                 len(stack), "END OF LINE" if PC>=len(prog) else prog[PC]))
  70.     if "C" in PRAGMA: leppard()
  71. def crash(text):
  72.     global CRASHED
  73.     CRASHED = True
  74.     print("\n[ERROR]",text,"... Debugging.")
  75. display.show(Image.HEART,wait=False)
  76. try:
  77.     prog = open(PROGNAME).read()
  78. except Exception as e:
  79.     prog = DEFPROG
  80.     with open(PROGNAME,"wt") as f: f.write(prog)
  81.     print("{0}. Using Hello World.\n".format(e))
  82.     reset()
  83. CRASHED = False         # Semaphore indicating an interpreter error.
  84. LEVEL = 0               # When zero, we are executing primitives.
  85.                         # When non-zero, we are seeking our matching ]
  86. PC = 0                  # Program Counter
  87. CP = 0                  # Cell Pointer
  88. cell = bytearray(CELLS) # Fixed memory of byte sized cells.
  89. stack = []              # [] stack.  Allocate last because it grows and shrinks.
  90. uart.init(115200)
  91. print("Brainfox Initalized.")
  92. if button_b.is_pressed():
  93.     PRAGMA = input("Pragmas: ").upper()
  94. if not "R" in PRAGMA:
  95.     try:
  96.         file = open(INPUTNAME)
  97.     except:
  98.         PRAGMA += "R"
  99. DEBUG = "D" in PRAGMA
  100. if "F" in PRAGMA: DELAY = 0
  101. display.show(Image.HAPPY, wait=False)
  102. collect()
  103. print("Prog size: {0}; Free: {1}B ({2} stk)".format(len(prog),mem_free(),int(mem_free()/4)))
  104. while True:
  105.     if PC >= len(prog):
  106.         if LEVEL: crash("Unbalanced [")
  107.         break
  108.     if DEBUG or button_a.is_pressed(): debug()
  109.     if "T" in PRAGMA:
  110.         display.show(prog[PC])
  111.         sleep(DELAY)
  112.     if prog[PC] in "[]":
  113.         if prog[PC] == "[":
  114.             stack += [PC]
  115.             if cell[CP] == 0 and not LEVEL:
  116.                 LEVEL = len(stack)
  117.         else:
  118.             if not (cell[CP] == 0) and not LEVEL:
  119.                 PC = stack[-1]+1
  120.                 continue
  121.             if stack == []:
  122.                 crash("Unbalanced ]")
  123.                 break
  124.             else:
  125.                 stack = stack[:-1]
  126.             if len(stack) < LEVEL: LEVEL = 0
  127.         if DEBUG: debug()
  128.     if not LEVEL:
  129.         if prog[PC] == ">":
  130.             CP +=1
  131.             if CP+1 >= CELLS: CP = 0
  132.         elif prog[PC] == "<":
  133.             CP -= 1
  134.             if CP < 0: CP = CELLS - 1
  135.         elif prog[PC] == "+":
  136.             cell[CP] = cell[CP] + 1
  137.         elif prog[PC] == "-":
  138.             cell[CP] = cell[CP] - 1
  139.         elif prog[PC] == ",":
  140.             cell[CP] = ord(get_input())
  141.         elif prog[PC] == ".":
  142.             bfprint(cell[CP])
  143.         elif "X" in PRAGMA and prog[PC] == "#":
  144.             DEBUG = not DEBUG
  145.         elif "X" in PRAGMA and prog[PC] == "|":
  146.             sleep(DELAY)
  147.     if CRASHED or button_b.is_pressed():
  148.         break
  149.     else:
  150.         PC+=1
  151. try:    file.close()
  152. except: pass
  153. print("\n--")
  154. debug()
  155. leppard()
  156. print("* Game Over. Hold A to upload or press B to reset *")
  157. while not button_a.is_pressed() and not button_b.is_pressed(): sleep(10)
  158. reset()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement