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 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
+ [![Downloads](https://static.pepy.tech/badge/bffuck)](https://pepy.tech/project/bffuck) [![Downloads](https://static.pepy.tech/badge/bffuck/month)](https://pepy.tech/project/bffuck) [![Downloads](https://static.pepy.tech/badge/bffuck/week)](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,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.38.4)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ bffuck = bffuck:_cli
@@ -0,0 +1 @@
1
+ bffuck