Compare commits

...

86 commits

Author SHA1 Message Date
b8157f2ceb things that don't work 2022-05-23 09:52:31 +02:00
04dd019806 pretty (OwO) 2022-05-16 12:32:56 +02:00
deefc18959 js 2022-05-16 12:32:10 +02:00
54b5c9b1f8 javascript 2022-05-16 12:25:31 +02:00
a52cbda492 Document command line flags 2022-05-09 11:26:02 +02:00
64e5ac616f Add newlines before profile info 2022-05-09 11:22:13 +02:00
b6982d5023
Update .gitattributes 2022-05-08 21:26:18 +02:00
5e401a0d6d
Create .gitattributes 2022-05-08 21:22:37 +02:00
3b8b091406 warning 2022-04-17 22:13:41 +02:00
d5d80f79b7 start with finding dead stores 2022-04-17 21:42:36 +02:00
039b5ea9c7 docs 2022-04-17 18:39:14 +02:00
f88c486088 upgrade nightly 2022-04-17 17:39:58 +02:00
bd2bde58b8 cleanup 2022-04-16 23:56:29 +02:00
9db60ac38d very basic const propagation possible 2022-04-16 23:14:33 +02:00
80b1b0e3f6 add mir 2022-04-16 22:43:50 +02:00
d0718adf7f rename lir lifetimes 2022-04-16 22:21:19 +02:00
5fc5c49dff rename a bunch of stuff 2022-04-16 20:13:15 +02:00
ddf2686049
Delete run-rust.sh 2022-04-16 14:59:39 +02:00
5d943ba51c rewrite pass_group 2022-04-16 14:55:11 +02:00
fb2986783e remove offset-less Add and Sub from IR 2022-04-16 14:45:38 +02:00
93f97e9a08 add pass_move_add_to 2022-04-16 14:35:56 +02:00
014770b6fe add pass_add_sub_offset 2022-04-16 12:35:26 +02:00
4490d49d35 make window_pass generic over window length 2022-04-16 12:05:34 +02:00
d7fea43acf try to fix pass_cancel_left_right_add_sub 2022-04-16 11:41:47 +02:00
290201ab98 oopd 2022-04-16 00:39:46 +02:00
31f2304a30 simplify window passes 2022-04-16 00:37:50 +02:00
3eb9486a8c add cancel_left_right_add_sub pass 2022-04-16 00:27:09 +02:00
904356eb4e make set_n pass more generic 2022-04-16 00:03:03 +02:00
46229fd74f remove SetNull from code 2022-04-16 00:01:28 +02:00
4d9648bf97 remove SetNull from IR 2022-04-15 23:59:50 +02:00
d9f163ef3a fix set_n pass 2022-04-15 23:50:03 +02:00
7973d9f77b improve debugging 2022-04-15 23:33:12 +02:00
c3c24c73fe add opt that doesn't make anything faster but might allow better opts later 2022-04-15 23:07:51 +02:00
6575e09957 fix profiling (still not entirely good) 2022-04-15 22:06:54 +02:00
9d140c45d7 remove debug thing 2022-04-15 21:12:26 +02:00
c130627b63 fix pass_group to use recursively optimize loop if loop is the first statement 2022-04-15 21:04:17 +02:00
53ad68e3f2 add 255 threshold 2022-04-15 20:44:53 +02:00
9924aa2037 rewrite group opt 2022-04-15 20:33:07 +02:00
b535178cb8 move places of casts 2022-04-15 19:27:48 +02:00
7dd2c82fa4 make stmt a single word big 2022-04-15 19:04:43 +02:00
1e1a2a277b remove bounds check 2022-04-15 18:57:39 +02:00
2df17352d1 codegen works 2022-04-15 18:32:29 +02:00
eda2476021 things that don't work but sound fun 2022-04-13 22:36:48 +02:00
799b1591e0 broken AF but profiling could perhaps work like mayb eidk 2022-04-12 22:28:41 +02:00
cec7204c6d things 2022-04-12 21:58:21 +02:00
5634330287 spans and tests 2022-04-12 21:49:59 +02:00
e82b14b09a bench setup that works 2022-04-12 21:20:16 +02:00
7b88c99039 things 2022-04-12 20:50:31 +02:00
539d0e0502 fix snap 2022-04-12 20:22:42 +02:00
66bd69e674 remove naive interpreter 2022-04-12 20:21:54 +02:00
2d854539aa works 2022-04-12 19:55:44 +02:00
2484fe1f44 parser works 2022-04-12 19:32:48 +02:00
2b1daa55fb
Delete bf.b 2021-07-23 09:05:37 +02:00
3994acef78
Delete examples directory 2021-07-23 09:05:29 +02:00
f9998535de
new plans 2021-07-15 12:53:17 +02:00
7d352e0b5c
wtf
wtf
2021-07-15 11:46:18 +02:00
d5520e1f42 oops 2021-07-15 11:44:33 +02:00
db362072b7 Merge branch 'master' of https://github.com/Nilstrieb/brainfuck 2021-07-15 11:42:11 +02:00
ab27352faa small changes 2021-07-15 11:41:47 +02:00
076156bd34
Update package.json 2021-07-12 14:22:19 +02:00
nilstrieb
a4fa459805 finally flamegraph 2021-06-27 08:59:58 -07:00
c2bdc73179 deleted 2021-06-27 17:52:56 +02:00
nilstrieb
6cc64160e1 flamegraph 2021-06-27 08:52:01 -07:00
nilstrieb
6df903675e flamegraph 2021-06-27 08:39:10 -07:00
e7165c876e
Update index.html 2021-06-26 13:49:44 +02:00
206e0293ec small changes 2021-06-25 16:58:53 +02:00
0a8ecd3a92 including brainfuck programs 2021-06-25 16:47:04 +02:00
e9d3a88bb6 blocking mode 2021-06-25 16:26:54 +02:00
2202c79521 better control 2021-06-25 14:35:27 +02:00
d1141cc6a6 Merge remote-tracking branch 'origin/master' into master 2021-06-25 13:05:31 +02:00
dc79c96f63 more settings 2021-06-25 13:05:12 +02:00
6d4c6f5b69
Update README.md 2021-06-24 20:01:34 +02:00
6f23444e4f
Update README.md 2021-06-24 20:01:24 +02:00
669b004044
Update README.md 2021-06-24 19:58:04 +02:00
e13d82ff46 wtf is going on 2021-06-24 15:55:03 +02:00
296fd4a279 gh-pages :( 2021-06-24 15:26:43 +02:00
579d81021a input 2021-06-24 14:42:26 +02:00
a96567038d can run 2021-06-24 13:22:16 +02:00
273027e8af display 2021-06-24 11:51:10 +02:00
5f6d1d5b4b works 2021-06-24 11:02:50 +02:00
e815fd8c66 interpreter 2021-06-23 17:01:15 +02:00
b30fa04dcc oops ts 2021-06-23 14:55:43 +02:00
3ee494fed9 created react app but not actually started doing anything nice 2021-06-18 16:11:51 +02:00
812e492640 Merge remote-tracking branch 'origin/master' into master 2021-05-10 14:01:03 +02:00
68d07ae79e version changed 2021-05-10 14:00:55 +02:00
2a147ef178
Update README.md 2021-05-10 13:57:36 +02:00
81 changed files with 18720 additions and 930 deletions

2
.gitattributes vendored Normal file
View file

@ -0,0 +1,2 @@
*.bf linguist-vendored
*.b linguist-vendored

View file

@ -1,15 +1,17 @@
# brainfuck
Brainfuck interpreters in different languages
Finished:
- Rust
- Rust o1
- Java
WIP:
- Rust o2
To-Do:
- Haskell
- TypeScript
- (JavaScript)
# brainfuck
Brainfuck interpreters in different languages
Get the releases!
Rust: CLI binary, in the release tab
Typescript: [react website](https://nilstrieb.github.io/brainfuck/)
Finished:
- Rust
- Java
- Interactive TypeScript
WIP:
To-Do:
- Idris

View file

@ -1,2 +1,2 @@
.idea
.idea
.stack-work

16
bfi-haskell/.idea/.gitignore generated vendored
View file

@ -1,8 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/../../../../../../../:\Users\nilsh\IdeaProjects\brainfuck\bfi-haskell\.idea/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/../../../../../../../:\Users\nilsh\IdeaProjects\brainfuck\bfi-haskell\.idea/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

View file

@ -1,11 +1,11 @@
<component name="libraryTable">
<library name="base-4.14.1.0">
<CLASSES>
<root url="file://$USER_HOME$/AppData/Local/rikvdkleij/intellij-haskell/cache/lib/bfi-haskell/base-4.14.1.0" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$USER_HOME$/AppData/Local/rikvdkleij/intellij-haskell/cache/lib/bfi-haskell/base-4.14.1.0" />
</SOURCES>
</library>
<component name="libraryTable">
<library name="base-4.14.1.0">
<CLASSES>
<root url="file://$USER_HOME$/AppData/Local/rikvdkleij/intellij-haskell/cache/lib/bfi-haskell/base-4.14.1.0" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$USER_HOME$/AppData/Local/rikvdkleij/intellij-haskell/cache/lib/bfi-haskell/base-4.14.1.0" />
</SOURCES>
</library>
</component>

View file

@ -1,11 +1,11 @@
<component name="libraryTable">
<library name="ghc-prim-0.6.1">
<CLASSES>
<root url="file://$USER_HOME$/AppData/Local/rikvdkleij/intellij-haskell/cache/lib/bfi-haskell/ghc-prim-0.6.1" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$USER_HOME$/AppData/Local/rikvdkleij/intellij-haskell/cache/lib/bfi-haskell/ghc-prim-0.6.1" />
</SOURCES>
</library>
<component name="libraryTable">
<library name="ghc-prim-0.6.1">
<CLASSES>
<root url="file://$USER_HOME$/AppData/Local/rikvdkleij/intellij-haskell/cache/lib/bfi-haskell/ghc-prim-0.6.1" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$USER_HOME$/AppData/Local/rikvdkleij/intellij-haskell/cache/lib/bfi-haskell/ghc-prim-0.6.1" />
</SOURCES>
</library>
</component>

View file

@ -1,11 +1,11 @@
<component name="libraryTable">
<library name="integer-gmp-1.0.3.0">
<CLASSES>
<root url="file://$USER_HOME$/AppData/Local/rikvdkleij/intellij-haskell/cache/lib/bfi-haskell/integer-gmp-1.0.3.0" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$USER_HOME$/AppData/Local/rikvdkleij/intellij-haskell/cache/lib/bfi-haskell/integer-gmp-1.0.3.0" />
</SOURCES>
</library>
<component name="libraryTable">
<library name="integer-gmp-1.0.3.0">
<CLASSES>
<root url="file://$USER_HOME$/AppData/Local/rikvdkleij/intellij-haskell/cache/lib/bfi-haskell/integer-gmp-1.0.3.0" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$USER_HOME$/AppData/Local/rikvdkleij/intellij-haskell/cache/lib/bfi-haskell/integer-gmp-1.0.3.0" />
</SOURCES>
</library>
</component>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Haskell Tool Stack" project-jdk-type="Haskell Tool Stack SDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Haskell Tool Stack" project-jdk-type="Haskell Tool Stack SDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/bfi-haskell.iml" filepath="$PROJECT_DIR$/bfi-haskell.iml" />
</modules>
</component>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/bfi-haskell.iml" filepath="$PROJECT_DIR$/bfi-haskell.iml" />
</modules>
</component>
</project>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

View file

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="HASKELL_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/app" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/.stack-work" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="base-4.14.1.0" level="project" />
<orderEntry type="library" name="ghc-prim-0.6.1" level="project" />
<orderEntry type="library" name="integer-gmp-1.0.3.0" level="project" />
</component>
<?xml version="1.0" encoding="UTF-8"?>
<module type="HASKELL_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/app" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/.stack-work" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="base-4.14.1.0" level="project" />
<orderEntry type="library" name="ghc-prim-0.6.1" level="project" />
<orderEntry type="library" name="integer-gmp-1.0.3.0" level="project" />
</component>
</module>

20
bfi-java/bf.b vendored
View file

@ -1,11 +1,11 @@
++++++++++[>++++++++++<-]>>++++++++++>->>>>>>>>>>>>>>>>-->+++++++[->++
++++++++<]>[->+>+>+>+<<<<]+++>>+++>>>++++++++[-<++++<++++<++++>>>]++++
+[-<++++<++++>>]>>-->++++++[->+++++++++++<]>[->+>+>+>+<<<<]+++++>>+>++
++++>++++++>++++++++[-<++++<++++<++++>>>]++++++[-<+++<+++<+++>>>]>>-->
---+[-<+]-<[+[->+]-<<->>>+>[-]++[-->++]-->+++[---++[--<++]---->>-<+>[+
+++[----<++++]--[>]++[-->++]--<]>++[--+[-<+]->>[-]+++++[---->++++]-->[
->+<]>>[.>]++[-->++]]-->+++]---+[-<+]->>-[+>>>+[-<+]->>>++++++++++<<[-
>+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>
+>>]<<<<<]>[-]>>[>++++++[-<++++++++>]<.<<+>+>[-]]<[<[->-<]++++++[->+++
+++++<]>.[-]]<<++++++[-<++++++++>]<.[-]<<[-<+>]+[-<+]->>]+[-]<<<.>>>+[
++++++++++[>++++++++++<-]>>++++++++++>->>>>>>>>>>>>>>>>-->+++++++[->++
++++++++<]>[->+>+>+>+<<<<]+++>>+++>>>++++++++[-<++++<++++<++++>>>]++++
+[-<++++<++++>>]>>-->++++++[->+++++++++++<]>[->+>+>+>+<<<<]+++++>>+>++
++++>++++++>++++++++[-<++++<++++<++++>>>]++++++[-<+++<+++<+++>>>]>>-->
---+[-<+]-<[+[->+]-<<->>>+>[-]++[-->++]-->+++[---++[--<++]---->>-<+>[+
+++[----<++++]--[>]++[-->++]--<]>++[--+[-<+]->>[-]+++++[---->++++]-->[
->+<]>>[.>]++[-->++]]-->+++]---+[-<+]->>-[+>>>+[-<+]->>>++++++++++<<[-
>+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>
+>>]<<<<<]>[-]>>[>++++++[-<++++++++>]<.<<+>+>[-]]<[<[->-<]++++++[->+++
+++++<]>.[-]]<<++++++[-<++++++++>]<.[-]<<[-<+>]+[-<+]->>]+[-]<<<.>>>+[
-<+]-<<]

View file

@ -1,111 +1,111 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
public class Brainfuck {
private static final int MEM_SIZE = 0xFFFF;
public List<Character> minify(String program) {
List<Character> chars = List.of('>', '<', '+', '-', '.', ',', '[', ']');
return program.chars()
.mapToObj(c -> (char) c)
.filter(chars::contains)
.collect(Collectors.toList());
}
public String interpret(List<Character> pgm) {
StringBuilder out = new StringBuilder();
int pointer = 0;
short[] memory = new short[MEM_SIZE];
int pc = 0;
while (pc < pgm.size()) {
switch (pgm.get(pc)) {
case '>' -> {
if (pointer == MEM_SIZE - 1) {
pointer = 0;
} else {
pointer++;
}
}
case '<' -> {
if (pointer == 0) {
pointer = MEM_SIZE - 1;
} else {
pointer--;
}
}
case '+' -> increment(memory, pointer);
case '-' -> decrement(memory, pointer);
case '.' -> {
out.append((char) memory[pointer]);
}
case ',' -> {
} //todo implement i guess
case '[' -> {
if (memory[pointer] == 0) {
int level = 0;
while (pgm.get(pc) != ']' || level > -1) {
pc++;
char instruction = pgm.get(pc);
if (instruction == '[') level++;
else if (instruction == ']') level--;
}
}
}
case ']' -> { //error lies here
if (memory[pointer] != 0) {
int level = 0;
while (pgm.get(pc) != '[' || level > -1) {
pc--;
char instruction = pgm.get(pc);
if (instruction == '[') level--;
else if (instruction == ']') level++;
}
}
}
}
pc++;
}
return out.toString();
}
private void increment(short[] memory, int pointer) {
if (memory[pointer] == 0xFF) {
memory[pointer] = 0;
} else {
memory[pointer]++;
}
}
private void decrement(short[] memory, int pointer) {
if (memory[pointer] == 0) {
memory[pointer] = 0xFF;
} else {
memory[pointer]--;
}
}
public static void main(String[] args) throws IOException {
Brainfuck brainfuck = new Brainfuck();
if (args.length < 1) {
System.out.println("Please specify a path");
return;
}
String program = Files.readString(Paths.get(args[0]));
List<Character> minified = brainfuck.minify(program);
long time1 = System.currentTimeMillis();
String result = brainfuck.interpret(minified);
long time = System.currentTimeMillis() - time1;
System.out.println(result);
System.out.println("Finished execution in " + time + "ms");
}
}
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
public class Brainfuck {
private static final int MEM_SIZE = 0xFFFF;
public List<Character> minify(String program) {
List<Character> chars = List.of('>', '<', '+', '-', '.', ',', '[', ']');
return program.chars().parallel()
.mapToObj(c -> (char) c)
.filter(chars::contains)
.collect(Collectors.toList());
}
public String interpret(List<Character> pgm) {
StringBuilder out = new StringBuilder();
int pointer = 0;
short[] memory = new short[MEM_SIZE];
int pc = 0;
while (pc < pgm.size()) {
switch (pgm.get(pc)) {
case '>' -> {
if (pointer == MEM_SIZE - 1) {
pointer = 0;
} else {
pointer++;
}
}
case '<' -> {
if (pointer == 0) {
pointer = MEM_SIZE - 1;
} else {
pointer--;
}
}
case '+' -> increment(memory, pointer);
case '-' -> decrement(memory, pointer);
case '.' -> {
out.append((char) memory[pointer]);
}
case ',' -> {
} //todo implement i guess
case '[' -> {
if (memory[pointer] == 0) {
int level = 0;
while (pgm.get(pc) != ']' || level > -1) {
pc++;
char instruction = pgm.get(pc);
if (instruction == '[') level++;
else if (instruction == ']') level--;
}
}
}
case ']' -> { //error lies here
if (memory[pointer] != 0) {
int level = 0;
while (pgm.get(pc) != '[' || level > -1) {
pc--;
char instruction = pgm.get(pc);
if (instruction == '[') level--;
else if (instruction == ']') level++;
}
}
}
}
pc++;
}
return out.toString();
}
private void increment(short[] memory, int pointer) {
if (memory[pointer] == 0xFF) {
memory[pointer] = 0;
} else {
memory[pointer]++;
}
}
private void decrement(short[] memory, int pointer) {
if (memory[pointer] == 0) {
memory[pointer] = 0xFF;
} else {
memory[pointer]--;
}
}
public static void main(String[] args) throws IOException {
Brainfuck brainfuck = new Brainfuck();
if (args.length < 1) {
System.out.println("Please specify a path");
return;
}
String program = Files.readString(Paths.get(args[0]));
List<Character> minified = brainfuck.minify(program);
long time1 = System.currentTimeMillis();
String result = brainfuck.interpret(minified);
long time = System.currentTimeMillis() - time1;
System.out.println(result);
System.out.println("Finished execution in " + time + "ms");
}
}

8
bfi-rust/.gitignore vendored
View file

@ -1,5 +1,3 @@
/target
.idea
# brainfuck testing code, get your own
*.b
*.bf
/target
.idea
# brainfuck testing code, get your own

2
bfi-rust/Cargo.lock generated
View file

@ -2,4 +2,4 @@
# It is not intended for manual editing.
[[package]]
name = "bfinterpreter"
version = "0.1.0"
version = "0.1.1"

View file

@ -1,13 +1,15 @@
[package]
name = "bfinterpreter"
version = "0.1.0"
authors = ["Nilstrieb <nilstrieb@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[profile.dev]
opt-level = 3
[package]
name = "bfinterpreter"
version = "0.1.1"
authors = ["Nilstrieb <nilstrieb@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[profile.release]
debug = true
[profile.dev]
opt-level = 3

412
bfi-rust/flamegraph.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 437 KiB

View file

@ -1,96 +1,96 @@
use crate::interpreter::optimized::PrintMode;
use std::str::Chars;
pub mod simple;
pub mod parsed;
pub mod optimized;
pub const MEM_SIZE: usize = 0xFFFF;
pub type Memory = [u8; MEM_SIZE];
#[derive(Debug, PartialOrd, PartialEq, Ord, Eq, Clone)]
pub enum Statement {
Inc,
Dec,
R,
L,
Out,
DOut,
In,
Loop(Vec<Statement>),
}
const ALLOWED_CHARS: [char; 8] = ['>', '<', '+', '-', '.', ',', '[', ']'];
pub fn minify(code: &str) -> String {
code.chars().filter(|c| ALLOWED_CHARS.contains(c)).collect()
}
pub fn parse(chars: Chars, print_mode: PrintMode) -> Vec<Statement> {
let mut loop_stack = vec![vec![]];
for c in chars {
match c {
'+' => loop_stack.last_mut().unwrap().push(Statement::Inc),
'-' => loop_stack.last_mut().unwrap().push(Statement::Dec),
'>' => loop_stack.last_mut().unwrap().push(Statement::R),
'<' => loop_stack.last_mut().unwrap().push(Statement::L),
'.' => {
match print_mode {
PrintMode::ToString => loop_stack.last_mut().unwrap().push(Statement::Out),
PrintMode::DirectPrint => loop_stack.last_mut().unwrap().push(Statement::DOut)
}
}
',' => loop_stack.last_mut().unwrap().push(Statement::In),
'[' => loop_stack.push(vec![]),
']' => {
let statement = Statement::Loop(loop_stack.pop().unwrap());
loop_stack.last_mut().unwrap().push(statement);
}
_ => ()
}
}
loop_stack.pop().unwrap()
}
#[cfg(test)]
mod tests {
use crate::interpreter::{parse, minify};
use crate::interpreter::Statement::{Dec, In, Inc, L, Loop, Out, R};
#[test]
fn minify_test() {
let program = "sdahf+saga-46<sgbv>a[r]r.hr,e";
let expected = "+-<>[].,";
assert_eq!(String::from(expected), minify(program));
}
#[test]
fn parse_no_loop() {
let program = "+-<>,.";
let statements = vec![Inc, Dec, L, R, In, Out];
let result = parse(program.chars().collect(), false);
assert_eq!(statements, result);
}
#[test]
fn parse_simple_loop() {
let program = "+[<<]-";
let statements = vec![Inc, Loop(vec![L, L]), Dec];
let result = parse(program.chars().collect(), false);
assert_eq!(statements, result);
}
#[test]
fn parse_complex_loops() {
let program = ">[<[][<[<]>]>[>]]";
let statements = vec![R, Loop(vec![L, Loop(vec![]), Loop(vec![L, Loop(vec![L]), R]), R, Loop(vec![R])])];
let result = parse(program.chars().collect(), false);
assert_eq!(statements, result);
}
use crate::interpreter::optimized::PrintMode;
use std::str::Chars;
pub mod simple;
pub mod parsed;
pub mod optimized;
pub const MEM_SIZE: usize = 0xFFFF;
pub type Memory = [u8; MEM_SIZE];
#[derive(Debug, PartialOrd, PartialEq, Ord, Eq, Clone)]
pub enum Statement {
Inc,
Dec,
R,
L,
Out,
DOut,
In,
Loop(Vec<Statement>),
}
const ALLOWED_CHARS: [char; 8] = ['>', '<', '+', '-', '.', ',', '[', ']'];
pub fn minify(code: &str) -> String {
code.chars().filter(|c| ALLOWED_CHARS.contains(c)).collect()
}
pub fn parse(chars: Chars, print_mode: PrintMode) -> Vec<Statement> {
let mut loop_stack = vec![vec![]];
for c in chars {
match c {
'+' => loop_stack.last_mut().unwrap().push(Statement::Inc),
'-' => loop_stack.last_mut().unwrap().push(Statement::Dec),
'>' => loop_stack.last_mut().unwrap().push(Statement::R),
'<' => loop_stack.last_mut().unwrap().push(Statement::L),
'.' => {
match print_mode {
PrintMode::ToString => loop_stack.last_mut().unwrap().push(Statement::Out),
PrintMode::DirectPrint => loop_stack.last_mut().unwrap().push(Statement::DOut)
}
}
',' => loop_stack.last_mut().unwrap().push(Statement::In),
'[' => loop_stack.push(vec![]),
']' => {
let statement = Statement::Loop(loop_stack.pop().unwrap());
loop_stack.last_mut().unwrap().push(statement);
}
_ => ()
}
}
loop_stack.pop().unwrap()
}
#[cfg(test)]
mod tests {
use crate::interpreter::{parse, minify};
use crate::interpreter::Statement::{Dec, In, Inc, L, Loop, Out, R};
#[test]
fn minify_test() {
let program = "sdahf+saga-46<sgbv>a[r]r.hr,e";
let expected = "+-<>[].,";
assert_eq!(String::from(expected), minify(program));
}
#[test]
fn parse_no_loop() {
let program = "+-<>,.";
let statements = vec![Inc, Dec, L, R, In, Out];
let result = parse(program.chars().collect(), false);
assert_eq!(statements, result);
}
#[test]
fn parse_simple_loop() {
let program = "+[<<]-";
let statements = vec![Inc, Loop(vec![L, L]), Dec];
let result = parse(program.chars().collect(), false);
assert_eq!(statements, result);
}
#[test]
fn parse_complex_loops() {
let program = ">[<[][<[<]>]>[>]]";
let statements = vec![R, Loop(vec![L, Loop(vec![]), Loop(vec![L, Loop(vec![L]), R]), R, Loop(vec![R])])];
let result = parse(program.chars().collect(), false);
assert_eq!(statements, result);
}
}

View file

@ -1,229 +1,229 @@
//! # optimization time
//! some better optimizations like set null, repeating and doing more stuff with simplifying stuff
//!
mod patterns;
use std::io::{Read, stdin, Write};
use crate::interpreter::{minify, parse, Statement, Memory, MEM_SIZE};
use std::error::Error;
use std::fmt::{Display, Formatter};
use std::fmt;
use std::ops::Deref;
#[derive(PartialOrd, PartialEq, Ord, Eq, Clone, Debug)]
enum ExStatement {
Inc,
Dec,
R,
L,
Out,
DOut,
In,
Loop(Vec<ExStatement>),
SetNull,
Repeat(Box<ExStatement>, usize),
_ForLoop(usize, Box<ExStatement>),
}
impl From<Statement> for ExStatement {
fn from(s: Statement) -> Self {
match s {
Statement::L => ExStatement::L,
Statement::R => ExStatement::R,
Statement::Inc => ExStatement::Inc,
Statement::Dec => ExStatement::Dec,
Statement::In => ExStatement::In,
Statement::Out => ExStatement::Out,
Statement::Loop(v) => ExStatement::Loop(
v.into_iter().map(ExStatement::from).collect()
),
Statement::DOut => ExStatement::DOut
}
}
}
#[derive(Debug)]
pub struct BfErr {
msg: &'static str,
}
impl BfErr {
pub fn new(msg: &'static str) -> BfErr {
BfErr { msg }
}
}
impl Display for BfErr {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "Error interpreting brainfuck code: {}", self.msg)
}
}
impl Error for BfErr {}
pub enum PrintMode {
ToString,
DirectPrint,
}
pub fn run(pgm: &str, print_mode: PrintMode) -> Result<String, BfErr> {
let pgm = minify(pgm);
if pgm.is_empty() { return Err(BfErr::new("no program found")); };
let pgm = parse(pgm.chars(), print_mode);
let pgm = optimize(&pgm);
let out = interpret(&pgm);
Ok(out)
}
fn optimize(code: &[Statement]) -> Vec<ExStatement> {
let code = o_set_null(code);
o_repeat(code)
}
fn o_set_null(code: &[Statement]) -> Vec<ExStatement> {
code.iter().map(|s| {
match s {
Statement::Loop(v) => {
if let [Statement::Dec] = v[..] {
ExStatement::SetNull
} else {
ExStatement::Loop(optimize(v))
}
}
Statement::Inc => ExStatement::Inc,
Statement::Dec => ExStatement::Dec,
Statement::R => ExStatement::R,
Statement::L => ExStatement::L,
Statement::Out => ExStatement::Out,
Statement::DOut => ExStatement::DOut,
Statement::In => ExStatement::In,
}
}).collect()
}
fn o_repeat(code: Vec<ExStatement>) -> Vec<ExStatement> {
let mut amount = 0;
let mut result: Vec<ExStatement> = vec![];
for i in 0..code.len() {
if code.get(i) == code.get(i + 1) {
amount += 1;
} else if amount == 0 {
result.push(code[i].clone())
} else {
amount += 1;
result.push(ExStatement::Repeat(Box::new(code[i].clone()), amount as usize));
amount = 0;
}
}
result
}
fn interpret(pgm: &[ExStatement]) -> String {
let mut out = String::new();
let mut pointer: usize = 0;
let mut mem: [u8; MEM_SIZE] = [0; MEM_SIZE];
for s in pgm {
execute(s, &mut mem, &mut pointer, &mut out)
}
out
}
fn execute(statement: &ExStatement, mem: &mut Memory, pointer: &mut usize, out: &mut String) {
match statement {
ExStatement::R => if *pointer == MEM_SIZE - 1 { *pointer = 0 } else { *pointer += 1 },
ExStatement::L => if *pointer == 0 { *pointer = MEM_SIZE - 1 } else { *pointer -= 1 },
ExStatement::Inc => mem[*pointer] = mem[*pointer].wrapping_add(1),
ExStatement::Dec => mem[*pointer] = mem[*pointer].wrapping_sub(1),
ExStatement::SetNull => mem[*pointer] = 0,
ExStatement::Out => out.push(mem[*pointer] as u8 as char),
ExStatement::DOut => {
print!("{}", mem[*pointer] as u8 as char);
std::io::stdout().flush().unwrap();
}
ExStatement::In => {
let mut in_buffer = [0, 1];
stdin().read_exact(&mut in_buffer).unwrap();
mem[*pointer] = in_buffer[0] as u8;
}
ExStatement::Loop(vec) => {
while mem[*pointer] != 0 {
for s in vec {
execute(&s, mem, pointer, out);
}
}
}
ExStatement::Repeat(statement, amount) => {
match statement.deref() {
ExStatement::R => {
*pointer += amount;
if *pointer > MEM_SIZE {
*pointer %= MEM_SIZE
}
}
ExStatement::L => *pointer = (*pointer).wrapping_sub(*amount),
ExStatement::Inc => mem[*pointer] = mem[*pointer].wrapping_add(*amount as u8),
ExStatement::Dec => mem[*pointer] = mem[*pointer].wrapping_sub(*amount as u8),
ExStatement::Loop(v) => {
for _ in 0..*amount {
execute(&ExStatement::Loop(v.clone()), mem, pointer, out)
}
}
s => {
for _ in 0..*amount {
execute(s, mem, pointer, out)
}
}
}
}
ExStatement::_ForLoop(offset, statement) => {
*pointer += offset;
while mem[*pointer - offset] != 0 {
execute(statement, mem, pointer, out);
}
}
};
}
#[cfg(test)]
mod test {
use crate::interpreter::optimized::{run, o_repeat};
use crate::interpreter::optimized::ExStatement::{Inc, Repeat, R, L, Dec};
#[test]
fn run_loop() {
let program = "++++++++++[>++++++++++<-]>.";
let out = run(program, false).unwrap();
assert_eq!(out, String::from("d"));
}
#[test]
fn hello_world() {
let program = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
let out = run(program, false).unwrap();
assert_eq!(out, String::from("Hello World!\n"));
}
#[test]
fn o_repeat_simple() {
let code = vec![Inc, Inc, Inc, R];
let expected = vec![Repeat(Box::new(Inc), 3), R];
println!("{}", code.len());
assert_eq!(expected, o_repeat(code));
}
#[test]
fn o_repeat_long() {
let code = vec![Inc, Inc, Inc, R, L, L, L, Dec, L, L, Dec];
let expected = vec![Repeat(Box::new(Inc), 3), R, Repeat(Box::new(L), 3), Dec, Repeat(Box::new(L), 2), Dec];
assert_eq!(expected, o_repeat(code));
}
}
//! # optimization time
//! some better optimizations like set null, repeating and doing more stuff with simplifying stuff
//!
mod patterns;
use std::io::{Read, stdin, Write};
use crate::interpreter::{minify, parse, Statement, Memory, MEM_SIZE};
use std::error::Error;
use std::fmt::{Display, Formatter};
use std::fmt;
use std::ops::Deref;
#[derive(PartialOrd, PartialEq, Ord, Eq, Clone, Debug)]
enum ExStatement {
Inc,
Dec,
R,
L,
Out,
DOut,
In,
Loop(Vec<ExStatement>),
SetNull,
Repeat(Box<ExStatement>, usize),
_ForLoop(usize, Box<ExStatement>),
}
impl From<Statement> for ExStatement {
fn from(s: Statement) -> Self {
match s {
Statement::L => ExStatement::L,
Statement::R => ExStatement::R,
Statement::Inc => ExStatement::Inc,
Statement::Dec => ExStatement::Dec,
Statement::In => ExStatement::In,
Statement::Out => ExStatement::Out,
Statement::Loop(v) => ExStatement::Loop(
v.into_iter().map(ExStatement::from).collect()
),
Statement::DOut => ExStatement::DOut
}
}
}
#[derive(Debug)]
pub struct BfErr {
msg: &'static str,
}
impl BfErr {
pub fn new(msg: &'static str) -> BfErr {
BfErr { msg }
}
}
impl Display for BfErr {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "Error interpreting brainfuck code: {}", self.msg)
}
}
impl Error for BfErr {}
pub enum PrintMode {
ToString,
DirectPrint,
}
pub fn run(pgm: &str, print_mode: PrintMode) -> Result<String, BfErr> {
let pgm = minify(pgm);
if pgm.is_empty() { return Err(BfErr::new("no program found")); };
let pgm = parse(pgm.chars(), print_mode);
let pgm = optimize(&pgm);
let out = interpret(&pgm);
Ok(out)
}
fn optimize(code: &[Statement]) -> Vec<ExStatement> {
let code = o_set_null(code);
o_repeat(code)
}
fn o_set_null(code: &[Statement]) -> Vec<ExStatement> {
code.iter().map(|s| {
match s {
Statement::Loop(v) => {
if let [Statement::Dec] = v[..] {
ExStatement::SetNull
} else {
ExStatement::Loop(optimize(v))
}
}
Statement::Inc => ExStatement::Inc,
Statement::Dec => ExStatement::Dec,
Statement::R => ExStatement::R,
Statement::L => ExStatement::L,
Statement::Out => ExStatement::Out,
Statement::DOut => ExStatement::DOut,
Statement::In => ExStatement::In,
}
}).collect()
}
fn o_repeat(code: Vec<ExStatement>) -> Vec<ExStatement> {
let mut amount = 0;
let mut result: Vec<ExStatement> = vec![];
for i in 0..code.len() {
if code.get(i) == code.get(i + 1) {
amount += 1;
} else if amount == 0 {
result.push(code[i].clone())
} else {
amount += 1;
result.push(ExStatement::Repeat(Box::new(code[i].clone()), amount as usize));
amount = 0;
}
}
result
}
fn interpret(pgm: &[ExStatement]) -> String {
let mut out = String::new();
let mut pointer: usize = 0;
let mut mem: [u8; MEM_SIZE] = [0; MEM_SIZE];
for s in pgm {
execute(s, &mut mem, &mut pointer, &mut out)
}
out
}
fn execute(statement: &ExStatement, mem: &mut Memory, pointer: &mut usize, out: &mut String) {
match statement {
ExStatement::R => if *pointer == MEM_SIZE - 1 { *pointer = 0 } else { *pointer += 1 },
ExStatement::L => if *pointer == 0 { *pointer = MEM_SIZE - 1 } else { *pointer -= 1 },
ExStatement::Inc => mem[*pointer] = mem[*pointer].wrapping_add(1),
ExStatement::Dec => mem[*pointer] = mem[*pointer].wrapping_sub(1),
ExStatement::SetNull => mem[*pointer] = 0,
ExStatement::Out => out.push(mem[*pointer] as u8 as char),
ExStatement::DOut => {
print!("{}", mem[*pointer] as u8 as char);
std::io::stdout().flush().unwrap();
}
ExStatement::In => {
let mut in_buffer = [0, 1];
stdin().read_exact(&mut in_buffer).unwrap();
mem[*pointer] = in_buffer[0] as u8;
}
ExStatement::Loop(vec) => {
while mem[*pointer] != 0 {
for s in vec {
execute(&s, mem, pointer, out);
}
}
}
ExStatement::Repeat(statement, amount) => {
match statement.deref() {
ExStatement::R => {
*pointer += amount;
if *pointer > MEM_SIZE {
*pointer %= MEM_SIZE
}
}
ExStatement::L => *pointer = (*pointer).wrapping_sub(*amount),
ExStatement::Inc => mem[*pointer] = mem[*pointer].wrapping_add(*amount as u8),
ExStatement::Dec => mem[*pointer] = mem[*pointer].wrapping_sub(*amount as u8),
ExStatement::Loop(v) => {
for _ in 0..*amount {
execute(&ExStatement::Loop(v.clone()), mem, pointer, out)
}
}
s => {
for _ in 0..*amount {
execute(s, mem, pointer, out)
}
}
}
}
ExStatement::_ForLoop(offset, statement) => {
*pointer += offset;
while mem[*pointer - offset] != 0 {
execute(statement, mem, pointer, out);
}
}
};
}
#[cfg(test)]
mod test {
use crate::interpreter::optimized::{run, o_repeat};
use crate::interpreter::optimized::ExStatement::{Inc, Repeat, R, L, Dec};
#[test]
fn run_loop() {
let program = "++++++++++[>++++++++++<-]>.";
let out = run(program, false).unwrap();
assert_eq!(out, String::from("d"));
}
#[test]
fn hello_world() {
let program = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
let out = run(program, false).unwrap();
assert_eq!(out, String::from("Hello World!\n"));
}
#[test]
fn o_repeat_simple() {
let code = vec![Inc, Inc, Inc, R];
let expected = vec![Repeat(Box::new(Inc), 3), R];
println!("{}", code.len());
assert_eq!(expected, o_repeat(code));
}
#[test]
fn o_repeat_long() {
let code = vec![Inc, Inc, Inc, R, L, L, L, Dec, L, L, Dec];
let expected = vec![Repeat(Box::new(Inc), 3), R, Repeat(Box::new(L), 3), Dec, Repeat(Box::new(L), 2), Dec];
assert_eq!(expected, o_repeat(code));
}
}

View file

@ -1,43 +1,43 @@
//!
//! # Patterns find and replace
//! Pattern-match ExStatements and replace them with optimizations like add, multiply etc
use crate::interpreter::optimized::ExStatement;
///
/// Replace this: `[>>x<<-]` or `[->>x<<]` with `WhileAdd(2, x)`
fn _for_loop(to_test: ExStatement) -> ExStatement {
match to_test {
ExStatement::Loop(v) => {
match v[..] {
[ExStatement::R, ExStatement::Inc, ExStatement::L, ExStatement::Dec] => {
ExStatement::_ForLoop(1, Box::from(ExStatement::Inc))
}
_ => ExStatement::Loop(v)
}
},
s => s
}
}
#[cfg(test)]
mod test {
use crate::interpreter::optimized::ExStatement::{Out, Loop, Inc, R, L, Dec, _ForLoop};
use crate::interpreter::optimized::patterns::_for_loop;
#[test]
fn for_loop_false() {
let statement = Loop(vec![Out, Inc]);
assert_eq!(statement.clone(), _for_loop(statement));
}
#[test]
fn for_loop_simplest() {
let statement = Loop(vec![R, Inc, L, Dec]);
assert_eq!(_ForLoop(1, Box::from(Inc)), _for_loop(statement));
}
//!
//! # Patterns find and replace
//! Pattern-match ExStatements and replace them with optimizations like add, multiply etc
use crate::interpreter::optimized::ExStatement;
///
/// Replace this: `[>>x<<-]` or `[->>x<<]` with `WhileAdd(2, x)`
fn _for_loop(to_test: ExStatement) -> ExStatement {
match to_test {
ExStatement::Loop(v) => {
match v[..] {
[ExStatement::R, ExStatement::Inc, ExStatement::L, ExStatement::Dec] => {
ExStatement::_ForLoop(1, Box::from(ExStatement::Inc))
}
_ => ExStatement::Loop(v)
}
},
s => s
}
}
#[cfg(test)]
mod test {
use crate::interpreter::optimized::ExStatement::{Out, Loop, Inc, R, L, Dec, _ForLoop};
use crate::interpreter::optimized::patterns::_for_loop;
#[test]
fn for_loop_false() {
let statement = Loop(vec![Out, Inc]);
assert_eq!(statement.clone(), _for_loop(statement));
}
#[test]
fn for_loop_simplest() {
let statement = Loop(vec![R, Inc, L, Dec]);
assert_eq!(_ForLoop(1, Box::from(Inc)), _for_loop(statement));
}
}

View file

@ -1,122 +1,122 @@
//!
//! # optimization time
//!
//! first parse the bf so that it can be executed faster
//! most importantly: loop jumps should be immediate
#![allow(dead_code)]
use std::io::{Read, stdin, Write};
use crate::interpreter::{MEM_SIZE, Memory, minify, parse, Statement};
use crate::interpreter::optimized::PrintMode;
use crate::repl::BrainfuckState;
pub fn run(pgm: &str) -> String {
let pgm = minify(pgm);
let pgm = parse(pgm.chars(), PrintMode::ToString);
interpret(&pgm)
}
fn interpret(pgm: &[Statement]) -> String {
let mut out = String::new();
let mut pointer: usize = 0;
let mut mem: [u8; MEM_SIZE] = [0; MEM_SIZE];
for s in pgm {
execute(s, &mut mem, &mut pointer, &mut out)
}
out
}
pub fn interpret_with_state(pgm: &[Statement], state: &mut BrainfuckState) {
for s in pgm {
execute(s, &mut state.memory, &mut state.pointer, &mut String::new())
}
}
fn execute(statement: &Statement, mem: &mut Memory, pointer: &mut usize, out: &mut String) {
match statement {
Statement::R => if *pointer == MEM_SIZE - 1 { *pointer = 0 } else { *pointer += 1 },
Statement::L => if *pointer == 0 { *pointer = MEM_SIZE - 1 } else { *pointer -= 1 },
Statement::Inc => mem[*pointer] = mem[*pointer].wrapping_add(1),
Statement::Dec => mem[*pointer] = mem[*pointer].wrapping_sub(1),
Statement::Out => out.push(mem[*pointer] as u8 as char),
Statement::In => {
let mut in_buffer = [0, 1];
stdin().read_exact(&mut in_buffer).unwrap();
mem[*pointer] = in_buffer[0] as u8;
}
Statement::Loop(vec) => {
while mem[*pointer] != 0 {
for s in vec {
execute(&s, mem, pointer, out);
}
}
}
Statement::DOut => {
print!("{}", mem[*pointer] as u8 as char);
std::io::stdout().flush().unwrap();
}
}
}
#[cfg(test)]
mod test {
use crate::interpreter::parsed::{execute, run, Statement};
#[test]
fn execute_simple() {
let mut pointer: usize = 0;
let mut mem: [u8; 65535] = [0; 65535];
let mut out = String::new();
execute(&Statement::R, &mut mem, &mut pointer, &mut out);
assert_eq!(pointer, 1);
execute(&Statement::L, &mut mem, &mut pointer, &mut out);
assert_eq!(pointer, 0);
execute(&Statement::Inc, &mut mem, &mut pointer, &mut out);
assert_eq!(mem[pointer], 1);
execute(&Statement::Dec, &mut mem, &mut pointer, &mut out);
assert_eq!(mem[pointer], 0);
}
#[test]
fn execute_false_loop() {
let statement = Statement::Loop(vec![Statement::Inc, Statement::Inc, Statement::R]);
let mut pointer: usize = 0;
let mut mem: [u8; 65535] = [0; 65535];
execute(&statement, &mut mem, &mut pointer, &mut String::new());
assert_eq!(mem[0], 0);
assert_eq!(mem[1], 0);
}
#[test]
fn execute_loop() {
let statement = Statement::Loop(vec![Statement::Inc, Statement::Inc, Statement::R]);
let mut pointer: usize = 0;
let mut mem: [u8; 65535] = [0; 65535];
mem[0] = 1;
execute(&statement, &mut mem, &mut pointer, &mut String::new());
assert_eq!(mem[0], 3);
assert_eq!(mem[1], 0);
}
#[test]
fn run_loop() {
let program = "++++++++++[>++++++++++<-]>.";
let out = run(program);
assert_eq!(out, String::from("d"));
}
#[test]
fn hello_world() {
let program = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
let out = run(program);
assert_eq!(out, String::from("Hello World!\n"));
}
//!
//! # optimization time
//!
//! first parse the bf so that it can be executed faster
//! most importantly: loop jumps should be immediate
#![allow(dead_code)]
use std::io::{Read, stdin, Write};
use crate::interpreter::{MEM_SIZE, Memory, minify, parse, Statement};
use crate::interpreter::optimized::PrintMode;
use crate::repl::BrainfuckState;
pub fn run(pgm: &str) -> String {
let pgm = minify(pgm);
let pgm = parse(pgm.chars(), PrintMode::ToString);
interpret(&pgm)
}
fn interpret(pgm: &[Statement]) -> String {
let mut out = String::new();
let mut pointer: usize = 0;
let mut mem: [u8; MEM_SIZE] = [0; MEM_SIZE];
for s in pgm {
execute(s, &mut mem, &mut pointer, &mut out)
}
out
}
pub fn interpret_with_state(pgm: &[Statement], state: &mut BrainfuckState) {
for s in pgm {
execute(s, &mut state.memory, &mut state.pointer, &mut String::new())
}
}
fn execute(statement: &Statement, mem: &mut Memory, pointer: &mut usize, out: &mut String) {
match statement {
Statement::R => if *pointer == MEM_SIZE - 1 { *pointer = 0 } else { *pointer += 1 },
Statement::L => if *pointer == 0 { *pointer = MEM_SIZE - 1 } else { *pointer -= 1 },
Statement::Inc => mem[*pointer] = mem[*pointer].wrapping_add(1),
Statement::Dec => mem[*pointer] = mem[*pointer].wrapping_sub(1),
Statement::Out => out.push(mem[*pointer] as u8 as char),
Statement::In => {
let mut in_buffer = [0, 1];
stdin().read_exact(&mut in_buffer).unwrap();
mem[*pointer] = in_buffer[0] as u8;
}
Statement::Loop(vec) => {
while mem[*pointer] != 0 {
for s in vec {
execute(&s, mem, pointer, out);
}
}
}
Statement::DOut => {
print!("{}", mem[*pointer] as u8 as char);
std::io::stdout().flush().unwrap();
}
}
}
#[cfg(test)]
mod test {
use crate::interpreter::parsed::{execute, run, Statement};
#[test]
fn execute_simple() {
let mut pointer: usize = 0;
let mut mem: [u8; 65535] = [0; 65535];
let mut out = String::new();
execute(&Statement::R, &mut mem, &mut pointer, &mut out);
assert_eq!(pointer, 1);
execute(&Statement::L, &mut mem, &mut pointer, &mut out);
assert_eq!(pointer, 0);
execute(&Statement::Inc, &mut mem, &mut pointer, &mut out);
assert_eq!(mem[pointer], 1);
execute(&Statement::Dec, &mut mem, &mut pointer, &mut out);
assert_eq!(mem[pointer], 0);
}
#[test]
fn execute_false_loop() {
let statement = Statement::Loop(vec![Statement::Inc, Statement::Inc, Statement::R]);
let mut pointer: usize = 0;
let mut mem: [u8; 65535] = [0; 65535];
execute(&statement, &mut mem, &mut pointer, &mut String::new());
assert_eq!(mem[0], 0);
assert_eq!(mem[1], 0);
}
#[test]
fn execute_loop() {
let statement = Statement::Loop(vec![Statement::Inc, Statement::Inc, Statement::R]);
let mut pointer: usize = 0;
let mut mem: [u8; 65535] = [0; 65535];
mem[0] = 1;
execute(&statement, &mut mem, &mut pointer, &mut String::new());
assert_eq!(mem[0], 3);
assert_eq!(mem[1], 0);
}
#[test]
fn run_loop() {
let program = "++++++++++[>++++++++++<-]>.";
let out = run(program);
assert_eq!(out, String::from("d"));
}
#[test]
fn hello_world() {
let program = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
let out = run(program);
assert_eq!(out, String::from("Hello World!\n"));
}
}

View file

@ -1,71 +1,71 @@
//!
//! The very basic interpreter without any optimizations
#![allow(dead_code)]
use crate::interpreter::{MEM_SIZE, minify};
use std::io::{stdin, Read};
pub fn run(program: &str) -> String{
let program = minify(program);
let out = interpret(program.chars().collect());
out
}
fn interpret(pgm: Vec<char>) -> String {
let mut out = String::new();
let mut pointer: usize = 0;
let mut mem: [u8; MEM_SIZE] = [0; MEM_SIZE];
let mut in_buffer = [0; 1];
let mut pc = 0;
let len = pgm.len();
while pc < len {
match pgm[pc] {
'>' => if pointer == MEM_SIZE - 1 { pointer = 0 } else { pointer += 1 },
'<' => if pointer == 0 { pointer = MEM_SIZE - 1 } else { pointer -= 1 },
'+' => mem[pointer] = mem[pointer].wrapping_add(1),
'-' => mem[pointer] = mem[pointer].wrapping_sub(1),
'.' => out.push(mem[pointer] as u8 as char),
',' => {
stdin().read_exact(&mut in_buffer).unwrap();
mem[pointer] = in_buffer[0] as u8;
}
'[' => {
//jump to corresponding ]
if mem[pointer] == 0 {
let mut level = 0;
while pgm[pc] != ']' || level > -1 {
pc += 1;
match pgm[pc] {
'[' => {
level += 1
}
']' => {
level -= 1
}
_ => (),
}
}
}
}
']' => {
if mem[pointer] != 0 {
//jump to corresponding [
let mut level = 0;
while pgm[pc] != '[' || level > -1 {
pc -= 1;
match pgm[pc] {
'[' => level -= 1,
']' => level += 1,
_ => (),
}
}
}
}
_ => (),
}
pc += 1;
}
out
//!
//! The very basic interpreter without any optimizations
#![allow(dead_code)]
use crate::interpreter::{MEM_SIZE, minify};
use std::io::{stdin, Read};
pub fn run(program: &str) -> String{
let program = minify(program);
let out = interpret(program.chars().collect());
out
}
fn interpret(pgm: Vec<char>) -> String {
let mut out = String::new();
let mut pointer: usize = 0;
let mut mem: [u8; MEM_SIZE] = [0; MEM_SIZE];
let mut in_buffer = [0; 1];
let mut pc = 0;
let len = pgm.len();
while pc < len {
match pgm[pc] {
'>' => if pointer == MEM_SIZE - 1 { pointer = 0 } else { pointer += 1 },
'<' => if pointer == 0 { pointer = MEM_SIZE - 1 } else { pointer -= 1 },
'+' => mem[pointer] = mem[pointer].wrapping_add(1),
'-' => mem[pointer] = mem[pointer].wrapping_sub(1),
'.' => out.push(mem[pointer] as u8 as char),
',' => {
stdin().read_exact(&mut in_buffer).unwrap();
mem[pointer] = in_buffer[0] as u8;
}
'[' => {
//jump to corresponding ]
if mem[pointer] == 0 {
let mut level = 0;
while pgm[pc] != ']' || level > -1 {
pc += 1;
match pgm[pc] {
'[' => {
level += 1
}
']' => {
level -= 1
}
_ => (),
}
}
}
}
']' => {
if mem[pointer] != 0 {
//jump to corresponding [
let mut level = 0;
while pgm[pc] != '[' || level > -1 {
pc -= 1;
match pgm[pc] {
'[' => level -= 1,
']' => level += 1,
_ => (),
}
}
}
}
_ => (),
}
pc += 1;
}
out
}

View file

@ -1,37 +1,37 @@
mod interpreter;
mod repl;
use std::{env, fs};
use std::time::SystemTime;
use crate::repl::start_repl;
use crate::interpreter::optimized::{PrintMode};
use std::error::Error;
fn main() {
let path = env::args().nth(1);
match path {
Some(p) => {
if let Err(why) = run_program(p) {
eprintln!("An error occurred in the program: {}", why)
}
},
None => start_repl()
};
}
fn run_program(path: String) -> Result<(), Box<dyn Error>> {
let program = match fs::read_to_string(path) {
Ok(p) => p,
Err(e) => {
println!("Error reading file: {}", e);
return Err(Box::from(e));
}
};
let start_time = SystemTime::now();
let out = interpreter::optimized::run(&*program, PrintMode::DirectPrint)?;
let duration = start_time.elapsed()?;
println!("{}\nFinished execution. Took {}ms", out, duration.as_millis());
Ok(())
mod interpreter;
mod repl;
use std::{env, fs};
use std::time::SystemTime;
use crate::repl::start_repl;
use crate::interpreter::optimized::{PrintMode};
use std::error::Error;
fn main() {
let path = env::args().nth(1);
match path {
Some(p) => {
if let Err(why) = run_program(p) {
eprintln!("An error occurred in the program: {}", why)
}
},
None => start_repl()
};
}
fn run_program(path: String) -> Result<(), Box<dyn Error>> {
let program = match fs::read_to_string(path) {
Ok(p) => p,
Err(e) => {
println!("Error reading file: {}", e);
return Err(Box::from(e));
}
};
let start_time = SystemTime::now();
let out = interpreter::optimized::run(&*program, PrintMode::DirectPrint)?;
let duration = start_time.elapsed()?;
println!("{}\nFinished execution. Took {}ms", out, duration.as_millis());
Ok(())
}

View file

@ -1,111 +1,111 @@
use std::fmt::{Display, Formatter};
use std::fmt;
use std::io::{stdin, stdout, Write};
use crate::interpreter::{minify, parse, parsed, Memory, MEM_SIZE};
use crate::interpreter::optimized::PrintMode;
pub struct BrainfuckState {
pub memory: Memory,
pub pointer: usize,
}
impl Display for BrainfuckState {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", display_state(self))
}
}
fn display_state(state: &BrainfuckState) -> String {
let start = if state.pointer < 5 {
0
} else if state.pointer > MEM_SIZE - 10 {
MEM_SIZE - 10
} else {
state.pointer - 5
};
format!("{}-\n|{}|\n{}-\n{}|\n{}|\n{}|\n{}-\n {}^^^^",
"----------".repeat(10),
{
let mut out = String::new();
let end = start + 10;
for i in start..end {
out.push_str(&*format!(" {: >5} ", i));
}
out
},
"----------".repeat(10),
"| ".repeat(10),
{
let mut out = String::new();
let end = start + 10;
for i in start..end {
out.push_str(&*format!("| {: >3} ", state.memory[i]));
}
out
},
"| ".repeat(10),
"----------".repeat(10),
" ".repeat(state.pointer - start))
}
pub fn start_repl() {
println!("Brainfuck REPL");
let mut state = BrainfuckState {
memory: [0; MEM_SIZE],
pointer: 0,
};
println!("Enter Brainfuck programs and they will be executed immediatly.");
println!("State is kept.");
println!("{}", state);
loop {
print!(">> ");
stdout().flush().unwrap();
match read_line() {
Ok(s) => {
match &*s {
":q" => break,
":?" | "help" | "?" => print_help(),
":r" => {
reset(&mut state);
println!("{}", state);
},
_ => {
print!("Output: ");
println!();
parse_input(s, &mut state);
println!("{}", state);
}
}
}
Err(why) => println!("Error reading input: {}\nPlease try again.", why)
}
}
}
fn reset(state: &mut BrainfuckState) {
state.pointer = 0;
state.memory = [0; MEM_SIZE];
}
fn print_help() {
println!("Brainfuck REPL help
:q => quit
:? => help
:r => reset state");
}
fn parse_input(pgm: String, state: &mut BrainfuckState) {
let pgm = minify(&*pgm);
let pgm = parse(pgm.chars(), PrintMode::DirectPrint);
parsed::interpret_with_state(&*pgm, state);
}
pub fn read_line() -> Result<String, std::io::Error> {
let mut buf = String::new();
stdin().read_line(&mut buf)?;
buf.pop();
Ok(buf)
use std::fmt::{Display, Formatter};
use std::fmt;
use std::io::{stdin, stdout, Write};
use crate::interpreter::{minify, parse, parsed, Memory, MEM_SIZE};
use crate::interpreter::optimized::PrintMode;
pub struct BrainfuckState {
pub memory: Memory,
pub pointer: usize,
}
impl Display for BrainfuckState {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", display_state(self))
}
}
fn display_state(state: &BrainfuckState) -> String {
let start = if state.pointer < 5 {
0
} else if state.pointer > MEM_SIZE - 10 {
MEM_SIZE - 10
} else {
state.pointer - 5
};
format!("{}-\n|{}|\n{}-\n{}|\n{}|\n{}|\n{}-\n {}^^^^",
"----------".repeat(10),
{
let mut out = String::new();
let end = start + 10;
for i in start..end {
out.push_str(&*format!(" {: >5} ", i));
}
out
},
"----------".repeat(10),
"| ".repeat(10),
{
let mut out = String::new();
let end = start + 10;
for i in start..end {
out.push_str(&*format!("| {: >3} ", state.memory[i]));
}
out
},
"| ".repeat(10),
"----------".repeat(10),
" ".repeat(state.pointer - start))
}
pub fn start_repl() {
println!("Brainfuck REPL");
let mut state = BrainfuckState {
memory: [0; MEM_SIZE],
pointer: 0,
};
println!("Enter Brainfuck programs and they will be executed immediatly.");
println!("State is kept.");
println!("{}", state);
loop {
print!(">> ");
stdout().flush().unwrap();
match read_line() {
Ok(s) => {
match &*s {
":q" => break,
":?" | "help" | "?" => print_help(),
":r" => {
reset(&mut state);
println!("{}", state);
},
_ => {
print!("Output: ");
println!();
parse_input(s, &mut state);
println!("{}", state);
}
}
}
Err(why) => println!("Error reading input: {}\nPlease try again.", why)
}
}
}
fn reset(state: &mut BrainfuckState) {
state.pointer = 0;
state.memory = [0; MEM_SIZE];
}
fn print_help() {
println!("Brainfuck REPL help
:q => quit
:? => help
:r => reset state");
}
fn parse_input(pgm: String, state: &mut BrainfuckState) {
let pgm = minify(&*pgm);
let pgm = parse(pgm.chars(), PrintMode::DirectPrint);
parsed::interpret_with_state(&*pgm, state);
}
pub fn read_line() -> Result<String, std::io::Error> {
let mut buf = String::new();
stdin().read_line(&mut buf)?;
buf.pop();
Ok(buf)
}

23
ibfi-ts/.gitignore vendored Normal file
View file

@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

27
ibfi-ts/README.md Normal file
View file

@ -0,0 +1,27 @@
# Interactive Brainfuck Interpreter in React TS
This is an interactive interpreter for the brainfuck programming language.
It provides simple brainfuck execution, along with a view of the memory, the memory pointer, the current state of the
code and more.
It is great for debugging brainfuck programs, including a memory view, program view, the location of the pointers, the
ability to directly edit memory.
You can step manually through the program, or set the execution speed to whatever speed fits best.
This interpreter also has the ability to set breakpoints using the • symbol. This means you can let your code run fast and
stopping it at any point in your program to see what went wrong.
## Features
* brainfuck execution including IO
* memory view
* code state view
* manual stepping
* breakpoints
* error messages
* seeing ASCII characters in memory
* manual code input
* fast excecution mode (no debugging info)
### Future features
* none-blocking fast excecution mode
* better speed control
* (limited) backstepping

50
ibfi-ts/package.json Normal file
View file

@ -0,0 +1,50 @@
{
"name": "ibfi-ts",
"version": "0.1.0",
"homepage": "https://nilstrieb.github.io/brainfuck",
"private": false,
"dependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"@types/jest": "^26.0.15",
"@types/node": "^12.0.0",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"node-sass": "^6.0.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"sass": "^1.35.1",
"typescript": "^4.1.2",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"deploy": "yarn build && gh-pages -d build"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"gh-pages": "^3.2.3"
}
}

BIN
ibfi-ts/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

43
ibfi-ts/public/index.html Normal file
View file

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Interactive Brainfuck Interpreter"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Brainfuck Interpreter</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

BIN
ibfi-ts/public/logo192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
ibfi-ts/public/logo512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

View file

@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View file

@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

128
ibfi-ts/src/App.scss Normal file
View file

@ -0,0 +1,128 @@
$main-color: #282c34;
$main-color-brighter: #323942;
$light-color: ghostwhite;
$medium-color: #78787f;
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
.App-header {
background-color: $main-color;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: $light-color;
}
.App-link {
color: #61dafb;
}
.bf-input {
.code-input {
resize: none;
width: 80vw;
height: 400px;
font-size: 100px;
}
.code-options-wrapper > * {
margin: 10px;
}
}
.code-display-wrapper {
max-width: 80vw;
font-family: monospace;
span {
word-wrap: break-word;
}
}
.memory-display-table {
$border: 1px solid $light-color;
th, .cell {
border: $border;
}
th, td {
min-width: 60px;
text-align: center;
}
.array-set-value-field {
min-width: 50px;
max-width: 100px;
height: 40px;
color: $light-color;
font-size: 30px;
background-color: $main-color-brighter;
}
}
.run-button {
height: 50px;
width: 200px;
}
.bf-run {
margin: 20px;
.speed-control-wrapper > * {
margin: 10px;
}
.small-speed-button {
height: 40px;
width: 40px;
}
.program-input-area {
resize: none;
width: 80vw;
height: 50px;
font-size: 30px;
}
.info {
background-color: #579ca7;
}
}
.bf-output {
.output-area {
resize: none;
width: 80vw;
height: 200px;
font-size: 20px;
}
}
textarea {
background-color: $main-color-brighter;
color: $light-color;
}
button {
background-color: $medium-color;
font-size: 20px;
border: 1px solid $main-color;
&:hover {
cursor: pointer;
background-color: $light-color;
}
}

View file

@ -0,0 +1,157 @@
import {CodeOptions} from "../components/CodeInput";
type InHandler = (() => number);
type OutHandler = ((char: number) => void);
export default class Interpreter {
private readonly _array: Uint8Array;
private _pointer: number;
private readonly _code: string;
private _programCounter: number;
private readonly _inHandler: InHandler;
private readonly _outHandler: OutHandler;
private readonly _options: CodeOptions;
constructor(input: [string, CodeOptions], outHandler: OutHandler, inHandler: InHandler) {
const buf = new ArrayBuffer(32000);
this._array = new Uint8Array(buf);
this._pointer = 0;
this._options = input[1];
if (input[1].minify) {
this._code = this.minify(input[0])
} else {
this._code = input[0];
}
this._programCounter = 0;
this._inHandler = inHandler;
this._outHandler = outHandler;
}
public next() {
this.execute(this._code[this._programCounter++]);
}
public execute(char: string) {
switch (char) {
case '+':
this._array[this._pointer]++;
break;
case '-':
this._array[this._pointer]--;
break;
case '>':
this._pointer++;
break;
case '<':
if (this._pointer === 0) {
throw new Error("Cannot wrap left");
}
this._pointer--;
break;
case '.':
this._outHandler(this.value);
break;
case ',':
this.input();
break;
case '[':
this.loopForwards();
break;
case ']':
this.loopBackwards();
break;
case '•':
if (this._options.enableBreakpoints) {
throw new Error("Breakpoint reached");
}
break;
case undefined:
this._programCounter = this._code.length;
break;
default:
break;
}
}
private loopForwards() {
if (this.value === 0) {
let level = 0;
while (this.lastInstruction !== ']' || level > -1) {
this._programCounter++;
if (this._programCounter > this._code.length) {
throw new Error("Reached end of code while searching ']'");
}
if (this.lastInstruction === '[') level++;
else if (this.lastInstruction === ']') level--;
}
}
}
private loopBackwards() {
if (this.value !== 0) {
let level = 0;
while (this.lastInstruction !== '[' || level > -1) {
this._programCounter--;
if (this._programCounter < 0) {
throw new Error("Reached start of code while searching '['");
}
if (this.lastInstruction === '[') level--;
else if (this.lastInstruction === ']') level++;
}
}
}
private input() {
try {
this._array[this._pointer] = this._inHandler();
} catch {
this._programCounter--;
}
}
get reachedEnd(): boolean {
return this._programCounter === this._code.length;
}
get lastInstruction(): string {
return this._code[this._programCounter - 1];
}
get value(): number {
return this._array[this._pointer];
}
get array(): Uint8Array {
return this._array;
}
get pointer(): number {
return this._pointer;
}
get code(): string {
return this._code;
}
get programCounter(): number {
return this._programCounter;
}
private minify(code: string): string {
const CHARS = ['+', '-', '<', '>', '.', ',', '[', ']'];
if (this._options.enableBreakpoints) {
CHARS.push('•');
}
return code.split("")
.filter(c => CHARS.includes(c))
.join("");
}
}

View file

@ -0,0 +1,41 @@
import '../App.scss';
import CodeInput, {CodeOptions} from "./CodeInput";
import ProgramOutput from "./ProgramOutput";
import React, {useCallback, useState} from "react";
import Runner from "./Runner";
export const OptionContext = React.createContext<CodeOptions>({});
function App() {
const [out, setOut] = useState("");
const [input, setInput] = useState<[string, CodeOptions]>(["", {}]);
const [running, setRunning] = useState(false);
const outHandler = useCallback((char: number) => {
setOut(oldOut => oldOut + String.fromCharCode(char))
}, []);
const runHandler = (run: boolean) => {
setRunning(run);
if (!run) {
setOut("");
}
}
const inputHandler = (code: string, options: CodeOptions) => setInput([code, options]);
return (
<div className="App-header">
<OptionContext.Provider value={input[1]}>
{
!running && <CodeInput input={input} setInput={inputHandler}/>
}
<Runner running={running} setRunning={runHandler} code={input[0]} outHandler={outHandler}/>
{
running && <ProgramOutput text={out}/>
}
</OptionContext.Provider>
</div>
);
}
export default App;

View file

@ -0,0 +1,22 @@
import React from 'react';
interface CodeDisplayProps {
code: string,
index: number,
}
const CodeDisplay = ({code, index}: CodeDisplayProps) => {
const firstCodePart = code.substr(0, index);
const secondCodePart = code.substr(index + 1, code.length - index + 1);
return (
<div className="code-display-wrapper">
<code>{firstCodePart}</code>
<code style={{backgroundColor: "red"}}>{code[index] || " "}</code>
<code>{secondCodePart}</code>
</div>
);
};
export default CodeDisplay;

View file

@ -0,0 +1,83 @@
import React, {ChangeEvent, useState} from 'react';
import presets from "../presets.json";
export interface CodeOptions {
minify?: boolean,
directStart?: boolean,
startSuperSpeed?: boolean,
enableBreakpoints?: boolean
asciiView?: boolean
}
interface CodeInputProps {
setInput: ((code: string, options: CodeOptions) => void),
input: [string, CodeOptions]
}
const codeOptions: Array<[string, keyof CodeOptions]> = [
["Minify Code", "minify"],
["Start directly", "directStart"],
["Start in blocking mode", "startSuperSpeed"],
["Breakpoints (•)", "enableBreakpoints"],
["Show ASCII in memory", "asciiView"]
]
const CodeInput = ({input: [code, options], setInput}: CodeInputProps) => {
const [fontSize, setFontSize] = useState(40);
const setPreset = (name: keyof typeof presets) => () => {
setInput(presets[name], options);
}
const changeHandler = (name: keyof CodeOptions) => (event: ChangeEvent<HTMLInputElement>) => {
setInput(code, {...options, [name]: event.target.checked})
}
return (
<div className="bf-input">
<div className="code-options-wrapper">
<div>
<label htmlFor="bf-input-fontsize-range">Font Size</label>
<input type="range" id="bf-input-fontsize-range" onChange={v => setFontSize(+v.target.value)}/>
</div>
{codeOptions.map(([display, id]) =>
<CodeOption displayName={display} name={id} options={options} onChange={changeHandler}/>
)}
</div>
<textarea value={code} onChange={e => setInput(e.target.value, options)} style={{fontSize}}
className="code-input"
placeholder="Input your code here..."/>
<div>
<div>Presets</div>
<div>
<button onClick={setPreset("helloworld")}>Hello World</button>
<button onClick={setPreset("hanoi")}>Towers of Hanoi</button>
<button onClick={setPreset("quine")}>Quine</button>
<button onClick={setPreset("gameoflife")}>Game Of Life</button>
<button onClick={setPreset("benchmark")}>Benchmark</button>
<button onClick={setPreset("fizzbuzz")}>Fizzbuzz</button>
</div>
</div>
</div>
);
};
interface CodeOptionProps {
displayName: string,
name: keyof CodeOptions,
options: CodeOptions,
onChange: (name: keyof CodeOptions) => (event: ChangeEvent<HTMLInputElement>) => void,
}
const CodeOption = ({displayName, name, options, onChange}: CodeOptionProps) => (
<span>
<input type="checkbox" checked={options[name]} id={`input-options-${name}`}
onChange={onChange(name)}/>
<label htmlFor={`input-options-${name}`}>{displayName}</label>
</span>
);
export default CodeInput;

View file

@ -0,0 +1,15 @@
import React from 'react';
interface ProgramOutputProps {
text: string
}
const ProgramOutput = ({text}: ProgramOutputProps) => {
return (
<div className="bf-output">
<textarea readOnly className="output-area" value={text}/>
</div>
);
};
export default ProgramOutput;

View file

@ -0,0 +1,118 @@
import React, {useContext, useRef, useState} from 'react';
import Interpreter from "../brainfuck/Interpreter";
import {OptionContext} from "./App";
const MAX_TABLE_COLUMNS = 20;
interface RunDisplayProps {
interpreter: Interpreter,
}
const RunDisplay = ({interpreter}: RunDisplayProps) => {
const options = useContext(OptionContext);
const index = interpreter.pointer;
let offset: number;
if (index < MAX_TABLE_COLUMNS / 2) {
offset = 0;
} else {
offset = index - MAX_TABLE_COLUMNS / 2;
}
const arrayWithIndex = Array(MAX_TABLE_COLUMNS).fill(0)
.map((_, i) => i + offset);
return (
<div>
<table className="memory-display-table">
<thead>
<tr>
{
arrayWithIndex.map((n => <th key={n}>{n}</th>))
}
</tr>
</thead>
<tbody>
<tr>
{
arrayWithIndex.map((n) => <MemoryCell key={n} index={n} interpreter={interpreter}/>)
}
</tr>
{
options.asciiView &&
<tr>
{
arrayWithIndex.map((n) => <MemoryCell key={n} index={n} interpreter={interpreter} ascii/>)
}
</tr>
}
<tr>
{
arrayWithIndex.map((n) => <td className="pointer"
key={n}>{interpreter.pointer === n && "^"}</td>)
}
</tr>
</tbody>
</table>
</div>
);
};
interface MemoryCellProps {
index: number,
interpreter: Interpreter,
ascii?: boolean,
}
const MemoryCell = ({index, interpreter, ascii}: MemoryCellProps) => {
const [isEditing, setIsEditing] = useState(false);
const [input, setInput] = useState(interpreter.array[index] + "");
const inputField = useRef<HTMLInputElement>(null);
const saveAndQuit = () => {
interpreter.array[index] = +(input);
setIsEditing(false);
}
const click = () => {
setIsEditing(true);
inputField.current?.select();
}
const keyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
console.log("key", e.key);
if (e.key === "Escape") {
setIsEditing(false);
} else if (e.key === "Enter") {
saveAndQuit();
}
}
const content = ascii ?
String.fromCharCode(interpreter.array[index])
:
interpreter.array[index];
return (
<td onClick={click} className="cell">
{
isEditing && !ascii ?
<input onKeyDown={keyDown}
className="array-set-value-field"
ref={inputField}
onChange={e => setInput(e.target.value)}
value={input}
onBlur={saveAndQuit}
autoFocus
/>
:
content
}
</td>
);
}
export default RunDisplay;

View file

@ -0,0 +1,189 @@
import React, {useCallback, useContext, useEffect, useRef, useState} from 'react';
import Interpreter from "../brainfuck/Interpreter";
import CodeDisplay from "./CodeDisplay";
import RunDisplay from "./RunDisplay";
import {OptionContext} from "./App";
interface RunInfoProps {
running: boolean,
setRunning: (running: boolean) => void,
code: string,
outHandler: (char: number) => void,
}
const Runner = ({setRunning, running, outHandler, code}: RunInfoProps) => {
const [speed, setSpeed] = useState(0);
const [interpreter, setInterpreter] = useState<Interpreter | null>(null);
const [info, setInfo] = useState<string | null>(null);
const [startTime, setStartTime] = useState(0);
const [, setRerenderNumber] = useState(0);
const rerender = () => setRerenderNumber(n => n + 1);
const options = useContext(OptionContext);
const inputArea = useRef<HTMLTextAreaElement>(null);
const inputHandler = () => {
if (!inputArea.current) {
throw new Error("Could not read input")
}
const value = inputArea.current.value;
if (value.length < 1) {
throw new Error("No input found");
}
const char = value.charCodeAt(0);
inputArea.current.value = value.substr(1);
return char;
}
const startHandler = useCallback(() => {
if (options.directStart) {
if (options.startSuperSpeed) {
setSpeed(-1);
} else {
setSpeed(100);
}
} else {
setSpeed(0);
}
setStartTime(Date.now);
setInterpreter(new Interpreter([code, options], outHandler, inputHandler));
setRunning(false);
setRunning(true);
}, [options, code, outHandler, setRunning]);
const stopHandler = () => {
setRunning(false);
setInfo(null);
}
const nextHandler = useCallback(() => {
setInfo(null);
try {
interpreter?.next();
} catch (e) {
setInfo(e.message);
setSpeed(0);
}
if (interpreter?.reachedEnd) {
setSpeed(0);
setInfo(`Finished Execution. Took ${(Date.now() - startTime) / 1000}s`)
}
rerender();
}, [interpreter, startTime]);
const runBlocking = useCallback(() => {
try {
while (speed === -1 && !interpreter?.reachedEnd) {
interpreter?.next();
}
setSpeed(0);
setInfo(`Finished Execution. Took ${(Date.now() - startTime) / 1000}s`)
} catch (e) {
setInfo(e.message);
setSpeed(0);
}
}, [speed, interpreter, startTime]);
useEffect(() => {
if (running) {
if (speed === 0) {
return;
}
if (speed > 0) {
const interval = setInterval(() => {
nextHandler();
}, 1000 / (speed * 10));
return () => clearInterval(interval);
}
runBlocking();
}
}, [runBlocking, running, nextHandler, speed]);
return (
<div className="bf-run">
{
running && interpreter && <>
<CodeDisplay code={interpreter.code} index={interpreter.programCounter}/>
<RunDisplay interpreter={interpreter}/>
</>
}
<div>
{running && <button className="run-button" onClick={stopHandler}>Back</button>}
<button className="run-button" onClick={startHandler}>{running ? "Restart" : "Start"}</button>
{running && <button className="run-button" onClick={nextHandler}>Next</button>}
</div>
{
running && interpreter &&
<>
<SpeedControl speed={speed} setSpeed={setSpeed}/>
<ManualControlButtons interpreter={interpreter} rerender={rerender}/>
</>
}
{info && <div className="info">{info}</div>}
{
running && <div>
<div>Input:</div>
<textarea className="program-input-area" ref={inputArea}/>
</div>
}
</div>
);
};
interface SpeedControlProps {
speed: number,
setSpeed: React.Dispatch<React.SetStateAction<number>>,
}
const SpeedControl = ({speed, setSpeed}: SpeedControlProps) => {
return (
<div className="speed-control-wrapper">
<label htmlFor="run-info-speed-range">Speed</label>
<input type="range" id="run-info-speed-range" value={speed}
onChange={e => setSpeed(+e.target.value)}/>
<span> {speed}</span>
<span>
<button onClick={() => setSpeed(s => s === 0 ? 0 : s - 1)}
className="small-speed-button">-</button>
<button onClick={() => setSpeed(0)}
className="small-speed-button">0</button>
<button onClick={() => setSpeed(s => s === 100 ? 100 : s + 1)}
className="small-speed-button">+</button>
</span>
<span>
<label>Superspeed Mode (blocking)</label>
<input id="superspeed-mode-check" type="checkbox" checked={speed === -1} onChange={() => setSpeed(-1)}/>
</span>
</div>
)
}
const ManualControlButtons = ({interpreter, rerender}: { interpreter: Interpreter, rerender: (() => void) }) => {
const run = (char: string) => {
try {
interpreter.execute(char);
} catch {
}
rerender();
}
return (
<div>
<button onClick={() => run('<')} className="small-speed-button">&lt;</button>
<button onClick={() => run('>')} className="small-speed-button">&gt;</button>
<button onClick={() => run('-')} className="small-speed-button">-</button>
<button onClick={() => run('+')} className="small-speed-button">+</button>
<button onClick={() => run('.')} className="small-speed-button">.</button>
</div>
)
}
export default Runner;

13
ibfi-ts/src/index.css Normal file
View file

@ -0,0 +1,13 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}

11
ibfi-ts/src/index.tsx Normal file
View file

@ -0,0 +1,11 @@
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);

8
ibfi-ts/src/presets.json Normal file

File diff suppressed because one or more lines are too long

1
ibfi-ts/src/react-app-env.d.ts vendored Normal file
View file

@ -0,0 +1 @@
/// <reference types="react-scripts" />

26
ibfi-ts/tsconfig.json Normal file
View file

@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}

11965
ibfi-ts/yarn.lock Normal file

File diff suppressed because it is too large Load diff

2
js/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
node_modules
.idea

4
js/.prettierrc.json Normal file
View file

@ -0,0 +1,4 @@
{
"singleQuote": true,
"printWidth": 100
}

1
js/fizzbuzz.bf vendored Normal file
View file

@ -0,0 +1 @@
hello...[[].]]

