mirror of
https://github.com/Noratrieb/brainfuck.git
synced 2026-01-14 21:35:02 +01:00
Compare commits
86 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b8157f2ceb | |||
| 04dd019806 | |||
| deefc18959 | |||
| 54b5c9b1f8 | |||
| a52cbda492 | |||
| 64e5ac616f | |||
| b6982d5023 | |||
| 5e401a0d6d | |||
| 3b8b091406 | |||
| d5d80f79b7 | |||
| 039b5ea9c7 | |||
| f88c486088 | |||
| bd2bde58b8 | |||
| 9db60ac38d | |||
| 80b1b0e3f6 | |||
| d0718adf7f | |||
| 5fc5c49dff | |||
| ddf2686049 | |||
| 5d943ba51c | |||
| fb2986783e | |||
| 93f97e9a08 | |||
| 014770b6fe | |||
| 4490d49d35 | |||
| d7fea43acf | |||
| 290201ab98 | |||
| 31f2304a30 | |||
| 3eb9486a8c | |||
| 904356eb4e | |||
| 46229fd74f | |||
| 4d9648bf97 | |||
| d9f163ef3a | |||
| 7973d9f77b | |||
| c3c24c73fe | |||
| 6575e09957 | |||
| 9d140c45d7 | |||
| c130627b63 | |||
| 53ad68e3f2 | |||
| 9924aa2037 | |||
| b535178cb8 | |||
| 7dd2c82fa4 | |||
| 1e1a2a277b | |||
| 2df17352d1 | |||
| eda2476021 | |||
| 799b1591e0 | |||
| cec7204c6d | |||
| 5634330287 | |||
| e82b14b09a | |||
| 7b88c99039 | |||
| 539d0e0502 | |||
| 66bd69e674 | |||
| 2d854539aa | |||
| 2484fe1f44 | |||
| 2b1daa55fb | |||
| 3994acef78 | |||
| f9998535de | |||
| 7d352e0b5c | |||
| d5520e1f42 | |||
| db362072b7 | |||
| ab27352faa | |||
| 076156bd34 | |||
|
|
a4fa459805 | ||
| c2bdc73179 | |||
|
|
6cc64160e1 | ||
|
|
6df903675e | ||
| e7165c876e | |||
| 206e0293ec | |||
| 0a8ecd3a92 | |||
| e9d3a88bb6 | |||
| 2202c79521 | |||
| d1141cc6a6 | |||
| dc79c96f63 | |||
| 6d4c6f5b69 | |||
| 6f23444e4f | |||
| 669b004044 | |||
| e13d82ff46 | |||
| 296fd4a279 | |||
| 579d81021a | |||
| a96567038d | |||
| 273027e8af | |||
| 5f6d1d5b4b | |||
| e815fd8c66 | |||
| b30fa04dcc | |||
| 3ee494fed9 | |||
| 812e492640 | |||
| 68d07ae79e | |||
| 2a147ef178 |
81 changed files with 18720 additions and 930 deletions
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
*.bf linguist-vendored
|
||||
*.b linguist-vendored
|
||||
32
README.md
32
README.md
|
|
@ -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
|
||||
|
|
|
|||
2
bfi-haskell/.gitignore
vendored
2
bfi-haskell/.gitignore
vendored
|
|
@ -1,2 +1,2 @@
|
|||
.idea
|
||||
.idea
|
||||
.stack-work
|
||||
16
bfi-haskell/.idea/.gitignore
generated
vendored
16
bfi-haskell/.idea/.gitignore
generated
vendored
|
|
@ -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/
|
||||
|
|
|
|||
20
bfi-haskell/.idea/libraries/base_4_14_1_0.xml
generated
20
bfi-haskell/.idea/libraries/base_4_14_1_0.xml
generated
|
|
@ -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>
|
||||
20
bfi-haskell/.idea/libraries/ghc_prim_0_6_1.xml
generated
20
bfi-haskell/.idea/libraries/ghc_prim_0_6_1.xml
generated
|
|
@ -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>
|
||||
20
bfi-haskell/.idea/libraries/integer_gmp_1_0_3_0.xml
generated
20
bfi-haskell/.idea/libraries/integer_gmp_1_0_3_0.xml
generated
|
|
@ -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>
|
||||
10
bfi-haskell/.idea/misc.xml
generated
10
bfi-haskell/.idea/misc.xml
generated
|
|
@ -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>
|
||||
14
bfi-haskell/.idea/modules.xml
generated
14
bfi-haskell/.idea/modules.xml
generated
|
|
@ -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>
|
||||
10
bfi-haskell/.idea/vcs.xml
generated
10
bfi-haskell/.idea/vcs.xml
generated
|
|
@ -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>
|
||||
|
|
@ -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
20
bfi-java/bf.b
vendored
|
|
@ -1,11 +1,11 @@
|
|||
++++++++++[>++++++++++<-]>>++++++++++>->>>>>>>>>>>>>>>>-->+++++++[->++
|
||||
++++++++<]>[->+>+>+>+<<<<]+++>>+++>>>++++++++[-<++++<++++<++++>>>]++++
|
||||
+[-<++++<++++>>]>>-->++++++[->+++++++++++<]>[->+>+>+>+<<<<]+++++>>+>++
|
||||
++++>++++++>++++++++[-<++++<++++<++++>>>]++++++[-<+++<+++<+++>>>]>>-->
|
||||
---+[-<+]-<[+[->+]-<<->>>+>[-]++[-->++]-->+++[---++[--<++]---->>-<+>[+
|
||||
+++[----<++++]--[>]++[-->++]--<]>++[--+[-<+]->>[-]+++++[---->++++]-->[
|
||||
->+<]>>[.>]++[-->++]]-->+++]---+[-<+]->>-[+>>>+[-<+]->>>++++++++++<<[-
|
||||
>+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>
|
||||
+>>]<<<<<]>[-]>>[>++++++[-<++++++++>]<.<<+>+>[-]]<[<[->-<]++++++[->+++
|
||||
+++++<]>.[-]]<<++++++[-<++++++++>]<.[-]<<[-<+>]+[-<+]->>]+[-]<<<.>>>+[
|
||||
++++++++++[>++++++++++<-]>>++++++++++>->>>>>>>>>>>>>>>>-->+++++++[->++
|
||||
++++++++<]>[->+>+>+>+<<<<]+++>>+++>>>++++++++[-<++++<++++<++++>>>]++++
|
||||
+[-<++++<++++>>]>>-->++++++[->+++++++++++<]>[->+>+>+>+<<<<]+++++>>+>++
|
||||
++++>++++++>++++++++[-<++++<++++<++++>>>]++++++[-<+++<+++<+++>>>]>>-->
|
||||
---+[-<+]-<[+[->+]-<<->>>+>[-]++[-->++]-->+++[---++[--<++]---->>-<+>[+
|
||||
+++[----<++++]--[>]++[-->++]--<]>++[--+[-<+]->>[-]+++++[---->++++]-->[
|
||||
->+<]>>[.>]++[-->++]]-->+++]---+[-<+]->>-[+>>>+[-<+]->>>++++++++++<<[-
|
||||
>+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>
|
||||
+>>]<<<<<]>[-]>>[>++++++[-<++++++++>]<.<<+>+>[-]]<[<[->-<]++++++[->+++
|
||||
+++++<]>.[-]]<<++++++[-<++++++++>]<.[-]<<[-<+>]+[-<+]->>]+[-]<<<.>>>+[
|
||||
-<+]-<<]
|
||||
|
|
@ -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
8
bfi-rust/.gitignore
vendored
|
|
@ -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
2
bfi-rust/Cargo.lock
generated
|
|
@ -2,4 +2,4 @@
|
|||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "bfinterpreter"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
|
|
|
|||
|
|
@ -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
412
bfi-rust/flamegraph.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 437 KiB |
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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(())
|
||||
}
|
||||
|
|
@ -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
23
ibfi-ts/.gitignore
vendored
Normal 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
27
ibfi-ts/README.md
Normal 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
50
ibfi-ts/package.json
Normal 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
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
43
ibfi-ts/public/index.html
Normal 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
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
BIN
ibfi-ts/public/logo512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
25
ibfi-ts/public/manifest.json
Normal file
25
ibfi-ts/public/manifest.json
Normal 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"
|
||||
}
|
||||
3
ibfi-ts/public/robots.txt
Normal file
3
ibfi-ts/public/robots.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
128
ibfi-ts/src/App.scss
Normal file
128
ibfi-ts/src/App.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
157
ibfi-ts/src/brainfuck/Interpreter.ts
Normal file
157
ibfi-ts/src/brainfuck/Interpreter.ts
Normal 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("");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
41
ibfi-ts/src/components/App.tsx
Normal file
41
ibfi-ts/src/components/App.tsx
Normal 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;
|
||||
22
ibfi-ts/src/components/CodeDisplay.tsx
Normal file
22
ibfi-ts/src/components/CodeDisplay.tsx
Normal 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;
|
||||
83
ibfi-ts/src/components/CodeInput.tsx
Normal file
83
ibfi-ts/src/components/CodeInput.tsx
Normal 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;
|
||||
15
ibfi-ts/src/components/ProgramOutput.tsx
Normal file
15
ibfi-ts/src/components/ProgramOutput.tsx
Normal 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;
|
||||
118
ibfi-ts/src/components/RunDisplay.tsx
Normal file
118
ibfi-ts/src/components/RunDisplay.tsx
Normal 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;
|
||||
189
ibfi-ts/src/components/Runner.tsx
Normal file
189
ibfi-ts/src/components/Runner.tsx
Normal 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"><</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>
|
||||
<button onClick={() => run('.')} className="small-speed-button">.</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Runner;
|
||||
13
ibfi-ts/src/index.css
Normal file
13
ibfi-ts/src/index.css
Normal 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
11
ibfi-ts/src/index.tsx
Normal 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
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
1
ibfi-ts/src/react-app-env.d.ts
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/// <reference types="react-scripts" />
|
||||
26
ibfi-ts/tsconfig.json
Normal file
26
ibfi-ts/tsconfig.json
Normal 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
11965
ibfi-ts/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
2
js/.gitignore
vendored
Normal file
2
js/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
.idea
|
||||
4
js/.prettierrc.json
Normal file
4
js/.prettierrc.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"singleQuote": true,
|
||||
"printWidth": 100
|
||||
}
|
||||
1
js/fizzbuzz.bf
vendored
Normal file
1
js/fizzbuzz.bf
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
hello...[[].]]
|
||||
11
js/package.json
Normal file
11
js/package.json
Normal 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
113
js/src/index.js
Normal 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
8
js/yarn.lock
Normal 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
2
rust2/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
target
|
||||
.idea
|
||||
3
rust2/.rustfmt.toml
Normal file
3
rust2/.rustfmt.toml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
imports_granularity = "Crate"
|
||||
newline_style = "Unix"
|
||||
group_imports = "StdExternalCrate"
|
||||
1238
rust2/Cargo.lock
generated
Normal file
1238
rust2/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
29
rust2/Cargo.toml
Normal file
29
rust2/Cargo.toml
Normal 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
5
rust2/benches/bench.bf
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
Benchmark brainf*ck program
|
||||
>++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++
|
||||
[>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++
|
||||
++++++++[>++++++++++[>++++++++++[>++++++++++[>+
|
||||
+++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++.
|
||||
44
rust2/benches/bottles.bf
vendored
Normal file
44
rust2/benches/bottles.bf
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
>+++++++++[<+++++++++++>-]<[>[-]>[-]<<[>+>+<<-]>>[<<+>>-]>>>
|
||||
[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+<
|
||||
-]<<-<-]+++++++++>[<->-]>>+>[<[-]<<+>>>-]>[-]+<<[>+>-<<-]<<<
|
||||
[>>+>+<<<-]>>>[<<<+>>>-]>[<+>-]<<-[>[-]<[-]]>>+<[>[-]<-]<+++
|
||||
+++++[<++++++<++++++>>-]>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-
|
||||
]<<<<<<.>>[-]>[-]++++[<++++++++>-]<.>++++[<++++++++>-]<++.>+
|
||||
++++[<+++++++++>-]<.><+++++..--------.-------.>>[>>+>+<<<-]>
|
||||
>>[<<<+>>>-]<[<<<<++++++++++++++.>>>>-]<<<<[-]>++++[<+++++++
|
||||
+>-]<.>+++++++++[<+++++++++>-]<--.---------.>+++++++[<------
|
||||
---->-]<.>++++++[<+++++++++++>-]<.+++..+++++++++++++.>++++++
|
||||
++[<---------->-]<--.>+++++++++[<+++++++++>-]<--.-.>++++++++
|
||||
[<---------->-]<++.>++++++++[<++++++++++>-]<++++.-----------
|
||||
-.---.>+++++++[<---------->-]<+.>++++++++[<+++++++++++>-]<-.
|
||||
>++[<----------->-]<.+++++++++++..>+++++++++[<---------->-]<
|
||||
-----.---.>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>>+++
|
||||
+[<++++++>-]<--.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.
|
||||
><+++++..--------.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++
|
||||
++++++++++++.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<++
|
||||
+++++++>-]<--.---------.>+++++++[<---------->-]<.>++++++[<++
|
||||
+++++++++>-]<.+++..+++++++++++++.>++++++++++[<---------->-]<
|
||||
-.---.>+++++++[<++++++++++>-]<++++.+++++++++++++.++++++++++.
|
||||
------.>+++++++[<---------->-]<+.>++++++++[<++++++++++>-]<-.
|
||||
-.---------.>+++++++[<---------->-]<+.>+++++++[<++++++++++>-
|
||||
]<--.+++++++++++.++++++++.---------.>++++++++[<---------->-]
|
||||
<++.>+++++[<+++++++++++++>-]<.+++++++++++++.----------.>++++
|
||||
+++[<---------->-]<++.>++++++++[<++++++++++>-]<.>+++[<----->
|
||||
-]<.>+++[<++++++>-]<..>+++++++++[<--------->-]<--.>+++++++[<
|
||||
++++++++++>-]<+++.+++++++++++.>++++++++[<----------->-]<++++
|
||||
.>+++++[<+++++++++++++>-]<.>+++[<++++++>-]<-.---.++++++.----
|
||||
---.----------.>++++++++[<----------->-]<+.---.[-]<<<->[-]>[
|
||||
-]<<[>+>+<<-]>>[<<+>>-]>>>[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]
|
||||
>[<+>-]>[<<++++++++++>>>+<-]<<-<-]+++++++++>[<->-]>>+>[<[-]<
|
||||
<+>>>-]>[-]+<<[>+>-<<-]<<<[>>+>+<<<-]>>>[<<<+>>>-]<>>[<+>-]<
|
||||
<-[>[-]<[-]]>>+<[>[-]<-]<++++++++[<++++++<++++++>>-]>>>[>+>+
|
||||
<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>[-]>[-]++++[<++++++++>
|
||||
-]<.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.><+++++..---
|
||||
-----.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++++++++++++++
|
||||
.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<+++++++++>-]<-
|
||||
-.---------.>+++++++[<---------->-]<.>++++++[<+++++++++++>-]
|
||||
<.+++..+++++++++++++.>++++++++[<---------->-]<--.>+++++++++[
|
||||
<+++++++++>-]<--.-.>++++++++[<---------->-]<++.>++++++++[<++
|
||||
++++++++>-]<++++.------------.---.>+++++++[<---------->-]<+.
|
||||
>++++++++[<+++++++++++>-]<-.>++[<----------->-]<.+++++++++++
|
||||
..>+++++++++[<---------->-]<-----.---.+++.---.[-]<<<]
|
||||
7
rust2/benches/fizzbuzz.bf
vendored
Normal file
7
rust2/benches/fizzbuzz.bf
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
++++++++++[>++++++++++<-]>>++++++++++>->>>>>>>>>>>>>>>>-->+++++++[->++\n++++++++<]>[->+>+>+>+<<<<]+++>>+++>>>++++++++[-<
|
||||
++++<++++<++++>>>]++++\n+[-<++++<++++>>]>>-->++++++[->+++++++++++<]>[->+>+>+>+<<<<]+++++>>+>++\n++++>++++++>++++++++[-<+
|
||||
+++<++++<++++>>>]++++++[-<+++<+++<+++>>>]>>-->\n---+[-<+]-<[+[->+]-<<->>>+>[-]++[-->++]-->+++[---++[--<++]---->>-<+>[+\n
|
||||
+++[----<++++]--[>]++[-->++]--<]>++[--+[-<+]->>[-]+++++[---->++++]-->[\n->+<]>>[.>]++[-->++]]-->+++]---+[-<+]->>-[+>>>+[
|
||||
-<+]->>>++++++++++<<[-\n>+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>\n+>>]<<<<<]>[-]>>[>++++++
|
||||
[-<++++++++>]<.<<+>+>[-]]<[<[->-<]++++++[->+++\n+++++<]>.[-]]<<++++++[-<++++++++>]<.[-]<<[-<+>]+[-<+]->>]+[-]<<<.>>>+[\n
|
||||
-<+]-<<]
|
||||
709
rust2/benches/hanoi.bf
vendored
Normal file
709
rust2/benches/hanoi.bf
vendored
Normal file
|
|
@ -0,0 +1,709 @@
|
|||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>[-]>[-]+++++++++++++++++++++++++++.++++++++++++++++
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++.-------------------.-------
|
||||
--------------------------------------.+++++++++++++++++++++++++++++++++++++
|
||||
+++++++++++++++++++++++++++.-----------------------------------------.++++++
|
||||
++++++++++++++++++.[-]+++++++++++++++++++++++++++.++++++++++++++++++++++++++
|
||||
++++++++++++++++++++++++++++++++++++++.-------------------------------------
|
||||
----.+++++++++.---------.+++++.+++++++++++++++++.++++++++++++.++++++++++++++
|
||||
+++++++++++++.++++++++.------------------.+++++++++++++.+.------------------
|
||||
-----------------------------------------------------------------.++++++++++
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.------
|
||||
---.----------------------------------------------------------------------.+
|
||||
+++++++++++++++++++++++++++++++++++++++.+++++++++++++++++++++++++.++++++++++
|
||||
+++.+.------.---------------------------------------------------------------
|
||||
----------.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
++++++++.+++++.-------------------------------------------------------------
|
||||
-----------------.++++++++++++++++++++++++++++++++++.+++++++++++++++++++++++
|
||||
+++++++++++++++++++++++++.-----------------.++++++++.+++++.--------.--------
|
||||
----------------------------------------------------.+++++++++++++++++++++++
|
||||
++++++++++++++++++++++++++++++++++.++++++++.[-]+++++++++++++++++++++++++++.+
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.------------
|
||||
----------------------------.++++++++.----------.++++.+++++++++++++++++++.++
|
||||
+++++++++++++.+++++++++++++++++++++++++++.---------.+++++++++++..-----------
|
||||
----.+++++++++.-------------------------------------------------------------
|
||||
-----------------.++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
++++++++.+++++++++++++++++++++++.-------------------------------------------
|
||||
----------------------------------------------.+++++++++++++++++++++++++++++
|
||||
++++++.+++++++++++++++++++++++++++++++++++++++++.---.---..+++++++++.+++.----
|
||||
----------.-----------------------------------------------------------------
|
||||
---.+++++++++++++++++++++++++++++++++++++++++++++++++++++++.++++++++++++++++
|
||||
++++++++.---.------.--------------------------------------------------------
|
||||
--------------.++++++++++++++++++++++++++++.++++++++++++++++++++++++++++++++
|
||||
++++++++++++.++++++++++++..----.--------------------------------------------
|
||||
----------.-----------..++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
++++++++++++++++++++...-----------------------------------------------------
|
||||
--------------------.+++++++++++++++++++++++++++++++++++++++++++++++++++++.+
|
||||
++++++++.---.---..+++++++++.+++.--------------.-----------------------------
|
||||
-------------------------.++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+.+++++++++++++++++++.------------------------------------------------------
|
||||
---------------.+++++++++++++++++++++++++++++++++++++++++++++++++++.++++.---
|
||||
.+++++++++++++.+++++.-------------------------------------------------------
|
||||
---------------.+++++++++++++++.[-]>[-]+++++++++>[-]+++>>[-]>[-]<<<<<[->>>>>
|
||||
+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<
|
||||
<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]
|
||||
>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-
|
||||
<<+>>]<<<[-]+>>>][-]<[->+<]>[[-<+>]<<<[-]+>>>]<<<[>[-]++++++++++++++++++++++
|
||||
+++++++++++++++++++++++>[-]<<<<<[->>>>>+<<<<<]>>>>>[[-<<<<<+>>>>>]<+++++++++
|
||||
++++++++++++++++++++++++++++++++++>]<<<[>>>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<<
|
||||
->>>][-]++++++++++++++++>[-]++++++++++++++>>>>[-]>[-]<<<<<<<<<[->>>>>>>>>+<<
|
||||
<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[
|
||||
[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+
|
||||
<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>
|
||||
>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<<+++++>>>>]>[-]>[-
|
||||
]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]+<<[-]+>>
|
||||
>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<
|
||||
]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<
|
||||
[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<
|
||||
[[-]<<<++++++++++>>>][-]>[-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>>>[-<+<<<<<<<+
|
||||
>>>>>>>>][-]+++++++++++++++++++++++++<<<[-]>>[>>[-]<[->+<]>[-<+<<<+>>>>]<<-]
|
||||
[-]<<[->>+<<]>>[-<<+<<+>>>>][-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>>>[-<<<<<<<
|
||||
<+>>>>->>>>][-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>>>[-<<<<<<<<+>>>>->>>>]>[-]
|
||||
>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]++<<[-
|
||||
]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+
|
||||
>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>
|
||||
>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>
|
||||
]<<<[[-]<<<<----->>>>][-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<<<<<<<<<
|
||||
+>>>>>>->>>][-]+++++++++++++++++++++++++++.+++++++++++++++++++++++++++++++++
|
||||
+++++++++++++++++++++++++++++++.>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>
|
||||
>>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[
|
||||
-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->
|
||||
>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<
|
||||
+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[->+<]
|
||||
>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-]>[-]<
|
||||
<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>
|
||||
+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>
|
||||
>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[
|
||||
-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>
|
||||
]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]+
|
||||
+++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-
|
||||
<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->
|
||||
>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<
|
||||
[-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<<->>>>
|
||||
]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>
|
||||
>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]
|
||||
<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[
|
||||
[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>
|
||||
[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<
|
||||
<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>
|
||||
>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->
|
||||
[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]
|
||||
+>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>>>]<<[
|
||||
-<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<
|
||||
<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>
|
||||
>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<
|
||||
<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[-
|
||||
>>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+>]<+++
|
||||
+++++++++++++++++++++++++++++++++++++++++++++.<+++++++++++++++++++++++++++++
|
||||
+++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>-<
|
||||
]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<+++++++++++++++++++++++
|
||||
+++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.
|
||||
>>>>>>-<]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>]
|
||||
<<]<<<<<<--------------------------------.>[-]>[-]<<<<<<[->>>>>>+<<<<<<]>>>>
|
||||
>>[-<+<<<<<+>>>>>>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]+++++
|
||||
+++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<
|
||||
+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+
|
||||
<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]
|
||||
>>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>
|
||||
>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>
|
||||
>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[
|
||||
-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>
|
||||
>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]
|
||||
>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<
|
||||
+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->
|
||||
>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>
|
||||
->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[
|
||||
-]+>>]<]<]<<<]<<[-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>
|
||||
>>]<<[-<<<<->>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]+++++
|
||||
+++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[
|
||||
[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[
|
||||
->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+
|
||||
>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+
|
||||
<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>]
|
||||
[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]
|
||||
+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>
|
||||
[[-<<<+>>>]<<[-]+>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-
|
||||
<<<+<<+>>>>>]<<[-<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>]
|
||||
[-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<
|
||||
<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>
|
||||
[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]
|
||||
<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>
|
||||
[-]+<[[-<+>]<++++++++++++++++++++++++++++++++++++++++++++++++.<+++++++++++++
|
||||
+++++++++++++++++++++++++++++++++++.<+++++++++++++++++++++++++++++++++++++++
|
||||
+++++++++.>>>>-<]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<+++++++
|
||||
+++++++++++++++++++++++++++++++++++++++++.<+++++++++++++++++++++++++++++++++
|
||||
+++++++++++++++.>>>>>>-<]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++
|
||||
++++++++.>>>>>>]<<]<<<<<<+++++++++++++.>[-]>[-]<<<<<<<[->>>>>>>+<<<<<<<]>>>>
|
||||
>>>[-<+<<<<<<+>>>>>>>][-]+++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+++++++++++++++++++++++++++++++++++++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+
|
||||
>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>
|
||||
>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<
|
||||
+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[-]++++++++++++++++++
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
++++++++++++++++++++++++++.<-<]>[[-]<<<<<<.>>>>>>]<[-]<<<<<<<<[->>>>>>>>+<<<
|
||||
<<<<<]>>>>>>[-]>>[-<<<<<<<<+>>>>>>+>>][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<..
|
||||
>>>-]<<<.>>>>>[-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>[-]>>[-<<<<<<<<+>>>>>>+>>
|
||||
][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<..>>>-]>>>[-]>[-]<<<<<<<[->>>>>>>+<<<<<
|
||||
<<]>>>>>>>[-<+<<<<<<+>>>>>>>][-]++++++++++++++++++++++++++++++++++++++++++++
|
||||
++++++++++++++++++++++++++++++++++++++++++++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>
|
||||
[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>
|
||||
+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]
|
||||
>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[-]+++++++++++
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+++++++++++++++++++++++++++++++++.<-<]>[[-]<<<<<<.>>>>>>]<<<<<<<<]>>>[-]<<<<
|
||||
<[->>>>>+<<<<<]>>>>>[[-<<<<<+>>>>>]<<<<<<<[-]<[-]<[-]>>>>>>>>>>[-]<<<<<[->>>
|
||||
>>+<<<<<]>>>>>[-<<<<<+<<<+>>>>>>>>][-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>]<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-
|
||||
[<<<<+>>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<<<<<[->>>>>+<<<<
|
||||
<]>>>>>[[-<<<<<+>>>>>]<<<<<->>>>>]<]<<<<<+>>[-]+>>[-]>[-]<<<<<[->>>>>+<<<<<]
|
||||
>>>>>[-<+<<<<+>>>>>][-]++++++++++<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>
|
||||
[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<
|
||||
<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<
|
||||
<<[-]+>>>][-]<[->+<]>[[-<+>]<<<[-]+>>>]<<<]<<<[-]>[-]+>[-]++>[-]++++++++>[-]
|
||||
+>[-]+[>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++<<[-]>>>[-]>[
|
||||
-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<-
|
||||
>->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>
|
||||
]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]+>>>][-]<[->+<]>[[-<+>]<<<[-]+>>>]<<<[>[-
|
||||
]<<<<<[->>>>>+<<<<<]>>>>>[[-<<<<<+>>>>>]>[-]>[-]>[-]>>[-]>[-]<<<<<<<<<<[->>>
|
||||
>>>>>>>+<<<<<<<<<<]>>>>>>>>>>[-<+<<<<<<<<<+>>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<<
|
||||
<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[
|
||||
-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<
|
||||
][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<[-]
|
||||
+>[-]+>>]>[-]>[-]<<<<<<<<<<[->>>>>>>>>>+<<<<<<<<<<]>>>>>>>>>>[-<+<<<<<<<<<+>
|
||||
>>>>>>>>>][-]+++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]
|
||||
>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[-
|
||||
>>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->
|
||||
+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<[-]+>>[-]+>][-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-
|
||||
]>>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>[-]>[-<
|
||||
<<<<<<<<<<<<<<+>>>>>>>>>>>>>>+>]<[<+>-]>[-]<<<<<<<<<<<<<<[->>>>>>>>>>>>>>+<<
|
||||
<<<<<<<<<<<<]>>>>>>>>>>>>>[-]>[-<<<<<<<<<<<<<<+>>>>>>>>>>>>>+>]<[<+++>-]>[-]
|
||||
<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>[-]>[-<<<<<<<<<<<<<+>
|
||||
>>>>>>>>>>>+>]<[<+++++++++>-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>[-]<<[->>+<<]>>[-<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<<
|
||||
<<<<<<<]>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<<<<]<<[-]>>>[<<<+>>
|
||||
>-]<<[>>>>]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>[-]<<<<<<<<<<<<[->>>>>>>>>>>>+<<<<<<<<<<<<]>>>>>>>>>>>>[-<
|
||||
<<<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<<
|
||||
<[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<+<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]
|
||||
<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<
|
||||
<<]>>>>>>>>>>>[-<<<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<<
|
||||
<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>[-<<<<<<<<
|
||||
<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<
|
||||
<<<+>>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>+>>>>>>>>>>>>>][-]<<[->>+<<]>>[[-<<+>>]>[-]<<<<<<<<<<<<[->>>>
|
||||
>>>>>>>>+<<<<<<<<<<<<]>>>>>[-]>>>>>>>[-<<<<<<<<<<<<+>>>>>+>>>>>>>][-]<<<<<<<
|
||||
<<<<[->>>>>>>>>>>+<<<<<<<<<<<]<[-]>>>>>>>>>>>>[-<<<<<<<<<<<+<+>>>>>>>>>>>>][
|
||||
-]<<<<<<<[->>>>>>>+<<<<<<<]<<<<[-]>>>>>>>>>>>[-<<<<<<<+<<<<+>>>>>>>>>>>]<<<<
|
||||
<<<<<<->[-]>+>>>>>>>][-]<[->+<]>[[-<+>]>[-]<<<<<<<<<<<<[->>>>>>>>>>>>+<<<<<<
|
||||
<<<<<<]>>>>>[-]>>>>>>>[-<<<<<<<<<<<<+>>>>>+>>>>>>>][-]<<<<<<<<<<<<<[->>>>>>>
|
||||
>>>>>>+<<<<<<<<<<<<<]>[-]>>>>>>>>>>>>[-<<<<<<<<<<<<<+>+>>>>>>>>>>>>][-]<<<<<
|
||||
<<[->>>>>>>+<<<<<<<]<<<<<<[-]>>>>>>>>>>>>>[-<<<<<<<+<<<<<<+>>>>>>>>>>>>>]<<<
|
||||
<<<<<<<->[-]>+>>>>>>>]<<<<]>[-]>[-]<<<<<<[->>>>>>+<<<<<<]>>>>>>[-<+<<<<<+>>>
|
||||
>>>][-]++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<
|
||||
<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<
|
||||
]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-
|
||||
<+>]<<<[-]>>>]<<<[[-]>>>>[-]++>>[-]>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<<
|
||||
<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>][-]<<[-]+>>>[-
|
||||
]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[
|
||||
<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]
|
||||
+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-
|
||||
]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>[-]>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>]<]>[-]>[-]<<<<<<<<<<<<<<<[-
|
||||
>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>>
|
||||
>>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-
|
||||
<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<
|
||||
<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[
|
||||
-<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>[-<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>+>>>>]<]>[-]>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<
|
||||
<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>][-]++<<[-]+>>
|
||||
>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<
|
||||
]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<
|
||||
[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<
|
||||
[[-]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>[-]>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>]<]>[-]
|
||||
>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<
|
||||
<<<<<<<<<<+>>>>>>>>>>>>>>>][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-
|
||||
]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<
|
||||
+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<
|
||||
[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>
|
||||
>>>>>>>>>>[-]>>>>>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<
|
||||
<<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+>>>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+
|
||||
<<<<]<<>>>>]>>[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<<
|
||||
<<<[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>
|
||||
>>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>
|
||||
>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->
|
||||
>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+
|
||||
<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>[-]>>>>>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+>>>>-]
|
||||
<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>
|
||||
>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>][-]++<<[
|
||||
-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]
|
||||
+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>
|
||||
>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>
|
||||
>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-
|
||||
]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>[-]<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+>>>>-]<<<<]<<
|
||||
[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<
|
||||
<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>
|
||||
>][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>
|
||||
>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>
|
||||
[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]
|
||||
<<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>[-]<<<<<[->>>>>
|
||||
+<<<<<]>>>>>[-<<<<<+<<<<<<<<<<<+>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>
|
||||
>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+
|
||||
>>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<
|
||||
<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>>
|
||||
][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>
|
||||
>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>
|
||||
[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]
|
||||
<<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]
|
||||
<<<<<[->>>>>+<<<<<]>>>>>[-<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<<<<
|
||||
]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<<<[
|
||||
->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>>][-]
|
||||
++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]
|
||||
<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-
|
||||
<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<
|
||||
[-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[-]<[-
|
||||
]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<<<<<[->>
|
||||
>>>+<<<<<]>>>>>[-<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<<
|
||||
<<]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>
|
||||
>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>>][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+
|
||||
>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>
|
||||
>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<
|
||||
+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>[-<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>+>>>]<]>[-]>[-]<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>
|
||||
>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>
|
||||
>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->
|
||||
>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<
|
||||
<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>[-]>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>]<]>[-]>[-]
|
||||
<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>
|
||||
>>>>>>>>>>][-]++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]
|
||||
>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[-
|
||||
>>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->
|
||||
+<]>[[-<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>+>>>]<]<[->>>>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]>>[-]<<
|
||||
<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>[-]>>>>
|
||||
>[-<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>+>>>>>][-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>
|
||||
>[-]>>>>[-<<<<<<<<+>>>>+>>>>]<<<[-]++++++++++++++++++++++++++++++++>>-<]>[[-
|
||||
]>[-]<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>[-]>>>>>
|
||||
[-<<<<<<<<<<<<<<<<+>>>>>>>>>>>+>>>>>][-]<<<<<<<[->>>>>>>+<<<<<<<]>>>[-]>>>>[
|
||||
-<<<<<<<+>>>+>>>>]<<<[-]++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
++++++++++++++++++++++++++++++++++++>>]<[-]++++++++++++++++>[-]+++++++++++++
|
||||
+>>>>[-]>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][
|
||||
-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]
|
||||
<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-
|
||||
<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<
|
||||
[-]>>>]<<<[[-]<<<<+++++>>>>]>[-]>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>
|
||||
[-<+<<<<<<<<+>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<
|
||||
<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>
|
||||
>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]
|
||||
>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<++++++++++>>>][-]>[-]<<<<<<<<[->>>
|
||||
>>>>>+<<<<<<<<]>>>>>>>>[-<+<<<<<<<+>>>>>>>>][-]+++++++++++++++++++++++++<<<[
|
||||
-]>>[>>[-]<[->+<]>[-<+<<<+>>>>]<<-][-]<<[->>+<<]>>[-<<+<<+>>>>][-]<<<<<<<<<<
|
||||
<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>>>[-<<<<<<<<<<<+>>>>>>>->>>>][-]<<<<<<<<
|
||||
<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>>>[-<<<<<<<<<<<+>>>>>>>->>>>]>[-]>[-]<
|
||||
<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]++<<[-]+>>>
|
||||
[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]
|
||||
<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[
|
||||
-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[
|
||||
[-]<<<<----->>>>][-]<<<<<<[->>>>>>+<<<<<<]>>>>>>[-<<<<<<+>>>->>>][-]++++++++
|
||||
+++++++++++++++++++.++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
++++++++.>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>]>>>[-]>[-]<<<<<[->>>
|
||||
>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>
|
||||
+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<
|
||||
[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]
|
||||
>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<
|
||||
<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>
|
||||
[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[
|
||||
-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<
|
||||
]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<
|
||||
<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<
|
||||
<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<
|
||||
<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+
|
||||
<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>
|
||||
>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<[-]>>>>>[-]<[->+<]>[[-<
|
||||
+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<<->>>>]>]<<<[-]>[-]<<<<<[->>>
|
||||
>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>
|
||||
[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+
|
||||
>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>
|
||||
>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<
|
||||
<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++
|
||||
>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>
|
||||
]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]
|
||||
>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<[-]>>>>[-]
|
||||
<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>>>]<<[-<<<->>>]>]<<<[-]>[-]<<
|
||||
<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+
|
||||
<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>
|
||||
>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-
|
||||
]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]
|
||||
<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+>]<++++++++++++++++++++++++++
|
||||
++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.<++
|
||||
++++++++++++++++++++++++++++++++++++++++++++++.>>>>-<]>[[-]>[-]<<<<[->>>>+<<
|
||||
<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++++++++++++++++++++++++++++++++++
|
||||
++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>-<]>[[-]<<<<<<+++
|
||||
+++++++++++++++++++++++++++++++++++++++++++++.>>>>>>]<<]<<<<<<--------------
|
||||
------------------.>[-]>[-]<<<<<<[->>>>>>+<<<<<<]>>>>>>[-<+<<<<<+>>>>>>]>>>[
|
||||
-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->
|
||||
>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]
|
||||
>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>
|
||||
[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[->+<]>[[-<+>
|
||||
]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-]>[-]<<<<<[->
|
||||
>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-
|
||||
]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<
|
||||
<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[-
|
||||
>>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<
|
||||
<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++
|
||||
++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>
|
||||
>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<
|
||||
<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<[-]>>>>
|
||||
>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<<->>>>]>]<<<[
|
||||
-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-
|
||||
]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>
|
||||
>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+
|
||||
>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>
|
||||
>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>
|
||||
>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]
|
||||
>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]
|
||||
<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<
|
||||
]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>>>]<<[-<<<->>
|
||||
>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>
|
||||
>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-
|
||||
]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>
|
||||
[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>
|
||||
>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+>]<++++++++++
|
||||
++++++++++++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++
|
||||
++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>-<]>[[-]>
|
||||
[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++++++++++++++++++
|
||||
++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>-
|
||||
<]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>]<<]<<<<
|
||||
<<+++++++++++++.>[-]>[-]<<<<<<<[->>>>>>>+<<<<<<<]>>>>>>>[-<+<<<<<<+>>>>>>>][
|
||||
-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
++++++++++++++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>
|
||||
>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>
|
||||
>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<
|
||||
]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[-]+++++++++++++++++++++++++++++++++++++++++
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+++.<-<]>[[-]<<<<<<.>>>>>>]<[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>
|
||||
>[-]>>[-<<<<<<<<<<<+>>>>>>>>>+>>][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<..>>>-]
|
||||
<<<.>>>>>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>[-]>>[-<<<<<<<<<<<
|
||||
+>>>>>>>>>+>>][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<..>>>-]>>>[-]>[-]<<<<<<<[-
|
||||
>>>>>>>+<<<<<<<]>>>>>>>[-<+<<<<<<+>>>>>>>][-]+++++++++++++++++++++++++++++++
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++<<[-]+>>>[-]>[-]<<<
|
||||
[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-
|
||||
]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]
|
||||
[-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[
|
||||
-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
++++++++++++++++++++++++++++++++++++++++++++++.<-<]>[[-]<<<<<<.>>>>>>]<<<<<<
|
||||
<<<]>[-]++++++++++.[-]+>[-]+>[-]+++++++++++++++++++++++++++.++++++++++++++++
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++.>[-]>[-]<<<[->>>+<<<]>>>[-<
|
||||
+<<+>>>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<
|
||||
[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<
|
||||
<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[
|
||||
-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[
|
||||
->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-]
|
||||
>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<
|
||||
<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+
|
||||
<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>
|
||||
>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]
|
||||
<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>
|
||||
][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>
|
||||
>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<
|
||||
<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<
|
||||
<<]<<[-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<<
|
||||
->>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[
|
||||
-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>
|
||||
]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]
|
||||
>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+
|
||||
<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>
|
||||
[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<
|
||||
[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<
|
||||
->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]
|
||||
<<[-]+>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>>
|
||||
>]<<[-<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++
|
||||
++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<
|
||||
<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>
|
||||
>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-
|
||||
]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+>
|
||||
]<++++++++++++++++++++++++++++++++++++++++++++++++.<++++++++++++++++++++++++
|
||||
++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.>
|
||||
>>>-<]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++++++
|
||||
++++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++
|
||||
++++.>>>>>>-<]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++++++++++.>>
|
||||
>>>>]<<]<<<<<<--------------------------------.>[-]>[-]<<<<[->>>>+<<<<]>>>>[
|
||||
-<+<<<+>>>>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[
|
||||
-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>
|
||||
[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>
|
||||
>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[
|
||||
-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<
|
||||
<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>
|
||||
[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[-
|
||||
>>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<
|
||||
<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<
|
||||
+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>
|
||||
>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<
|
||||
<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[
|
||||
-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<
|
||||
]<]<<<]<<[-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-
|
||||
<<<<->>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<
|
||||
<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+
|
||||
>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<
|
||||
<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[
|
||||
->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>
|
||||
>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]
|
||||
<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<
|
||||
[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+
|
||||
>>>]<<[-]+>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+
|
||||
>>>>>]<<[-<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++
|
||||
++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>
|
||||
[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<
|
||||
[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]
|
||||
+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[
|
||||
-<+>]<++++++++++++++++++++++++++++++++++++++++++++++++.<++++++++++++++++++++
|
||||
++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++
|
||||
++.>>>>-<]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++
|
||||
++++++++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++
|
||||
++++++++.>>>>>>-<]>[[-]<<<<<<+++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+.>>>>>>]<<]<<<<<<+++++++++++++.<<[-]+++++++++++++++++++++++++++++++++++++++
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+++++++++[>[-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++[>[-]+++++++++
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+++++++++++++++[-]<-]<-]<<<<<]<<<<+>>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<
|
||||
<<+>>>>>][-]++++<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>
|
||||
>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->
|
||||
>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]+>>>][-]<[->
|
||||
+<]>[[-<+>]<<<[-]+>>>]<<<]<<->>[-]<<[->>+<<]>>[[-<<+>>]<<<<<<<<-<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>>>>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>
|
||||
>>>>>>>>[-<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+>
|
||||
>>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>[-]>>>>>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<<<<<<<<<+<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>
|
||||
-[<<<<+>>>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-
|
||||
]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>[-]<<<<<<<<<[
|
||||
->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>
|
||||
>>-[<<<<+>>>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
[-]>[-]>>>>>>>[-]++++++++>[-]>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>
|
||||
>>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>
|
||||
[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<
|
||||
<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<[->+<]>[[-<+>]<<<[-]+
|
||||
>>>]<<<[<<<<<<<<--------->>+>>>>>>>[-]++++++++>[-]>[-]<<<<<<<<<<<[->>>>>>>>>
|
||||
>>+<<<<<<<<<<<]>>>>>>>>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->>
|
||||
>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-
|
||||
]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<
|
||||
[->+<]>[[-<+>]<<<[-]+>>>]<<<]>[-]++>[-]>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<
|
||||
<<<]>>>>>>>>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[
|
||||
-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<
|
||||
<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<[->+<]>[[-<
|
||||
+>]<<<[-]+>>>]<<<[<<<<<<<<--->+>>>>>>>>[-]++>[-]>[-]<<<<<<<<<<<[->>>>>>>>>>>
|
||||
+<<<<<<<<<<<]>>>>>>>>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->>>+
|
||||
<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<
|
||||
<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<[-
|
||||
>+<]>[[-<+>]<<<[-]+>>>]<<<]<<<<+>>>]<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
212
rust2/benches/mandelbrot.bf
vendored
Normal file
212
rust2/benches/mandelbrot.bf
vendored
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
A mandelbrot set fractal viewer in brainf*** written by Erik Bosman
|
||||
+++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++
|
||||
+++++++-[[>>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>>>>>>>>[
|
||||
-]<<<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+<<<<<<<<>+++++<>[<>-
|
||||
<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>>+<<<<<<<<>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>[<<<>>>
|
||||
>>>>>>[>>>>>>>[-]<<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>[-]+<<<<<<<
|
||||
>++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>+<<<<<<<>++
|
||||
+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>+<<<<<<<<<<
|
||||
<<<<<<[<<<<<<<<<]>>>[<<<>>>[-]<<<>>>>>>>>>[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<
|
||||
<<<<<>[-<>>>>>>>+<<<<<<<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<
|
||||
]>>>>>>>>>[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]<<<<<<<<>[-<>>>>>>>>+<<<<<<<<>>
|
||||
>>>>+<<<<<<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>[<<<<<<<>>>>>>
|
||||
>-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>+<<<<<]>>>>>>>>>+++++++++
|
||||
+++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<
|
||||
<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>
|
||||
>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<[->>[-<<+>>]<<[->>+<<
|
||||
>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>>>>>]<<<<<
|
||||
<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<<>>-<<>>>>
|
||||
>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<<<[>[-]<->
|
||||
>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<>>>>>>>>>>]<[->+<]>>>>]<<<<>[
|
||||
<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>
|
||||
>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>>[-<<<+>>>
|
||||
]<<<[->>>+<<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>
|
||||
>>>>>>>]<<<<<<<<<<>[<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<
|
||||
<<<<>]<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<<<<<>>>>>>>>>>
|
||||
+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<
|
||||
>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>[-
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>
|
||||
>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>+<<<[<<<<<<<<<]>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>>>[-<<
|
||||
<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>
|
||||
>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<
|
||||
<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<
|
||||
<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]<<<<<<<[->+>>>-<<<<]>>>>>>>>>+++++
|
||||
+++++++++++++++++++++<<>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>[-]<<]>>[<<<<<<<
|
||||
+<[-<+>>>>+<<[-]]>[-><<<[->+>>>-<<<<]>>>]>>>>>>>>>>>>>[>>[-]<<>>>[-]<<<>
|
||||
>>>[-]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]<<<>>>>>>>>>[>>>>>[-<<<<<>
|
||||
+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>
|
||||
>>>[>>[-<<<<<<<<<+>>>>>>>>>]<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++
|
||||
+++++++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<
|
||||
[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<
|
||||
<<]>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>[-<<+
|
||||
>>]<<[->>+<<>>>+<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>
|
||||
>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<
|
||||
<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<
|
||||
<<[>[-]<->>>[<<<>>>-<<<+>[<->-<<<<<<<<<<>>>+<<<>>>>>>>>>>]<[->+<]>>>]<<<
|
||||
>[<>-<>>>+<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>
|
||||
>>>>>+<<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>
|
||||
]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>
|
||||
>>+<<<<<<[->>[-<<+>>]<<[->>+<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]
|
||||
<>]<>>>>>>>>>>[>>>>>>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>
|
||||
>]<<<<<<<<<<<>]<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>
|
||||
>+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<
|
||||
<>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>[
|
||||
-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<>>>>>>>>>]<<<<<
|
||||
<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]<<<<<<<<<-<<<<<<<<<
|
||||
[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]
|
||||
<<<<<<<<>[-<>>>>>>>>+<<<<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>
|
||||
>>>>[>>>>>>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+<<<<>>>>>[<<<<<>>
|
||||
>>>-<<<<<>>>>-<<<<+>>>>>]<<<<<>>>>>>[<<<<<<>>>>>>-<<<<<<[->>>>>+<<<<<>>>
|
||||
>+<<<<>>>>+<<<<]>>>>>[<<<<<>>>>>-<<<<<+>>>>>]<<<<<>>>>-<<<<>>>>>+<<<<<>>
|
||||
>>>>]<<<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>>>+<<<<<<>>>>>]<<<<<[->>>>>+<<<<<]>
|
||||
>>>>>[-]<<<<<<+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>>>>>>>[-+>>[-<<->>]+<<
|
||||
[->>-<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[
|
||||
>>>>>>>>>]>+<]]+>>>[-<<<->>>]+<<<[->>>-<<<>>[-<<+>>]<<[->>+<<<<<<<<<<<[<
|
||||
<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<
|
||||
<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>
|
||||
>>>[>+<>>>[-<<<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>>
|
||||
+<<<<<<>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>[-<<<>>>>>>+<<<<<<>>>]
|
||||
<<<>>]<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>]<>>[-<<>>>>>>
|
||||
+<<<<<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>>]<<>>>[-<<<>>>
|
||||
>>>+<<<<<<>>>]<<<<<<<<<<<<]>>>>[-]<<<<]>>>[-<<<+>>>]<<<[->>>+<<<>>>>>>>>
|
||||
>[>+<>>[-<<>-<>>]<<>[-<>>+<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>>+<<<<<<>
|
||||
>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>[-<<>>>>>>+<<<<<<>>]<<>>>]<<<
|
||||
>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>]<<>]<>>>[-<<<>>>>>>+<<<<<<>>[
|
||||
-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>]<<>>>]<<<>>[-<<>>>>>>+<<<<<<>>]<
|
||||
<<<<<<<<<<]>>>>>>+<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>>>>>
|
||||
>>>>]<<<<<<<<<[>[-<>>>>>>+<<<<<<>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><
|
||||
>>>[-<<<>>>>>>+<<<<<<>>>]<<<>>]<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>
|
||||
>><>>>]<<<>]<>>[-<<>>>>>>+<<<<<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>
|
||||
><>>>]<<<>>]<<>>>[-<<<>>>>>>+<<<<<<>>>]<<<<<<<<<<<<]]>[-]<>>>[-]<<<>>>>[
|
||||
-]<<<<>>>>>>>>>[>>[-]<<>>>[-]<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[
|
||||
>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<
|
||||
<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[
|
||||
-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>
|
||||
>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<
|
||||
<<<<[->>[-<<+>>]<<[->>+<<>>>+<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>
|
||||
>>>>>>>[>>>>>>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<
|
||||
<<<<<<>]<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>
|
||||
>>>>>]<<<<<<<<<[>[-]<->>>[<<<>>>-<<<+>[<->-<<<<<<<<<<>>>+<<<>>>>>>>>>>]<
|
||||
[->+<]>>>]<<<>[<>-<>>>+<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<>>>>>>>>>]<<
|
||||
<<<<<<<[<<<<<<<<<]>>>>>[-]<<<<<>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]<<<
|
||||
<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[-+>>>[-<<<->>>
|
||||
]+<<<[->>>-<<<>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]
|
||||
+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+
|
||||
>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<
|
||||
]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>
|
||||
]<<<[->>>+<<<>>>>>>>>>[>+<>>>>[-<<<<>-<>>>>]<<<<>[-<>>>>+<<<<>]<>>>>>>>>
|
||||
>]<<<<<<<<<>+<[>[-<>>+<<>>>[-<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>[-<<<<>>+<
|
||||
<>>>>]<<<<>>>]<<<>>>>[-<<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>]<<<<>]<>>>[-<<
|
||||
<>>+<<>>>>[-<<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>]<<<<>>>]<<<>>>>[-<<<<>>+<
|
||||
<>>>>]<<<<<<<<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>+<>>>[-<<
|
||||
<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>+<<>>>>[-<<<<>>-<<
|
||||
><<<<<<<<<+>>>>>>>>><>>>[-<<<>>+<<>>>]<<<>>>>]<<<<>>>[-<<<>>-<<><<<<<<<<
|
||||
<+>>>>>>>>><>>>]<<<>]<>>>>[-<<<<>>+<<>>>[-<<<>>-<<><<<<<<<<<+>>>>>>>>><>
|
||||
>>]<<<>>>>]<<<<>>>[-<<<>>+<<>>>]<<<<<<<<<<<<]>>>>>+<<<<<]>>>>>>>>>[>>>[-
|
||||
]<<<>>>>[-]<<<<>>>>>[-]<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]<<<>>>>[
|
||||
-]<<<<>>>>>>>>>[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<<<<<<>[-<>>>>>>>+<<<<<<<>>>
|
||||
+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>
|
||||
-<<<<+>>>>>]<<<<<>>>>>>>[<<<<<<<>>>>>>>-<<<<<<<[->>>>>+<<<<<>>>>+<<<<>>>
|
||||
>+<<<<]>>>>>[<<<<<>>>>>-<<<<<+>>>>>]<<<<<>>>>-<<<<>>>>>+<<<<<>>>>>>>]<<<
|
||||
<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>>>>+<<<<<<<>>>>>]<<<<<[->>>>>+<<<<<]+>>>>[
|
||||
-<<<<->>>>]+<<<<[->>>>-<<<<>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>[-<<+
|
||||
>>]<<[->>+<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>
|
||||
[-<<->>]+<<[->>-<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<
|
||||
<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<
|
||||
<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+<<<>>>>>>>>>[>+<>>[-<<>-<>>]<<>[-<>
|
||||
>+<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>+<<<<<>>>[-<<<>>>>>-<<<<<><<<<<<<
|
||||
<<+>>>>>>>>><>>[-<<>>>>>+<<<<<>>]<<>>>]<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>
|
||||
>>>>>>><>>]<<>]<>>>[-<<<>>>>>+<<<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>>
|
||||
<>>]<<>>>]<<<>>[-<<>>>>>+<<<<<>>]<<<<<<<<<<<]>>>>>[-]<<<<<>>>>>>>[<<<<<<
|
||||
<>>>>>>>-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>+<<<<<]]>>>>[-<<<<
|
||||
+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>+<>>>[-<<<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>
|
||||
>>>]<<<<<<<<<>+<[>[-<>>>>>+<<<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>
|
||||
>[-<<<>>>>>+<<<<<>>>]<<<>>]<<>>>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>
|
||||
]<<<>]<>>[-<<>>>>>+<<<<<>>>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>
|
||||
>]<<>>>[-<<<>>>>>+<<<<<>>>]<<<<<<<<<<<<]]>>>>[-]<<<<]>>>>[-<<<<+>>>>]<<<
|
||||
<[->>>>+<<<<>>>>>[-]<<<<<>>>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>>>>>>>]<<<<<<<[
|
||||
->>>>>>>+<<<<<<<>>>>>+<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-<>>>>>+<<<<
|
||||
<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>[-<<<>>>>>+<<<<<>>>]<<<>>]<<>>
|
||||
>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>]<>>[-<<>>>>>+<<<<<>>>[-<<
|
||||
<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>>]<<>>>[-<<<>>>>>+<<<<<>>>]<<<<
|
||||
<<<<<<<<]]>>>>>>>>>[>>[-]<<>>>[-]<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]
|
||||
<<<>>>>[-]<<<<>>>>>>>>>[>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]
|
||||
<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>
|
||||
[-<>>>>>>+<<<<<<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++
|
||||
+++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<
|
||||
<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>
|
||||
>>>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<[->>[-<<+>>]<<[->>+
|
||||
<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>>>>>]<<<
|
||||
<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<<>>-<<>>
|
||||
>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<<<[>[-]<
|
||||
->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<>>>>>>>>>>]<[->+<]>>>>]<<<<
|
||||
>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]
|
||||
>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>>[-<<<+>
|
||||
>>]<<<[->>>+<<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[
|
||||
>>>>>>>>>]<<<<<<<<<<>[<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<
|
||||
<<<<<<>]<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<<<<<>>>>>>>>
|
||||
>>+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<
|
||||
<<>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>
|
||||
[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>
|
||||
>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>+<<<[<<<<<<<<<]>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>>>[-
|
||||
<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>
|
||||
>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<
|
||||
<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<
|
||||
<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>-<<>>>>[-<<<<+>>>>]<<<<[->>>>+
|
||||
<<<<>>[-]<<]>>]<<+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<<<.>>]>>>>[<<<<>>>>-<<
|
||||
<<<<<.>>>>>>>]<<<<>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<>>>>>>>>>[>[-]>[-]>[-]>[
|
||||
-]>[-]>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-]<<<<<>>>
|
||||
>>>>>>]<<<<<<<<<[<<<<<<<<<]>++++++++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<
|
||||
>]<>>>>>>>>>>]<>>>>>+<<<<<>>>>>>>>>>>>>>+<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>
|
||||
>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>>>[-]<<<<<<<>>>>>>>>>[>>
|
||||
>>>>>>>]<<<<<<<<<[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<<<<<<>[-<>>>>>>>+<<<<<<<[
|
||||
<<<<<<<<<]>>>>>>>[-]+<<<<<<<>>>>>>>>>>]<<<<<<<<<<]]>>>>>>>[-<<<<<<<+>>>>
|
||||
>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>>>>>[>+<>>>>>[-<<<<<>-<>>>>>]<<<<<>[-<>
|
||||
>>>>+<<<<<>]<>>>>>>>>>]<<<<<<<<<>>>>>>>+<<<<<<<[>>>>>[<<<<<>>>>>-<<<<<>>
|
||||
>>>>>+<<<<<<<>>>>>]<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-]<->>
|
||||
>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>+<<<<<<<>>>>>>>>>>]<
|
||||
[->+<]>>>>>>>]<<<<<<<>[<>-<>>>>>>>+<<<<<<<>]<+<<<<<<<<<]>>>>>>>-<<<<<<<>
|
||||
>>[-]+<<<]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<<<<<<>>>>>>>>>[>
|
||||
>>>>[<<<<<>>>>>-<<<<<>>>>>>>+<<<<<<<>>>>>]<<<<<>>>>>>>>>]<<<<<<<<<[>[-]<
|
||||
->>>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>+<<<<<<<>>>>>>>>>
|
||||
>]<[->+<]>>>>>>>]<<<<<<<>[<>-<>>>>>>>+<<<<<<<>]<+<<<<<<<<<]>+++++<>[<>-<
|
||||
>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>+<<<<<[<<<<<<<<<]>>>>>>>>
|
||||
>[-+>>>>>[-<<<<<->>>>>]+<<<<<[->>>>>-<<<<<>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<
|
||||
<<[->>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>
|
||||
+<]]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<<<<<<>>>>>[-<<<<<+>>>>
|
||||
>]<<<<<[->>>>>+<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[
|
||||
-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<
|
||||
<<<>+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>-<<<<<[<<
|
||||
<<<<<<<]]>>>]<<<<.>>>>>>>>>>[>>>>>>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<
|
||||
<]>+++++++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>+<<<<
|
||||
<<>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-<<<<<<<<+>>>>>>>>]
|
||||
<<<<<<<<[->>>>>>>>+<<<<<<<<>>>>>>>>[-]<<<<<<<<>>>>>>>>>[>>>>>>>>>]<<<<<<
|
||||
<<<[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]<<<<<<<<>[-<>>>>>>>>+<<<<<<<<[<<<<<<<<
|
||||
<]>>>>>>>>[-]+<<<<<<<<>>>>>>>>>>]<<<<<<<<<<]]>>>>>>>>[-<<<<<<<<+>>>>>>>>
|
||||
]<<<<<<<<[->>>>>>>>+<<<<<<<<>>>>>>>>>[>+<>>>>>>[-<<<<<<>-<>>>>>>]<<<<<<>
|
||||
[-<>>>>>>+<<<<<<>]<>>>>>>>>>]<<<<<<<<<>>>>>>>>+<<<<<<<<[>>>>>>[<<<<<<>>>
|
||||
>>>-<<<<<<>>>>>>>>+<<<<<<<<>>>>>>]<<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<
|
||||
<<<<<<<[>[-]<->>>>>>>>[<<<<<<<<>>>>>>>>-<<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>
|
||||
>+<<<<<<<<>>>>>>>>>>]<[->+<]>>>>>>>>]<<<<<<<<>[<>-<>>>>>>>>+<<<<<<<<>]<+
|
||||
<<<<<<<<<]>>>>>>>>-<<<<<<<<>>>[-]+<<<]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<
|
||||
<<<<[->>>>>>>>-<<<<<<<<>>>>>>>>>[>>>>>>[<<<<<<>>>>>>-<<<<<<>>>>>>>>+<<<<
|
||||
<<<<>>>>>>]<<<<<<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>>>>>[<<<<<<<<>>>>>>>>-<<<
|
||||
<<<<<+>[<->-<<<<<<<<<<>>>>>>>>+<<<<<<<<>>>>>>>>>>]<[->+<]>>>>>>>>]<<<<<<
|
||||
<<>[<>-<>>>>>>>>+<<<<<<<<>]<+<<<<<<<<<]>+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<
|
||||
<<<<<<<>]<>>>>>>>>>>]<>>>>>>+<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<
|
||||
<<<[<<<<<<<<<]>>>>>>>>>[-+>>>>>>[-<<<<<<->>>>>>]+<<<<<<[->>>>>>-<<<<<<>>
|
||||
>>>>>>[-<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<<<
|
||||
]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<
|
||||
<<<<[->>>>>>>>-<<<<<<<<>>>>>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<<<<<<
|
||||
<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<
|
||||
<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<<>+++++<>[<>-<>[<>-<>>>>
|
||||
>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>-<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>-<<<<<<[<<<<<<<<<]]>>>]<<<
|
||||
55
rust2/benches/opts.rs
Normal file
55
rust2/benches/opts.rs
Normal 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
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
212
rust2/mandelbrot.bf
vendored
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
A mandelbrot set fractal viewer in brainf*** written by Erik Bosman
|
||||
+++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++
|
||||
+++++++-[[>>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>>>>>>>>[
|
||||
-]<<<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+<<<<<<<<>+++++<>[<>-
|
||||
<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>>+<<<<<<<<>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>[<<<>>>
|
||||
>>>>>>[>>>>>>>[-]<<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>[-]+<<<<<<<
|
||||
>++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>+<<<<<<<>++
|
||||
+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>+<<<<<<<<<<
|
||||
<<<<<<[<<<<<<<<<]>>>[<<<>>>[-]<<<>>>>>>>>>[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<
|
||||
<<<<<>[-<>>>>>>>+<<<<<<<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<
|
||||
]>>>>>>>>>[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]<<<<<<<<>[-<>>>>>>>>+<<<<<<<<>>
|
||||
>>>>+<<<<<<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>[<<<<<<<>>>>>>
|
||||
>-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>+<<<<<]>>>>>>>>>+++++++++
|
||||
+++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<
|
||||
<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>
|
||||
>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<[->>[-<<+>>]<<[->>+<<
|
||||
>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>>>>>]<<<<<
|
||||
<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<<>>-<<>>>>
|
||||
>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<<<[>[-]<->
|
||||
>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<>>>>>>>>>>]<[->+<]>>>>]<<<<>[
|
||||
<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>
|
||||
>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>>[-<<<+>>>
|
||||
]<<<[->>>+<<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>
|
||||
>>>>>>>]<<<<<<<<<<>[<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<
|
||||
<<<<>]<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<<<<<>>>>>>>>>>
|
||||
+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<
|
||||
>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>[-
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>
|
||||
>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>+<<<[<<<<<<<<<]>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>>>[-<<
|
||||
<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>
|
||||
>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<
|
||||
<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<
|
||||
<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]<<<<<<<[->+>>>-<<<<]>>>>>>>>>+++++
|
||||
+++++++++++++++++++++<<>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>[-]<<]>>[<<<<<<<
|
||||
+<[-<+>>>>+<<[-]]>[-><<<[->+>>>-<<<<]>>>]>>>>>>>>>>>>>[>>[-]<<>>>[-]<<<>
|
||||
>>>[-]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]<<<>>>>>>>>>[>>>>>[-<<<<<>
|
||||
+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>
|
||||
>>>[>>[-<<<<<<<<<+>>>>>>>>>]<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++
|
||||
+++++++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<
|
||||
[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<
|
||||
<<]>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>[-<<+
|
||||
>>]<<[->>+<<>>>+<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>
|
||||
>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<
|
||||
<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<
|
||||
<<[>[-]<->>>[<<<>>>-<<<+>[<->-<<<<<<<<<<>>>+<<<>>>>>>>>>>]<[->+<]>>>]<<<
|
||||
>[<>-<>>>+<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>
|
||||
>>>>>+<<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>
|
||||
]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>
|
||||
>>+<<<<<<[->>[-<<+>>]<<[->>+<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]
|
||||
<>]<>>>>>>>>>>[>>>>>>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>
|
||||
>]<<<<<<<<<<<>]<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>
|
||||
>+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<
|
||||
<>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>[
|
||||
-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<>>>>>>>>>]<<<<<
|
||||
<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]<<<<<<<<<-<<<<<<<<<
|
||||
[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]
|
||||
<<<<<<<<>[-<>>>>>>>>+<<<<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>
|
||||
>>>>[>>>>>>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+<<<<>>>>>[<<<<<>>
|
||||
>>>-<<<<<>>>>-<<<<+>>>>>]<<<<<>>>>>>[<<<<<<>>>>>>-<<<<<<[->>>>>+<<<<<>>>
|
||||
>+<<<<>>>>+<<<<]>>>>>[<<<<<>>>>>-<<<<<+>>>>>]<<<<<>>>>-<<<<>>>>>+<<<<<>>
|
||||
>>>>]<<<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>>>+<<<<<<>>>>>]<<<<<[->>>>>+<<<<<]>
|
||||
>>>>>[-]<<<<<<+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>>>>>>>[-+>>[-<<->>]+<<
|
||||
[->>-<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[
|
||||
>>>>>>>>>]>+<]]+>>>[-<<<->>>]+<<<[->>>-<<<>>[-<<+>>]<<[->>+<<<<<<<<<<<[<
|
||||
<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<
|
||||
<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>
|
||||
>>>[>+<>>>[-<<<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>>
|
||||
+<<<<<<>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>[-<<<>>>>>>+<<<<<<>>>]
|
||||
<<<>>]<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>]<>>[-<<>>>>>>
|
||||
+<<<<<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>>]<<>>>[-<<<>>>
|
||||
>>>+<<<<<<>>>]<<<<<<<<<<<<]>>>>[-]<<<<]>>>[-<<<+>>>]<<<[->>>+<<<>>>>>>>>
|
||||
>[>+<>>[-<<>-<>>]<<>[-<>>+<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>>+<<<<<<>
|
||||
>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>[-<<>>>>>>+<<<<<<>>]<<>>>]<<<
|
||||
>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>]<<>]<>>>[-<<<>>>>>>+<<<<<<>>[
|
||||
-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>]<<>>>]<<<>>[-<<>>>>>>+<<<<<<>>]<
|
||||
<<<<<<<<<<]>>>>>>+<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>>>>>
|
||||
>>>>]<<<<<<<<<[>[-<>>>>>>+<<<<<<>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><
|
||||
>>>[-<<<>>>>>>+<<<<<<>>>]<<<>>]<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>
|
||||
>><>>>]<<<>]<>>[-<<>>>>>>+<<<<<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>
|
||||
><>>>]<<<>>]<<>>>[-<<<>>>>>>+<<<<<<>>>]<<<<<<<<<<<<]]>[-]<>>>[-]<<<>>>>[
|
||||
-]<<<<>>>>>>>>>[>>[-]<<>>>[-]<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[
|
||||
>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<
|
||||
<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[
|
||||
-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>
|
||||
>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<
|
||||
<<<<[->>[-<<+>>]<<[->>+<<>>>+<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>
|
||||
>>>>>>>[>>>>>>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<
|
||||
<<<<<<>]<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>
|
||||
>>>>>]<<<<<<<<<[>[-]<->>>[<<<>>>-<<<+>[<->-<<<<<<<<<<>>>+<<<>>>>>>>>>>]<
|
||||
[->+<]>>>]<<<>[<>-<>>>+<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<
|
||||
<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<>>>>>>>>>]<<
|
||||
<<<<<<<[<<<<<<<<<]>>>>>[-]<<<<<>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]<<<
|
||||
<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[-+>>>[-<<<->>>
|
||||
]+<<<[->>>-<<<>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]
|
||||
+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+
|
||||
>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<
|
||||
]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>
|
||||
]<<<[->>>+<<<>>>>>>>>>[>+<>>>>[-<<<<>-<>>>>]<<<<>[-<>>>>+<<<<>]<>>>>>>>>
|
||||
>]<<<<<<<<<>+<[>[-<>>+<<>>>[-<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>[-<<<<>>+<
|
||||
<>>>>]<<<<>>>]<<<>>>>[-<<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>]<<<<>]<>>>[-<<
|
||||
<>>+<<>>>>[-<<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>]<<<<>>>]<<<>>>>[-<<<<>>+<
|
||||
<>>>>]<<<<<<<<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>+<>>>[-<<
|
||||
<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>+<<>>>>[-<<<<>>-<<
|
||||
><<<<<<<<<+>>>>>>>>><>>>[-<<<>>+<<>>>]<<<>>>>]<<<<>>>[-<<<>>-<<><<<<<<<<
|
||||
<+>>>>>>>>><>>>]<<<>]<>>>>[-<<<<>>+<<>>>[-<<<>>-<<><<<<<<<<<+>>>>>>>>><>
|
||||
>>]<<<>>>>]<<<<>>>[-<<<>>+<<>>>]<<<<<<<<<<<<]>>>>>+<<<<<]>>>>>>>>>[>>>[-
|
||||
]<<<>>>>[-]<<<<>>>>>[-]<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]<<<>>>>[
|
||||
-]<<<<>>>>>>>>>[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<<<<<<>[-<>>>>>>>+<<<<<<<>>>
|
||||
+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>
|
||||
-<<<<+>>>>>]<<<<<>>>>>>>[<<<<<<<>>>>>>>-<<<<<<<[->>>>>+<<<<<>>>>+<<<<>>>
|
||||
>+<<<<]>>>>>[<<<<<>>>>>-<<<<<+>>>>>]<<<<<>>>>-<<<<>>>>>+<<<<<>>>>>>>]<<<
|
||||
<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>>>>+<<<<<<<>>>>>]<<<<<[->>>>>+<<<<<]+>>>>[
|
||||
-<<<<->>>>]+<<<<[->>>>-<<<<>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>[-<<+
|
||||
>>]<<[->>+<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>
|
||||
[-<<->>]+<<[->>-<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<
|
||||
<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<
|
||||
<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+<<<>>>>>>>>>[>+<>>[-<<>-<>>]<<>[-<>
|
||||
>+<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>+<<<<<>>>[-<<<>>>>>-<<<<<><<<<<<<
|
||||
<<+>>>>>>>>><>>[-<<>>>>>+<<<<<>>]<<>>>]<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>
|
||||
>>>>>>><>>]<<>]<>>>[-<<<>>>>>+<<<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>>
|
||||
<>>]<<>>>]<<<>>[-<<>>>>>+<<<<<>>]<<<<<<<<<<<]>>>>>[-]<<<<<>>>>>>>[<<<<<<
|
||||
<>>>>>>>-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>+<<<<<]]>>>>[-<<<<
|
||||
+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>+<>>>[-<<<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>
|
||||
>>>]<<<<<<<<<>+<[>[-<>>>>>+<<<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>
|
||||
>[-<<<>>>>>+<<<<<>>>]<<<>>]<<>>>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>
|
||||
]<<<>]<>>[-<<>>>>>+<<<<<>>>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>
|
||||
>]<<>>>[-<<<>>>>>+<<<<<>>>]<<<<<<<<<<<<]]>>>>[-]<<<<]>>>>[-<<<<+>>>>]<<<
|
||||
<[->>>>+<<<<>>>>>[-]<<<<<>>>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>>>>>>>]<<<<<<<[
|
||||
->>>>>>>+<<<<<<<>>>>>+<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-<>>>>>+<<<<
|
||||
<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>[-<<<>>>>>+<<<<<>>>]<<<>>]<<>>
|
||||
>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>]<>>[-<<>>>>>+<<<<<>>>[-<<
|
||||
<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>>]<<>>>[-<<<>>>>>+<<<<<>>>]<<<<
|
||||
<<<<<<<<]]>>>>>>>>>[>>[-]<<>>>[-]<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]
|
||||
<<<>>>>[-]<<<<>>>>>>>>>[>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]
|
||||
<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>
|
||||
[-<>>>>>>+<<<<<<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++
|
||||
+++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<
|
||||
<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>
|
||||
>>>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<[->>[-<<+>>]<<[->>+
|
||||
<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>>>>>]<<<
|
||||
<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<<>>-<<>>
|
||||
>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<<<[>[-]<
|
||||
->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<>>>>>>>>>>]<[->+<]>>>>]<<<<
|
||||
>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]
|
||||
>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>>[-<<<+>
|
||||
>>]<<<[->>>+<<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[
|
||||
>>>>>>>>>]<<<<<<<<<<>[<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<
|
||||
<<<<<<>]<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<<<<<>>>>>>>>
|
||||
>>+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<
|
||||
<<>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>
|
||||
[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>
|
||||
>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>+<<<[<<<<<<<<<]>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>>>[-
|
||||
<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>
|
||||
>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<
|
||||
<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<
|
||||
<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>-<<>>>>[-<<<<+>>>>]<<<<[->>>>+
|
||||
<<<<>>[-]<<]>>]<<+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<<<.>>]>>>>[<<<<>>>>-<<
|
||||
<<<<<.>>>>>>>]<<<<>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<>>>>>>>>>[>[-]>[-]>[-]>[
|
||||
-]>[-]>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-]<<<<<>>>
|
||||
>>>>>>]<<<<<<<<<[<<<<<<<<<]>++++++++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<
|
||||
>]<>>>>>>>>>>]<>>>>>+<<<<<>>>>>>>>>>>>>>+<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>
|
||||
>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>>>[-]<<<<<<<>>>>>>>>>[>>
|
||||
>>>>>>>]<<<<<<<<<[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<<<<<<>[-<>>>>>>>+<<<<<<<[
|
||||
<<<<<<<<<]>>>>>>>[-]+<<<<<<<>>>>>>>>>>]<<<<<<<<<<]]>>>>>>>[-<<<<<<<+>>>>
|
||||
>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>>>>>[>+<>>>>>[-<<<<<>-<>>>>>]<<<<<>[-<>
|
||||
>>>>+<<<<<>]<>>>>>>>>>]<<<<<<<<<>>>>>>>+<<<<<<<[>>>>>[<<<<<>>>>>-<<<<<>>
|
||||
>>>>>+<<<<<<<>>>>>]<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-]<->>
|
||||
>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>+<<<<<<<>>>>>>>>>>]<
|
||||
[->+<]>>>>>>>]<<<<<<<>[<>-<>>>>>>>+<<<<<<<>]<+<<<<<<<<<]>>>>>>>-<<<<<<<>
|
||||
>>[-]+<<<]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<<<<<<>>>>>>>>>[>
|
||||
>>>>[<<<<<>>>>>-<<<<<>>>>>>>+<<<<<<<>>>>>]<<<<<>>>>>>>>>]<<<<<<<<<[>[-]<
|
||||
->>>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>+<<<<<<<>>>>>>>>>
|
||||
>]<[->+<]>>>>>>>]<<<<<<<>[<>-<>>>>>>>+<<<<<<<>]<+<<<<<<<<<]>+++++<>[<>-<
|
||||
>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>+<<<<<[<<<<<<<<<]>>>>>>>>
|
||||
>[-+>>>>>[-<<<<<->>>>>]+<<<<<[->>>>>-<<<<<>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<
|
||||
<<[->>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>
|
||||
+<]]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<<<<<<>>>>>[-<<<<<+>>>>
|
||||
>]<<<<<[->>>>>+<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[
|
||||
-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<
|
||||
<<<>+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>-<<<<<[<<
|
||||
<<<<<<<]]>>>]<<<<.>>>>>>>>>>[>>>>>>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<
|
||||
<]>+++++++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>+<<<<
|
||||
<<>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-<<<<<<<<+>>>>>>>>]
|
||||
<<<<<<<<[->>>>>>>>+<<<<<<<<>>>>>>>>[-]<<<<<<<<>>>>>>>>>[>>>>>>>>>]<<<<<<
|
||||
<<<[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]<<<<<<<<>[-<>>>>>>>>+<<<<<<<<[<<<<<<<<
|
||||
<]>>>>>>>>[-]+<<<<<<<<>>>>>>>>>>]<<<<<<<<<<]]>>>>>>>>[-<<<<<<<<+>>>>>>>>
|
||||
]<<<<<<<<[->>>>>>>>+<<<<<<<<>>>>>>>>>[>+<>>>>>>[-<<<<<<>-<>>>>>>]<<<<<<>
|
||||
[-<>>>>>>+<<<<<<>]<>>>>>>>>>]<<<<<<<<<>>>>>>>>+<<<<<<<<[>>>>>>[<<<<<<>>>
|
||||
>>>-<<<<<<>>>>>>>>+<<<<<<<<>>>>>>]<<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<
|
||||
<<<<<<<[>[-]<->>>>>>>>[<<<<<<<<>>>>>>>>-<<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>
|
||||
>+<<<<<<<<>>>>>>>>>>]<[->+<]>>>>>>>>]<<<<<<<<>[<>-<>>>>>>>>+<<<<<<<<>]<+
|
||||
<<<<<<<<<]>>>>>>>>-<<<<<<<<>>>[-]+<<<]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<
|
||||
<<<<[->>>>>>>>-<<<<<<<<>>>>>>>>>[>>>>>>[<<<<<<>>>>>>-<<<<<<>>>>>>>>+<<<<
|
||||
<<<<>>>>>>]<<<<<<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>>>>>[<<<<<<<<>>>>>>>>-<<<
|
||||
<<<<<+>[<->-<<<<<<<<<<>>>>>>>>+<<<<<<<<>>>>>>>>>>]<[->+<]>>>>>>>>]<<<<<<
|
||||
<<>[<>-<>>>>>>>>+<<<<<<<<>]<+<<<<<<<<<]>+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<
|
||||
<<<<<<<>]<>>>>>>>>>>]<>>>>>>+<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<
|
||||
<<<[<<<<<<<<<]>>>>>>>>>[-+>>>>>>[-<<<<<<->>>>>>]+<<<<<<[->>>>>>-<<<<<<>>
|
||||
>>>>>>[-<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<<<
|
||||
]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<
|
||||
<<<<[->>>>>>>>-<<<<<<<<>>>>>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<<<<<<
|
||||
<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<
|
||||
<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<<>+++++<>[<>-<>[<>-<>>>>
|
||||
>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>-<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>-<<<<<<[<<<<<<<<<]]>>>]<<<
|
||||
2
rust2/rust-toolchain.toml
Normal file
2
rust2/rust-toolchain.toml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2022-04-17"
|
||||
102
rust2/src/hir/mod.rs
Normal file
102
rust2/src/hir/mod.rs
Normal 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
321
rust2/src/hir/opts.rs
Normal 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
185
rust2/src/lib.rs
Normal 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));
|
||||
}
|
||||
}
|
||||
139
rust2/src/lir/interpreter.rs
Normal file
139
rust2/src/lir/interpreter.rs
Normal 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
137
rust2/src/lir/mod.rs
Normal 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
31
rust2/src/main.rs
Normal 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
120
rust2/src/mir/mod.rs
Normal 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
215
rust2/src/mir/opts.rs
Normal 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(¤t_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(¤t_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
220
rust2/src/mir/state.rs
Normal 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
176
rust2/src/parse.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
),
|
||||
],
|
||||
)
|
||||
43
rust2/src/snapshots/brainfuck__parse__tests__simple.snap
Normal file
43
rust2/src/snapshots/brainfuck__parse__tests__simple.snap
Normal 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,
|
||||
),
|
||||
],
|
||||
)
|
||||
8
rust2/src/snapshots/brainfuck__tests__fizzbuzz.snap
Normal file
8
rust2/src/snapshots/brainfuck__tests__fizzbuzz.snap
Normal 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",
|
||||
)
|
||||
7
rust2/src/snapshots/brainfuck__tests__mandelbrot.snap
Normal file
7
rust2/src/snapshots/brainfuck__tests__mandelbrot.snap
Normal 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
1
rust2/test.bf
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
+++++>[-]+++[<.>]
|
||||
Loading…
Add table
Add a link
Reference in a new issue