move interpter to own file

main
Brett 2023-11-17 00:25:52 -05:00
parent 64619f4325
commit 2670e34e25
8 changed files with 565 additions and 120 deletions

245
bfponggen.py Normal file
View File

@ -0,0 +1,245 @@
# pongff="/tmp/pongff"; [ ! -p "$pongff" ] && mkfifo "$pongff";
# rm -f /tmp/p; python3 bfponggen.py >/tmp/p.bf && python2.7 ~/bfc.py /tmp/p.bf && <"$pongff" ../pipevm.py | /tmp/p >"$pongff"
import struct
class BfGen():
def __init__(self, generators):
self.labels = {}
for i in range(len(generators)):
self.labels[generators[i][0]] = i
print(generators[i][1])
print()
self.curPos = len(generators) - 9 # FIXME
def moveToPos(self, goalPos):
d = self.curPos - goalPos
self.curPos -= d
if d >= 0:
return "<" * d
return ">" * -d
def output(self, s):
result = ""
label = ""
for c in s:
if c in '[]<>{}+-.,':
if label:
label = label.strip()
v = self.moveToPos(self.labels[label])
result += v
label = ""
result += c
else:
label += c
if label:
label = label.strip()
v = self.moveToPos(self.labels[label])
result += v
print(result)
generators = [
('00', ">"), # 0
('01', "+>"), # 1
('05', "+++++>"), # 5
('paddle_size', ">+++++[<++++++>-]"), # 30
('paddle_right_x', ">++++++++[<++++++++>-]"), # 64
('paddle_right_y', ">>+>+>+[+>++[-<+++>]<<]>-[-<+<+>>]"), # 103
('paddle_left_y', ""), # 103
('ball_x0', ""), # 0
('ball_x1', ">+>+>+++[+>+[-<++++>]<<]>>"), # 158
('ball_y0', ">"), # 0
('ball_y1', ">+++++++++[<+++++++++++++>-]"), # 117
('ff', ">+>+>+>+[++>[-<++++>]<<]>[-<+>]"), # 255
('device', "++++[>++++<-]>[<++++++++>-]<+>"), # 129
('f0', ">+>+>+>+[++>+[-<+++>]<<]>[-<+>]"), # 240
('ball_direction_x', ""), # 0 (left)
('ball_direction_y', ">"), # 0 (top)
('mem0', ""), # 0
('mem1', ""), # 0
('mem2', ""), # 0
('mem3', ""), # 0
('mem4', ""), # 0
('mem5', ""), # 0
('mem6', ""), # 0
('mem7', ""), # 0
]
bfgen = BfGen(generators)
bfgen.output("ff.device.")
# black screen # struct.pack(">BHHHHBBB", command, x, y, w, h, r, g, b)
# paddle_right_x starts with [320 (width) - 256 (overflow)], but will later have 10 subtracted from it
bfgen.output("05.00.00.00.00.01.paddle_right_x.00.f0.00.00.00.")
# we don't need to save "320" anymore, decrease by 10 so it can be used as paddle_right_x
bfgen.output("paddle_right_x----------")
# draw left paddle
bfgen.output("05.00.05.00.paddle_left_y.00.05.00.paddle_size.f0.f0.f0.")
# draw right paddle
bfgen.output("05.01.paddle_right_x.00.paddle_right_y.00.05.00.paddle_size.f0.f0.f0.")
bfgen.output("05")
bfgen.output("[") # main loop [
# delete ball
bfgen.output("05.ball_x0.ball_x1.ball_y0.ball_y1.00.05.00.05.00.00.00.")
# moves ball_x, handling over/underflow
bfgen.output("ball_direction_x[-mem0+mem1+ball_direction_x]mem1[-ball_direction_x+mem1]+ball_x1-----[-mem0+ball_x1]mem0+++[mem1-]>")
bfgen.output("[ball_y0+ball_x0[-ball_y0-ball_x0]ball_y0[-ball_x0+ball_y0]ball_x1+ball_x0[mem0+++++ball_x1-]>")
bfgen.output("[mem0-----ball_x1-ball_y0]mem1-mem2]")
bfgen.output("mem0---[-ball_x1+mem0]")
bfgen.output("ball_direction_y[-mem0+ball_y1+ball_direction_y]mem0[-ball_direction_y+mem0]ball_y1-----")
# reverse direction of ball_y if ball_y1 == 2
bfgen.output("ball_y1[-mem0+mem2+ball_y1]mem1+")
bfgen.output("mem2--[mem1-mem2[-]]")
bfgen.output("mem1[-ball_direction_y++++++++++mem1]")
bfgen.output("mem0[-ball_y1+mem0]")
# reverse direction of ball_y if ball_y1 == 237
bfgen.output("ball_y1[-mem0+mem2+ball_y1]mem1+")
bfgen.output("mem2+++++++++++++++++++[mem1-mem2[-]]")
bfgen.output("mem1[-ball_direction_y----------mem1]")
bfgen.output("mem0[-ball_y1+mem0]")
# check ball boundaries
# mem0 = ball_x0-ball_x1, using ball_y0 as a buffer
print("start boundaries check")
bfgen.output("ball_x0[-ball_y0+mem1+ball_x0]ball_y0[-ball_x0+ball_y0]")
bfgen.output("ball_x1[-ball_y0+mem5+ball_x1]ball_y0[-ball_x1+ball_y0]")
bfgen.output("mem1+mem5[-mem6+mem7+mem5]mem6[-mem3+mem6]")
print("check left boundary")
# if mem0 == 13, reached left boundary
bfgen.output("mem4+mem3-------------[mem4-]>")
# algorithm (done in debugger, not converted here) to
# bounce the ball if it hits the paddle or to reset
# ball_x and ball_y to the center otherwise
print("""
[
-
copy ball_y to mem3 and paddle_left_y to mem4
<<<<<<<<<<[-<+>>>>>>>>>>+<<<<<<<<<]<[->+<]
<<<[->>>+>>>>>>>>>>>+<<<<<<<<<<<<<<]>>>[-<<<+>>>]
>>>>>>>>>>
if mem3 ge mem4
[->-[>]<<]< (mem3 ends up = mem4 minus men3)
[
then if mem3 ge 31
>>>>+++++[<++++++>-]<+
<[->-[>]<<]<
[then just clean up ->]<
[else set mem0=1 ><<+>-]>
]
>>[-]<<<[-]+<
if mem0 eq 1 (ball hit left paddle)
[
then change direction of the ball
<<++++++++++>>-
>-]>
[< else reset ball_y
>>[-]>>[-]<<<<
<<<<<<[-]<<[-]
+>+++[++>++[-<++++++>]<<]> 117
[->+>+<<]
<++++++++++[->++++<]>+>[-<+>] 158
request a random char (ff 03 01 01 ff 01)
>>.>++.>>[-]+..<<<.>--.
>>->[-]>+>[-]>+>[-]>+>>
read random char (mem6) and set mem1 and mem2 to (mem6 % 4) (in binary)
,[
-
<<<<
[-[<[-<->]<[->+<]+>>-->]>>[-]]<[<]>[-]<<++
>>+>>
]<<-<<-<<->>
set the ball (x and y) directions based on mem1 and mem2
[-<<<++++++++++>>>]<[-<<<++++++++++>>>]
>
]
>>>
]
<<[-]<<[-]<
""")
bfgen.curPos = bfgen.labels["mem0"]
# now repeat the check for mem0 = 47 (+256=303) (reached right boundary)
bfgen.output("mem7[-mem0+mem7]")
bfgen.output("mem1+mem0-----------------------------------------------[mem1-]>")
bfgen.output("[ball_direction_x----------mem1-mem2]mem0[-]")
bfgen.output("mem1[-]mem2[-]mem3[-]")
print("end boundaries check")
# draw new ball
bfgen.output("05.ball_x0.ball_x1.ball_y0.ball_y1.00.05.00.05.f0.f0.00.")
print("move right paddle (computer)")
# move paddle_right_x
bfgen.output("mem0+ball_direction_x[") # if ball_direction_x != 0
bfgen.output("05.01.paddle_right_x.00.paddle_right_y.00.05.00.paddle_size.00.00.00.")
# use ball_y0 as buffer to copy ball_y1 to mem2 and paddle_right_y to mem3
bfgen.output("ball_y1[-ball_y0+mem2+ball_y1]ball_y0[-ball_y1+ball_y0]")
bfgen.output("paddle_right_y[-ball_y0+mem3+paddle_right_y]ball_y0[-paddle_right_y+ball_y0]")
# compare mem2 and mem3
bfgen.output("mem5+mem3+++++++++++++++mem2[-mem3-[mem4]mem2]mem5")
bfgen.curPos = bfgen.labels["mem4"]
bfgen.output("[-")
# mem2 >= mem3
bfgen.output("paddle_right_x-----mem3") # must be 1 position before paddle_right_y
bfgen.curPos = bfgen.labels["mem4"]
bfgen.output("]mem5")
# mem2 < mem3
bfgen.output("[-")
bfgen.output("paddle_right_y+++++mem5")
bfgen.output("]mem3[-]mem2[-]")
bfgen.output("05.01.paddle_right_x.00.paddle_right_y.00.05.00.paddle_size.f0.f0.f0.")
bfgen.output("mem0-ball_direction_x[mem1+ball_direction_x-]")
bfgen.output("]mem1[ball_direction_x+mem1-]mem0[-]")
print("move left paddle (user input)")
bfgen.output("ff.device+.-01.") # ff 02 01 (ff device command)
bfgen.output("mem0,") # read char
bfgen.output("mem0[,mem2+mem3+mem4+++[mem5[-mem4++++++mem5]mem3]") # if mem0 != 0, read another char and generate 115 ('s')
bfgen.curPos = bfgen.labels["mem1"]
bfgen.output("mem2[-mem0-mem2]mem1+mem0")
bfgen.output("[----[>-]mem1[mem3+++++mem5+mem1-mem2]mem1[-]]")
bfgen.output("mem2[mem5+++++>+<mem2->]mem0[-]]")
bfgen.output("ff.device.")
bfgen.output("mem5[05.00.05.00.paddle_left_y.00.05.00.paddle_size.00.00.00.mem5[-]]") # delete left paddle
bfgen.output("mem3[-paddle_left_y-mem2+mem3]") # paddle_left_y += mem3, set mem2
bfgen.output("mem4[-paddle_left_y+mem2+mem4]") # paddle_left_y -= mem4, set mem2
bfgen.output("mem2[05.00.05.00.paddle_left_y.00.05.00.paddle_size.f0.f0.f0.mem2[-]]") # redraw left paddle
# draw right paddle
bfgen.output("05.01.paddle_right_x.00.paddle_right_y.00.05.00.paddle_size.f0.f0.f0.")
# return to initial position of the loop
bfgen.output("05")
bfgen.output("]")