11
js/package.json Normal file
View file

@ -0,0 +1,11 @@
{
"name": "brainfuck",
"version": "1.0.0",
"main": "src/index.js",
"license": "MIT",
"type": "module",
"devDependencies": {
"prettier": "^2.6.2"
},
"dependencies": {}
}

113
js/src/index.js Normal file
View file

@ -0,0 +1,113 @@
import fs from 'fs';
const RED = '\x1B[1;31m';
const RESET = '\x1B[1;0m';
function lex(string) {
const tokens = [];
for (let i = 0; i < string.length; i++) {
const char = string[i];
if (['+', '-', '>', '<', '.', ',', '[', ']'].includes(char)) {
tokens.push({
char,
span: i,
});
}
}
return tokens;
}
function ParseError(message, span) {
this.message = message;
this.span = span;
}
function Parser(tokens) {
this.tokens = tokens;
this.position = 0;
}
Parser.prototype.next = function () {
const token = this.tokens[this.position];
this.position++;
return token;
};
Parser.prototype.parse = function (isLoop) {
const body = [];
let nextToken;
while ((nextToken = this.next()) !== undefined) {
switch (nextToken.char) {
case '[': {
const loopBody = this.parse(true);
body.push(loopBody);
break;
}
case ']': {
if (isLoop) {
return body;
} else {
throw new ParseError('No matching `[` found', nextToken.span);
}
}
default: {
body.push(nextToken);
}
}
}
if (isLoop) {
throw new ParseError('No matching `]` found', this.tokens[this.tokens.length - 1].span);
} else {
return body;
}
};
function reportError(source, message, span) {
let lineIdx = 0;
let lastNewlineIdx = 0;
for (let i = 0; i < source.length; i++) {
const char = source[i];
if (i === span) {
break;
}
if (char === '\n') {
lineIdx++;
lastNewlineIdx = i;
}
}
const lines = source.split('\n');
const line = lines[lineIdx];
const lineNumber = String(lineIdx + 1);
const linePrefix = `${lineNumber} | `;
const lineSpan = span - lastNewlineIdx;
console.error(`${RED}error: ${message}${RESET}`);
console.error(`${linePrefix}${line}`);
console.error(`${' '.repeat(linePrefix.length + lineSpan)}${RED}^${RESET}`);
}
const file = process.argv[2];
if (!file) {
console.error('Usage: [filename]');
process.exit(1);
}
const source = fs.readFileSync(file, 'utf-8');
const tokens = lex(source);
const parser = new Parser(tokens);
try {
const ast = parser.parse(false);
console.log(ast);
} catch (parseError) {
if (!(parseError instanceof ParseError)) {
throw parseError;
}
reportError(source, parseError.message, parseError.span);
}

