1 module brainfuck; 2 3 import std.conv; 4 import std.array; 5 import std.stdio; 6 import std.format; 7 8 class VM { 9 uint pointer = 0; 10 ubyte[] tape; 11 12 this() { 13 tape.length = 30000; 14 } 15 } 16 17 class BrainfuckInstruction { 18 abstract void run(VM); 19 abstract string compile(uint); 20 abstract string to_string(uint); 21 22 string compile() { 23 return compile(0); 24 } 25 26 string to_string() { 27 return to_string(0); 28 } 29 } 30 31 class Modify : BrainfuckInstruction { 32 int amt; 33 34 this(int amt) { 35 this.amt = amt; 36 } 37 38 override void run(VM vm) { 39 vm.tape[vm.pointer] += amt; 40 } 41 42 override string compile(uint depth) { 43 return " ".replicate(depth) ~ "*p += %s;".format(amt); 44 } 45 46 override string to_string(uint depth) { 47 return " ".replicate(depth) ~ "Modify(" ~ amt.to!string ~ ")"; 48 } 49 } 50 51 class Select : BrainfuckInstruction { 52 int amt; 53 54 this(int amt) { 55 this.amt = amt; 56 } 57 58 override void run(VM vm) { 59 vm.pointer += amt; 60 } 61 62 override string compile(uint depth) { 63 return " ".replicate(depth) ~ "p += %s;".format(amt); 64 } 65 66 override string to_string(uint depth) { 67 return " ".replicate(depth) ~ "Select(" ~ amt.to!string ~ ")"; 68 } 69 } 70 71 class Loop : BrainfuckInstruction { 72 BrainfuckInstruction[] insts; 73 74 this(BrainfuckInstruction[] insts) { 75 this.insts = insts; 76 } 77 78 override void run(VM vm) { 79 while(vm.tape[vm.pointer] != 0) { 80 foreach(inst; insts) { 81 inst.run(vm); 82 } 83 } 84 } 85 86 override string compile(uint depth) { 87 char[] s; 88 s ~= " ".replicate(depth) ~ "while(*p) {\n"; 89 90 foreach(inst; insts) { 91 s ~= inst.compile(depth + 1) ~ "\n"; 92 } 93 94 s ~= " ".replicate(depth) ~ "}"; 95 return cast(string) s; 96 } 97 98 override string to_string(uint depth) { 99 char[] s; 100 s ~= " ".replicate(depth) ~ "Loop {\n"; 101 102 foreach(inst; insts) { 103 s ~= inst.to_string(depth + 1) ~ "\n"; 104 } 105 106 s ~= " ".replicate(depth) ~ "}"; 107 return cast(string) s; 108 } 109 } 110 111 class Input : BrainfuckInstruction { 112 override void run(VM vm) { 113 char c; 114 readf("%s", &c); 115 vm.tape[vm.pointer] = c; 116 } 117 118 override string compile(uint depth) { 119 return " ".replicate(depth) ~ "*p = getchar();"; 120 } 121 122 override string to_string(uint depth) { 123 return " ".replicate(depth) ~ "Input"; 124 } 125 } 126 127 class Output : BrainfuckInstruction { 128 override void run(VM vm) { 129 write(cast(char) vm.tape[vm.pointer]); 130 stdout.flush(); 131 } 132 133 override string compile(uint depth) { 134 return " ".replicate(depth) ~ "putchar(*p); fflush(stdout);"; 135 } 136 137 override string to_string(uint depth) { 138 return " ".replicate(depth) ~ "Output"; 139 } 140 } 141 142 class Clear : BrainfuckInstruction { 143 override void run(VM vm) { 144 vm.tape[vm.pointer] = 0; 145 } 146 147 override string compile(uint depth) { 148 return " ".replicate(depth) ~ "*p = 0;"; 149 } 150 151 override string to_string(uint depth) { 152 return " ".replicate(depth) ~ "Clear"; 153 } 154 } 155 156 class MoveLoop : BrainfuckInstruction { 157 int[int] modifications; 158 159 this(int[int] modifications) { 160 this.modifications = modifications; 161 } 162 163 override void run(VM vm) { 164 auto src = vm.tape[vm.pointer]; 165 if(src == 0) return; 166 167 foreach(pointer, modify; modifications) { 168 vm.tape[vm.pointer + pointer] += modify * src; 169 } 170 171 vm.tape[vm.pointer] = 0; 172 } 173 174 override string compile(uint depth) { 175 char[] s; 176 s ~= " ".replicate(depth) ~ "if(*p) {\n"; 177 178 foreach(pointer, modify; modifications) { 179 s ~= " ".replicate(depth + 1) ~ "*(p + %s) += %s * (*p);\n".format(pointer, modify); 180 } 181 182 s ~= " ".replicate(depth + 1) ~ "*p = 0;\n"; 183 s ~= " ".replicate(depth) ~ "}"; 184 return cast(string) s; 185 } 186 187 override string to_string(uint depth) { 188 return " ".replicate(depth) ~ "MoveLoop " ~ modifications.to!string; 189 } 190 }