View File

@ -1,2 +1 @@
~../hellobf.bf
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.

88
include/bf_interpreter.h Normal file
View File

@ -0,0 +1,88 @@
#pragma once
/*
* Created by Brett on 17/11/23.
* Licensed under GNU General Public License V3.0
* See LICENSE file for license detail
*/
#ifndef BRAINFUCK_MISC_BF_INTERPRETER_H
#define BRAINFUCK_MISC_BF_INTERPRETER_H
#include <cstdint>
#include <cstring>
#include <string>
class brainfuck_interpreter
{
private:
size_t _size;
size_t _dp;
char* _data;
void check_size();
public:
brainfuck_interpreter(): _size(30000), _dp(0), _data(new char[_size])
{std::memset(_data, 0, _size);}
void increment_dp()
{
_dp++;
}
void decrement_dp()
{
if (_dp != 0)
_dp--;
}
void increment()
{
check_size();
_data[_dp]++;
}
void decrement()
{
check_size();
_data[_dp]--;
}
template<typename OutStream>
void print(OutStream& stream)
{
stream << _data[_dp];
}
template<typename InStream>
void read(InStream& stream)
{
_data[_dp] = stream.get();
}
char is()
{
return _data[_dp];
}
~brainfuck_interpreter()
{ delete[] _data; }
};
template<typename functor>
static inline void match(functor f, int sp, size_t& index, const std::string& program)
{
while (f(index) < program.size())
{
if (program[index] == '[')
sp++;
if (program[index] == ']')
sp--;
if (sp == 0)
break;
}
}
void interpret_bf(const std::string& program);
#endif //BRAINFUCK_MISC_BF_INTERPRETER_H