8
js/yarn.lock Normal file
View file

@ -0,0 +1,8 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
prettier@^2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032"
integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==

2
rust2/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
target
.idea

3
rust2/.rustfmt.toml Normal file
View file

@ -0,0 +1,3 @@
imports_granularity = "Crate"
newline_style = "Unix"
group_imports = "StdExternalCrate"

1238
rust2/Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

29
rust2/Cargo.toml Normal file
View file

@ -0,0 +1,29 @@
[package]
name = "brainfuck"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bumpalo = { version = "3.9.1", features = ["allocator_api"] }
clap = { version = "3.1.9", features = ["derive"] }
dbg-pls = { version = "0.3.2", features = ["colors", "derive"] }
owo-colors = "3.3.0"
rand = "0.8.5"
tracing = "0.1.34"
tracing-subscriber = { version = "0.3.11", features = ["env-filter"] }
[dev-dependencies]
criterion = "0.3.5"
insta = "1.14.0"
[profile.release]
debug = true
[profile.dev]
opt-level = 3
[[bench]]
name = "opts"
harness = false

5
rust2/benches/bench.bf vendored Normal file
View file

@ -0,0 +1,5 @@
Benchmark brainf*ck program
>++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++
[>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++
++++++++[>++++++++++[>++++++++++[>++++++++++[>+
+++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++.

44
rust2/benches/bottles.bf vendored Normal file
View file

@ -0,0 +1,44 @@
>+++++++++[<+++++++++++>-]<[>[-]>[-]<<[>+>+<<-]>>[<<+>>-]>>>
[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+<
-]<<-<-]+++++++++>[<->-]>>+>[<[-]<<+>>>-]>[-]+<<[>+>-<<-]<<<
[>>+>+<<<-]>>>[<<<+>>>-]>[<+>-]<<-[>[-]<[-]]>>+<[>[-]<-]<+++
+++++[<++++++<++++++>>-]>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-
]<<<<<<.>>[-]>[-]++++[<++++++++>-]<.>++++[<++++++++>-]<++.>+
++++[<+++++++++>-]<.><+++++..--------.-------.>>[>>+>+<<<-]>
>>[<<<+>>>-]<[<<<<++++++++++++++.>>>>-]<<<<[-]>++++[<+++++++
+>-]<.>+++++++++[<+++++++++>-]<--.---------.>+++++++[<------
---->-]<.>++++++[<+++++++++++>-]<.+++..+++++++++++++.>++++++
++[<---------->-]<--.>+++++++++[<+++++++++>-]<--.-.>++++++++
[<---------->-]<++.>++++++++[<++++++++++>-]<++++.-----------
-.---.>+++++++[<---------->-]<+.>++++++++[<+++++++++++>-]<-.
>++[<----------->-]<.+++++++++++..>+++++++++[<---------->-]<
-----.---.>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>>+++
+[<++++++>-]<--.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.
><+++++..--------.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++
++++++++++++.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<++
+++++++>-]<--.---------.>+++++++[<---------->-]<.>++++++[<++
+++++++++>-]<.+++..+++++++++++++.>++++++++++[<---------->-]<
-.---.>+++++++[<++++++++++>-]<++++.+++++++++++++.++++++++++.
------.>+++++++[<---------->-]<+.>++++++++[<++++++++++>-]<-.
-.---------.>+++++++[<---------->-]<+.>+++++++[<++++++++++>-
]<--.+++++++++++.++++++++.---------.>++++++++[<---------->-]
<++.>+++++[<+++++++++++++>-]<.+++++++++++++.----------.>++++
+++[<---------->-]<++.>++++++++[<++++++++++>-]<.>+++[<----->
-]<.>+++[<++++++>-]<..>+++++++++[<--------->-]<--.>+++++++[<
++++++++++>-]<+++.+++++++++++.>++++++++[<----------->-]<++++
.>+++++[<+++++++++++++>-]<.>+++[<++++++>-]<-.---.++++++.----
---.----------.>++++++++[<----------->-]<+.---.[-]<<<->[-]>[
-]<<[>+>+<<-]>>[<<+>>-]>>>[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]
>[<+>-]>[<<++++++++++>>>+<-]<<-<-]+++++++++>[<->-]>>+>[<[-]<
<+>>>-]>[-]+<<[>+>-<<-]<<<[>>+>+<<<-]>>>[<<<+>>>-]<>>[<+>-]<
<-[>[-]<[-]]>>+<[>[-]<-]<++++++++[<++++++<++++++>>-]>>>[>+>+
<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>[-]>[-]++++[<++++++++>
-]<.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.><+++++..---
-----.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++++++++++++++
.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<+++++++++>-]<-
-.---------.>+++++++[<---------->-]<.>++++++[<+++++++++++>-]
<.+++..+++++++++++++.>++++++++[<---------->-]<--.>+++++++++[
<+++++++++>-]<--.-.>++++++++[<---------->-]<++.>++++++++[<++
++++++++>-]<++++.------------.---.>+++++++[<---------->-]<+.
>++++++++[<+++++++++++>-]<-.>++[<----------->-]<.+++++++++++
..>+++++++++[<---------->-]<-----.---.+++.---.[-]<<<]

7
rust2/benches/fizzbuzz.bf vendored Normal file
View file

@ -0,0 +1,7 @@
++++++++++[>++++++++++<-]>>++++++++++>->>>>>>>>>>>>>>>>-->+++++++[->++\n++++++++<]>[->+>+>+>+<<<<]+++>>+++>>>++++++++[-<
++++<++++<++++>>>]++++\n+[-<++++<++++>>]>>-->++++++[->+++++++++++<]>[->+>+>+>+<<<<]+++++>>+>++\n++++>++++++>++++++++[-<+
+++<++++<++++>>>]++++++[-<+++<+++<+++>>>]>>-->\n---+[-<+]-<[+[->+]-<<->>>+>[-]++[-->++]-->+++[---++[--<++]---->>-<+>[+\n
+++[----<++++]--[>]++[-->++]--<]>++[--+[-<+]->>[-]+++++[---->++++]-->[\n->+<]>>[.>]++[-->++]]-->+++]---+[-<+]->>-[+>>>+[
-<+]->>>++++++++++<<[-\n>+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>\n+>>]<<<<<]>[-]>>[>++++++
[-<++++++++>]<.<<+>+>[-]]<[<[->-<]++++++[->+++\n+++++<]>.[-]]<<++++++[-<++++++++>]<.[-]<<[-<+>]+[-<+]->>]+[-]<<<.>>>+[\n
-<+]-<<]

