View difference between Paste ID: 3MTWadiL and HXSMxugM
SHOW: | | - or go back to the newest paste.
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()