bffuck 3.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bffuck/__init__.py +42 -0
- bffuck/bffuck.py +1092 -0
- bffuck-3.0.1.dist-info/METADATA +172 -0
- bffuck-3.0.1.dist-info/RECORD +7 -0
- bffuck-3.0.1.dist-info/WHEEL +5 -0
- bffuck-3.0.1.dist-info/entry_points.txt +2 -0
- bffuck-3.0.1.dist-info/top_level.txt +1 -0
bffuck/__init__.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from .bffuck import BFFuck
|
|
2
|
+
import argparse, sys
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def _cli():
|
|
6
|
+
ap = argparse.ArgumentParser(
|
|
7
|
+
description="BFFuck CLI tool\nMakes Brainfucking Easier!\nEnjoy brainfucking with the tool\nIf you encounter any error, you can post an issue at GitHub."
|
|
8
|
+
)
|
|
9
|
+
ap.add_argument("program", help="BFFuck program file name")
|
|
10
|
+
ap.add_argument(
|
|
11
|
+
"--playfield", "-p", help="Number of bytes for playfield, must be an integer"
|
|
12
|
+
)
|
|
13
|
+
ap.add_argument(
|
|
14
|
+
"--output",
|
|
15
|
+
"-o",
|
|
16
|
+
help="Output brainfuck file name, default is the standard output",
|
|
17
|
+
)
|
|
18
|
+
ap.add_argument("--byte", "-b", help="Use multi-byte integers (1 or 2 or 3 bytes)")
|
|
19
|
+
a = ap.parse_args()
|
|
20
|
+
program = a.program
|
|
21
|
+
with open(program, "r") as f:
|
|
22
|
+
code = f.read()
|
|
23
|
+
playfield = 15
|
|
24
|
+
if a.playfield:
|
|
25
|
+
playfield = int(a.playfield)
|
|
26
|
+
if a.byte:
|
|
27
|
+
byte = int(a.byte)
|
|
28
|
+
try:
|
|
29
|
+
bf = BFFuck(playfield).compile(code, byte=int(a.byte))
|
|
30
|
+
except Exception as err:
|
|
31
|
+
print("Compilation error: %s" % str(err))
|
|
32
|
+
sys.exit(1)
|
|
33
|
+
else:
|
|
34
|
+
file = sys.stdout
|
|
35
|
+
if a.output:
|
|
36
|
+
file = open(a.output, "w")
|
|
37
|
+
print(bf, file=file)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
if __name__ == "__main__":
|
|
41
|
+
_cli()
|
|
42
|
+
|
bffuck/bffuck.py
ADDED
|
@@ -0,0 +1,1092 @@
|
|
|
1
|
+
import re, os
|
|
2
|
+
|
|
3
|
+
multipliers = ["[>++++++++++<-]>", "[<++++++++++>-]<"]
|
|
4
|
+
expanders = {
|
|
5
|
+
1: {">": ">", "<": "<", "+": "+", "-": "-", "[": "[", "]": "]"},
|
|
6
|
+
2: {
|
|
7
|
+
">": ">>>>",
|
|
8
|
+
"<": "<<<<",
|
|
9
|
+
"+": ">+<+[>-]>[->>+<]<<",
|
|
10
|
+
"-": ">+<[>-]>[->>-<]<<-",
|
|
11
|
+
"[": ">+<[>-]>[->+>[<-]<[<]>[-<+>]]<-[+<",
|
|
12
|
+
"]": ">+<[>-]>[->+>[<-]<[<]>[-<+>]]<-]<",
|
|
13
|
+
},
|
|
14
|
+
4: {
|
|
15
|
+
">": ">>>>>",
|
|
16
|
+
"<": "<<<<<",
|
|
17
|
+
"+": "+[<+>>>>>+<<<<-]<[>+<-]+>>>>>[<<<<<->>>>>[-]]<<<<<[->>+[<<+>>>>>+<<<-]<<[>>+<<-]+>>>>>[<<<<<->>>>>[-]]<<<<<[->>>+[<<<+>>>>>+<<-]<<<[>>>+<<<-]+>>>>>[<<<<<->>>>>[-]]<<<<<[->>>>+<<<<]]]>",
|
|
18
|
+
"-": "[<+>>>>>+<<<<-]<[>+<-]+>>>>>[<<<<<->>>>>[-]]<<<<<[->>[<<+>>>>>+<<<-]<<[>>+<<-]+>>>>>[<<<<<->>>>>[-]]<<<<<[->>>[<<<+>>>>>+<<-]<<<[>>>+<<<-]+>>>>>[<<<<<->>>>>[-]]<<<<<[->>>>-<<<<]>>>-<<<]>>-<<]>-",
|
|
19
|
+
"[": "[>>>>+>>>>>+<<<<<<<<<-]>>>>>>>>>[<<<<<<<<<+>>>>>>>>>-]<<<<<[[-]<<<<<+>>>>>]<<<[>>>+>>>>>+<<<<<<<<-]>>>>>>>>[<<<<<<<<+>>>>>>>>-]<<<<<[[-]<<<<<+>>>>>]<<[>>+>>>>>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<<<<<[[-]<<<<<+>>>>>]<[>+>>>>>+<<<<<<-]>>>>>>[<<<<<<+>>>>>>-]<<<<<[[-]<<<<<+>>>>>]<<<<<[[-]>",
|
|
20
|
+
"]": "[>>>>+>>>>>+<<<<<<<<<-]>>>>>>>>>[<<<<<<<<<+>>>>>>>>>-]<<<<<[[-]<<<<<+>>>>>]<<<[>>>+>>>>>+<<<<<<<<-]>>>>>>>>[<<<<<<<<+>>>>>>>>-]<<<<<[[-]<<<<<+>>>>>]<<[>>+>>>>>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<<<<<[[-]<<<<<+>>>>>]<[>+>>>>>+<<<<<<-]>>>>>>[<<<<<<+>>>>>>-]<<<<<[[-]<<<<<+>>>>>]<<<<<]>",
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _power_series(k, m):
|
|
26
|
+
x = int(k)
|
|
27
|
+
if not k:
|
|
28
|
+
return ""
|
|
29
|
+
if not x and len(k) < 2:
|
|
30
|
+
return ""
|
|
31
|
+
if len(k) < 2:
|
|
32
|
+
return "+" * x
|
|
33
|
+
top, rest = k[0], k[1:]
|
|
34
|
+
return "+" * int(top) + multipliers[m] + _power_series(rest, 1 - m)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def power_series(x):
|
|
38
|
+
if not x:
|
|
39
|
+
return ""
|
|
40
|
+
if len(str(x)) & 1:
|
|
41
|
+
return _power_series(str(x), 0)
|
|
42
|
+
return _power_series(str(x), 0) + "[<+>-]<"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def getstr(x):
|
|
46
|
+
normal, power = "+" * x, power_series(x)
|
|
47
|
+
if len(normal) < len(power):
|
|
48
|
+
return normal
|
|
49
|
+
return power
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class BFFuck(object):
|
|
53
|
+
"""Main implementation of BFFuck, a compiler making brainfucking easier"""
|
|
54
|
+
|
|
55
|
+
def __init__(self, playfield=15):
|
|
56
|
+
"""Init object, playfield is the number of bytes used for temporary memory, the lesser the playfield is, the faster the final program is, but setting playfield to a number that is too small causes problems, especially if you want to use integer output."""
|
|
57
|
+
self.valdict = {} # Variable address
|
|
58
|
+
self.bf = "" # Brainfuck program
|
|
59
|
+
self.ptr = 0 # Current pointer
|
|
60
|
+
self.mem = playfield # Leftmost unused memory
|
|
61
|
+
self.stack = [] # Stack for while loop
|
|
62
|
+
self.ifstack = [] # Stack for if statement
|
|
63
|
+
self.ifvarstack = []
|
|
64
|
+
self.whilevarstack = []
|
|
65
|
+
self.haveelse = []
|
|
66
|
+
self.playfield = playfield
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
def movptr(self, pos):
|
|
70
|
+
"""Creates brainfuck that moves the pointer to a specific position"""
|
|
71
|
+
if pos > self.ptr:
|
|
72
|
+
p = ">" * (pos - self.ptr)
|
|
73
|
+
self.ptr = pos
|
|
74
|
+
return p
|
|
75
|
+
if pos < self.ptr:
|
|
76
|
+
p = "<" * (self.ptr - pos)
|
|
77
|
+
self.ptr = pos
|
|
78
|
+
return p
|
|
79
|
+
return ""
|
|
80
|
+
|
|
81
|
+
def program(self, code):
|
|
82
|
+
"""Compile one line of strict BFFuck program"""
|
|
83
|
+
if "=" in code:
|
|
84
|
+
v = code.split("=")
|
|
85
|
+
if len(v) > 2:
|
|
86
|
+
raise Exception("BFFuck currently does not support multiple ='s")
|
|
87
|
+
val, stmt = v[0], v[1]
|
|
88
|
+
if val in self.valdict:
|
|
89
|
+
self.bf += self.movptr(self.valdict[val])
|
|
90
|
+
else:
|
|
91
|
+
self.bf += self.movptr(self.mem)
|
|
92
|
+
self.valdict[val] = self.mem
|
|
93
|
+
self.mem += 2
|
|
94
|
+
if stmt == "inc":
|
|
95
|
+
self.bf += ","
|
|
96
|
+
elif stmt == "in":
|
|
97
|
+
tmppos = self.ptr
|
|
98
|
+
self.bf += self.movptr(0)
|
|
99
|
+
self.bf += "[-]>[-]+[[-]>[-],[+[-----------[>[-]++++++[<------>-]<--<<[->>++++++++++<<]>>[-<<+>>]<+>]]]<]<" # https://esolangs.org/wiki/Brainfuck_algorithms#Input_a_decimal_number
|
|
100
|
+
self.bf += (
|
|
101
|
+
self.movptr(tmppos)
|
|
102
|
+
+ "[-]"
|
|
103
|
+
+ self.movptr(0)
|
|
104
|
+
+ "["
|
|
105
|
+
+ self.movptr(tmppos)
|
|
106
|
+
+ "+"
|
|
107
|
+
+ self.movptr(0)
|
|
108
|
+
+ "-]"
|
|
109
|
+
)
|
|
110
|
+
elif stmt.isdigit():
|
|
111
|
+
self.bf += (
|
|
112
|
+
"[-]"
|
|
113
|
+
+ self.movptr(0)
|
|
114
|
+
+ getstr(int(stmt))
|
|
115
|
+
+ "["
|
|
116
|
+
+ self.movptr(self.valdict[val])
|
|
117
|
+
+ "+"
|
|
118
|
+
+ self.movptr(0)
|
|
119
|
+
+ "-"
|
|
120
|
+
+ "]"
|
|
121
|
+
)
|
|
122
|
+
else:
|
|
123
|
+
if stmt in self.valdict:
|
|
124
|
+
self.bf += (
|
|
125
|
+
self.movptr(self.valdict[val])
|
|
126
|
+
+ "[-]"
|
|
127
|
+
+ self.movptr(self.valdict[stmt])
|
|
128
|
+
)
|
|
129
|
+
self.bf += (
|
|
130
|
+
"["
|
|
131
|
+
+ self.movptr(self.valdict[val])
|
|
132
|
+
+ "+"
|
|
133
|
+
+ self.movptr(0)
|
|
134
|
+
+ "+"
|
|
135
|
+
+ self.movptr(self.valdict[stmt])
|
|
136
|
+
+ "-"
|
|
137
|
+
+ "]"
|
|
138
|
+
+ self.movptr(0)
|
|
139
|
+
+ "["
|
|
140
|
+
+ self.movptr(self.valdict[stmt])
|
|
141
|
+
+ "+"
|
|
142
|
+
+ self.movptr(0)
|
|
143
|
+
+ "-"
|
|
144
|
+
+ "]"
|
|
145
|
+
)
|
|
146
|
+
else:
|
|
147
|
+
raise Exception("Variable not found")
|
|
148
|
+
else:
|
|
149
|
+
if code.startswith("while("):
|
|
150
|
+
if not (code.endswith(")")):
|
|
151
|
+
raise Exception("Unmatched bracket")
|
|
152
|
+
else:
|
|
153
|
+
vn = code[6:-1]
|
|
154
|
+
if not vn.isdigit():
|
|
155
|
+
if vn not in self.valdict:
|
|
156
|
+
raise Exception("Variable not found")
|
|
157
|
+
else:
|
|
158
|
+
self.bf += self.movptr(self.valdict[vn])
|
|
159
|
+
self.bf += "["
|
|
160
|
+
self.stack.append(self.valdict[vn])
|
|
161
|
+
else:
|
|
162
|
+
if int(vn): # while(1) is equivalent to while(2), while(3), etc
|
|
163
|
+
self.valdict["0"] = self.mem
|
|
164
|
+
self.mem += 2
|
|
165
|
+
self.bf += self.movptr(self.valdict["0"]) + "+["
|
|
166
|
+
self.stack.append(self.valdict["0"])
|
|
167
|
+
else: # Skip program
|
|
168
|
+
self.temp = self.bf
|
|
169
|
+
self.stack.append(-1)
|
|
170
|
+
elif code.startswith(
|
|
171
|
+
"if("
|
|
172
|
+
): # https://esolangs.org/wiki/Brainfuck_algorithms#if_(x)_{_code_}
|
|
173
|
+
self.haveelse.append(False)
|
|
174
|
+
if not (code.endswith(")")):
|
|
175
|
+
raise Exception("Unmatched bracket")
|
|
176
|
+
else:
|
|
177
|
+
vn = code[3:-1]
|
|
178
|
+
x, y, z = self.mem, self.mem + 1, self.mem + 2
|
|
179
|
+
self.mem += 6
|
|
180
|
+
if not vn.isdigit():
|
|
181
|
+
if vn not in self.valdict:
|
|
182
|
+
raise Exception("Variable not found")
|
|
183
|
+
else:
|
|
184
|
+
self.bf += (
|
|
185
|
+
self.movptr(x)
|
|
186
|
+
+ "["
|
|
187
|
+
+ "-"
|
|
188
|
+
+ "]"
|
|
189
|
+
+ self.movptr(y)
|
|
190
|
+
+ "["
|
|
191
|
+
+ "-"
|
|
192
|
+
+ "]"
|
|
193
|
+
+ self.movptr(self.valdict[vn])
|
|
194
|
+
+ "["
|
|
195
|
+
+ self.movptr(x)
|
|
196
|
+
+ "+"
|
|
197
|
+
+ self.movptr(y)
|
|
198
|
+
+ "+"
|
|
199
|
+
+ self.movptr(self.valdict[vn])
|
|
200
|
+
+ "-"
|
|
201
|
+
+ "]"
|
|
202
|
+
+ self.movptr(x)
|
|
203
|
+
+ "["
|
|
204
|
+
+ self.movptr(self.valdict[vn])
|
|
205
|
+
+ "+"
|
|
206
|
+
+ self.movptr(x)
|
|
207
|
+
+ "-"
|
|
208
|
+
+ "]+"
|
|
209
|
+
+ self.movptr(y)
|
|
210
|
+
+ "["
|
|
211
|
+
)
|
|
212
|
+
self.ifstack.append(self.valdict[vn])
|
|
213
|
+
self.ifvarstack.append(x)
|
|
214
|
+
else:
|
|
215
|
+
self.ifvarstack.append(-1)
|
|
216
|
+
if int(vn):
|
|
217
|
+
self.ifstack.append(-1)
|
|
218
|
+
else:
|
|
219
|
+
self.temp = self.bf
|
|
220
|
+
self.ifstack.append(-2) # Skip program
|
|
221
|
+
if code == "endif":
|
|
222
|
+
if not self.ifstack:
|
|
223
|
+
raise Exception("End if without if")
|
|
224
|
+
prev = self.ifstack.pop()
|
|
225
|
+
x = self.ifvarstack.pop()
|
|
226
|
+
if prev == -2:
|
|
227
|
+
self.bf = self.temp + "]"
|
|
228
|
+
elif prev == -1:
|
|
229
|
+
pass
|
|
230
|
+
else:
|
|
231
|
+
if not self.haveelse[-1]:
|
|
232
|
+
self.bf += self.movptr(x + 1) + "[-]]"
|
|
233
|
+
else:
|
|
234
|
+
self.bf += self.movptr(x) + "-]"
|
|
235
|
+
self.haveelse.pop()
|
|
236
|
+
if code == "endwhile":
|
|
237
|
+
if not self.stack:
|
|
238
|
+
raise Exception("End while without while")
|
|
239
|
+
prev = self.stack.pop()
|
|
240
|
+
if prev == -1:
|
|
241
|
+
self.bf = self.temp
|
|
242
|
+
else:
|
|
243
|
+
self.bf += self.movptr(prev)
|
|
244
|
+
self.bf += "]"
|
|
245
|
+
if code == "else":
|
|
246
|
+
self.haveelse[-1] = True
|
|
247
|
+
if not self.ifstack:
|
|
248
|
+
raise Exception("Else without if")
|
|
249
|
+
prev = self.ifstack.pop()
|
|
250
|
+
x = self.ifvarstack.pop()
|
|
251
|
+
y = x + 1
|
|
252
|
+
z = prev
|
|
253
|
+
if prev == -2:
|
|
254
|
+
self.bf = self.temp + "]"
|
|
255
|
+
self.ifstack.append(-1)
|
|
256
|
+
elif prev == -1:
|
|
257
|
+
self.temp = self.bf
|
|
258
|
+
self.ifstack.append(-2)
|
|
259
|
+
else:
|
|
260
|
+
self.bf += (
|
|
261
|
+
self.movptr(x)
|
|
262
|
+
+ "-"
|
|
263
|
+
+ self.movptr(y)
|
|
264
|
+
+ "[-]]"
|
|
265
|
+
+ self.movptr(x)
|
|
266
|
+
+ "["
|
|
267
|
+
)
|
|
268
|
+
self.ifstack.append(z)
|
|
269
|
+
self.ifvarstack.append(x)
|
|
270
|
+
if code.startswith("outc("):
|
|
271
|
+
if not (code.endswith(")")):
|
|
272
|
+
raise Exception("Unmatched bracket")
|
|
273
|
+
else:
|
|
274
|
+
vn = code[5:-1]
|
|
275
|
+
if not vn.isdigit():
|
|
276
|
+
if vn not in self.valdict:
|
|
277
|
+
raise Exception("Variable not found")
|
|
278
|
+
else:
|
|
279
|
+
self.bf += self.movptr(self.valdict[vn])
|
|
280
|
+
self.bf += "."
|
|
281
|
+
else:
|
|
282
|
+
ivn = int(vn)
|
|
283
|
+
self.bf += self.movptr(0) + "[-]" + getstr(ivn) + ".[-]"
|
|
284
|
+
elif code.startswith("out("):
|
|
285
|
+
if not (code.endswith(")")):
|
|
286
|
+
raise Exception("Unmatched bracket")
|
|
287
|
+
else:
|
|
288
|
+
vn = code[4:-1]
|
|
289
|
+
if not vn.isdigit():
|
|
290
|
+
if vn not in self.valdict:
|
|
291
|
+
raise Exception("Variable not found")
|
|
292
|
+
else:
|
|
293
|
+
self.bf += self.movptr(self.valdict[vn])
|
|
294
|
+
self.bf += (
|
|
295
|
+
"["
|
|
296
|
+
+ self.movptr(0)
|
|
297
|
+
+ "+"
|
|
298
|
+
+ self.movptr(self.playfield - 1)
|
|
299
|
+
+ "+"
|
|
300
|
+
+ self.movptr(self.valdict[vn])
|
|
301
|
+
+ "-]"
|
|
302
|
+
)
|
|
303
|
+
self.bf += (
|
|
304
|
+
self.movptr(0)
|
|
305
|
+
+ ">[-]>[-]+>[-]+<[>[-<-<<[->+>+<<]>[-<+>]>>]++++++++++>[-]+>[-]>[-]>[-]<<<<<[->-[>+>>]>[[-<+>]+>+>>]<<<<<]>>-[-<<+>>]<[-]++++++++[-<++++++>]>>[-<<+>>]<<]<[.[-]<]<[-]"
|
|
306
|
+
) # https://esolangs.org/wiki/Brainfuck_algorithms#Print_value_of_cell_x_as_number_for_ANY_sized_cell_(eg_8bit,_100000bit_etc)
|
|
307
|
+
self.bf += (
|
|
308
|
+
self.movptr(self.playfield - 1)
|
|
309
|
+
+ "["
|
|
310
|
+
+ self.movptr(self.valdict[vn])
|
|
311
|
+
+ "+"
|
|
312
|
+
+ self.movptr(self.playfield - 1)
|
|
313
|
+
+ "-"
|
|
314
|
+
+ "]"
|
|
315
|
+
)
|
|
316
|
+
else:
|
|
317
|
+
ivn = int(vn)
|
|
318
|
+
self.bf += (
|
|
319
|
+
self.movptr(0)
|
|
320
|
+
+ "[-]"
|
|
321
|
+
+ getstr(ivn)
|
|
322
|
+
+ ">[-]>[-]+>[-]+<[>[-<-<<[->+>+<<]>[-<+>]>>]++++++++++>[-]+>[-]>[-]>[-]<<<<<[->-[>+>>]>[[-<+>]+>+>>]<<<<<]>>-[-<<+>>]<[-]++++++++[-<++++++>]>>[-<<+>>]<<]<[.[-]<]<[-]"
|
|
323
|
+
)
|
|
324
|
+
elif code.startswith("add("):
|
|
325
|
+
expr = code[4:-1]
|
|
326
|
+
w = expr.split(",")
|
|
327
|
+
if len(w) != 2:
|
|
328
|
+
raise Exception("add() needs 2 arguments")
|
|
329
|
+
else:
|
|
330
|
+
a, b = w[0], w[1]
|
|
331
|
+
if a in self.valdict:
|
|
332
|
+
if b.isdigit():
|
|
333
|
+
self.bf += self.movptr(self.valdict[a])
|
|
334
|
+
self.bf += "+" * int(b)
|
|
335
|
+
else:
|
|
336
|
+
if b in self.valdict:
|
|
337
|
+
self.bf += (
|
|
338
|
+
self.movptr(self.playfield - 1)
|
|
339
|
+
+ "[-]"
|
|
340
|
+
+ self.movptr(self.valdict[b])
|
|
341
|
+
+ "["
|
|
342
|
+
+ self.movptr(self.valdict[a])
|
|
343
|
+
+ "+"
|
|
344
|
+
+ self.movptr(self.playfield - 1)
|
|
345
|
+
+ "+"
|
|
346
|
+
+ self.movptr(self.valdict[b])
|
|
347
|
+
+ "-"
|
|
348
|
+
+ "]"
|
|
349
|
+
+ self.movptr(self.playfield - 1)
|
|
350
|
+
+ "["
|
|
351
|
+
+ self.movptr(self.valdict[b])
|
|
352
|
+
+ "+"
|
|
353
|
+
+ self.movptr(self.playfield - 1)
|
|
354
|
+
+ "-"
|
|
355
|
+
+ "]"
|
|
356
|
+
) # https://esolangs.org/wiki/Brainfuck_algorithms#x%C2%B4_=_x_+_y
|
|
357
|
+
else:
|
|
358
|
+
raise Exception("Variable not found")
|
|
359
|
+
else:
|
|
360
|
+
raise Exception("Variable not found")
|
|
361
|
+
elif code.startswith("sub("):
|
|
362
|
+
expr = code[4:-1]
|
|
363
|
+
w = expr.split(",")
|
|
364
|
+
if len(w) != 2:
|
|
365
|
+
raise Exception("sub() needs 2 arguments")
|
|
366
|
+
else:
|
|
367
|
+
a, b = w[0], w[1]
|
|
368
|
+
if a in self.valdict:
|
|
369
|
+
if b.isdigit():
|
|
370
|
+
self.bf += self.movptr(self.valdict[a])
|
|
371
|
+
self.bf += "-" * int(b)
|
|
372
|
+
else:
|
|
373
|
+
if b in self.valdict:
|
|
374
|
+
self.bf += (
|
|
375
|
+
self.movptr(self.playfield - 1)
|
|
376
|
+
+ "[-]"
|
|
377
|
+
+ self.movptr(self.valdict[b])
|
|
378
|
+
+ "["
|
|
379
|
+
+ self.movptr(self.valdict[a])
|
|
380
|
+
+ "-"
|
|
381
|
+
+ self.movptr(self.playfield - 1)
|
|
382
|
+
+ "+"
|
|
383
|
+
+ self.movptr(self.valdict[b])
|
|
384
|
+
+ "-"
|
|
385
|
+
+ "]"
|
|
386
|
+
+ self.movptr(self.playfield - 1)
|
|
387
|
+
+ "["
|
|
388
|
+
+ self.movptr(self.valdict[b])
|
|
389
|
+
+ "+"
|
|
390
|
+
+ self.movptr(self.playfield - 1)
|
|
391
|
+
+ "-"
|
|
392
|
+
+ "]"
|
|
393
|
+
) # https://esolangs.org/wiki/Brainfuck_algorithms#x%C2%B4_=_x_-_y
|
|
394
|
+
else:
|
|
395
|
+
raise Exception("Variable not found")
|
|
396
|
+
else:
|
|
397
|
+
raise Exception("Variable not found")
|
|
398
|
+
elif code.startswith("mul("):
|
|
399
|
+
expr = code[4:-1]
|
|
400
|
+
w = expr.split(",")
|
|
401
|
+
if len(w) != 2:
|
|
402
|
+
raise Exception("mul() needs 2 arguments")
|
|
403
|
+
else:
|
|
404
|
+
a, b = w[0], w[1]
|
|
405
|
+
tmppos = self.ptr
|
|
406
|
+
if a in self.valdict:
|
|
407
|
+
if b.isdigit():
|
|
408
|
+
self.bf += (
|
|
409
|
+
self.movptr(self.playfield - 3)
|
|
410
|
+
+ "[-]"
|
|
411
|
+
+ "+" * int(b)
|
|
412
|
+
+ self.movptr(self.playfield - 1)
|
|
413
|
+
+ "["
|
|
414
|
+
+ "-"
|
|
415
|
+
+ "]"
|
|
416
|
+
+ self.movptr(self.playfield - 2)
|
|
417
|
+
+ "["
|
|
418
|
+
+ "-"
|
|
419
|
+
+ "]"
|
|
420
|
+
+ self.movptr(self.valdict[a])
|
|
421
|
+
+ "["
|
|
422
|
+
+ self.movptr(self.playfield - 2)
|
|
423
|
+
+ "+"
|
|
424
|
+
+ self.movptr(self.valdict[a])
|
|
425
|
+
+ "-"
|
|
426
|
+
+ "]"
|
|
427
|
+
+ self.movptr(self.playfield - 2)
|
|
428
|
+
+ "["
|
|
429
|
+
+ self.movptr(self.playfield - 3)
|
|
430
|
+
+ "["
|
|
431
|
+
+ self.movptr(self.valdict[a])
|
|
432
|
+
+ "+"
|
|
433
|
+
+ self.movptr(self.playfield - 1)
|
|
434
|
+
+ "+"
|
|
435
|
+
+ self.movptr(self.playfield - 3)
|
|
436
|
+
+ "-"
|
|
437
|
+
+ "]"
|
|
438
|
+
+ self.movptr(self.playfield - 1)
|
|
439
|
+
+ "["
|
|
440
|
+
+ self.movptr(self.playfield - 3)
|
|
441
|
+
+ "+"
|
|
442
|
+
+ self.movptr(self.playfield - 1)
|
|
443
|
+
+ "-"
|
|
444
|
+
+ "]"
|
|
445
|
+
+ self.movptr(self.playfield - 2)
|
|
446
|
+
+ "-"
|
|
447
|
+
+ "]"
|
|
448
|
+
+ self.movptr(self.playfield - 3)
|
|
449
|
+
+ "[-]"
|
|
450
|
+
)
|
|
451
|
+
else:
|
|
452
|
+
if b in self.valdict:
|
|
453
|
+
self.bf += (
|
|
454
|
+
self.movptr(self.playfield - 1)
|
|
455
|
+
+ "["
|
|
456
|
+
+ "-"
|
|
457
|
+
+ "]"
|
|
458
|
+
+ self.movptr(self.playfield - 2)
|
|
459
|
+
+ "["
|
|
460
|
+
+ "-"
|
|
461
|
+
+ "]"
|
|
462
|
+
+ self.movptr(self.valdict[a])
|
|
463
|
+
+ "["
|
|
464
|
+
+ self.movptr(self.playfield - 2)
|
|
465
|
+
+ "+"
|
|
466
|
+
+ self.movptr(self.valdict[a])
|
|
467
|
+
+ "-"
|
|
468
|
+
+ "]"
|
|
469
|
+
+ self.movptr(self.playfield - 2)
|
|
470
|
+
+ "["
|
|
471
|
+
+ self.movptr(self.valdict[b])
|
|
472
|
+
+ "["
|
|
473
|
+
+ self.movptr(self.valdict[a])
|
|
474
|
+
+ "+"
|
|
475
|
+
+ self.movptr(self.playfield - 1)
|
|
476
|
+
+ "+"
|
|
477
|
+
+ self.movptr(self.valdict[b])
|
|
478
|
+
+ "-"
|
|
479
|
+
+ "]"
|
|
480
|
+
+ self.movptr(self.playfield - 1)
|
|
481
|
+
+ "["
|
|
482
|
+
+ self.movptr(self.valdict[b])
|
|
483
|
+
+ "+"
|
|
484
|
+
+ self.movptr(self.playfield - 1)
|
|
485
|
+
+ "-"
|
|
486
|
+
+ "]"
|
|
487
|
+
+ self.movptr(self.playfield - 2)
|
|
488
|
+
+ "-"
|
|
489
|
+
+ "]"
|
|
490
|
+
)
|
|
491
|
+
else:
|
|
492
|
+
raise Exception("Variable not found")
|
|
493
|
+
else:
|
|
494
|
+
raise Exception("Variable not found")
|
|
495
|
+
elif code.startswith("lt("):
|
|
496
|
+
expr = code[3:-1]
|
|
497
|
+
w = expr.split(",")
|
|
498
|
+
if len(w) != 2:
|
|
499
|
+
raise Exception("lt() needs 2 arguments")
|
|
500
|
+
else:
|
|
501
|
+
a, b = w[0], w[1]
|
|
502
|
+
tmppos = self.ptr
|
|
503
|
+
if a in self.valdict:
|
|
504
|
+
post = False
|
|
505
|
+
if b.isdigit():
|
|
506
|
+
self.bf += self.movptr(self.playfield - 1) + "+" * int(b)
|
|
507
|
+
b = self.playfield - 1
|
|
508
|
+
post = True
|
|
509
|
+
else:
|
|
510
|
+
if b in self.valdict:
|
|
511
|
+
b = self.valdict[b]
|
|
512
|
+
else:
|
|
513
|
+
raise Exception("Variable not found")
|
|
514
|
+
self.bf += (
|
|
515
|
+
self.movptr(0)
|
|
516
|
+
+ "["
|
|
517
|
+
+ "-"
|
|
518
|
+
+ "]"
|
|
519
|
+
+ self.movptr(1)
|
|
520
|
+
+ "["
|
|
521
|
+
+ "-"
|
|
522
|
+
+ "]"
|
|
523
|
+
+ ">"
|
|
524
|
+
+ "["
|
|
525
|
+
+ "-"
|
|
526
|
+
+ "]"
|
|
527
|
+
+ "+"
|
|
528
|
+
+ ">"
|
|
529
|
+
+ "["
|
|
530
|
+
+ "-"
|
|
531
|
+
+ "]"
|
|
532
|
+
+ "<"
|
|
533
|
+
+ "<"
|
|
534
|
+
+ self.movptr(b)
|
|
535
|
+
+ "["
|
|
536
|
+
+ self.movptr(0)
|
|
537
|
+
+ "+"
|
|
538
|
+
+ self.movptr(1)
|
|
539
|
+
+ "+"
|
|
540
|
+
+ self.movptr(b)
|
|
541
|
+
+ "-"
|
|
542
|
+
+ "]"
|
|
543
|
+
+ self.movptr(0)
|
|
544
|
+
+ "["
|
|
545
|
+
+ self.movptr(b)
|
|
546
|
+
+ "+"
|
|
547
|
+
+ self.movptr(0)
|
|
548
|
+
+ "-"
|
|
549
|
+
+ "]"
|
|
550
|
+
+ self.movptr(self.valdict[a])
|
|
551
|
+
+ "["
|
|
552
|
+
+ self.movptr(0)
|
|
553
|
+
+ "+"
|
|
554
|
+
+ self.movptr(self.valdict[a])
|
|
555
|
+
+ "-"
|
|
556
|
+
+ "]"
|
|
557
|
+
+ "+"
|
|
558
|
+
+ self.movptr(1)
|
|
559
|
+
+ "["
|
|
560
|
+
+ ">"
|
|
561
|
+
+ "-"
|
|
562
|
+
+ "]"
|
|
563
|
+
+ ">"
|
|
564
|
+
+ "["
|
|
565
|
+
+ "<"
|
|
566
|
+
+ self.movptr(self.valdict[a])
|
|
567
|
+
+ "-"
|
|
568
|
+
+ self.movptr(0)
|
|
569
|
+
+ "["
|
|
570
|
+
+ "-"
|
|
571
|
+
+ "]"
|
|
572
|
+
+ self.movptr(1)
|
|
573
|
+
+ ">"
|
|
574
|
+
+ "-"
|
|
575
|
+
+ ">"
|
|
576
|
+
+ "]"
|
|
577
|
+
+ "<"
|
|
578
|
+
+ "+"
|
|
579
|
+
+ "<"
|
|
580
|
+
+ self.movptr(0)
|
|
581
|
+
+ "["
|
|
582
|
+
+ self.movptr(1)
|
|
583
|
+
+ "-"
|
|
584
|
+
+ "["
|
|
585
|
+
+ ">"
|
|
586
|
+
+ "-"
|
|
587
|
+
+ "]"
|
|
588
|
+
+ ">"
|
|
589
|
+
+ "["
|
|
590
|
+
+ "<"
|
|
591
|
+
+ self.movptr(self.valdict[a])
|
|
592
|
+
+ "-"
|
|
593
|
+
+ self.movptr(0)
|
|
594
|
+
+ "["
|
|
595
|
+
+ "-"
|
|
596
|
+
+ "]"
|
|
597
|
+
+ "+"
|
|
598
|
+
+ self.movptr(1)
|
|
599
|
+
+ ">"
|
|
600
|
+
+ "-"
|
|
601
|
+
+ ">"
|
|
602
|
+
+ "]"
|
|
603
|
+
+ "<"
|
|
604
|
+
+ "+"
|
|
605
|
+
+ "<"
|
|
606
|
+
+ self.movptr(0)
|
|
607
|
+
+ "-"
|
|
608
|
+
+ "]"
|
|
609
|
+
) # https://esolangs.org/wiki/Brainfuck_algorithms#x%C2%B4_=_x_%3C_y
|
|
610
|
+
if post:
|
|
611
|
+
self.bf += self.movptr(b) + "[-]"
|
|
612
|
+
else:
|
|
613
|
+
raise Exception("Variable not found")
|
|
614
|
+
elif code.startswith("eq("):
|
|
615
|
+
expr = code[3:-1]
|
|
616
|
+
w = expr.split(",")
|
|
617
|
+
if len(w) != 2:
|
|
618
|
+
raise Exception("eq() needs 2 arguments")
|
|
619
|
+
else:
|
|
620
|
+
a, b = w[0], w[1]
|
|
621
|
+
tmppos = self.ptr
|
|
622
|
+
if a in self.valdict:
|
|
623
|
+
post = False
|
|
624
|
+
if b.isdigit():
|
|
625
|
+
self.bf += self.movptr(self.playfield - 3) + "+" * int(b)
|
|
626
|
+
b = self.playfield - 3
|
|
627
|
+
post = True
|
|
628
|
+
else:
|
|
629
|
+
if b in self.valdict:
|
|
630
|
+
b = self.valdict[b]
|
|
631
|
+
else:
|
|
632
|
+
raise Exception("Variable not found")
|
|
633
|
+
self.bf += (
|
|
634
|
+
self.movptr(self.playfield - 1)
|
|
635
|
+
+ "["
|
|
636
|
+
+ "-"
|
|
637
|
+
+ "]"
|
|
638
|
+
+ self.movptr(self.playfield - 2)
|
|
639
|
+
+ "["
|
|
640
|
+
+ "-"
|
|
641
|
+
+ "]"
|
|
642
|
+
+ self.movptr(self.valdict[a])
|
|
643
|
+
+ "["
|
|
644
|
+
+ self.movptr(self.playfield - 2)
|
|
645
|
+
+ "+"
|
|
646
|
+
+ self.movptr(self.valdict[a])
|
|
647
|
+
+ "-"
|
|
648
|
+
+ "]"
|
|
649
|
+
+ "+"
|
|
650
|
+
+ self.movptr(b)
|
|
651
|
+
+ "["
|
|
652
|
+
+ self.movptr(self.playfield - 2)
|
|
653
|
+
+ "-"
|
|
654
|
+
+ self.movptr(self.playfield - 1)
|
|
655
|
+
+ "+"
|
|
656
|
+
+ self.movptr(b)
|
|
657
|
+
+ "-"
|
|
658
|
+
+ "]"
|
|
659
|
+
+ self.movptr(self.playfield - 1)
|
|
660
|
+
+ "["
|
|
661
|
+
+ self.movptr(b)
|
|
662
|
+
+ "+"
|
|
663
|
+
+ self.movptr(self.playfield - 1)
|
|
664
|
+
+ "-"
|
|
665
|
+
+ "]"
|
|
666
|
+
+ self.movptr(self.playfield - 2)
|
|
667
|
+
+ "["
|
|
668
|
+
+ self.movptr(self.valdict[a])
|
|
669
|
+
+ "-"
|
|
670
|
+
+ self.movptr(self.playfield - 2)
|
|
671
|
+
+ "["
|
|
672
|
+
+ "-"
|
|
673
|
+
+ "]"
|
|
674
|
+
+ "]"
|
|
675
|
+
) # https://esolangs.org/wiki/Brainfuck_algorithms#x%C2%B4_=_x_==_y
|
|
676
|
+
if post:
|
|
677
|
+
self.bf += self.movptr(b) + "[-]"
|
|
678
|
+
else:
|
|
679
|
+
raise Exception("Variable not found")
|
|
680
|
+
elif code.startswith("mod("):
|
|
681
|
+
expr = code[4:-1]
|
|
682
|
+
w = expr.split(",")
|
|
683
|
+
if len(w) != 2:
|
|
684
|
+
raise Exception("mod() needs 2 arguments")
|
|
685
|
+
else:
|
|
686
|
+
a, b = w[0], w[1]
|
|
687
|
+
if a in self.valdict:
|
|
688
|
+
self.bf += (
|
|
689
|
+
self.movptr(self.valdict[a])
|
|
690
|
+
+ "["
|
|
691
|
+
+ self.movptr(1)
|
|
692
|
+
+ "+"
|
|
693
|
+
+ self.movptr(self.valdict[a])
|
|
694
|
+
+ "-]"
|
|
695
|
+
)
|
|
696
|
+
if b.isdigit():
|
|
697
|
+
self.bf += self.movptr(3) + "+" * int(b)
|
|
698
|
+
post = False
|
|
699
|
+
else:
|
|
700
|
+
if b in self.valdict:
|
|
701
|
+
self.bf += (
|
|
702
|
+
self.movptr(self.valdict[b])
|
|
703
|
+
+ "["
|
|
704
|
+
+ self.movptr(3)
|
|
705
|
+
+ "+"
|
|
706
|
+
+ self.movptr(self.playfield - 1)
|
|
707
|
+
+ "+"
|
|
708
|
+
+ self.movptr(self.valdict[b])
|
|
709
|
+
+ "-]"
|
|
710
|
+
)
|
|
711
|
+
post = True
|
|
712
|
+
else:
|
|
713
|
+
raise Exception("Variable not found")
|
|
714
|
+
self.bf += (
|
|
715
|
+
self.movptr(1)
|
|
716
|
+
+ "[>+>->+<[>]>[<+>-]<<[<]>-]"
|
|
717
|
+
+ self.movptr(2)
|
|
718
|
+
+ "[-]"
|
|
719
|
+
+ self.movptr(3)
|
|
720
|
+
+ "[-]"
|
|
721
|
+
+ self.movptr(4)
|
|
722
|
+
+ "["
|
|
723
|
+
+ self.movptr(self.valdict[a])
|
|
724
|
+
+ "+"
|
|
725
|
+
+ self.movptr(4)
|
|
726
|
+
+ "-]"
|
|
727
|
+
) # https://esolangs.org/wiki/Brainfuck_algorithms#Modulus_algorithm
|
|
728
|
+
if post:
|
|
729
|
+
self.bf += (
|
|
730
|
+
self.movptr(self.playfield - 1)
|
|
731
|
+
+ "["
|
|
732
|
+
+ self.movptr(self.valdict[b])
|
|
733
|
+
+ "+"
|
|
734
|
+
+ self.movptr(self.playfield - 1)
|
|
735
|
+
+ "-]"
|
|
736
|
+
)
|
|
737
|
+
else:
|
|
738
|
+
raise Exception("Variable not found")
|
|
739
|
+
elif code.startswith("print("):
|
|
740
|
+
if not (code.endswith(")")):
|
|
741
|
+
raise Exception("Unmatched bracket")
|
|
742
|
+
s = code[6:-1]
|
|
743
|
+
tmppos = self.ptr
|
|
744
|
+
self.bf += self.movptr(self.playfield - 2)
|
|
745
|
+
for i in s:
|
|
746
|
+
if ord(i) > 255:
|
|
747
|
+
raise Exception("print() only supports ASCII")
|
|
748
|
+
else:
|
|
749
|
+
self.bf += getstr(ord(i)) + "." + "[-]"
|
|
750
|
+
self.bf += self.movptr(tmppos)
|
|
751
|
+
elif code.startswith("ptr("):
|
|
752
|
+
if not (code.endswith(")")):
|
|
753
|
+
raise Exception("Unmatched bracket")
|
|
754
|
+
a, b = code[4:-1].split(",")
|
|
755
|
+
if a not in self.valdict or b not in self.valdict:
|
|
756
|
+
raise Exception("Variable not found")
|
|
757
|
+
self.bf += self.movptr(self.valdict[b]) + getstr(self.valdict[a])
|
|
758
|
+
elif code.startswith("bf "):
|
|
759
|
+
self.bf += code[4:-1]
|
|
760
|
+
elif code.startswith("ref("):
|
|
761
|
+
if not (code.endswith(")")):
|
|
762
|
+
raise Exception("Unmatched bracket")
|
|
763
|
+
a, b = code[4:-1].split(",")
|
|
764
|
+
if a not in self.valdict:
|
|
765
|
+
raise Exception("Variable not found")
|
|
766
|
+
if b.isdigit():
|
|
767
|
+
b = int(b)
|
|
768
|
+
self.bf += (
|
|
769
|
+
self.movptr(0)
|
|
770
|
+
+ "[-]"
|
|
771
|
+
+ self.movptr(b)
|
|
772
|
+
+ "["
|
|
773
|
+
+ self.movptr(0)
|
|
774
|
+
+ "+"
|
|
775
|
+
+ self.movptr(1)
|
|
776
|
+
+ "+"
|
|
777
|
+
+ self.movptr(b)
|
|
778
|
+
+ "-]"
|
|
779
|
+
+ self.movptr(self.valdict[a])
|
|
780
|
+
+ "[-]"
|
|
781
|
+
+ self.movptr(0)
|
|
782
|
+
+ "["
|
|
783
|
+
+ self.movptr(self.valdict[a])
|
|
784
|
+
+ "+"
|
|
785
|
+
+ self.movptr(0)
|
|
786
|
+
+ "-"
|
|
787
|
+
+ "]"
|
|
788
|
+
+ self.movptr(1)
|
|
789
|
+
+ "["
|
|
790
|
+
+ self.movptr(b)
|
|
791
|
+
+ "+"
|
|
792
|
+
+ self.movptr(1)
|
|
793
|
+
+ "-]"
|
|
794
|
+
)
|
|
795
|
+
else:
|
|
796
|
+
if b not in self.valdict:
|
|
797
|
+
raise Exception("Variable not found")
|
|
798
|
+
else:
|
|
799
|
+
self.bf += (
|
|
800
|
+
self.movptr(self.valdict[a])
|
|
801
|
+
+ "[-]"
|
|
802
|
+
+ self.movptr(self.playfield - 4)
|
|
803
|
+
+ "[-]"
|
|
804
|
+
+ self.movptr(self.valdict[b])
|
|
805
|
+
+ "["
|
|
806
|
+
+ self.movptr(self.playfield - 2)
|
|
807
|
+
+ "+"
|
|
808
|
+
+ self.movptr(self.playfield - 8)
|
|
809
|
+
+ "+"
|
|
810
|
+
+ self.movptr(self.valdict[b])
|
|
811
|
+
+ "-]"
|
|
812
|
+
+ self.movptr(self.playfield - 5)
|
|
813
|
+
+ "[-]++"
|
|
814
|
+
+ self.movptr(self.playfield - 1)
|
|
815
|
+
+ "[-]+"
|
|
816
|
+
+ self.movptr(self.playfield - 2)
|
|
817
|
+
+ "-" * (self.playfield - 2)
|
|
818
|
+
+ "["
|
|
819
|
+
+ self.movptr(self.playfield - 1)
|
|
820
|
+
+ "-[+>>-]>>[-]+<<--[++<<--]++>>>>"
|
|
821
|
+
+ self.movptr(self.playfield - 2)
|
|
822
|
+
+ "--]"
|
|
823
|
+
+ self.movptr(self.playfield - 1)
|
|
824
|
+
+ "-[+>>-]+<[>--[++<<--]++<+>>>>>-[+>>-]+<-]>--[++<<--]++>>>>"
|
|
825
|
+
+ self.movptr(self.playfield - 8)
|
|
826
|
+
+ "["
|
|
827
|
+
+ self.movptr(self.valdict[b])
|
|
828
|
+
+ "+"
|
|
829
|
+
+ self.movptr(self.playfield - 8)
|
|
830
|
+
+ "-]"
|
|
831
|
+
+ self.movptr(self.playfield - 6)
|
|
832
|
+
+ "["
|
|
833
|
+
+ self.movptr(self.valdict[a])
|
|
834
|
+
+ "+"
|
|
835
|
+
+ self.movptr(self.playfield - 1)
|
|
836
|
+
+ "-[+>>-]+<+>--[++<<--]++>>>>"
|
|
837
|
+
+ self.movptr(self.playfield - 6)
|
|
838
|
+
+ "-]"
|
|
839
|
+
)
|
|
840
|
+
elif code.startswith("set("):
|
|
841
|
+
if not (code.endswith(")")):
|
|
842
|
+
raise Exception("Unmatched bracket")
|
|
843
|
+
a, b = code[4:-1].split(",")
|
|
844
|
+
if not a.isdigit():
|
|
845
|
+
if a not in self.valdict:
|
|
846
|
+
raise Exception("Variable not found")
|
|
847
|
+
else:
|
|
848
|
+
self.bf += (
|
|
849
|
+
self.movptr(self.playfield - 11)
|
|
850
|
+
+ "[-]"
|
|
851
|
+
+ self.movptr(self.playfield - 10)
|
|
852
|
+
+ "[-]"
|
|
853
|
+
+ self.movptr(self.valdict[a])
|
|
854
|
+
+ "["
|
|
855
|
+
+ self.movptr(self.playfield - 11)
|
|
856
|
+
+ "+"
|
|
857
|
+
+ self.movptr(self.playfield - 10)
|
|
858
|
+
+ "+"
|
|
859
|
+
+ self.movptr(self.valdict[a])
|
|
860
|
+
+ "-]"
|
|
861
|
+
+ self.movptr(self.playfield - 11)
|
|
862
|
+
+ "["
|
|
863
|
+
+ self.movptr(self.valdict[a])
|
|
864
|
+
+ "+"
|
|
865
|
+
+ self.movptr(self.playfield - 11)
|
|
866
|
+
+ "-]"
|
|
867
|
+
)
|
|
868
|
+
else:
|
|
869
|
+
self.bf += self.movptr(self.playfield - 10) + "[-]" + getstr(int(a))
|
|
870
|
+
if b.isdigit():
|
|
871
|
+
b = int(b)
|
|
872
|
+
self.bf += (
|
|
873
|
+
self.movptr(b)
|
|
874
|
+
+ "[-]"
|
|
875
|
+
+ self.movptr(self.playfield - 10)
|
|
876
|
+
+ "["
|
|
877
|
+
+ self.movptr(b)
|
|
878
|
+
+ "+"
|
|
879
|
+
+ self.movptr(self.playfield - 10)
|
|
880
|
+
+ "-]"
|
|
881
|
+
)
|
|
882
|
+
else:
|
|
883
|
+
if b not in self.valdict:
|
|
884
|
+
raise Exception("Variable not found")
|
|
885
|
+
else:
|
|
886
|
+
self.bf += (
|
|
887
|
+
self.movptr(self.playfield - 4)
|
|
888
|
+
+ "[-]"
|
|
889
|
+
+ self.movptr(self.valdict[b])
|
|
890
|
+
+ "["
|
|
891
|
+
+ self.movptr(self.playfield - 2)
|
|
892
|
+
+ "+"
|
|
893
|
+
+ self.movptr(self.playfield - 8)
|
|
894
|
+
+ "+"
|
|
895
|
+
+ self.movptr(self.valdict[b])
|
|
896
|
+
+ "-]"
|
|
897
|
+
+ self.movptr(self.playfield - 5)
|
|
898
|
+
+ "[-]++"
|
|
899
|
+
+ self.movptr(self.playfield - 1)
|
|
900
|
+
+ "[-]+"
|
|
901
|
+
+ self.movptr(self.playfield - 2)
|
|
902
|
+
+ "-" * (self.playfield - 2)
|
|
903
|
+
+ "["
|
|
904
|
+
+ self.movptr(self.playfield - 1)
|
|
905
|
+
+ "-[+>>-]>>[-]+<<--[++<<--]++>>>>"
|
|
906
|
+
+ self.movptr(self.playfield - 2)
|
|
907
|
+
+ "--]"
|
|
908
|
+
+ self.movptr(self.playfield - 1)
|
|
909
|
+
+ "-[+>>-]+<[-]>--[++<<--]++<<<<<[>>>>>>>>>-[+>>-]+<+>--[++<<--]++<<<<<-]>>>>>>>>>"
|
|
910
|
+
+ self.movptr(self.playfield - 8)
|
|
911
|
+
+ "["
|
|
912
|
+
+ self.movptr(self.valdict[b])
|
|
913
|
+
+ "+"
|
|
914
|
+
+ self.movptr(self.playfield - 8)
|
|
915
|
+
+ "-]"
|
|
916
|
+
)
|
|
917
|
+
|
|
918
|
+
def join_semantically(self, strings):
|
|
919
|
+
res = strings[0]
|
|
920
|
+
for i, j in enumerate(strings):
|
|
921
|
+
if i == len(strings) - 1:
|
|
922
|
+
break
|
|
923
|
+
if j[-1].isalpha() and strings[i + 1][0].isalpha():
|
|
924
|
+
res += " " + strings[i + 1]
|
|
925
|
+
else:
|
|
926
|
+
res += strings[i + 1]
|
|
927
|
+
return res
|
|
928
|
+
|
|
929
|
+
def opt(self, prog):
|
|
930
|
+
"""Finally optimization!"""
|
|
931
|
+
curch = ""
|
|
932
|
+
curnum = 0
|
|
933
|
+
temp = []
|
|
934
|
+
prog += "@"
|
|
935
|
+
for i in prog:
|
|
936
|
+
if i == curch:
|
|
937
|
+
curnum += 1
|
|
938
|
+
else:
|
|
939
|
+
curnum += 1
|
|
940
|
+
temp.append((curnum, curch))
|
|
941
|
+
curch = i
|
|
942
|
+
curnum = 0
|
|
943
|
+
temp.append(("_", 0))
|
|
944
|
+
out = ""
|
|
945
|
+
dct = {"+": "-", ">": "<", "-": "+", "<": ">"}
|
|
946
|
+
curch = ""
|
|
947
|
+
curnum = 0
|
|
948
|
+
for i, j in temp:
|
|
949
|
+
if j in dct:
|
|
950
|
+
if curch in dct and j == dct[curch]:
|
|
951
|
+
curnum -= i
|
|
952
|
+
if curnum < 0:
|
|
953
|
+
curch = dct[curch]
|
|
954
|
+
curnum = -curnum
|
|
955
|
+
else:
|
|
956
|
+
out += curch * curnum
|
|
957
|
+
if curch != j:
|
|
958
|
+
curnum = 0
|
|
959
|
+
curnum = i
|
|
960
|
+
curch = j
|
|
961
|
+
else:
|
|
962
|
+
if curch:
|
|
963
|
+
out += curch * curnum
|
|
964
|
+
curch = ""
|
|
965
|
+
out += j * i
|
|
966
|
+
return out.rstrip("+-><")
|
|
967
|
+
|
|
968
|
+
def expand(self, prog, byte):
|
|
969
|
+
"""Expand program"""
|
|
970
|
+
if byte not in (1, 2, 4):
|
|
971
|
+
raise ValueError("Byte should by 1, 2, or 4, not {}".format(byte))
|
|
972
|
+
res = "" if byte != 4 else ">"
|
|
973
|
+
for i in prog:
|
|
974
|
+
if i in expanders[byte]:
|
|
975
|
+
res += expanders[byte][i]
|
|
976
|
+
else:
|
|
977
|
+
res += i
|
|
978
|
+
return res
|
|
979
|
+
|
|
980
|
+
def getmacros(self, prog):
|
|
981
|
+
macros = {}
|
|
982
|
+
macro = []
|
|
983
|
+
no_macro = []
|
|
984
|
+
macro_name = ""
|
|
985
|
+
for i in prog.split("\n"):
|
|
986
|
+
i = i.strip()
|
|
987
|
+
if i == "endmacro":
|
|
988
|
+
macros[macro_name] = macro
|
|
989
|
+
macro_name = ""
|
|
990
|
+
macro = []
|
|
991
|
+
continue
|
|
992
|
+
if macro_name:
|
|
993
|
+
macro.append(i)
|
|
994
|
+
continue
|
|
995
|
+
y = i
|
|
996
|
+
while " " in y:
|
|
997
|
+
y = y.replace(" ", " ")
|
|
998
|
+
y, k = y[: y.find(" ")], y[y.find(" ") :].replace(" ", "")
|
|
999
|
+
if y == "macro":
|
|
1000
|
+
if not k.startswith("$"):
|
|
1001
|
+
raise SyntaxError("Macros must start with '$'")
|
|
1002
|
+
macro_name = k
|
|
1003
|
+
else:
|
|
1004
|
+
no_macro.append(i)
|
|
1005
|
+
return (macros, "\n".join(no_macro))
|
|
1006
|
+
|
|
1007
|
+
def preprocess_libraries(self, prog):
|
|
1008
|
+
flag = False
|
|
1009
|
+
res = []
|
|
1010
|
+
for i in prog.split("\n"):
|
|
1011
|
+
i = i.strip()
|
|
1012
|
+
if i and i[0] == "?":
|
|
1013
|
+
try:
|
|
1014
|
+
with open(i[1:].strip(), "r") as f:
|
|
1015
|
+
c = f.read().split("\n")
|
|
1016
|
+
res += c
|
|
1017
|
+
except FileNotFoundError:
|
|
1018
|
+
try:
|
|
1019
|
+
with open(
|
|
1020
|
+
os.path.join(
|
|
1021
|
+
os.path.dirname(__file__), "stdlib", i[1:].strip()
|
|
1022
|
+
),
|
|
1023
|
+
"r",
|
|
1024
|
+
) as f:
|
|
1025
|
+
c = f.read().split("\n")
|
|
1026
|
+
res += c
|
|
1027
|
+
except:
|
|
1028
|
+
raise FileNotFoundError(f"Library {i[1:].strip()} not found")
|
|
1029
|
+
flag = True
|
|
1030
|
+
else:
|
|
1031
|
+
res.append(i)
|
|
1032
|
+
return flag, "\n".join(res)
|
|
1033
|
+
|
|
1034
|
+
def can_be_preprocessed(self, prog):
|
|
1035
|
+
macros, no_macro = self.getmacros(prog)
|
|
1036
|
+
for i in no_macro.split("\n"):
|
|
1037
|
+
if i.startswith("$"):
|
|
1038
|
+
return True
|
|
1039
|
+
return False
|
|
1040
|
+
|
|
1041
|
+
def preprocess(self, macros, no_macro):
|
|
1042
|
+
"""Preprocess macros"""
|
|
1043
|
+
res = []
|
|
1044
|
+
for i in no_macro.split("\n"):
|
|
1045
|
+
i = i.split("#")[0].strip()
|
|
1046
|
+
if i.startswith("$"):
|
|
1047
|
+
if "(" not in i:
|
|
1048
|
+
res += macros[i]
|
|
1049
|
+
else:
|
|
1050
|
+
mac_name, mac_args = i[: i.find("(")], i[i.find("(") :]
|
|
1051
|
+
for name, info in macros.items():
|
|
1052
|
+
if name.startswith(mac_name + "("):
|
|
1053
|
+
_args = name[name.find("(") :]
|
|
1054
|
+
args1, args2 = mac_args[1:-1].split(","), _args[1:-1].split(
|
|
1055
|
+
","
|
|
1056
|
+
)
|
|
1057
|
+
if len(args1) != len(args2):
|
|
1058
|
+
raise SyntaxError("Argument table length wrong")
|
|
1059
|
+
for j in info:
|
|
1060
|
+
if j.strip().startswith("print("):
|
|
1061
|
+
res.append(j)
|
|
1062
|
+
else:
|
|
1063
|
+
t = j
|
|
1064
|
+
for _i, _j in zip(args2, args1):
|
|
1065
|
+
t = re.sub("\\b" + re.escape(_i) + "\\b", _j, t)
|
|
1066
|
+
res.append(t)
|
|
1067
|
+
break
|
|
1068
|
+
else:
|
|
1069
|
+
res.append(i)
|
|
1070
|
+
return "\n".join(res)
|
|
1071
|
+
|
|
1072
|
+
def compile(self, prog, byte=1):
|
|
1073
|
+
"""Compiles BFFuck programs into brainfuck"""
|
|
1074
|
+
clean = ""
|
|
1075
|
+
flag, prog = self.preprocess_libraries(prog)
|
|
1076
|
+
while flag:
|
|
1077
|
+
flag, prog = self.preprocess_libraries(prog)
|
|
1078
|
+
all_macros = {}
|
|
1079
|
+
while self.can_be_preprocessed(prog):
|
|
1080
|
+
macros, no_macro = self.getmacros(prog)
|
|
1081
|
+
for i, j in macros.items():
|
|
1082
|
+
all_macros[i] = j
|
|
1083
|
+
prog = self.preprocess(all_macros, no_macro)
|
|
1084
|
+
for i in prog.split("\n"):
|
|
1085
|
+
if len(i.strip()) == 0:
|
|
1086
|
+
continue
|
|
1087
|
+
if i.strip().startswith("print(") or i.strip().startswith("bf "):
|
|
1088
|
+
clean = i.strip() # Print and bf need to preserve whitespaces
|
|
1089
|
+
else:
|
|
1090
|
+
clean = self.join_semantically(i.split()).split("#")[0]
|
|
1091
|
+
self.program(clean)
|
|
1092
|
+
return self.opt(self.expand(self.opt(self.bf), byte))
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: bffuck
|
|
3
|
+
Version: 3.0.1
|
|
4
|
+
Summary: Makes Brainfucking Easier!
|
|
5
|
+
Home-page: https://github.com/none-None1/BFFuck
|
|
6
|
+
Classifier: Operating System :: OS Independent
|
|
7
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
8
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
[](https://pepy.tech/project/bffuck) [](https://pepy.tech/project/bffuck) [](https://pepy.tech/project/bffuck)
|
|
12
|
+
|
|
13
|
+
# BFFuck
|
|
14
|
+
Makes brainfucking easier
|
|
15
|
+
|
|
16
|
+
The tools is an esoteric language that compiles to brainfuck, using algorithms in [brainfuck algorithms](https://esolangs.org/wiki/Brainfuck_algorithms).
|
|
17
|
+
|
|
18
|
+
### Usage:
|
|
19
|
+
Run this in Python:
|
|
20
|
+
```python
|
|
21
|
+
from bffuck import BFFuck
|
|
22
|
+
bff=BFFuck()
|
|
23
|
+
bf=bff.compile('Your code')
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Note that if a BFFuck object is created and used, its status will change and therefore cannot compile another program.
|
|
27
|
+
### Syntax
|
|
28
|
+
BFFuck currently supports the following syntax:
|
|
29
|
+
|
|
30
|
+
Comment:
|
|
31
|
+
```
|
|
32
|
+
# Comment
|
|
33
|
+
```
|
|
34
|
+
Variable definition:
|
|
35
|
+
```text
|
|
36
|
+
<variable 1>=<variable 2>
|
|
37
|
+
or
|
|
38
|
+
<variable>=<number>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Addition:
|
|
42
|
+
```text
|
|
43
|
+
add(x,<number>)
|
|
44
|
+
or
|
|
45
|
+
add(x,<variable>)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Subtraction:
|
|
49
|
+
```
|
|
50
|
+
sub(x,<number>)
|
|
51
|
+
or
|
|
52
|
+
sub(x,<variable>)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Multiplication:
|
|
56
|
+
```
|
|
57
|
+
mul(x,<number>)
|
|
58
|
+
or
|
|
59
|
+
mul(x,<variable>)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Modulo:
|
|
63
|
+
```
|
|
64
|
+
mod(x,<number>)
|
|
65
|
+
or
|
|
66
|
+
mod(x,<variable>)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
While loop:
|
|
70
|
+
```text
|
|
71
|
+
while(<variable or number>)
|
|
72
|
+
CODE
|
|
73
|
+
endwhile
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
I/O:
|
|
77
|
+
```text
|
|
78
|
+
<variable>=in # Reads <variable> as decimal integer
|
|
79
|
+
<variable>=inc # Reads <variable> as ASCII character
|
|
80
|
+
out(<variable or number>) # Outputs <variable> as decimal integer
|
|
81
|
+
outc(<variable or number>) # Outputs <variable> as ASCII character
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
String output shortcut:
|
|
85
|
+
```text
|
|
86
|
+
print(STRING) # Without quotes
|
|
87
|
+
# For instance
|
|
88
|
+
print(Hello World!)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
If statement:
|
|
92
|
+
```text
|
|
93
|
+
if(<variable or number>)
|
|
94
|
+
CODE
|
|
95
|
+
endif
|
|
96
|
+
|
|
97
|
+
if(<variable or number>)
|
|
98
|
+
CODE1
|
|
99
|
+
else
|
|
100
|
+
CODE2
|
|
101
|
+
endif
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Comparison:
|
|
105
|
+
```text
|
|
106
|
+
lt(x,<number>) # Compares x and the variable or number, if x is less than the variable or number, set x to 1, otherwise 0
|
|
107
|
+
or
|
|
108
|
+
lt(x,<variable>)
|
|
109
|
+
|
|
110
|
+
eq(x,<number>) # Compares x and the variable or number, if x is equal to the variable or number, set x to 1, otherwise 0
|
|
111
|
+
or
|
|
112
|
+
eq(x,<variable>)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Macros:
|
|
116
|
+
```text
|
|
117
|
+
macro $<name> # Macro with no arguments
|
|
118
|
+
CODE
|
|
119
|
+
endmacro
|
|
120
|
+
|
|
121
|
+
macro $<name>(<arg1>,<arg2>,...) # Macro with arguments
|
|
122
|
+
CODE
|
|
123
|
+
endmacro
|
|
124
|
+
|
|
125
|
+
$<name> # Using a macro with no arguments
|
|
126
|
+
$<name>(<arg1>,<arg2>,...) # Using a macro with arguments
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Memory:
|
|
130
|
+
```text
|
|
131
|
+
ptr(a,b) # Store address of a to variable b
|
|
132
|
+
ref(a,b) # Store value of address b to variable a
|
|
133
|
+
set(a,b) # Set value of address b to a (variable or integer literal)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Libraries
|
|
137
|
+
```text
|
|
138
|
+
?libraryname
|
|
139
|
+
```
|
|
140
|
+
Includes the library `library name` (with file extension).
|
|
141
|
+
|
|
142
|
+
It first searches the library in current directory, and then in the `stdlib` directory in the package.
|
|
143
|
+
|
|
144
|
+
There are standard libraries for BFFuck, they are:
|
|
145
|
+
* `env.bff` gets size of a "byte" specified by the compiler
|
|
146
|
+
* `alloc.bff` allocates memory
|
|
147
|
+
* `array.bff` manages memory using arrays
|
|
148
|
+
* `rng.bff` a not very decent random number generator
|
|
149
|
+
|
|
150
|
+
An example of the `rng.bff` library is here:
|
|
151
|
+
```text
|
|
152
|
+
?rng.bff
|
|
153
|
+
x=0
|
|
154
|
+
while(1)
|
|
155
|
+
$rnd(x)
|
|
156
|
+
outc(x)
|
|
157
|
+
endwhile
|
|
158
|
+
```
|
|
159
|
+
Prints random bytes.
|
|
160
|
+
### Platform
|
|
161
|
+
BFFuck is in **pure Python** and therefore it supports any platform.
|
|
162
|
+
|
|
163
|
+
### Constraints
|
|
164
|
+
Programs compiled from BFFuck needs you to have 8 bit cells that wrap.
|
|
165
|
+
|
|
166
|
+
### Disadvantages
|
|
167
|
+
BFFuck currently has these disadvantages:
|
|
168
|
+
1. <s>It's numbers are 8 bit numbers.</s> You can choose 8-bit, 16-bit or 32-bit numbers using the `byte` keyword argument. But you need to run it on a 8-bit interpreter. <font color="red">REMEMBER: Using numbers with more bits is slower and increases the size of program largely! If you're using 32 bit, remember to use an extremely optimizing interpreter like bffsree!</font>
|
|
169
|
+
2. It has some bugs.
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
The repository contains some examples, including a Hello World program, a cat program and an A+B program.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
bffuck/__init__.py,sha256=YkDc0nIFsKgkfQqqJd2oJ4B5vLBCXijCyLbYRjXF67A,1272
|
|
2
|
+
bffuck/bffuck.py,sha256=5MzjCGDJ0TcW0LgpHsv0l8JafmvGxzNCQ4f6_2QCsJ8,47800
|
|
3
|
+
bffuck-3.0.1.dist-info/METADATA,sha256=2EZSgbH0JaFLIybaYNWIRzQxGxstODIeA--OKhXl6eM,4195
|
|
4
|
+
bffuck-3.0.1.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
|
|
5
|
+
bffuck-3.0.1.dist-info/entry_points.txt,sha256=JWHCxYZS68WD_Gc18kDBZMAMREpY8-iB8zoUFWzc3vU,39
|
|
6
|
+
bffuck-3.0.1.dist-info/top_level.txt,sha256=ojvYjcwO-Ge5VjqeNdGOILMlWc4Bo0b9e6A7s-Hg3fk,7
|
|
7
|
+
bffuck-3.0.1.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
bffuck
|