709
rust2/benches/hanoi.bf vendored Normal file
View file

@ -0,0 +1,709 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>[-]>[-]+++++++++++++++++++++++++++.++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++.-------------------.-------
--------------------------------------.+++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++.-----------------------------------------.++++++
++++++++++++++++++.[-]+++++++++++++++++++++++++++.++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++.-------------------------------------
----.+++++++++.---------.+++++.+++++++++++++++++.++++++++++++.++++++++++++++
+++++++++++++.++++++++.------------------.+++++++++++++.+.------------------
-----------------------------------------------------------------.++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.------
---.----------------------------------------------------------------------.+
+++++++++++++++++++++++++++++++++++++++.+++++++++++++++++++++++++.++++++++++
+++.+.------.---------------------------------------------------------------
----------.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++.+++++.-------------------------------------------------------------
-----------------.++++++++++++++++++++++++++++++++++.+++++++++++++++++++++++
+++++++++++++++++++++++++.-----------------.++++++++.+++++.--------.--------
----------------------------------------------------.+++++++++++++++++++++++
++++++++++++++++++++++++++++++++++.++++++++.[-]+++++++++++++++++++++++++++.+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.------------
----------------------------.++++++++.----------.++++.+++++++++++++++++++.++
+++++++++++++.+++++++++++++++++++++++++++.---------.+++++++++++..-----------
----.+++++++++.-------------------------------------------------------------
-----------------.++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++.+++++++++++++++++++++++.-------------------------------------------
----------------------------------------------.+++++++++++++++++++++++++++++
++++++.+++++++++++++++++++++++++++++++++++++++++.---.---..+++++++++.+++.----
----------.-----------------------------------------------------------------
---.+++++++++++++++++++++++++++++++++++++++++++++++++++++++.++++++++++++++++
++++++++.---.------.--------------------------------------------------------
--------------.++++++++++++++++++++++++++++.++++++++++++++++++++++++++++++++
++++++++++++.++++++++++++..----.--------------------------------------------
----------.-----------..++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++...-----------------------------------------------------
--------------------.+++++++++++++++++++++++++++++++++++++++++++++++++++++.+
++++++++.---.---..+++++++++.+++.--------------.-----------------------------
-------------------------.++++++++++++++++++++++++++++++++++++++++++++++++++
+.+++++++++++++++++++.------------------------------------------------------
---------------.+++++++++++++++++++++++++++++++++++++++++++++++++++.++++.---
.+++++++++++++.+++++.-------------------------------------------------------
---------------.+++++++++++++++.[-]>[-]+++++++++>[-]+++>>[-]>[-]<<<<<[->>>>>
+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<
<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]
>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-
<<+>>]<<<[-]+>>>][-]<[->+<]>[[-<+>]<<<[-]+>>>]<<<[>[-]++++++++++++++++++++++
+++++++++++++++++++++++>[-]<<<<<[->>>>>+<<<<<]>>>>>[[-<<<<<+>>>>>]<+++++++++
++++++++++++++++++++++++++++++++++>]<<<[>>>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<<
->>>][-]++++++++++++++++>[-]++++++++++++++>>>>[-]>[-]<<<<<<<<<[->>>>>>>>>+<<
<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[
[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+
<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>
>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<<+++++>>>>]>[-]>[-
]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]+<<[-]+>>
>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<
]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<
[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<
[[-]<<<++++++++++>>>][-]>[-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>>>[-<+<<<<<<<+
>>>>>>>>][-]+++++++++++++++++++++++++<<<[-]>>[>>[-]<[->+<]>[-<+<<<+>>>>]<<-]
[-]<<[->>+<<]>>[-<<+<<+>>>>][-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>>>[-<<<<<<<
<+>>>>->>>>][-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>>>[-<<<<<<<<+>>>>->>>>]>[-]
>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]++<<[-
]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+
>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>
>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>
]<<<[[-]<<<<----->>>>][-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<<<<<<<<<
+>>>>>>->>>][-]+++++++++++++++++++++++++++.+++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++.>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>
>>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[
-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->
>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<
+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[->+<]
>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-]>[-]<
<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>
+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>
>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[
-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>
]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]+
+++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-
<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->
>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<
[-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<<->>>>
]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>
>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]
<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[
[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>
[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<
<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>
>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->
[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]
+>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>>>]<<[
-<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<
<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>
>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<
<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[-
>>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+>]<+++
+++++++++++++++++++++++++++++++++++++++++++++.<+++++++++++++++++++++++++++++
+++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>-<
]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<+++++++++++++++++++++++
+++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.
>>>>>>-<]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>]
<<]<<<<<<--------------------------------.>[-]>[-]<<<<<<[->>>>>>+<<<<<<]>>>>
>>[-<+<<<<<+>>>>>>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]+++++
+++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<
+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+
<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]
>>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>
>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>
>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[
-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>
>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]
>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<
+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->
>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>
->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[
-]+>>]<]<]<<<]<<[-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>
>>]<<[-<<<<->>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]+++++
+++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[
[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[
->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+
>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+
<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>]
[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]
+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>
[[-<<<+>>>]<<[-]+>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-
<<<+<<+>>>>>]<<[-<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>]
[-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<
<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>
[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]
<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>
[-]+<[[-<+>]<++++++++++++++++++++++++++++++++++++++++++++++++.<+++++++++++++
+++++++++++++++++++++++++++++++++++.<+++++++++++++++++++++++++++++++++++++++
+++++++++.>>>>-<]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<+++++++
+++++++++++++++++++++++++++++++++++++++++.<+++++++++++++++++++++++++++++++++
+++++++++++++++.>>>>>>-<]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++
++++++++.>>>>>>]<<]<<<<<<+++++++++++++.>[-]>[-]<<<<<<<[->>>>>>>+<<<<<<<]>>>>
>>>[-<+<<<<<<+>>>>>>>][-]+++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+
>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>
>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<
+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[-]++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++.<-<]>[[-]<<<<<<.>>>>>>]<[-]<<<<<<<<[->>>>>>>>+<<<
<<<<<]>>>>>>[-]>>[-<<<<<<<<+>>>>>>+>>][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<..
>>>-]<<<.>>>>>[-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>[-]>>[-<<<<<<<<+>>>>>>+>>
][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<..>>>-]>>>[-]>[-]<<<<<<<[->>>>>>>+<<<<<
<<]>>>>>>>[-<+<<<<<<+>>>>>>>][-]++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>
[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>
+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]
>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[-]+++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++.<-<]>[[-]<<<<<<.>>>>>>]<<<<<<<<]>>>[-]<<<<
<[->>>>>+<<<<<]>>>>>[[-<<<<<+>>>>>]<<<<<<<[-]<[-]<[-]>>>>>>>>>>[-]<<<<<[->>>
>>+<<<<<]>>>>>[-<<<<<+<<<+>>>>>>>>][-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>]<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-
[<<<<+>>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<<<<<[->>>>>+<<<<
<]>>>>>[[-<<<<<+>>>>>]<<<<<->>>>>]<]<<<<<+>>[-]+>>[-]>[-]<<<<<[->>>>>+<<<<<]
>>>>>[-<+<<<<+>>>>>][-]++++++++++<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>
[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<
<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<
<<[-]+>>>][-]<[->+<]>[[-<+>]<<<[-]+>>>]<<<]<<<[-]>[-]+>[-]++>[-]++++++++>[-]
+>[-]+[>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++<<[-]>>>[-]>[
-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<-
>->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>
]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]+>>>][-]<[->+<]>[[-<+>]<<<[-]+>>>]<<<[>[-
]<<<<<[->>>>>+<<<<<]>>>>>[[-<<<<<+>>>>>]>[-]>[-]>[-]>>[-]>[-]<<<<<<<<<<[->>>
>>>>>>>+<<<<<<<<<<]>>>>>>>>>>[-<+<<<<<<<<<+>>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<<
<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[
-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<
][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<[-]
+>[-]+>>]>[-]>[-]<<<<<<<<<<[->>>>>>>>>>+<<<<<<<<<<]>>>>>>>>>>[-<+<<<<<<<<<+>
>>>>>>>>>][-]+++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]
>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[-
>>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->
+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<[-]+>>[-]+>][-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-
]>>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>[-]>[-<
<<<<<<<<<<<<<<+>>>>>>>>>>>>>>+>]<[<+>-]>[-]<<<<<<<<<<<<<<[->>>>>>>>>>>>>>+<<
<<<<<<<<<<<<]>>>>>>>>>>>>>[-]>[-<<<<<<<<<<<<<<+>>>>>>>>>>>>>+>]<[<+++>-]>[-]
<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>[-]>[-<<<<<<<<<<<<<+>
>>>>>>>>>>>+>]<[<+++++++++>-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>[-]<<[->>+<<]>>[-<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<<
<<<<<<<]>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<<<<]<<[-]>>>[<<<+>>
>-]<<[>>>>]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>[-]<<<<<<<<<<<<[->>>>>>>>>>>>+<<<<<<<<<<<<]>>>>>>>>>>>>[-<
<<<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<<
<[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<+<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]
<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<
<<]>>>>>>>>>>>[-<<<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<<
<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>[-<<<<<<<<
<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<
<<<+>>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>+>>>>>>>>>>>>>][-]<<[->>+<<]>>[[-<<+>>]>[-]<<<<<<<<<<<<[->>>>
>>>>>>>>+<<<<<<<<<<<<]>>>>>[-]>>>>>>>[-<<<<<<<<<<<<+>>>>>+>>>>>>>][-]<<<<<<<
<<<<[->>>>>>>>>>>+<<<<<<<<<<<]<[-]>>>>>>>>>>>>[-<<<<<<<<<<<+<+>>>>>>>>>>>>][
-]<<<<<<<[->>>>>>>+<<<<<<<]<<<<[-]>>>>>>>>>>>[-<<<<<<<+<<<<+>>>>>>>>>>>]<<<<
<<<<<<->[-]>+>>>>>>>][-]<[->+<]>[[-<+>]>[-]<<<<<<<<<<<<[->>>>>>>>>>>>+<<<<<<
<<<<<<]>>>>>[-]>>>>>>>[-<<<<<<<<<<<<+>>>>>+>>>>>>>][-]<<<<<<<<<<<<<[->>>>>>>
>>>>>>+<<<<<<<<<<<<<]>[-]>>>>>>>>>>>>[-<<<<<<<<<<<<<+>+>>>>>>>>>>>>][-]<<<<<
<<[->>>>>>>+<<<<<<<]<<<<<<[-]>>>>>>>>>>>>>[-<<<<<<<+<<<<<<+>>>>>>>>>>>>>]<<<
<<<<<<<->[-]>+>>>>>>>]<<<<]>[-]>[-]<<<<<<[->>>>>>+<<<<<<]>>>>>>[-<+<<<<<+>>>
>>>][-]++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<
<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<
]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-
<+>]<<<[-]>>>]<<<[[-]>>>>[-]++>>[-]>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<<
<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>][-]<<[-]+>>>[-
]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[
<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]
+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-
]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>[-]>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>]<]>[-]>[-]<<<<<<<<<<<<<<<[-
>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>>
>>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-
<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<
<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[
-<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>[-<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>+>>>>]<]>[-]>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<
<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>][-]++<<[-]+>>
>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<
]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<
[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<
[[-]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>[-]>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>]<]>[-]
>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<
<<<<<<<<<<+>>>>>>>>>>>>>>>][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-
]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<
+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<
[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>
>>>>>>>>>>[-]>>>>>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<
<<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+>>>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+
<<<<]<<>>>>]>>[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<<
<<<[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>
>>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>
>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->
>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+
<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>[-]>>>>>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+>>>>-]
<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>
>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>][-]++<<[
-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]
+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>
>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>
>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-
]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>[-]<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+>>>>-]<<<<]<<
[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<
<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>
>][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>
>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>
[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]
<<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>[-]<<<<<[->>>>>
+<<<<<]>>>>>[-<<<<<+<<<<<<<<<<<+>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>
>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+
>>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<
<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>>
][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>
>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>
[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]
<<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]
<<<<<[->>>>>+<<<<<]>>>>>[-<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<<<<
]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<<<[
->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>>][-]
++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]
<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-
<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<
[-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[-]<[-
]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<<<<<[->>
>>>+<<<<<]>>>>>[-<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<<
<<]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>
>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>>][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+
>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>
>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<
+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>[-<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>+>>>]<]>[-]>[-]<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>
>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>
>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->
>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<
<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>[-]>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>]<]>[-]>[-]
<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>
>>>>>>>>>>][-]++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]
>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[-
>>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->
+<]>[[-<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>+>>>]<]<[->>>>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]>>[-]<<
<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>[-]>>>>
>[-<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>+>>>>>][-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>
>[-]>>>>[-<<<<<<<<+>>>>+>>>>]<<<[-]++++++++++++++++++++++++++++++++>>-<]>[[-
]>[-]<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>[-]>>>>>
[-<<<<<<<<<<<<<<<<+>>>>>>>>>>>+>>>>>][-]<<<<<<<[->>>>>>>+<<<<<<<]>>>[-]>>>>[
-<<<<<<<+>>>+>>>>]<<<[-]++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++>>]<[-]++++++++++++++++>[-]+++++++++++++
+>>>>[-]>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][
-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]
<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-
<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<
[-]>>>]<<<[[-]<<<<+++++>>>>]>[-]>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>
[-<+<<<<<<<<+>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<
<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>
>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]
>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<++++++++++>>>][-]>[-]<<<<<<<<[->>>
>>>>>+<<<<<<<<]>>>>>>>>[-<+<<<<<<<+>>>>>>>>][-]+++++++++++++++++++++++++<<<[
-]>>[>>[-]<[->+<]>[-<+<<<+>>>>]<<-][-]<<[->>+<<]>>[-<<+<<+>>>>][-]<<<<<<<<<<
<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>>>[-<<<<<<<<<<<+>>>>>>>->>>>][-]<<<<<<<<
<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>>>[-<<<<<<<<<<<+>>>>>>>->>>>]>[-]>[-]<
<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]++<<[-]+>>>
[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]
<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[
-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[
[-]<<<<----->>>>][-]<<<<<<[->>>>>>+<<<<<<]>>>>>>[-<<<<<<+>>>->>>][-]++++++++
+++++++++++++++++++.++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++.>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>]>>>[-]>[-]<<<<<[->>>
>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>
+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<
[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]
>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<
<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>
[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[
-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<
]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<
<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<
<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<
<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+
<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>
>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<[-]>>>>>[-]<[->+<]>[[-<
+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<<->>>>]>]<<<[-]>[-]<<<<<[->>>
>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>
[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+
>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>
>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<
<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++
>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>
]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]
>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<[-]>>>>[-]
<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>>>]<<[-<<<->>>]>]<<<[-]>[-]<<
<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+
<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>
>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-
]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]
<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+>]<++++++++++++++++++++++++++
++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.<++
++++++++++++++++++++++++++++++++++++++++++++++.>>>>-<]>[[-]>[-]<<<<[->>>>+<<
<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++++++++++++++++++++++++++++++++++
++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>-<]>[[-]<<<<<<+++
+++++++++++++++++++++++++++++++++++++++++++++.>>>>>>]<<]<<<<<<--------------
------------------.>[-]>[-]<<<<<<[->>>>>>+<<<<<<]>>>>>>[-<+<<<<<+>>>>>>]>>>[
-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->
>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]
>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>
[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[->+<]>[[-<+>
]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-]>[-]<<<<<[->
>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-
]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<
<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[-
>>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<
<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++
++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>
>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<
<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<[-]>>>>
>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<<->>>>]>]<<<[
-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-
]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>
>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+
>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>
>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>
>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]
>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]
<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<
]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>>>]<<[-<<<->>
>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>
>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-
]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>
[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>
>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+>]<++++++++++
++++++++++++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++
++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>-<]>[[-]>
[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++++++++++++++++++
++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>-
<]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>]<<]<<<<
<<+++++++++++++.>[-]>[-]<<<<<<<[->>>>>>>+<<<<<<<]>>>>>>>[-<+<<<<<<+>>>>>>>][
-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>
>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>
>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<
]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[-]+++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++.<-<]>[[-]<<<<<<.>>>>>>]<[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>
>[-]>>[-<<<<<<<<<<<+>>>>>>>>>+>>][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<..>>>-]
<<<.>>>>>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>[-]>>[-<<<<<<<<<<<
+>>>>>>>>>+>>][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<..>>>-]>>>[-]>[-]<<<<<<<[-
>>>>>>>+<<<<<<<]>>>>>>>[-<+<<<<<<+>>>>>>>][-]+++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++<<[-]+>>>[-]>[-]<<<
[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-
]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]
[-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[
-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++.<-<]>[[-]<<<<<<.>>>>>>]<<<<<<
<<<]>[-]++++++++++.[-]+>[-]+>[-]+++++++++++++++++++++++++++.++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++.>[-]>[-]<<<[->>>+<<<]>>>[-<
+<<+>>>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<
[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<
<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[
-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[
->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-]
>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<
<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+
<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>
>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]
<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>
][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>
>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<
<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<
<<]<<[-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<<
->>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[
-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>
]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]
>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+
<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>
[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<
[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<
->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]
<<[-]+>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>>
>]<<[-<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++
++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<
<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>
>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-
]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+>
]<++++++++++++++++++++++++++++++++++++++++++++++++.<++++++++++++++++++++++++
++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.>
>>>-<]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++++++
++++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++
++++.>>>>>>-<]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++++++++++.>>
>>>>]<<]<<<<<<--------------------------------.>[-]>[-]<<<<[->>>>+<<<<]>>>>[
-<+<<<+>>>>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[
-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>
[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>
>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[
-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<
<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>
[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[-
>>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<
<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<
+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>
>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<
<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[
-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<
]<]<<<]<<[-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-
<<<<->>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<
<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+
>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<
<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[
->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>
>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]
<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<
[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+
>>>]<<[-]+>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+
>>>>>]<<[-<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++
++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>
[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<
[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]
+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[
-<+>]<++++++++++++++++++++++++++++++++++++++++++++++++.<++++++++++++++++++++
++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++
++.>>>>-<]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++
++++++++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++
++++++++.>>>>>>-<]>[[-]<<<<<<+++++++++++++++++++++++++++++++++++++++++++++++
+.>>>>>>]<<]<<<<<<+++++++++++++.<<[-]+++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++[>[-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++[>[-]+++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++[-]<-]<-]<<<<<]<<<<+>>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<
<<+>>>>>][-]++++<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>
>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->
>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]+>>>][-]<[->
+<]>[[-<+>]<<<[-]+>>>]<<<]<<->>[-]<<[->>+<<]>>[[-<<+>>]<<<<<<<<-<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>>>>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>
>>>>>>>>[-<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+>
>>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>[-]>>>>>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<<<<<<<<<+<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>
-[<<<<+>>>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-
]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>[-]<<<<<<<<<[
->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>
>>-[<<<<+>>>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
[-]>[-]>>>>>>>[-]++++++++>[-]>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>
>>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>
[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<
<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<[->+<]>[[-<+>]<<<[-]+
>>>]<<<[<<<<<<<<--------->>+>>>>>>>[-]++++++++>[-]>[-]<<<<<<<<<<<[->>>>>>>>>
>>+<<<<<<<<<<<]>>>>>>>>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->>
>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-
]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<
[->+<]>[[-<+>]<<<[-]+>>>]<<<]>[-]++>[-]>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<
<<<]>>>>>>>>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[
-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<
<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<[->+<]>[[-<
+>]<<<[-]+>>>]<<<[<<<<<<<<--->+>>>>>>>>[-]++>[-]>[-]<<<<<<<<<<<[->>>>>>>>>>>
+<<<<<<<<<<<]>>>>>>>>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->>>+
<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<
<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<[-
>+<]>[[-<+>]<<<[-]+>>>]<<<]<<<<+>>>]<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

212
rust2/benches/mandelbrot.bf vendored Normal file
View file

@ -0,0 +1,212 @@
A mandelbrot set fractal viewer in brainf*** written by Erik Bosman
+++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++
+++++++-[[>>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>>>>>>>>[
-]<<<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+<<<<<<<<>+++++<>[<>-
<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>>+<<<<<<<<>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>[<<<>>>
>>>>>>[>>>>>>>[-]<<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>[-]+<<<<<<<
>++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>+<<<<<<<>++
+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>+<<<<<<<<<<
<<<<<<[<<<<<<<<<]>>>[<<<>>>[-]<<<>>>>>>>>>[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<
<<<<<>[-<>>>>>>>+<<<<<<<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<
]>>>>>>>>>[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]<<<<<<<<>[-<>>>>>>>>+<<<<<<<<>>
>>>>+<<<<<<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>[<<<<<<<>>>>>>
>-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>+<<<<<]>>>>>>>>>+++++++++
+++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<
<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>
>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<[->>[-<<+>>]<<[->>+<<
>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>>>>>]<<<<<
<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<<>>-<<>>>>
>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<<<[>[-]<->
>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<>>>>>>>>>>]<[->+<]>>>>]<<<<>[
<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>
>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>>[-<<<+>>>
]<<<[->>>+<<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>
>>>>>>>]<<<<<<<<<<>[<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<
<<<<>]<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<<<<<>>>>>>>>>>
+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<
>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>[-
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>
>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>+<<<[<<<<<<<<<]>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>>>[-<<
<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>
>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<
<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<
<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]<<<<<<<[->+>>>-<<<<]>>>>>>>>>+++++
+++++++++++++++++++++<<>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>[-]<<]>>[<<<<<<<
+<[-<+>>>>+<<[-]]>[-><<<[->+>>>-<<<<]>>>]>>>>>>>>>>>>>[>>[-]<<>>>[-]<<<>
>>>[-]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]<<<>>>>>>>>>[>>>>>[-<<<<<>
+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>
>>>[>>[-<<<<<<<<<+>>>>>>>>>]<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++
+++++++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<
[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<
<<]>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>[-<<+
>>]<<[->>+<<>>>+<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>
>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<
<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<
<<[>[-]<->>>[<<<>>>-<<<+>[<->-<<<<<<<<<<>>>+<<<>>>>>>>>>>]<[->+<]>>>]<<<
>[<>-<>>>+<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>
>>>>>+<<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>
]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>
>>+<<<<<<[->>[-<<+>>]<<[->>+<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]
<>]<>>>>>>>>>>[>>>>>>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>
>]<<<<<<<<<<<>]<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>
>+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<
<>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>[
-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<>>>>>>>>>]<<<<<
<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]<<<<<<<<<-<<<<<<<<<
[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]
<<<<<<<<>[-<>>>>>>>>+<<<<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>
>>>>[>>>>>>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+<<<<>>>>>[<<<<<>>
>>>-<<<<<>>>>-<<<<+>>>>>]<<<<<>>>>>>[<<<<<<>>>>>>-<<<<<<[->>>>>+<<<<<>>>
>+<<<<>>>>+<<<<]>>>>>[<<<<<>>>>>-<<<<<+>>>>>]<<<<<>>>>-<<<<>>>>>+<<<<<>>
>>>>]<<<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>>>+<<<<<<>>>>>]<<<<<[->>>>>+<<<<<]>
>>>>>[-]<<<<<<+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>>>>>>>[-+>>[-<<->>]+<<
[->>-<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[
>>>>>>>>>]>+<]]+>>>[-<<<->>>]+<<<[->>>-<<<>>[-<<+>>]<<[->>+<<<<<<<<<<<[<
<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<
<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>
>>>[>+<>>>[-<<<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>>
+<<<<<<>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>[-<<<>>>>>>+<<<<<<>>>]
<<<>>]<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>]<>>[-<<>>>>>>
+<<<<<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>>]<<>>>[-<<<>>>
>>>+<<<<<<>>>]<<<<<<<<<<<<]>>>>[-]<<<<]>>>[-<<<+>>>]<<<[->>>+<<<>>>>>>>>
>[>+<>>[-<<>-<>>]<<>[-<>>+<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>>+<<<<<<>
>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>[-<<>>>>>>+<<<<<<>>]<<>>>]<<<
>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>]<<>]<>>>[-<<<>>>>>>+<<<<<<>>[
-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>]<<>>>]<<<>>[-<<>>>>>>+<<<<<<>>]<
<<<<<<<<<<]>>>>>>+<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>>>>>
>>>>]<<<<<<<<<[>[-<>>>>>>+<<<<<<>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><
>>>[-<<<>>>>>>+<<<<<<>>>]<<<>>]<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>
>><>>>]<<<>]<>>[-<<>>>>>>+<<<<<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>
><>>>]<<<>>]<<>>>[-<<<>>>>>>+<<<<<<>>>]<<<<<<<<<<<<]]>[-]<>>>[-]<<<>>>>[
-]<<<<>>>>>>>>>[>>[-]<<>>>[-]<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[
>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<
<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[
-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>
>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<
<<<<[->>[-<<+>>]<<[->>+<<>>>+<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>
>>>>>>>[>>>>>>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<
<<<<<<>]<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>
>>>>>]<<<<<<<<<[>[-]<->>>[<<<>>>-<<<+>[<->-<<<<<<<<<<>>>+<<<>>>>>>>>>>]<
[->+<]>>>]<<<>[<>-<>>>+<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<>>>>>>>>>]<<
<<<<<<<[<<<<<<<<<]>>>>>[-]<<<<<>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]<<<
<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[-+>>>[-<<<->>>
]+<<<[->>>-<<<>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]
+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+
>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<
]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>
]<<<[->>>+<<<>>>>>>>>>[>+<>>>>[-<<<<>-<>>>>]<<<<>[-<>>>>+<<<<>]<>>>>>>>>
>]<<<<<<<<<>+<[>[-<>>+<<>>>[-<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>[-<<<<>>+<
<>>>>]<<<<>>>]<<<>>>>[-<<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>]<<<<>]<>>>[-<<
<>>+<<>>>>[-<<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>]<<<<>>>]<<<>>>>[-<<<<>>+<
<>>>>]<<<<<<<<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>+<>>>[-<<
<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>+<<>>>>[-<<<<>>-<<
><<<<<<<<<+>>>>>>>>><>>>[-<<<>>+<<>>>]<<<>>>>]<<<<>>>[-<<<>>-<<><<<<<<<<
<+>>>>>>>>><>>>]<<<>]<>>>>[-<<<<>>+<<>>>[-<<<>>-<<><<<<<<<<<+>>>>>>>>><>
>>]<<<>>>>]<<<<>>>[-<<<>>+<<>>>]<<<<<<<<<<<<]>>>>>+<<<<<]>>>>>>>>>[>>>[-
]<<<>>>>[-]<<<<>>>>>[-]<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]<<<>>>>[
-]<<<<>>>>>>>>>[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<<<<<<>[-<>>>>>>>+<<<<<<<>>>
+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>
-<<<<+>>>>>]<<<<<>>>>>>>[<<<<<<<>>>>>>>-<<<<<<<[->>>>>+<<<<<>>>>+<<<<>>>
>+<<<<]>>>>>[<<<<<>>>>>-<<<<<+>>>>>]<<<<<>>>>-<<<<>>>>>+<<<<<>>>>>>>]<<<
<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>>>>+<<<<<<<>>>>>]<<<<<[->>>>>+<<<<<]+>>>>[
-<<<<->>>>]+<<<<[->>>>-<<<<>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>[-<<+
>>]<<[->>+<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>
[-<<->>]+<<[->>-<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<
<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<
<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+<<<>>>>>>>>>[>+<>>[-<<>-<>>]<<>[-<>
>+<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>+<<<<<>>>[-<<<>>>>>-<<<<<><<<<<<<
<<+>>>>>>>>><>>[-<<>>>>>+<<<<<>>]<<>>>]<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>
>>>>>>><>>]<<>]<>>>[-<<<>>>>>+<<<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>>
<>>]<<>>>]<<<>>[-<<>>>>>+<<<<<>>]<<<<<<<<<<<]>>>>>[-]<<<<<>>>>>>>[<<<<<<
<>>>>>>>-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>+<<<<<]]>>>>[-<<<<
+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>+<>>>[-<<<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>
>>>]<<<<<<<<<>+<[>[-<>>>>>+<<<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>
>[-<<<>>>>>+<<<<<>>>]<<<>>]<<>>>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>
]<<<>]<>>[-<<>>>>>+<<<<<>>>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>
>]<<>>>[-<<<>>>>>+<<<<<>>>]<<<<<<<<<<<<]]>>>>[-]<<<<]>>>>[-<<<<+>>>>]<<<
<[->>>>+<<<<>>>>>[-]<<<<<>>>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>>>>>>>]<<<<<<<[
->>>>>>>+<<<<<<<>>>>>+<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-<>>>>>+<<<<
<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>[-<<<>>>>>+<<<<<>>>]<<<>>]<<>>
>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>]<>>[-<<>>>>>+<<<<<>>>[-<<
<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>>]<<>>>[-<<<>>>>>+<<<<<>>>]<<<<
<<<<<<<<]]>>>>>>>>>[>>[-]<<>>>[-]<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]
<<<>>>>[-]<<<<>>>>>>>>>[>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]
<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>
[-<>>>>>>+<<<<<<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++
+++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<
<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>
>>>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<[->>[-<<+>>]<<[->>+
<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>>>>>]<<<
<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<<>>-<<>>
>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<<<[>[-]<
->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<>>>>>>>>>>]<[->+<]>>>>]<<<<
>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]
>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>>[-<<<+>
>>]<<<[->>>+<<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[
>>>>>>>>>]<<<<<<<<<<>[<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<
<<<<<<>]<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<<<<<>>>>>>>>
>>+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<
<<>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>
[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>
>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>+<<<[<<<<<<<<<]>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>>>[-
<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>
>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<
<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<
<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>-<<>>>>[-<<<<+>>>>]<<<<[->>>>+
<<<<>>[-]<<]>>]<<+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<<<.>>]>>>>[<<<<>>>>-<<
<<<<<.>>>>>>>]<<<<>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<>>>>>>>>>[>[-]>[-]>[-]>[
-]>[-]>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-]<<<<<>>>
>>>>>>]<<<<<<<<<[<<<<<<<<<]>++++++++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<
>]<>>>>>>>>>>]<>>>>>+<<<<<>>>>>>>>>>>>>>+<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>
>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>>>[-]<<<<<<<>>>>>>>>>[>>
>>>>>>>]<<<<<<<<<[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<<<<<<>[-<>>>>>>>+<<<<<<<[
<<<<<<<<<]>>>>>>>[-]+<<<<<<<>>>>>>>>>>]<<<<<<<<<<]]>>>>>>>[-<<<<<<<+>>>>
>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>>>>>[>+<>>>>>[-<<<<<>-<>>>>>]<<<<<>[-<>
>>>>+<<<<<>]<>>>>>>>>>]<<<<<<<<<>>>>>>>+<<<<<<<[>>>>>[<<<<<>>>>>-<<<<<>>
>>>>>+<<<<<<<>>>>>]<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-]<->>
>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>+<<<<<<<>>>>>>>>>>]<
[->+<]>>>>>>>]<<<<<<<>[<>-<>>>>>>>+<<<<<<<>]<+<<<<<<<<<]>>>>>>>-<<<<<<<>
>>[-]+<<<]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<<<<<<>>>>>>>>>[>
>>>>[<<<<<>>>>>-<<<<<>>>>>>>+<<<<<<<>>>>>]<<<<<>>>>>>>>>]<<<<<<<<<[>[-]<
->>>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>+<<<<<<<>>>>>>>>>
>]<[->+<]>>>>>>>]<<<<<<<>[<>-<>>>>>>>+<<<<<<<>]<+<<<<<<<<<]>+++++<>[<>-<
>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>+<<<<<[<<<<<<<<<]>>>>>>>>
>[-+>>>>>[-<<<<<->>>>>]+<<<<<[->>>>>-<<<<<>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<
<<[->>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>
+<]]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<<<<<<>>>>>[-<<<<<+>>>>
>]<<<<<[->>>>>+<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[
-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<
<<<>+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>-<<<<<[<<
<<<<<<<]]>>>]<<<<.>>>>>>>>>>[>>>>>>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<
<]>+++++++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>+<<<<
<<>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-<<<<<<<<+>>>>>>>>]
<<<<<<<<[->>>>>>>>+<<<<<<<<>>>>>>>>[-]<<<<<<<<>>>>>>>>>[>>>>>>>>>]<<<<<<
<<<[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]<<<<<<<<>[-<>>>>>>>>+<<<<<<<<[<<<<<<<<
<]>>>>>>>>[-]+<<<<<<<<>>>>>>>>>>]<<<<<<<<<<]]>>>>>>>>[-<<<<<<<<+>>>>>>>>
]<<<<<<<<[->>>>>>>>+<<<<<<<<>>>>>>>>>[>+<>>>>>>[-<<<<<<>-<>>>>>>]<<<<<<>
[-<>>>>>>+<<<<<<>]<>>>>>>>>>]<<<<<<<<<>>>>>>>>+<<<<<<<<[>>>>>>[<<<<<<>>>
>>>-<<<<<<>>>>>>>>+<<<<<<<<>>>>>>]<<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<
<<<<<<<[>[-]<->>>>>>>>[<<<<<<<<>>>>>>>>-<<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>
>+<<<<<<<<>>>>>>>>>>]<[->+<]>>>>>>>>]<<<<<<<<>[<>-<>>>>>>>>+<<<<<<<<>]<+
<<<<<<<<<]>>>>>>>>-<<<<<<<<>>>[-]+<<<]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<
<<<<[->>>>>>>>-<<<<<<<<>>>>>>>>>[>>>>>>[<<<<<<>>>>>>-<<<<<<>>>>>>>>+<<<<
<<<<>>>>>>]<<<<<<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>>>>>[<<<<<<<<>>>>>>>>-<<<
<<<<<+>[<->-<<<<<<<<<<>>>>>>>>+<<<<<<<<>>>>>>>>>>]<[->+<]>>>>>>>>]<<<<<<
<<>[<>-<>>>>>>>>+<<<<<<<<>]<+<<<<<<<<<]>+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<
<<<<<<<>]<>>>>>>>>>>]<>>>>>>+<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<
<<<[<<<<<<<<<]>>>>>>>>>[-+>>>>>>[-<<<<<<->>>>>>]+<<<<<<[->>>>>>-<<<<<<>>
>>>>>>[-<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<<<
]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<
<<<<[->>>>>>>>-<<<<<<<<>>>>>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<<<<<<
<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<
<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<<>+++++<>[<>-<>[<>-<>>>>
>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>-<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>-<<<<<<[<<<<<<<<<]]>>>]<<<

55
rust2/benches/opts.rs Normal file
View file

@ -0,0 +1,55 @@
use std::io::{Read, Write};
use bumpalo::Bump;
use criterion::{black_box, criterion_main, Criterion};
struct MockReadWrite;
impl Read for MockReadWrite {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
buf.fill(b'A');
Ok(buf.len())
}
}
impl Write for MockReadWrite {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
fn run_bf(bf: &str) {
let bump = Bump::new();
let ast = brainfuck::parse::parse(&bump, bf.bytes().enumerate()).unwrap();
let hir = brainfuck::hir::optimized_hir(&bump, &ast);
let lir = brainfuck::lir::generate(&bump, &hir);
brainfuck::lir::interpreter::run(&lir, MockReadWrite, MockReadWrite, |_| {});
}
fn optimized(c: &mut Criterion) {
let fizzbuzz = include_str!("fizzbuzz.bf");
let bench = include_str!("bench.bf");
let twinkle = include_str!("twinkle.bf");
let bottles = include_str!("bottles.bf");
let mandelbrot = include_str!("mandelbrot.bf");
let hanoi = include_str!("hanoi.bf");
c.bench_function("fizzbuzz", |b| b.iter(|| run_bf(black_box(fizzbuzz))));
c.bench_function("bench", |b| b.iter(|| run_bf(black_box(bench))));
c.bench_function("twinkle", |b| b.iter(|| run_bf(black_box(twinkle))));
c.bench_function("bottles", |b| b.iter(|| run_bf(black_box(bottles))));
c.bench_function("mandelbrot", |b| b.iter(|| run_bf(black_box(mandelbrot))));
c.bench_function("hanoi", |b| b.iter(|| run_bf(black_box(hanoi))));
}
pub fn benches() {
// we need such a low sample size because the benches take ages otherwise
let mut c = Criterion::default().configure_from_args().sample_size(30);
optimized(&mut c);
}
criterion_main!(benches);

3
rust2/benches/twinkle.bf vendored Normal file

File diff suppressed because one or more lines are too long

212
rust2/mandelbrot.bf vendored Normal file
View file

@ -0,0 +1,212 @@
A mandelbrot set fractal viewer in brainf*** written by Erik Bosman
+++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++
+++++++-[[>>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>>>>>>>>[
-]<<<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+<<<<<<<<>+++++<>[<>-
<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>>+<<<<<<<<>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>[<<<>>>
>>>>>>[>>>>>>>[-]<<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>[-]+<<<<<<<
>++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>+<<<<<<<>++
+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>+<<<<<<<<<<
<<<<<<[<<<<<<<<<]>>>[<<<>>>[-]<<<>>>>>>>>>[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<
<<<<<>[-<>>>>>>>+<<<<<<<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<
]>>>>>>>>>[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]<<<<<<<<>[-<>>>>>>>>+<<<<<<<<>>
>>>>+<<<<<<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>[<<<<<<<>>>>>>
>-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>+<<<<<]>>>>>>>>>+++++++++
+++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<
<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>
>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<[->>[-<<+>>]<<[->>+<<
>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>>>>>]<<<<<
<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<<>>-<<>>>>
>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<<<[>[-]<->
>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<>>>>>>>>>>]<[->+<]>>>>]<<<<>[
<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>
>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>>[-<<<+>>>
]<<<[->>>+<<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>
>>>>>>>]<<<<<<<<<<>[<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<
<<<<>]<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<<<<<>>>>>>>>>>
+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<
>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>[-
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>
>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>+<<<[<<<<<<<<<]>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>>>[-<<
<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>
>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<
<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<
<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]<<<<<<<[->+>>>-<<<<]>>>>>>>>>+++++
+++++++++++++++++++++<<>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>[-]<<]>>[<<<<<<<
+<[-<+>>>>+<<[-]]>[-><<<[->+>>>-<<<<]>>>]>>>>>>>>>>>>>[>>[-]<<>>>[-]<<<>
>>>[-]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]<<<>>>>>>>>>[>>>>>[-<<<<<>
+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>
>>>[>>[-<<<<<<<<<+>>>>>>>>>]<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++
+++++++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<
[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<
<<]>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>[-<<+
>>]<<[->>+<<>>>+<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>
>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<
<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<
<<[>[-]<->>>[<<<>>>-<<<+>[<->-<<<<<<<<<<>>>+<<<>>>>>>>>>>]<[->+<]>>>]<<<
>[<>-<>>>+<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>
>>>>>+<<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>
]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>
>>+<<<<<<[->>[-<<+>>]<<[->>+<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]
<>]<>>>>>>>>>>[>>>>>>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>
>]<<<<<<<<<<<>]<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>
>+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<
<>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>[
-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<>>>>>>>>>]<<<<<
<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]<<<<<<<<<-<<<<<<<<<
[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]
<<<<<<<<>[-<>>>>>>>>+<<<<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>
>>>>[>>>>>>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+<<<<>>>>>[<<<<<>>
>>>-<<<<<>>>>-<<<<+>>>>>]<<<<<>>>>>>[<<<<<<>>>>>>-<<<<<<[->>>>>+<<<<<>>>
>+<<<<>>>>+<<<<]>>>>>[<<<<<>>>>>-<<<<<+>>>>>]<<<<<>>>>-<<<<>>>>>+<<<<<>>
>>>>]<<<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>>>+<<<<<<>>>>>]<<<<<[->>>>>+<<<<<]>
>>>>>[-]<<<<<<+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>>>>>>>[-+>>[-<<->>]+<<
[->>-<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[
>>>>>>>>>]>+<]]+>>>[-<<<->>>]+<<<[->>>-<<<>>[-<<+>>]<<[->>+<<<<<<<<<<<[<
<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<
<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>
>>>[>+<>>>[-<<<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>>
+<<<<<<>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>[-<<<>>>>>>+<<<<<<>>>]
<<<>>]<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>]<>>[-<<>>>>>>
+<<<<<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>>]<<>>>[-<<<>>>
>>>+<<<<<<>>>]<<<<<<<<<<<<]>>>>[-]<<<<]>>>[-<<<+>>>]<<<[->>>+<<<>>>>>>>>
>[>+<>>[-<<>-<>>]<<>[-<>>+<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>>+<<<<<<>
>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>[-<<>>>>>>+<<<<<<>>]<<>>>]<<<
>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>]<<>]<>>>[-<<<>>>>>>+<<<<<<>>[
-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>]<<>>>]<<<>>[-<<>>>>>>+<<<<<<>>]<
<<<<<<<<<<]>>>>>>+<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>>>>>
>>>>]<<<<<<<<<[>[-<>>>>>>+<<<<<<>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><
>>>[-<<<>>>>>>+<<<<<<>>>]<<<>>]<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>
>><>>>]<<<>]<>>[-<<>>>>>>+<<<<<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>
><>>>]<<<>>]<<>>>[-<<<>>>>>>+<<<<<<>>>]<<<<<<<<<<<<]]>[-]<>>>[-]<<<>>>>[
-]<<<<>>>>>>>>>[>>[-]<<>>>[-]<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[
>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<
<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[
-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>
>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<
<<<<[->>[-<<+>>]<<[->>+<<>>>+<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>
>>>>>>>[>>>>>>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<
<<<<<<>]<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>
>>>>>]<<<<<<<<<[>[-]<->>>[<<<>>>-<<<+>[<->-<<<<<<<<<<>>>+<<<>>>>>>>>>>]<
[->+<]>>>]<<<>[<>-<>>>+<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<>>>>>>>>>]<<
<<<<<<<[<<<<<<<<<]>>>>>[-]<<<<<>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]<<<
<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[-+>>>[-<<<->>>
]+<<<[->>>-<<<>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]
+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+
>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<
]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>
]<<<[->>>+<<<>>>>>>>>>[>+<>>>>[-<<<<>-<>>>>]<<<<>[-<>>>>+<<<<>]<>>>>>>>>
>]<<<<<<<<<>+<[>[-<>>+<<>>>[-<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>[-<<<<>>+<
<>>>>]<<<<>>>]<<<>>>>[-<<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>]<<<<>]<>>>[-<<
<>>+<<>>>>[-<<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>]<<<<>>>]<<<>>>>[-<<<<>>+<
<>>>>]<<<<<<<<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>+<>>>[-<<
<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>+<<>>>>[-<<<<>>-<<
><<<<<<<<<+>>>>>>>>><>>>[-<<<>>+<<>>>]<<<>>>>]<<<<>>>[-<<<>>-<<><<<<<<<<
<+>>>>>>>>><>>>]<<<>]<>>>>[-<<<<>>+<<>>>[-<<<>>-<<><<<<<<<<<+>>>>>>>>><>
>>]<<<>>>>]<<<<>>>[-<<<>>+<<>>>]<<<<<<<<<<<<]>>>>>+<<<<<]>>>>>>>>>[>>>[-
]<<<>>>>[-]<<<<>>>>>[-]<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]<<<>>>>[
-]<<<<>>>>>>>>>[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<<<<<<>[-<>>>>>>>+<<<<<<<>>>
+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>
-<<<<+>>>>>]<<<<<>>>>>>>[<<<<<<<>>>>>>>-<<<<<<<[->>>>>+<<<<<>>>>+<<<<>>>
>+<<<<]>>>>>[<<<<<>>>>>-<<<<<+>>>>>]<<<<<>>>>-<<<<>>>>>+<<<<<>>>>>>>]<<<
<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>>>>+<<<<<<<>>>>>]<<<<<[->>>>>+<<<<<]+>>>>[
-<<<<->>>>]+<<<<[->>>>-<<<<>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>[-<<+
>>]<<[->>+<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>
[-<<->>]+<<[->>-<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<
<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<
<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+<<<>>>>>>>>>[>+<>>[-<<>-<>>]<<>[-<>
>+<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>+<<<<<>>>[-<<<>>>>>-<<<<<><<<<<<<
<<+>>>>>>>>><>>[-<<>>>>>+<<<<<>>]<<>>>]<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>
>>>>>>><>>]<<>]<>>>[-<<<>>>>>+<<<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>>
<>>]<<>>>]<<<>>[-<<>>>>>+<<<<<>>]<<<<<<<<<<<]>>>>>[-]<<<<<>>>>>>>[<<<<<<
<>>>>>>>-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>+<<<<<]]>>>>[-<<<<
+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>+<>>>[-<<<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>
>>>]<<<<<<<<<>+<[>[-<>>>>>+<<<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>
>[-<<<>>>>>+<<<<<>>>]<<<>>]<<>>>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>
]<<<>]<>>[-<<>>>>>+<<<<<>>>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>
>]<<>>>[-<<<>>>>>+<<<<<>>>]<<<<<<<<<<<<]]>>>>[-]<<<<]>>>>[-<<<<+>>>>]<<<
<[->>>>+<<<<>>>>>[-]<<<<<>>>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>>>>>>>]<<<<<<<[
->>>>>>>+<<<<<<<>>>>>+<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-<>>>>>+<<<<
<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>[-<<<>>>>>+<<<<<>>>]<<<>>]<<>>
>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>]<>>[-<<>>>>>+<<<<<>>>[-<<
<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>>]<<>>>[-<<<>>>>>+<<<<<>>>]<<<<
<<<<<<<<]]>>>>>>>>>[>>[-]<<>>>[-]<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]
<<<>>>>[-]<<<<>>>>>>>>>[>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]
<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>
[-<>>>>>>+<<<<<<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++
+++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<
<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>
>>>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<[->>[-<<+>>]<<[->>+
<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>>>>>]<<<
<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<<>>-<<>>
>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<<<[>[-]<
->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<>>>>>>>>>>]<[->+<]>>>>]<<<<
>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]
>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>>[-<<<+>
>>]<<<[->>>+<<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[
>>>>>>>>>]<<<<<<<<<<>[<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<
<<<<<<>]<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<<<<<>>>>>>>>
>>+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<
<<>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>
[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>
>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>+<<<[<<<<<<<<<]>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>>>[-
<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>
>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<
<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<
<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>-<<>>>>[-<<<<+>>>>]<<<<[->>>>+
<<<<>>[-]<<]>>]<<+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<<<.>>]>>>>[<<<<>>>>-<<
<<<<<.>>>>>>>]<<<<>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<>>>>>>>>>[>[-]>[-]>[-]>[
-]>[-]>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-]<<<<<>>>
>>>>>>]<<<<<<<<<[<<<<<<<<<]>++++++++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<
>]<>>>>>>>>>>]<>>>>>+<<<<<>>>>>>>>>>>>>>+<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>
>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>>>[-]<<<<<<<>>>>>>>>>[>>
>>>>>>>]<<<<<<<<<[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<<<<<<>[-<>>>>>>>+<<<<<<<[
<<<<<<<<<]>>>>>>>[-]+<<<<<<<>>>>>>>>>>]<<<<<<<<<<]]>>>>>>>[-<<<<<<<+>>>>
>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>>>>>[>+<>>>>>[-<<<<<>-<>>>>>]<<<<<>[-<>
>>>>+<<<<<>]<>>>>>>>>>]<<<<<<<<<>>>>>>>+<<<<<<<[>>>>>[<<<<<>>>>>-<<<<<>>
>>>>>+<<<<<<<>>>>>]<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-]<->>
>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>+<<<<<<<>>>>>>>>>>]<
[->+<]>>>>>>>]<<<<<<<>[<>-<>>>>>>>+<<<<<<<>]<+<<<<<<<<<]>>>>>>>-<<<<<<<>
>>[-]+<<<]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<<<<<<>>>>>>>>>[>
>>>>[<<<<<>>>>>-<<<<<>>>>>>>+<<<<<<<>>>>>]<<<<<>>>>>>>>>]<<<<<<<<<[>[-]<
->>>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>+<<<<<<<>>>>>>>>>
>]<[->+<]>>>>>>>]<<<<<<<>[<>-<>>>>>>>+<<<<<<<>]<+<<<<<<<<<]>+++++<>[<>-<
>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>+<<<<<[<<<<<<<<<]>>>>>>>>
>[-+>>>>>[-<<<<<->>>>>]+<<<<<[->>>>>-<<<<<>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<
<<[->>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>
+<]]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<<<<<<>>>>>[-<<<<<+>>>>
>]<<<<<[->>>>>+<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[
-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<
<<<>+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>-<<<<<[<<
<<<<<<<]]>>>]<<<<.>>>>>>>>>>[>>>>>>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<
<]>+++++++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>+<<<<
<<>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-<<<<<<<<+>>>>>>>>]
<<<<<<<<[->>>>>>>>+<<<<<<<<>>>>>>>>[-]<<<<<<<<>>>>>>>>>[>>>>>>>>>]<<<<<<
<<<[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]<<<<<<<<>[-<>>>>>>>>+<<<<<<<<[<<<<<<<<
<]>>>>>>>>[-]+<<<<<<<<>>>>>>>>>>]<<<<<<<<<<]]>>>>>>>>[-<<<<<<<<+>>>>>>>>
]<<<<<<<<[->>>>>>>>+<<<<<<<<>>>>>>>>>[>+<>>>>>>[-<<<<<<>-<>>>>>>]<<<<<<>
[-<>>>>>>+<<<<<<>]<>>>>>>>>>]<<<<<<<<<>>>>>>>>+<<<<<<<<[>>>>>>[<<<<<<>>>
>>>-<<<<<<>>>>>>>>+<<<<<<<<>>>>>>]<<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<
<<<<<<<[>[-]<->>>>>>>>[<<<<<<<<>>>>>>>>-<<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>
>+<<<<<<<<>>>>>>>>>>]<[->+<]>>>>>>>>]<<<<<<<<>[<>-<>>>>>>>>+<<<<<<<<>]<+
<<<<<<<<<]>>>>>>>>-<<<<<<<<>>>[-]+<<<]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<
<<<<[->>>>>>>>-<<<<<<<<>>>>>>>>>[>>>>>>[<<<<<<>>>>>>-<<<<<<>>>>>>>>+<<<<
<<<<>>>>>>]<<<<<<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>>>>>[<<<<<<<<>>>>>>>>-<<<
<<<<<+>[<->-<<<<<<<<<<>>>>>>>>+<<<<<<<<>>>>>>>>>>]<[->+<]>>>>>>>>]<<<<<<
<<>[<>-<>>>>>>>>+<<<<<<<<>]<+<<<<<<<<<]>+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<
<<<<<<<>]<>>>>>>>>>>]<>>>>>>+<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<
<<<[<<<<<<<<<]>>>>>>>>>[-+>>>>>>[-<<<<<<->>>>>>]+<<<<<<[->>>>>>-<<<<<<>>
>>>>>>[-<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<<<
]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<
<<<<[->>>>>>>>-<<<<<<<<>>>>>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<<<<<<
<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<
<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<<>+++++<>[<>-<>[<>-<>>>>
>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>-<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>-<<<<<<[<<<<<<<<<]]>>>]<<<

View file

@ -0,0 +1,2 @@
[toolchain]
channel = "nightly-2022-04-17"

102
rust2/src/hir/mod.rs Normal file
View file

@ -0,0 +1,102 @@
use std::fmt::{Debug, Formatter};
use bumpalo::Bump;
use dbg_pls::DebugPls;
use crate::{
parse::{Ast, Instr, Span},
BumpVec,
};
pub mod opts;
#[derive(Clone)]
pub struct Hir<'hir> {
pub stmts: BumpVec<'hir, Stmt<'hir>>,
}
impl Debug for Hir<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Debug::fmt(&self.stmts, f)
}
}
impl DebugPls for Hir<'_> {
fn fmt(&self, f: dbg_pls::Formatter<'_>) {
DebugPls::fmt(&self.stmts.iter().collect::<Vec<_>>(), f)
}
}
#[derive(Clone)]
pub struct Stmt<'hir> {
pub kind: StmtKind<'hir>,
pub span: Span,
}
impl<'hir> Stmt<'hir> {
fn new(kind: StmtKind<'hir>, span: Span) -> Stmt<'hir> {
Self { kind, span }
}
pub fn kind(&self) -> &StmtKind<'hir> {
&self.kind
}
}
impl Debug for Stmt<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Debug::fmt(&self.kind, f)
}
}
impl DebugPls for Stmt<'_> {
fn fmt(&self, f: dbg_pls::Formatter<'_>) {
DebugPls::fmt(&self.kind, f)
}
}
#[derive(Debug, Clone, DebugPls)]
pub enum StmtKind<'hir> {
Add(i32, u8),
Sub(i32, u8),
/// Sets the current cell to 0 and adds that value of the cell to another cell at `offset`
MoveAddTo {
offset: i32,
},
Right(usize),
Left(usize),
Loop(Hir<'hir>),
Out,
In,
SetN(u8),
}
fn ast_to_ir<'hir>(alloc: &'hir Bump, ast: &Ast<'_>) -> Hir<'hir> {
let mut stmts = Vec::new_in(alloc);
let stmts_iter = ast.iter().map(|(instr, span)| {
let kind = match instr {
Instr::Add => StmtKind::Add(0, 1),
Instr::Sub => StmtKind::Sub(0, 1),
Instr::Right => StmtKind::Right(1),
Instr::Left => StmtKind::Left(1),
Instr::Out => StmtKind::Out,
Instr::In => StmtKind::In,
Instr::Loop(body) => {
let ir_body = ast_to_ir(alloc, body);
StmtKind::Loop(ir_body)
}
};
Stmt::new(kind, *span)
});
stmts.extend(stmts_iter);
Hir { stmts }
}
pub fn optimized_hir<'hir>(alloc: &'hir Bump, ast: &Ast<'_>) -> Hir<'hir> {
let mut hir = ast_to_ir(alloc, ast);
opts::optimize(alloc, &mut hir);
hir
}