@ -1 +1 @@
Subproject commit 5472783bd7194cfc844da81bfa696e7761bd2047
Subproject commit fd9fa5454d47c60e41792c65beccf3988f3f2225

38
life.bf Normal file
View File

@ -0,0 +1,38 @@
[life.b -- John Horton Conway's Game of Life
(c) 2021 Daniel B. Cristofani
http://brainfuck.org/]
>>>->+>+++++>(++++++++++)[[>>>+<<<-]>+++++>+>>+[<<+>>>>>+<<<-]<-]>>>>[
[>>>+>+<<<<-]+++>>+[<+>>>+>+<<<-]>>[>[[>>>+<<<-]<]<<++>+>>>>>>-]<-
]+++>+>[[-]<+<[>+++++++++++++++++<-]<+]>>[
[+++++++++.-------->>>]+[-<<<]>>>[>>,----------[>]<]<<[
<<<[
>--[<->>+>-<<-]<[[>>>]+>-[+>>+>-]+[<<<]<-]>++>[<+>-]
>[[>>>]+[<<<]>>>-]+[->>>]<-[++>]>[------<]>+++[<<<]>
]<
]>[
-[+>>+>-]+>>+>>>+>[<<<]>->+>[
>[->+>+++>>++[>>>]+++<<<++<<<++[>>>]>>>]<<<[>[>>>]+>>>]
<<<<<<<[<<++<+[-<<<+]->++>>>++>>>++<<<<]<<<+[-<<<+]+>->>->>
]<<+<<+<<<+<<-[+<+<<-]+<+[
->+>[-<-<<[<<<]>[>>[>>>]<<+<[<<<]>-]]
<[<[<[<<<]>+>>[>>>]<<-]<[<<<]]>>>->>>[>>>]+>
]>+[-<<[-]<]-[
[>>>]<[<<[<<<]>>>>>+>[>>>]<-]>>>[>[>>>]<<<<+>[<<<]>>-]>
]<<<<<<[---<-----[-[-[<->>+++<+++++++[-]]]]<+<+]>
]>>
]
[This program simulates the Game of Life cellular automaton.
It duplicates the interface of the classic program at
http://www.linusakesson.net/programming/brainfuck/index.php,
but this program was written from scratch.
Type e.g. "be" to toggle the fifth cell in the second row, "q" to quit,
or a bare linefeed to advance one generation.
Grid wraps toroidally. Board size in parentheses in first line (2-166 work).
This program is licensed under a Creative Commons Attribution-ShareAlike 4.0
International License (http://creativecommons.org/licenses/by-sa/4.0/).]

127
pong.bf Normal file
View File

@ -0,0 +1,127 @@
>
+>
+++++>
>+++++[<++++++>-]
>++++++++[<++++++++>-]
>>+>+>+[+>++[-<+++>]<<]>-[-<+<+>>]
>+>+>+++[+>+[-<++++>]<<]>>
>
>+++++++++[<+++++++++++++>-]
>+>+>+>+[++>[-<++++>]<<]>[-<+>]
++++[>++++<-]>[<++++++++>-]<+>
>+>+>+>+[++>+[-<+++>]<<]>[-<+>]
>
<<<<.>.
<<<<<<<<<<.<<....>.>>>.<<<<.>>>>>>>>>>>>>.<<<<<<<<<<<<<...
>>>>----------
<<.<<.>>.<<.>>>>>>.<<<<<<.>>.<<.>>>.>>>>>>>>>>...
<<<<<<<<<<<.<.>>>.<<<<.>>>>>.<<<<<.>>.<<.>>>.>>>>>>>>>>...
<<<<<<<<<<<
[
.>>>>>.>.>.>.<<<<<<<<<<.>>.<<.>>.<<...
>>>>>>>>>>>>>>[->>+>+<<<]>>>[-<<<+>>>]+<<<<<<<<<-----[->>>>>>>>+<<<<<<<<]>>>>>>>>+++[>-]>
[<<<<<<<<+<<[->>-<<]>>[-<<+>>]<+<[>>>>>>>>>+++++<<<<<<<<-]>
[>>>>>>>>-----<<<<<<<<->]>>>>>>>>->]
<<---[-<<<<<<<<+>>>>>>>>]
<[->+<<<<<<+>>>>>]>[-<+>]<<<<<<-----
[->>>>>>+>>+<<<<<<<<]>>>>>>>+
>--[<->[-]]
<[-<<++++++++++>>]
<[-<<<<<<+>>>>>>]
<<<<<<[->>>>>>+>>+<<<<<<<<]>>>>>>>+
>+++++++++++++++++++[<->[-]]
<[-<<---------->>]
<[-<<<<<<+>>>>>>]
start boundaries check
<<<<<<<<<[->>+>>>>>>>>+<<<<<<<<<<]>>[-<<+>>]
<[->+>>>>>>>>>>>>+<<<<<<<<<<<<<]>[-<+>]
>>>>>>>>+>>>>[->+>+<<]>[-<<<+>>>]
check left boundary
<<+<-------------[>-]>
[
-
copy ball_y to mem3 and paddle_left_y to mem4
<<<<<<<<<<[-<+>>>>>>>>>>+<<<<<<<<<]<[->+<]
<<<[->>>+>>>>>>>>>>>+<<<<<<<<<<<<<<]>>>[-<<<+>>>]
>>>>>>>>>>
if mem3 ge mem4
[->-[>]<<]< (mem3 ends up = mem4 minus men3)
[
then if mem3 ge 31
>>>>+++++[<++++++>-]<+
<[->-[>]<<]<
[then just clean up ->]<
[else set mem0=1 ><<+>-]>
]
>>[-]<<<[-]+<
if mem0 eq 1 (ball hit left paddle)
[
then change direction of the ball
<<++++++++++>>-
>-]>
[< else reset ball_y
>>[-]>>[-]<<<<
<<<<<<[-]<<[-]
+>+++[++>++[-<++++++>]<<]> 117
[->+>+<<]
<++++++++++[->++++<]>+>[-<+>] 158
request a random char (ff 03 01 01 ff 01)
>>.>++.>>[-]+..<<<.>--.
>>->[-]>+>[-]>+>[-]>+>>
read random char (mem6) and set mem1 and mem2 to (mem6 % 4) (in binary)
,[
-
<<<<
[-[<[-<->]<[->+<]+>>-->]>>[-]]<[<]>[-]<<++
>>+>>
]<<-<<-<<->>
set the ball (x and y) directions based on mem1 and mem2
[-<<<++++++++++>>>]<[-<<<++++++++++>>>]
>
]
>>>
]
<<[-]<<[-]<
>>>>>>>[-<<<<<<<+>>>>>>>]
<<<<<<+<-----------------------------------------------[>-]>
[<<<---------->>>->]<<[-]
>[-]>[-]>[-]
end boundaries check
<<<<<<<<<<<<<<<<<.>>>>>.>.>.>.<<<<<<<<<<.>>.<<.>>.>>>>>>>>>>>..<<<<<<<<<<<<<.
move right paddle (computer)
>>>>>>>>>>>>>>>>+<<[
<<<<<<<<<<<<.<.>>>.<<<<.>>>>>.<<<<<.>>.<<.>>>.<<<...
>>>>>>>>>>[-<+>>>>>>>>>+<<<<<<<<]<[->+<]
<<<<[->>>>+>>>>>>>>>>+<<<<<<<<<<<<<<]>>>>[-<<<<+>>>>]
>>>>>>>>>>>>+<<+++++++++++++++<[->-[>]<<]>>>
[-
<<<<<<<<<<<<<<<<----->>>>>>>>>>>>>>>
]>
[-
<<<<<<<<<<<<<<<<+++++>>>>>>>>>>>>>>>>
]<<[-]<[-]
<<<<<<<<<<<<<<<<.<.>>>.<<<<.>>>>>.<<<<<.>>.<<.>>>.>>>>>>>>>>...
>>>-<<[>>>+<<<-]
]>>>[<<<+>>>-]<[-]
move left paddle (user input)
<<<<<.>+.-<<<<<<<<<<<.
>>>>>>>>>>>>>>>,
[,>>+>+>+++[>[-<++++++>]<<]
>[-<<->>]<+<
[----[>-]>[>>+++++>>+<<<<->]<[-]]
>[>>>+++++>+<<<<->]<<[-]]
<<<<<.>.
>>>>>>>>>[<<<<<<<<<<<<<<<<<<<.<<.>>.<<.>>>>>>.<<<<<<.>>.<<.>>>.<<<...>>>>>>>>>>>>>>>>>>>>>[-]]
<<[-<<<<<<<<<<<<<->>>>>>>>>>>>+>]
>[-<<<<<<<<<<<<<<+>>>>>>>>>>>>+>>]
<<[<<<<<<<<<<<<<<<<.<<.>>.<<.>>>>>>.<<<<<<.>>.<<.>>>.>>>>>>>>>>...>>>>>[-]]
<<<<<<<<<<<<<<<<.<.>>>.<<<<.>>>>>.<<<<<.>>.<<.>>>.>>>>>>>>>>...
<<<<<<<<<<<
]

63
src/bf_interpreter.cpp Normal file
View File

@ -0,0 +1,63 @@
/*
* Created by Brett on 17/11/23.
* Licensed under GNU General Public License V3.0
* See LICENSE file for license detail
*/
#include <bf_interpreter.h>
#include <iostream>
void interpret_bf(const std::string& program)
{
brainfuck_interpreter fuck;
size_t index = 0;
while (index < program.size())
{
auto c = program[index];
switch (c)
{
case '>':
fuck.increment_dp();
break;
case '<':
fuck.decrement_dp();
break;
case '+':
fuck.increment();
break;
case '-':
fuck.decrement();
break;
case '.':
fuck.print(std::cout);
break;
case ',':
fuck.read(std::cin);
break;
case '[':
if (fuck.is() == 0)
match([](size_t& idx) { return ++idx; }, 1, index, program);
break;
case ']':
if (fuck.is() != 0)
match([](size_t& idx) { return --idx; }, -1, index, program);
break;
default:
break;
}
index++;
}
}
void brainfuck_interpreter::check_size()
{
if (_dp >= _size)
{
char* tmp = new char[_size * 2];
std::memset(&tmp[_size], 0, _size);
std::memcpy(tmp, _data, _size);
_size = _size * 2;
delete[] _data;
_data = tmp;
}
}

View File

@ -4,132 +4,17 @@
#include <sstream>
#include <blt/std/loader.h>
class brainfuck
{
private:
size_t _size;
size_t _dp;
char* _data;
#include <bf_interpreter.h>
void check_size()
{
if (_dp >= _size)
{
char* tmp = new char[_size * 2];
std::memset(&tmp[_size], 0, _size);
std::memcpy(tmp, _data, _size);
_size = _size * 2;
delete[] _data;
_data = tmp;
}
}
public:
brainfuck(): _size(2), _dp(0), _data(new char[_size])
{std::memset(_data, 0, _size);}
void increment_dp()
{
_dp++;
}
void decrement_dp()
{
if (_dp != 0)
_dp--;
}
void increment()
{
check_size();
_data[_dp]++;
}
void decrement()
{
check_size();
_data[_dp]--;
}
void print()
{
std::cout << _data[_dp];
}
void read()
{
std::cin >> _data[_dp];
}
char is()
{
return _data[_dp];
}
~brainfuck()
{ delete[] _data; }
};
template<typename functor>
void match(functor f, int sp, size_t& index, const std::string& program)
{
while (f(index) < program.size())
{
if (program[index] == '[')
sp++;
if (program[index] == ']')
sp--;
if (sp == 0)
break;
}
}
int main(int argc, const char** argv)
{
std::string file{"../bf.bf"};
std::string file{"../life.bf"};
if (argc > 1)
file = argv[1];
auto program = blt::fs::loadBrainFuckFile(file);
brainfuck fuck;
size_t index = 0;
while (index < program.size())
{
auto c = program[index];
switch (c)
{
case '>':
fuck.increment_dp();
break;
case '<':
fuck.decrement_dp();
break;
case '+':
fuck.increment();
break;
case '-':
fuck.decrement();
break;
case '.':
fuck.print();
break;
case ',':
fuck.read();
break;
case '[':
if (fuck.is() == 0)
match([](size_t& idx) { return ++idx; }, 1, index, program);
break;
case ']':
if (fuck.is() != 0)
match([](size_t& idx) { return --idx; }, -1, index, program);
break;
default:
break;
}
index++;
}
interpret_bf(program);
return 0;
}