321
rust2/src/hir/opts.rs Normal file
View file

@ -0,0 +1,321 @@
use std::cmp::Ordering;
use bumpalo::Bump;
use tracing::trace;
use crate::{
hir::{Hir, Stmt, StmtKind},
BumpVec,
};
pub fn optimize<'hir>(alloc: &'hir Bump, hir: &mut Hir<'hir>) {
pass_group(alloc, hir);
pass_find_set_null(hir);
pass_set_n(hir);
pass_cancel_left_right_add_sub(hir);
pass_add_sub_offset(hir);
pass_move_add_to(hir);
// pass_unroll_loops(hir);
// pass_cancel_left_right_add_sub(hir);
}
/// pass that replaces things like `Sub(1) Sub(1)` with `Sub(2)`
// TODO: This pass is really slow, speed it up please
#[tracing::instrument(skip(alloc, ir_param))]
fn pass_group<'hir>(alloc: &'hir Bump, ir_param: &mut Hir<'hir>) {
let empty_ir = Hir {
stmts: Vec::new_in(alloc),
};
let ir = std::mem::replace(ir_param, empty_ir);
let new_stmts = Vec::new_in(alloc);
let stmts =
ir.stmts
.into_iter()
.fold(new_stmts, |mut stmts: BumpVec<'hir, Stmt<'hir>>, next| {
let Some(old) = stmts.last_mut() else {
if let StmtKind::Loop(mut body) = next.kind {
pass_group(alloc, &mut body);
stmts.push(Stmt::new(
StmtKind::Loop(body),
next.span,
));
} else {
stmts.push(next);
}
return stmts;
};
match (&mut old.kind, next.kind) {
(StmtKind::Add(offset_a, a), StmtKind::Add(offset_b, b))
if *a < 255 && *offset_a == offset_b =>
{
old.span = old.span.merge(next.span);
*a += b;
}
(StmtKind::Sub(offset_a, a), StmtKind::Sub(offset_b, b))
if *a < 255 && *offset_a == offset_b =>
{
old.span = old.span.merge(next.span);
*a += b;
}
(StmtKind::Right(a), StmtKind::Right(b)) if *a < 255 => {
old.span = old.span.merge(next.span);
*a += b;
}
(StmtKind::Left(a), StmtKind::Left(b)) if *a < 255 => {
old.span = old.span.merge(next.span);
*a += b;
}
(_, StmtKind::Loop(mut body)) => {
pass_group(alloc, &mut body);
stmts.push(Stmt {
span: next.span,
kind: StmtKind::Loop(body),
});
}
(_, kind) => {
stmts.push(Stmt::new(kind, next.span));
}
}
stmts
});
*ir_param = Hir { stmts };
}
/// pass that replaces `Loop([Sub(_)])` to `SetNull`
#[tracing::instrument(skip(ir))]
fn pass_find_set_null(ir: &mut Hir<'_>) {
pass_find_set_null_inner(ir)
}
fn pass_find_set_null_inner(ir: &mut Hir<'_>) {
for stmt in &mut ir.stmts {
if let Stmt {
kind: StmtKind::Loop(body),
span,
} = stmt
{
if let [Stmt {
kind: StmtKind::Sub(0, _),
..
}] = body.stmts.as_slice()
{
trace!(?span, "Replacing Statement with SetNull");
*stmt = Stmt::new(StmtKind::SetN(0), *span);
} else {
pass_find_set_null_inner(body);
}
}
}
}
/// pass that replaces `SetN(n) Add(m)` with `SetN(n + m)`
#[tracing::instrument(skip(ir))]
fn pass_set_n(ir: &mut Hir<'_>) {
pass_set_n_inner(ir)
}
fn pass_set_n_inner(ir: &mut Hir<'_>) {
window_pass(ir, pass_set_n_inner, |[a, b]| {
if let StmtKind::SetN(before) = a.kind() {
let new = match b.kind() {
StmtKind::Add(0, n) => StmtKind::SetN(before.wrapping_add(*n)),
StmtKind::Sub(0, n) => StmtKind::SetN(before.wrapping_sub(*n)),
_ => {
return WindowPassAction::None;
}
};
return WindowPassAction::Merge(new);
}
WindowPassAction::None
});
}
/// pass that replaces `Left(5) Right(3)` with `Left(2)`
#[tracing::instrument(skip(ir))]
fn pass_cancel_left_right_add_sub(ir: &mut Hir<'_>) {
pass_cancel_left_right_add_sub_inner(ir)
}
fn pass_cancel_left_right_add_sub_inner(ir: &mut Hir<'_>) {
window_pass(ir, pass_cancel_left_right_add_sub_inner, |[a, b]| {
match (a.kind(), b.kind()) {
(StmtKind::Right(r), StmtKind::Left(l)) | (StmtKind::Left(l), StmtKind::Right(r)) => {
let new = match r.cmp(l) {
Ordering::Equal => {
return WindowPassAction::RemoveAll;
}
Ordering::Less => StmtKind::Left(l - r),
Ordering::Greater => StmtKind::Right(r - l),
};
WindowPassAction::Merge(new)
}
(StmtKind::Add(offset_a, r), StmtKind::Sub(offset_b, l))
| (StmtKind::Sub(offset_a, l), StmtKind::Add(offset_b, r))
if offset_a == offset_b =>
{
let new = match r.cmp(l) {
Ordering::Equal => return WindowPassAction::RemoveAll,
Ordering::Less => StmtKind::Sub(*offset_a, l - r),
Ordering::Greater => StmtKind::Add(*offset_a, r - l),
};
WindowPassAction::Merge(new)
}
_ => WindowPassAction::None,
}
})
}
/// pass that replaces `Right(9) Add(5) Left(9)` with `AddOffset(9, 5)`
#[tracing::instrument(skip(ir))]
fn pass_add_sub_offset(ir: &mut Hir<'_>) {
pass_add_sub_offset_inner(ir)
}
fn pass_add_sub_offset_inner(ir: &mut Hir<'_>) {
window_pass(ir, pass_add_sub_offset_inner, |[a, b, c]| {
match (a.kind(), b.kind(), c.kind()) {
(StmtKind::Right(r), StmtKind::Add(0, n), StmtKind::Left(l)) if r == l => {
WindowPassAction::Merge(StmtKind::Add(i32::try_from(*r).unwrap(), *n))
}
(StmtKind::Left(l), StmtKind::Add(0, n), StmtKind::Right(r)) if r == l => {
WindowPassAction::Merge(StmtKind::Add(-i32::try_from(*r).unwrap(), *n))
}
(StmtKind::Right(r), StmtKind::Sub(0, n), StmtKind::Left(l)) if r == l => {
WindowPassAction::Merge(StmtKind::Sub(i32::try_from(*r).unwrap(), *n))
}
(StmtKind::Left(l), StmtKind::Sub(0, n), StmtKind::Right(r)) if r == l => {
WindowPassAction::Merge(StmtKind::Sub(-i32::try_from(*r).unwrap(), *n))
}
_ => WindowPassAction::None,
}
})
}
/// pass that replaces `Loop([Sub(1) AddOffset(o, 1)])` with `MoveAddTo(o)`
#[tracing::instrument(skip(ir))]
fn pass_move_add_to(ir: &mut Hir<'_>) {
pass_move_add_to_inner(ir)
}
fn pass_move_add_to_inner(ir: &mut Hir<'_>) {
for stmt in &mut ir.stmts {
if let Stmt {
kind: StmtKind::Loop(body),
span,
} = stmt
{
if let [Stmt {
kind: StmtKind::Sub(0, 1),
..
}, Stmt {
kind: StmtKind::Add(offset, 1),
..
}]
| [Stmt {
kind: StmtKind::Add(offset, 1),
..
}, Stmt {
kind: StmtKind::Sub(0, 1),
..
}] = body.stmts.as_slice()
{
trace!(?span, ?offset, "Replacing Statement with MoveAddTo");
*stmt = Stmt::new(StmtKind::MoveAddTo { offset: *offset }, *span);
} else {
pass_move_add_to_inner(body);
}
}
}
}
#[tracing::instrument(skip(ir))]
fn pass_unroll_loops(ir: &mut Hir<'_>) {
let alloc = Bump::new();
pass_unroll_loops_inner(&alloc, ir);
}
fn pass_unroll_loops_inner(alloc: &Bump, ir: &mut Hir<'_>) {
window_pass(ir, pass_unroll_loops, |[a, b]| {
if let (StmtKind::SetN(n), StmtKind::Loop(body)) = (a.kind(), b.kind()) {
let mut stmts_vec = BumpVec::new_in(alloc);
let stmts = std::iter::repeat(body.stmts.iter())
.take(usize::from(*n))
.flatten()
.cloned();
stmts_vec.extend(stmts);
WindowPassAction::MergeMany(stmts_vec)
} else {
WindowPassAction::None
}
})
}
enum WindowPassAction<'hir, 'pass> {
None,
Merge(StmtKind<'hir>),
MergeMany(BumpVec<'pass, Stmt<'hir>>),
RemoveAll,
}
fn window_pass<'hir, 'pass, P, F, const N: usize>(ir: &mut Hir<'hir>, pass_recur: P, action: F)
where
P: Fn(&mut Hir<'hir>),
F: Fn([&Stmt<'hir>; N]) -> WindowPassAction<'hir, 'pass>,
{
assert!(N > 0);
let stmts = &mut ir.stmts;
let mut i = 0;
while i < stmts.len() {
let a = &mut stmts[i];
if let StmtKind::Loop(body) = &mut a.kind {
pass_recur(body);
}
if i + N > stmts.len() {
break; // there aren't N elements left
}
let mut elements = stmts[i..][..N].iter();
let elements = [(); N].map(|()| elements.next().unwrap());
let merged_span = elements[0].span.merge(elements.last().unwrap().span);
let result = action(elements);
match result {
WindowPassAction::None => {
// only increment i if we haven't removed anything
i += 1;
}
WindowPassAction::RemoveAll => {
trace!(?elements, "Removing all statements");
for _ in 0..N {
stmts.remove(i);
}
}
WindowPassAction::Merge(new) => {
trace!(?elements, ?new, "Merging statements");
for _ in 1..N {
stmts.remove(i);
}
stmts[i] = Stmt::new(new, merged_span);
}
WindowPassAction::MergeMany(new) => {
trace!(?elements, ?new, "Merging many");
for _ in 0..N {
stmts.remove(i);
}
for stmt in new.into_iter().rev() {
stmts.insert(i, stmt);
}
}
}
}
}

185
rust2/src/lib.rs Normal file
View file

@ -0,0 +1,185 @@
#![feature(allocator_api, let_else)]
#![feature(nonzero_ops)]
#![deny(unsafe_op_in_unsafe_fn)]
#![warn(rust_2018_idioms)]
use std::{
fmt::Display,
io::{Read, Write},
path::PathBuf,
str::FromStr,
};
use bumpalo::Bump;
use owo_colors::OwoColorize;
use crate::parse::ParseError;
pub mod hir;
pub mod lir;
mod mir;
pub mod parse;
#[derive(clap::Parser, Default)]
#[clap(author, about)]
pub struct Args {
/// Print colored source code depending on how often it was run.
/// Makes the interpreter ~30% slower.
#[clap(short, long)]
pub profile: bool,
/// Dump the IR info (ast, hir, mir, lir)
#[clap(long)]
pub dump: Option<DumpKind>,
/// Use experimental mid-level IR
#[clap(long)]
pub mir: bool,
/// The file to run
pub file: PathBuf,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DumpKind {
Ast,
Hir,
Mir,
Lir,
}
impl FromStr for DumpKind {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"ast" => Ok(Self::Ast),
"hir" => Ok(Self::Hir),
"mir" => Ok(Self::Mir),
"lir" => Ok(Self::Lir),
other => Err(format!("Invalid IR level: '{other}'")),
}
}
}
type BumpVec<'a, T> = Vec<T, &'a Bump>;
pub enum UseProfile {
Yes,
No,
}
pub fn run<R, W>(src: &str, stdout: W, stdin: R, config: &Args) -> Result<(), ParseError>
where
W: Write,
R: Read,
{
let ast_alloc = Bump::new();
let parsed = parse::parse(&ast_alloc, src.bytes().enumerate())?;
if let Some(DumpKind::Ast) = config.dump {
println!("{parsed:#?}");
return Ok(());
}
let hir_alloc = Bump::new();
let optimized_hir = hir::optimized_hir(&hir_alloc, &parsed);
if let Some(DumpKind::Hir) = config.dump {
println!("{}", dbg_pls::color(&optimized_hir));
return Ok(());
}
drop(parsed);
drop(ast_alloc);
if config.dump == Some(DumpKind::Mir) || config.mir {
let mir_alloc = Bump::new();
let mir = mir::optimized_mir(&mir_alloc, &optimized_hir);
if config.dump == Some(DumpKind::Mir) {
println!("{mir:#?}");
}
}
let cg_alloc = Bump::new();
let lir = lir::generate(&cg_alloc, &optimized_hir);
if let Some(DumpKind::Lir) = config.dump {
println!("{lir:#?}");
return Ok(());
}
drop(optimized_hir);
drop(hir_alloc);
match config.profile {
true => {
let mut code_profile_count = vec![0; lir.debug().len()];
lir::interpreter::run(&lir, stdout, stdin, |ip| unsafe {
*code_profile_count.get_unchecked_mut(ip) += 1;
});
let mut src_profile_count = vec![0u64; src.len()];
for (stmt_span, stmt_count) in lir.debug().iter().zip(&code_profile_count) {
for i in &mut src_profile_count[stmt_span.start()..stmt_span.end()] {
*i += stmt_count;
}
}
let max = src_profile_count.iter().max().copied().unwrap_or(0);
println!("\n\n---------------- Profile ----------------");
for (char, value) in src.bytes().zip(src_profile_count) {
print!("{}", color_by_profile(char as char, value, max));
}
}
false => {
lir::interpreter::run(&lir, stdout, stdin, |_| {});
}
}
Ok(())
}
fn color_by_profile(char: char, value: u64, max: u64) -> impl Display {
let max = max as f64;
let value = value as f64;
let ratio = value / max;
let logged = -ratio.log10();
let logged = (logged * 100.) as u64;
match logged {
0..=15 => char.bright_red().to_string(),
16..=70 => char.yellow().to_string(),
71..=300 => char.green().to_string(),
_ => char.default_color().to_string(),
}
}
#[cfg(test)]
mod tests {
use crate::Args;
#[test]
fn fizzbuzz() {
let str = include_str!("../benches/fizzbuzz.bf");
let mut stdout = Vec::new();
let stdin = [];
super::run(str, &mut stdout, stdin.as_slice(), &Args::default()).unwrap();
insta::assert_debug_snapshot!(String::from_utf8(stdout));
}
#[test]
fn mandelbrot() {
let str = include_str!("../benches/mandelbrot.bf");
let mut stdout = Vec::new();
let stdin = [];
super::run(str, &mut stdout, stdin.as_slice(), &Args::default()).unwrap();
insta::assert_debug_snapshot!(String::from_utf8(stdout));
}
}

View file

@ -0,0 +1,139 @@
use std::{
io::{Read, Write},
num::Wrapping,
};
use crate::lir::{Lir, Stmt};
const MEM_SIZE: usize = 32_000;
type Memory = [Wrapping<u8>; MEM_SIZE];
// `repr(C)` to make sure rustc never reorders the fields weirdly
// maybe useless, but seems to give tiny wins
#[repr(C)]
struct Interpreter<'lir, W, R, P> {
code: &'lir Lir<'lir>,
profile_collector: P,
ip: usize,
ptr: usize,
mem: Memory,
stdout: W,
stdin: R,
}
pub fn run<W, R, P>(code: &Lir<'_>, stdout: W, stdin: R, profile_collector: P)
where
W: Write,
R: Read,
P: FnMut(usize),
{
let mut interpreter = Interpreter {
code,
ip: 0,
ptr: 0,
stdout,
stdin,
mem: [Wrapping(0u8); MEM_SIZE],
profile_collector,
};
// SAFETY: `Lir` can only be produced by the `crate::lir` module, which is trusted to not
// produce out of bounds jumps and put the `End` at the end
unsafe {
interpreter.execute();
}
}
impl<'c, W: Write, R: Read, P> Interpreter<'c, W, R, P>
where
P: FnMut(usize),
{
unsafe fn execute(&mut self) {
let stmts = self.code.stmts();
loop {
// SAFETY: If the code ends with an `End` and there are no out of bounds jumps,
// `self.ip` will never be out of bounds
// Removing this bounds check speeds up execution by about 40%
debug_assert!(self.ip < stmts.len());
let instr = unsafe { *stmts.get_unchecked(self.ip) };
self.ip += 1;
match instr {
Stmt::Add(n) => {
*self.elem_mut() += n;
}
Stmt::Sub(n) => {
*self.elem_mut() -= n;
}
Stmt::AddOffset { offset, n } => *self.elem_mut_offset(offset) += n,
Stmt::SubOffset { offset, n } => *self.elem_mut_offset(offset) -= n,
Stmt::MoveAddTo { offset } => {
let value = self.elem();
*self.elem_mut() = Wrapping(0);
*self.elem_mut_offset(offset) += value;
}
Stmt::Right(n) => {
self.ptr += n as usize;
if self.ptr >= MEM_SIZE {
self.ptr = 0;
}
}
Stmt::Left(n) => {
if self.ptr < n as usize {
let diff = n as usize - self.ptr;
self.ptr = MEM_SIZE - 1 - diff;
} else {
self.ptr -= n as usize;
}
}
Stmt::Out => {
let char = self.elem() as char;
write!(self.stdout, "{char}").unwrap();
self.stdout.flush().unwrap();
}
Stmt::In => {
let mut buf = [0; 1];
self.stdin.read_exact(&mut buf).unwrap();
*self.elem_mut() = Wrapping(buf[0]);
}
Stmt::SetN(n) => {
*self.elem_mut() = Wrapping(n);
}
Stmt::JmpIfZero(pos) => {
if self.elem() == 0 {
self.ip = pos as usize;
}
}
Stmt::JmpIfNonZero(pos) => {
if self.elem() != 0 {
self.ip = pos as usize;
}
}
Stmt::End => break,
}
// this should be a no-op if `profile_collector` is does nothing
(self.profile_collector)(self.ip);
}
}
fn elem_mut_offset(&mut self, offset: i32) -> &mut Wrapping<u8> {
let ptr = self.ptr as isize;
let offset = offset as isize;
// SAFETY: `self.ptr` is never out of bounds
debug_assert!(self.ptr < self.mem.len());
unsafe { self.mem.get_unchecked_mut((ptr + offset) as usize) }
}
fn elem_mut(&mut self) -> &mut Wrapping<u8> {
// SAFETY: `self.ptr` is never out of bounds
debug_assert!(self.ptr < self.mem.len());
unsafe { self.mem.get_unchecked_mut(self.ptr) }
}
fn elem(&self) -> u8 {
// SAFETY: `self.ptr` is never out of bounds
debug_assert!(self.ptr < self.mem.len());
unsafe { self.mem.get_unchecked(self.ptr).0 }
}
}

137
rust2/src/lir/mod.rs Normal file
View file

@ -0,0 +1,137 @@
//! codegen to flat code
//!
//! ```bf
//! ++[-].
//! ```
//! compiles down to
//! ```text
//! Add | Add | JmpIfZero | Sub | JumpIfNotZero | Out | End
//! | ^ | ^
//! +-------|-----------|---------|
//! +-----------+
//! ```
//!
//! technically, the `JumpIfNotZero` would be an unconditional Jmp to the `JmpIfZero`, but that's
//! a needless indirection.
//!
//! this module must not produce out of bounds jumps and always put the `End` instruction at the
//! end
pub mod interpreter;
use std::fmt::{Debug, Formatter};
use bumpalo::Bump;
use crate::{
hir::{Hir, Stmt as HirStmt, StmtKind as HirStmtKind},
parse::Span,
BumpVec,
};
#[derive(Debug, Clone, Copy)]
pub enum Stmt {
Add(u8),
Sub(u8),
AddOffset { offset: i32, n: u8 },
SubOffset { offset: i32, n: u8 },
MoveAddTo { offset: i32 },
Right(u32),
Left(u32),
Out,
In,
SetN(u8),
JmpIfZero(u32),
JmpIfNonZero(u32),
End,
}
const _: [(); 8] = [(); std::mem::size_of::<Stmt>()];
#[derive(Clone)]
pub struct Lir<'lir> {
stmts: BumpVec<'lir, Stmt>,
debug: BumpVec<'lir, Span>,
}
impl Debug for Lir<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.stmts.fmt(f)
}
}
impl Lir<'_> {
pub fn stmts(&self) -> &[Stmt] {
&self.stmts
}
pub fn debug(&self) -> &[Span] {
&self.debug
}
}
pub fn generate<'lir>(alloc: &'lir Bump, ir: &Hir<'_>) -> Lir<'lir> {
let stmts = Vec::new_in(alloc);
let debug = Vec::new_in(alloc);
let mut lir = Lir { stmts, debug };
hir_to_lir(&mut lir, &ir.stmts);
lir.stmts.push(Stmt::End);
lir.debug.push(Span::default());
assert_eq!(lir.stmts.len(), lir.debug.len());
lir
}
fn hir_to_lir<'lir>(lir: &mut Lir<'lir>, ir: &[HirStmt<'_>]) {
for ir_stmt in ir {
hir_stmt_to_lir_stmt(lir, ir_stmt);
}
debug_assert_eq!(lir.stmts.len(), lir.debug.len());
}
fn hir_stmt_to_lir_stmt<'lir>(lir: &mut Lir<'lir>, ir_stmt: &HirStmt<'_>) {
let stmt = match &ir_stmt.kind {
HirStmtKind::Add(0, n) => Stmt::Add(*n),
HirStmtKind::Sub(0, n) => Stmt::Sub(*n),
HirStmtKind::Add(offset, n) => Stmt::AddOffset {
offset: *offset,
n: *n,
},
HirStmtKind::Sub(offset, n) => Stmt::SubOffset {
offset: *offset,
n: *n,
},
HirStmtKind::MoveAddTo { offset } => Stmt::MoveAddTo { offset: *offset },
HirStmtKind::Right(n) => Stmt::Right(u32::try_from(*n).unwrap()),
HirStmtKind::Left(n) => Stmt::Left(u32::try_from(*n).unwrap()),
HirStmtKind::Out => Stmt::Out,
HirStmtKind::In => Stmt::In,
HirStmtKind::SetN(n) => Stmt::SetN(*n),
HirStmtKind::Loop(instr) => {
let skip_jmp_idx = lir.stmts.len();
lir.stmts.push(Stmt::JmpIfZero(0)); // placeholder
lir.debug.push(ir_stmt.span);
// compile the loop body now
hir_to_lir(lir, &instr.stmts);
// if the loop body is empty, we jmp to ourselves, which is an infinite loop - as expected
let first_loop_body_idx = skip_jmp_idx + 1;
lir.stmts
.push(Stmt::JmpIfNonZero(first_loop_body_idx.try_into().unwrap()));
lir.debug.push(ir_stmt.span);
// there will always at least be an `End` instruction after the loop
let after_loop_idx = lir.stmts.len();
// fix the placeholder with the actual index
lir.stmts[skip_jmp_idx] = Stmt::JmpIfZero(after_loop_idx.try_into().unwrap());
return;
}
};
lir.stmts.push(stmt);
lir.debug.push(ir_stmt.span);
}

31
rust2/src/main.rs Normal file
View file

@ -0,0 +1,31 @@
#![feature(allocator_api, let_else)]
#![warn(rust_2018_idioms)]
use std::{fs, io, process};
use brainfuck::Args;
use clap::Parser;
fn main() {
let stdout = io::stdout();
let stdout = stdout.lock();
let stdin = io::stdin();
let stdin = stdin.lock();
let args = Args::parse();
tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::filter::EnvFilter::from_default_env())
.without_time()
.init();
let src = fs::read_to_string(&args.file).unwrap_or_else(|err| {
eprintln!("error: Failed to read file: {err}");
process::exit(1);
});
brainfuck::run(&src, stdout, stdin, &args).unwrap_or_else(|_| {
eprintln!("error: Failed to parse brainfuck code");
process::exit(1);
});
}

120
rust2/src/mir/mod.rs Normal file
View file

@ -0,0 +1,120 @@
//! an experimental MIR (mid-level-ir)
//!
//! The MIR consists of two parts. First, there are instructions (`Stmt`). These instructions
//! can be seen as an extended version of the default brainfuck instruction set `+-<>,.[]`.
//! These instructions modify the classic tape. What MIR does is that it attaches an abstract
//! `MemoryState` to *each* statement. This state contains all facts known about the state of the
//! tape at the point of execution of the statement.
//!
//! For example, for the code `++.`, the `MemoryState` for the `.` instruction contains a single
//! fact: "The current cell was written to, by the instruction before and with the value 2". MIR
//! tracks as much of the reads/writes to determine their dependencies and eliminate as many
//! of them as possible.
//!
//! Note that MIR is always pessimized, so if it can't determine for sure that something is true,
//! it will not act on it.
#![allow(dead_code)]
mod opts;
mod state;
use std::fmt::{Debug, Formatter};
use bumpalo::Bump;
use crate::{
hir::{Hir, StmtKind as HirStmtKind},
mir::state::{MemoryState, Store},
parse::Span,
BumpVec,
};
#[derive(Debug, Clone)]
pub struct Mir<'mir> {
stmts: BumpVec<'mir, Stmt<'mir>>,
}
#[derive(Clone)]
struct Stmt<'mir> {
kind: StmtKind<'mir>,
state: MemoryState<'mir>,
span: Span,
}
impl Debug for Stmt<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Stmt")
.field("kind", &self.kind)
.field("state", &self.state)
.finish()
}
}
type Offset = i32;
#[derive(Debug, Clone)]
enum StmtKind<'mir> {
/// Add or sub, the value has the valid range -255..=255
AddSub {
offset: Offset,
n: i16,
store: Store,
},
/// Sets the current cell to 0 and adds that value of the cell to another cell at `offset`
MoveAddTo {
offset: Offset,
store_set_null: Store,
store_move: Store,
},
/// Left or Right pointer move (`<>`)
PointerMove(Offset),
Loop(Mir<'mir>),
Out,
In(Store),
SetN(u8, Store),
}
#[tracing::instrument(skip(alloc, hir))]
pub fn optimized_mir<'mir>(alloc: &'mir Bump, hir: &Hir<'_>) -> Mir<'mir> {
let mut mir = hir_to_mir(alloc, hir);
opts::passes(alloc, &mut mir);
mir
}
/// compiles hir down to a minimal mir
fn hir_to_mir<'mir>(alloc: &'mir Bump, hir: &Hir<'_>) -> Mir<'mir> {
let mut stmts = Vec::new_in(alloc);
let iter = hir.stmts.iter().map(|hir_stmt| {
let kind = match *hir_stmt.kind() {
HirStmtKind::Add(offset, n) => StmtKind::AddSub {
offset,
n: i16::from(n),
store: Store::dead(),
},
HirStmtKind::Sub(offset, n) => StmtKind::AddSub {
offset,
n: -i16::from(n),
store: Store::dead(),
},
HirStmtKind::MoveAddTo { offset } => StmtKind::MoveAddTo {
offset,
store_set_null: Store::dead(),
store_move: Store::dead(),
},
HirStmtKind::Right(n) => StmtKind::PointerMove(i32::try_from(n).unwrap()),
HirStmtKind::Left(n) => StmtKind::PointerMove(-i32::try_from(n).unwrap()),
HirStmtKind::Loop(ref body) => StmtKind::Loop(hir_to_mir(alloc, body)),
HirStmtKind::Out => StmtKind::Out,
HirStmtKind::In => StmtKind::In(Store::dead()),
HirStmtKind::SetN(n) => StmtKind::SetN(n, Store::dead()),
};
Stmt {
kind,
span: hir_stmt.span,
state: MemoryState::empty(alloc),
}
});
stmts.extend(iter);
Mir { stmts }
}

215
rust2/src/mir/opts.rs Normal file
View file

@ -0,0 +1,215 @@
use std::collections::{hash_map::Entry, HashMap};
use bumpalo::Bump;
use tracing::info;
use crate::mir::{
state::{CellState, MemoryState, MemoryStateChange, Store},
Mir, Offset, StmtKind,
};
/// this pass fills out as much state info for all statements as possible
#[tracing::instrument(skip(alloc, mir))]
pub fn passes<'mir>(alloc: &'mir Bump, mir: &mut Mir<'mir>) {
pass_fill_state_info(alloc, mir);
pass_const_propagation(mir);
pass_dead_store_elimination(mir);
}
/// this pass fills out as much state info for all statements as possible
#[tracing::instrument(skip(alloc, mir))]
pub fn pass_fill_state_info<'mir>(alloc: &'mir Bump, mir: &mut Mir<'mir>) {
let empty_state = MemoryState::empty(alloc);
pass_fill_state_info_inner(alloc, mir, empty_state);
}
// note: this whole thing is unsound because it doesn't consider that stores inside a loop
// could be loaded from after the loop
fn pass_fill_state_info_inner<'mir>(
alloc: &'mir Bump,
mir: &mut Mir<'mir>,
mut outer: MemoryState<'mir>,
) {
for stmt in &mut mir.stmts {
let state = match &mut stmt.kind {
StmtKind::AddSub { offset, n, store } => {
let prev_state = outer.state_for_offset(*offset);
let new_state = match prev_state {
CellState::WrittenToKnown(_, prev_n) => {
let n = i16::from(prev_n).wrapping_add(*n);
let n = u8::try_from(n).unwrap();
CellState::WrittenToKnown(store.clone(), n)
}
_ => CellState::WrittenToUnknown(store.clone()),
};
MemoryState::single(
alloc,
outer,
MemoryStateChange::Change {
offset: *offset,
new_state,
},
)
}
StmtKind::MoveAddTo {
offset,
store_set_null,
store_move,
} => MemoryState::double(
alloc,
outer,
MemoryStateChange::Change {
offset: 0,
new_state: CellState::WrittenToKnown(store_set_null.clone(), 0),
},
MemoryStateChange::Change {
offset: *offset,
new_state: CellState::WrittenToUnknown(store_move.clone()),
},
),
StmtKind::PointerMove(n) => {
MemoryState::single(alloc, outer, MemoryStateChange::Move(*n))
}
StmtKind::Loop(body) => {
// TODO: we can get a lot smarter here and get huge benefits; we don't yet
pass_fill_state_info_inner(alloc, body, MemoryState::empty(alloc));
MemoryState::double(
alloc,
outer,
// forget all knowledge, the opaque loop might have touched it all
MemoryStateChange::Forget,
// we certainly know that the current cell is zero, since the loop exited
MemoryStateChange::Change {
offset: 0,
new_state: CellState::LoopNull,
},
)
}
StmtKind::Out => outer,
StmtKind::In(store) => MemoryState::single(
alloc,
outer,
MemoryStateChange::Change {
offset: 0,
new_state: CellState::WrittenToUnknown(store.clone()),
},
),
StmtKind::SetN(value, store) => MemoryState::single(
alloc,
outer,
MemoryStateChange::Change {
offset: 0,
new_state: CellState::WrittenToKnown(store.clone(), *value),
},
),
};
stmt.state = state.clone();
outer = state;
}
}
/// This pass eliminates dead stores. It should probably be run multiple times between other passes
/// for cleanup
#[tracing::instrument(skip(mir))]
fn pass_dead_store_elimination(mir: &mut Mir<'_>) {
pass_dead_store_elimination_mark_dead_stores(mir)
}
#[tracing::instrument(skip(mir))]
fn pass_dead_store_elimination_mark_dead_stores(mir: &Mir<'_>) {
fn mark_store(
potential_dead_stores: &mut HashMap<Offset, Store>,
offset: Offset,
store: &Store,
) {
match potential_dead_stores.entry(offset) {
Entry::Occupied(mut entry) => {
let old = entry.insert(store.clone());
if old.is_maybe_dead() {
// it's certainly dead
info!("We have a dead one!!!");
old.mark_dead();
} else {
// it's alive and well, drop it and keep it marked alive
drop(old);
}
}
Entry::Vacant(entry) => {
entry.insert(store.clone());
}
}
}
let mut potential_dead_stores = HashMap::new();
let mut current_offset = 0;
for stmt in &mir.stmts {
match &stmt.kind {
StmtKind::AddSub { store, offset, .. } => {
mark_store(&mut potential_dead_stores, current_offset + offset, store);
}
StmtKind::MoveAddTo {
offset,
store_move,
store_set_null,
} => {
mark_store(&mut potential_dead_stores, current_offset, store_set_null);
mark_store(
&mut potential_dead_stores,
current_offset + offset,
store_move,
);
}
StmtKind::PointerMove(offset) => {
current_offset += offset; // ???
}
StmtKind::Loop(body) => {
let store = potential_dead_stores.get(&current_offset);
if let Some(store) = store {
store.add_load();
}
pass_dead_store_elimination_mark_dead_stores(body);
}
StmtKind::Out => {
let store = potential_dead_stores.get(&current_offset);
if let Some(store) = store {
store.add_load();
}
}
StmtKind::In(store) | StmtKind::SetN(_, store) => {
mark_store(&mut potential_dead_stores, current_offset, store);
}
}
if stmt.state.has_forget_delta() {
// they might all have loads now
potential_dead_stores.values().for_each(Store::clobber);
}
info!(?potential_dead_stores, ?current_offset, "stores");
}
}
// test pass
#[tracing::instrument(skip(mir))]
fn pass_const_propagation(mir: &mut Mir<'_>) {
pass_const_propagation_inner(mir)
}
fn pass_const_propagation_inner(mir: &mut Mir<'_>) {
for stmt in &mut mir.stmts {
match &mut stmt.kind {
StmtKind::Out => {
let _state = stmt.state.state_for_offset(0);
// we could now insert a `SetN` before the `Out`, to mark the previous store
// as dead.
}
StmtKind::Loop(body) => {
let _state = stmt.state.state_for_offset(0);
// we could now insert a `SetN` before the `Loop`, to mark the previous store
// as dead.
pass_const_propagation_inner(body);
}
_ => {}
}
}
}

220
rust2/src/mir/state.rs Normal file
View file

@ -0,0 +1,220 @@
// todo: we're gonna leak `Rc`s here aren't we?
use std::{
cell::{Cell, RefCell},
fmt::{Debug, Formatter},
num::NonZeroU32,
rc::Rc,
};
use bumpalo::Bump;
use crate::{mir::Offset, BumpVec};
/// The known state of a cell in the MIR
#[derive(Debug, Clone)]
pub enum CellState {
/// The state of this cell is completely unknown and could be anything, for example after `,`
Unknown,
/// This cell is guaranteed to be `0` because a loop just terminated on it
LoopNull,
/// Some value was written to this cell classified by the `Store`, but we do not know the value
WrittenToUnknown(Store),
/// A known value was written to this cell
WrittenToKnown(Store, u8),
}
/// A change in the known state of the memory caused by a single instruction
#[derive(Debug, Clone)]
pub enum MemoryStateChange {
/// A cell value was changed to a new state.
Change {
offset: Offset,
new_state: CellState,
},
/// The pointer was moved. This affects the `offset` calculations from previous states.
Move(Offset),
/// Forget everything about the memory state. This currently happens after each loop, since
/// the loop is opaque and might clobber everything.
Forget,
/// Load a value from memory. This is not a direct change of the memory itself, but it does
/// change the state in that it marks the corresponding store, if any, as alive. Loads should
/// be eliminated whenever possible, to remove as many dead stores as possible.
Load { offset: Offset },
}
/// The known state of memory at a specific instance in the instruction sequence
#[derive(Clone)]
pub struct MemoryState<'mir>(Rc<RefCell<MemoryStateInner<'mir>>>);
impl<'mir> MemoryState<'mir> {
pub fn empty(alloc: &'mir Bump) -> Self {
Self::new(None, Vec::new_in(alloc))
}
pub fn single(
alloc: &'mir Bump,
prev: MemoryState<'mir>,
delta: MemoryStateChange,
) -> MemoryState<'mir> {
let mut deltas = Vec::new_in(alloc);
deltas.push(delta);
Self::new(Some(prev), deltas)
}
pub fn double(
alloc: &'mir Bump,
prev: MemoryState<'mir>,
delta1: MemoryStateChange,
delta2: MemoryStateChange,
) -> MemoryState<'mir> {
let mut deltas = Vec::new_in(alloc);
deltas.push(delta1);
deltas.push(delta2);
Self::new(Some(prev), deltas)
}
pub fn new(
prev: Option<MemoryState<'mir>>,
deltas: BumpVec<'mir, MemoryStateChange>,
) -> MemoryState<'mir> {
Self(Rc::new(RefCell::new(MemoryStateInner { prev, deltas })))
}
pub fn state_for_offset(&self, offset: Offset) -> CellState {
self.0.borrow().state_for_offset(offset)
}
pub fn has_forget_delta(&self) -> bool {
self.0
.borrow()
.deltas
.iter()
.any(|d| matches!(d, MemoryStateChange::Forget))
}
}
impl Debug for MemoryState<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.0
.try_borrow()
.map(|s| MemoryStateInner::fmt(&*s, f))
.unwrap_or_else(|_| f.debug_struct("MemoryState").finish_non_exhaustive())
}
}
/// The known state of memory relative to the pointer
#[derive(Debug, Clone)]
struct MemoryStateInner<'mir> {
prev: Option<MemoryState<'mir>>,
deltas: BumpVec<'mir, MemoryStateChange>,
}
impl<'mir> MemoryStateInner<'mir> {
fn state_for_offset(&self, offset: Offset) -> CellState {
let mut offset = offset;
for delta in &self.deltas {
match delta {
MemoryStateChange::Change {
offset: write_offset,
new_state,
} if *write_offset == offset => return new_state.clone(),
MemoryStateChange::Move(change) => offset -= change,
// we may not access the forbidden knowledge
MemoryStateChange::Forget => return CellState::Unknown,
_ => {}
}
}
self.prev
.as_ref()
.map(|state| state.state_for_offset(offset))
.unwrap_or(CellState::Unknown)
}
}
/// The abstract representation of a store in memory. Corresponding loads can also hold
/// a reference to this to mark the store as alive
#[derive(Clone)]
pub struct Store(Rc<Cell<StoreInner>>);
impl Store {
pub fn dead() -> Self {
StoreKind::Dead.into()
}
pub fn id(&self) -> u64 {
self.inner().id
}
pub fn add_load(&self) {
let old = self.inner();
let kind = match old.kind {
StoreKind::Unknown => StoreKind::UsedAtLeast(NonZeroU32::new(1).unwrap()),
StoreKind::UsedExact(n) => StoreKind::UsedExact(n.checked_add(1).unwrap()),
StoreKind::UsedAtLeast(n) => StoreKind::UsedAtLeast(n.checked_add(1).unwrap()),
StoreKind::Dead => StoreKind::UsedExact(NonZeroU32::new(1).unwrap()),
};
self.0.set(StoreInner { id: old.id, kind })
}
pub fn is_maybe_dead(&self) -> bool {
matches!(self.inner().kind, StoreKind::Dead | StoreKind::Unknown)
}
pub fn mark_dead(&self) {
let old = self.inner();
self.0.set(StoreInner {
id: old.id,
kind: StoreKind::Dead,
})
}
pub fn clobber(&self) {
let old = self.inner();
let kind = match old.kind {
StoreKind::Unknown => StoreKind::Unknown,
StoreKind::UsedExact(n) => StoreKind::UsedAtLeast(n),
StoreKind::UsedAtLeast(n) => StoreKind::UsedAtLeast(n),
StoreKind::Dead => StoreKind::Unknown,
};
self.0.set(StoreInner { id: old.id, kind })
}
fn inner(&self) -> StoreInner {
self.0.get()
}
}
impl Debug for Store {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.inner().kind.fmt(f)
}
}
#[derive(Debug, Clone, Copy)]
struct StoreInner {
id: u64,
kind: StoreKind,
}
#[derive(Debug, Clone, Copy)]
enum StoreKind {
/// No information is known about uses of the store, it has probably been clobbered
Unknown,
/// The exact amount of subsequent loads is known about the store, and it's this
UsedExact(NonZeroU32),
/// The exact amount of subsequent loads not known about this store, but it's at least this
UsedAtLeast(NonZeroU32),
/// The store is known to be dead
Dead,
}
impl From<StoreKind> for Store {
fn from(kind: StoreKind) -> Self {
Self(Rc::new(Cell::new(StoreInner {
id: rand::random(),
kind,
})))
}
}

176
rust2/src/parse.rs Normal file
View file

@ -0,0 +1,176 @@
use std::{
cmp,
fmt::{Debug, Formatter},
};
use bumpalo::Bump;
#[derive(Clone, Copy, PartialEq, Eq, Default)]
pub struct Span {
start: u32,
len: u32,
}
impl Span {
fn single(idx: usize) -> Self {
Self {
start: idx.try_into().unwrap(),
len: 1,
}
}
/// start..end
fn start_end(start: usize, end: usize) -> Span {
Self {
start: start.try_into().unwrap(),
len: (end - start).try_into().unwrap(),
}
}
// start..=end
fn start_end_incl(start: usize, end: usize) -> Span {
Self {
start: start.try_into().unwrap(),
len: (end - start + 1).try_into().unwrap(),
}
}
#[must_use]
pub fn until(&self, other: Self) -> Self {
Self {
start: self.start,
len: (other.start + other.len) - self.len,
}
}
#[must_use]
pub fn merge(&self, other: Self) -> Self {
Self::start_end(
cmp::min(self.start(), other.start()),
cmp::max(self.end(), other.end()),
)
}
pub fn start(&self) -> usize {
self.start.try_into().unwrap()
}
pub fn len(&self) -> usize {
self.len.try_into().unwrap()
}
/// ..end
pub fn end(&self) -> usize {
self.start() + self.len()
}
}
impl Debug for Span {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Debug::fmt(&(self.start..(self.start + self.len)), f)
}
}
pub type Ast<'ast> = Vec<(Instr<'ast>, Span), &'ast Bump>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Instr<'ast> {
Add,
Sub,
Right,
Left,
Out,
In,
Loop(Ast<'ast>),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseError;
pub fn parse<I>(alloc: &Bump, mut src: I) -> Result<Ast<'_>, ParseError>
where
I: Iterator<Item = (usize, u8)>,
{
let mut instrs = Vec::new_in(alloc);
loop {
match src.next() {
Some((idx, b'+')) => instrs.push((Instr::Add, Span::single(idx))),
Some((idx, b'-')) => instrs.push((Instr::Sub, Span::single(idx))),
Some((idx, b'>')) => instrs.push((Instr::Right, Span::single(idx))),
Some((idx, b'<')) => instrs.push((Instr::Left, Span::single(idx))),
Some((idx, b'.')) => instrs.push((Instr::Out, Span::single(idx))),
Some((idx, b',')) => instrs.push((Instr::In, Span::single(idx))),
Some((idx, b'[')) => {
let (loop_instrs, span) = parse_loop(alloc, &mut src, 0, idx)?;
instrs.push((Instr::Loop(loop_instrs), span));
}
Some((_, b']')) => return Err(ParseError),
Some(_) => {} // comment
None => break,
}
}
Ok(instrs)
}
fn parse_loop<'ast, I>(
alloc: &'ast Bump,
src: &mut I,
depth: u16,
start_idx: usize,
) -> Result<(Ast<'ast>, Span), ParseError>
where
I: Iterator<Item = (usize, u8)>,
{
const MAX_DEPTH: u16 = 1000;
if depth > MAX_DEPTH {
return Err(ParseError);
}
let mut instrs = Vec::new_in(alloc);
let end_idx = loop {
match src.next() {
Some((idx, b'+')) => instrs.push((Instr::Add, Span::single(idx))),
Some((idx, b'-')) => instrs.push((Instr::Sub, Span::single(idx))),
Some((idx, b'>')) => instrs.push((Instr::Right, Span::single(idx))),
Some((idx, b'<')) => instrs.push((Instr::Left, Span::single(idx))),
Some((idx, b'.')) => instrs.push((Instr::Out, Span::single(idx))),
Some((idx, b',')) => instrs.push((Instr::In, Span::single(idx))),
Some((idx, b'[')) => {
let (loop_instrs, span) = parse_loop(alloc, src, depth + 1, idx)?;
instrs.push((Instr::Loop(loop_instrs), span));
}
Some((idx, b']')) => break idx,
Some(_) => {} // comment
None => return Err(ParseError),
}
};
Ok((instrs, Span::start_end_incl(start_idx, end_idx)))
}
#[cfg(test)]
mod tests {
use bumpalo::Bump;
#[test]
fn simple() {
let alloc = Bump::new();
let bf = ">+<++[-].";
let instrs = super::parse(&alloc, bf.bytes().enumerate());
insta::assert_debug_snapshot!(instrs);
}
#[test]
fn nested_loop() {
let alloc = Bump::new();
let bf = "+[-[-[-]]+>>>]";
let instrs = super::parse(&alloc, bf.bytes().enumerate());
insta::assert_debug_snapshot!(instrs);
}
}

View file

@ -0,0 +1,61 @@
---
source: src/parse.rs
expression: instrs
---
Ok(
[
(
Add,
0..1,
),
(
Loop(
[
(
Sub,
2..3,
),
(
Loop(
[
(
Sub,
4..5,
),
(
Loop(
[
(
Sub,
6..7,
),
],
),
5..8,
),
],
),
3..9,
),
(
Add,
9..10,
),
(
Right,
10..11,
),
(
Right,
11..12,
),
(
Right,
12..13,
),
],
),
1..14,
),
],
)

View file

@ -0,0 +1,43 @@
---
source: src/parse.rs
expression: instrs
---
Ok(
[
(
Right,
0..1,
),
(
Add,
1..2,
),
(
Left,
2..3,
),
(
Add,
3..4,
),
(
Add,
4..5,
),
(
Loop(
[
(
Sub,
6..7,
),
],
),
5..8,
),
(
Out,
8..9,
),
],
)

View file

@ -0,0 +1,8 @@
---
source: src/lib.rs
assertion_line: 43
expression: "String::from_utf8(stdout)"
---
Ok(
"1\n2\nFizz\n4\nBuzz\nFizz\n7\n8\nFizz\nBuzz\n11\nFizz\n13\n14\nFizzBuzz\n16\n17\nFizz\n19\nBuzz\nFizz\n22\n23\nFizz\nBuzz\n26\nFizz\n28\n29\nFizzBuzz\n31\n32\nFizz\n34\nBuzz\nFizz\n37\n38\nFizz\nBuzz\n41\nFizz\n43\n44\nFizzBuzz\n46\n47\nFizz\n49\nBuzz\nFizz\n52\n53\nFizz\nBuzz\n56\nFizz\n58\n59\nFizzBuzz\n61\n62\nFizz\n64\nBuzz\nFizz\n67\n68\nFizz\nBuzz\n71\nFizz\n73\n74\nFizzBuzz\n76\n77\nFizz\n79\nBuzz\nFizz\n82\n83\nFizz\nBuzz\n86\nFizz\n88\n89\nFizzBuzz\n91\n92\nFizz\n94\nBuzz\nFizz\n97\n98\nFizz\nBuzz\n",
)

View file

@ -0,0 +1,7 @@
---
source: src/lib.rs
expression: "String::from_utf8(stdout)"
---
Ok(
"AAAAAAAABBBBBBBBCCCCCCCCCCCCCCCCCCDDDDEFEEDDDCCCCCBBBBBBBBBBBBBBB\nAAAAAAABBBBBBCCCCCCCCCCCCCCCCCDDDDDDEEFIKGGGDDDDDCCCCBBBBBBBBBBBB\nAAAAAABBBBCCCCCCCCCCCCCCCCCDDDDDDDEEEFGHKPIGFEDDDDDCCCCCBBBBBBBBB\nAAAAABBBCCCCCCCCCCCCCCCCCDDDDDDDEEEFGPVT Q[HEEEEDDDCCCCCCBBBBBBB\nAAAABBCCCCCCCCCCCCCCCCDDDDDDDEEFFFGGHK HGFFEEEDDDCCCCCBBBBBB\nAAABBCCCCCCCCCCCCCCCDDDDDEEEFGK MJJ NR YS L HHGIJFDDCCCCCCBBBB\nAAABCCCCCCCCCCCCCDDDEEEEEEFFFHI MGEDDCCCCCCBBB\nAABCCCCCCCCCCCDDEEEEEEEEFFFGY Q MHGEEDCCCCCCCBB\nAACCCCCCDDDDDEEFLHGGHMHGGGHIR QLHEDDCCCCCCCB\nABCCDDDDDDEEEEFGIKU RLJJL IFEDDCCCCCCCB\nACDDDDDDEEEEEGGHOS QR JFEDDDCCCCCCC\nADDDDDEFFFGGHKOPS GEEDDDCCCCCCC\nA PJGFEEDDDCCCCCCC\nADDDDDEFFFGGHKOPS GEEDDDCCCCCCC\nACDDDDDDEEEEEGGHOS QR JFEDDDCCCCCCC\nABCCDDDDDDEEEEFGIKU RLJJL IFEDDCCCCCCCB\nAACCCCCCDDDDDEEFLHGGHMHGGGHIR QLHEDDCCCCCCCB\nAABCCCCCCCCCCCDDEEEEEEEEFFFGY Q MHGEEDCCCCCCCBB\nAAABCCCCCCCCCCCCCDDDEEEEEEFFFHI MGEDDCCCCCCBBB\nAAABBCCCCCCCCCCCCCCCDDDDDEEEFGK MJJ NR YS L HHGIJFDDCCCCCCBBBB\nAAAABBCCCCCCCCCCCCCCCCDDDDDDDEEFFFGGHK HGFFEEEDDDCCCCCBBBBBB\nAAAAABBBCCCCCCCCCCCCCCCCCDDDDDDDEEEFGPVT Q[HEEEEDDDCCCCCCBBBBBBB\nAAAAAABBBBCCCCCCCCCCCCCCCCCDDDDDDDEEEFGHKPIGFEDDDDDCCCCCBBBBBBBBB\nAAAAAAABBBBBBCCCCCCCCCCCCCCCCCDDDDDDEEFIKGGGDDDDDCCCCBBBBBBBBBBBB\n",
)

1
rust2/test.bf vendored Normal file
View file

@ -0,0 +1 @@
+++++>[-]+++[<.>]