|
| 1 | +Brainfuck Self Interpreter: by Clive Gifford |
| 2 | +
|
| 3 | +Version 1: 01 December 2006 (one trip between code and data per op) |
| 4 | +Version 2: 16 December 2006 (virtual codes for various combinations) |
| 5 | +
|
| 6 | +Credits |
| 7 | +
|
| 8 | +A large section of code to load the input to the interpreter is copied |
| 9 | +from the the 423 byte dbfi interpreter as described in the November 2003 |
| 10 | +paper "A Very Small Interpeter" by Oleg Mazonka and Daniel B Cristofani |
| 11 | +
|
| 12 | +Goals |
| 13 | +
|
| 14 | +The goal for this interpreter was to be efficient rather than small and |
| 15 | +particularly to allow as many copies of itself as possible to be "stacked" |
| 16 | +up with something else on top / In other words to achieve a low "eigenratio" |
| 17 | +(See http eigenratios dot blogspot dot com for more information) |
| 18 | +
|
| 19 | +The main idea of the first version was to only make one round trip between |
| 20 | +the emulated code and emulated data for each instruction executed instead |
| 21 | +of multiple round trips which is what Daniel and Oleg's version does |
| 22 | +
|
| 23 | +The second version does more pre processing of the guest program in order |
| 24 | +to map several common sequences to virtual codes thus reducing the memory |
| 25 | +footprint and also further reducing the number of round trips between the |
| 26 | +emulated code and data |
| 27 | +
|
| 28 | +Other info: |
| 29 | +
|
| 30 | +The input must consist of valid brainfuck code (to be interpreted) which |
| 31 | +must always be followed by an exclamation mark and then any associated data |
| 32 | +Input can also include "comments" (if desired) except for exclamation mark |
| 33 | +
|
| 34 | +If you are stacking multiple copies of this interpreter then each additional |
| 35 | +level also has to appear in the input with a trailing exclamation mark and |
| 36 | +then we finally have the input for the very top level to finish things off |
| 37 | +
|
| 38 | +The underlying brainfuck machine determines the possible range of values in |
| 39 | +the data cell values and what happens if an attempt is made to go outside the |
| 40 | +supported range but this interpreter does not more than 8 bit data itself |
| 41 | +
|
| 42 | +Loops in the emulated code can be nested up to the maximum cell value in the |
| 43 | +underlying machine and this interpreter requires that at least 17 levels of |
| 44 | +nesting is supported |
| 45 | +
|
| 46 | +Behaviour on end of input is also inherited from the next level down |
| 47 | +
|
| 48 | +>>>> leave a little extra space before the program code |
| 49 | ++ start in left hand cell of first program code pair |
| 50 | +[ |
| 51 | + ->>> clear flag and move to the starting position |
| 52 | + ++>+>+++++++ setup differences and read char as per dbfi |
| 53 | + [<++++>>++<-]++>>+>+> (by Daniel B Cristofani) |
| 54 | + +++++[>++>++++++<<-] |
| 55 | + +>>>,<++ |
| 56 | + [ |
| 57 | + [>[->>]<[>>]<<-] see section 3 of dbfi paper |
| 58 | + <[<]<+>>[>]> |
| 59 | + [ see section 4 of dbfi paper |
| 60 | + <+>- |
| 61 | + [[<+>-]>] see section 5 of dbfi paper |
| 62 | + < see section 6 of dbfi paper |
| 63 | + [ |
| 64 | + [[-]<] scan left and zero the differences |
| 65 | + ++<- see section 7 of dbfi paper |
| 66 | + [ |
| 67 | + <+++++++++>[<->-]>> |
| 68 | + ] |
| 69 | + >> |
| 70 | + ] |
| 71 | + ] |
| 72 | + << |
| 73 | + ] |
| 74 | +
|
| 75 | + a three way switch to handle possibilities and adjust positioning |
| 76 | + |
| 77 | + >[-]+<< set "done" flag and position to value |
| 78 | + [ |
| 79 | + -- 2 means last decode was for a valid instruction |
| 80 | + [ so if we still have something left now it was a 9 |
| 81 | + [-] originally (meaning input should be ignored) |
| 82 | + >>- <<<+> so all we do is set the "more input" flag |
| 83 | + ] |
| 84 | + >> |
| 85 | + [ |
| 86 | + - |
| 87 | + <<<<[>+<-] for valid input move everything right one |
| 88 | +
|
| 89 | + start of processing to find and recode certain combinations of codes |
| 90 | +
|
| 91 | + +<<+ set flags to indicate we want to process |
| 92 | + the last two instructions in the loop below |
| 93 | + [ |
| 94 | + -> clear flag and move to instruction |
| 95 | + [<+>>>>>>+<<<<<-] double copy instruction and then |
| 96 | + <[>+<-]>>>>>> restore original before moving to copy |
| 97 | +
|
| 98 | + map relevant codes to values giving unique pairwise sums and also |
| 99 | + set a flag if we see the end of a loop |
| 100 | +
|
| 101 | + >+< |
| 102 | + [ |
| 103 | + -[ |
| 104 | + -[ |
| 105 | + -[ |
| 106 | + -[ |
| 107 | + -[ |
| 108 | + -[ |
| 109 | + -[ |
| 110 | + -[ |
| 111 | + [-] |
| 112 | + >-< |
| 113 | + ]>[-<<+++++++>>] < |
| 114 | + ] |
| 115 | + ] |
| 116 | + ]>[-]< |
| 117 | + ]>[-<<+++>>]< |
| 118 | + ]>[-<<+>>]< |
| 119 | + ]>[-]< |
| 120 | + ]>[-<<<<<<<+>>>>>>>]< set flag if it is end of loop |
| 121 | + ]>[-]< |
| 122 | + <<<< goto next instruction flag |
| 123 | + ] |
| 124 | +
|
| 125 | + add values from above together to get unique sum |
| 126 | +
|
| 127 | + >>>[<<+>>-] |
| 128 | + <+< |
| 129 | +
|
| 130 | + setup a switch to figure out what it means |
| 131 | +
|
| 132 | + [ |
| 133 | + -[ |
| 134 | + -[ |
| 135 | + -[ |
| 136 | + -[ |
| 137 | + -[ |
| 138 | + -[ |
| 139 | + -[ |
| 140 | + -[ |
| 141 | + -[ |
| 142 | + -[ |
| 143 | + [-] |
| 144 | + >-<<<[-]<<+>> change code 8 (add 1) to 9 (add 2) |
| 145 | + ] |
| 146 | + ] |
| 147 | + ] |
| 148 | + ]>[-]< |
| 149 | + ]>[-<<<[-]<<+++++++>>>]< change code 4 (left) to 11 (left 2) |
| 150 | + ] |
| 151 | + ] |
| 152 | + ]>[-]< |
| 153 | + ]>[-<<<[-]<<+++++++>>>]< change code 3 (right) to 10 (right 2) |
| 154 | + ] |
| 155 | + ]>[-]< |
| 156 | +
|
| 157 | + clear flag set if second to last was end of loop |
| 158 | + and go to similar flag for last instruction |
| 159 | +
|
| 160 | + <<<<<[-]>> |
| 161 | + [ |
| 162 | + - |
| 163 | + <<<[>+>>+<<<-]>[<+>-]>> copy third to last instruction |
| 164 | + |
| 165 | + if it is the start of a loop then we can (in some cases) |
| 166 | + collapse the last three instructions to single virtual code |
| 167 | +
|
| 168 | + [ |
| 169 | + -[ |
| 170 | + -[ |
| 171 | + [-] |
| 172 | + >> |
| 173 | + ] |
| 174 | + > |
| 175 | + [ Now we are ready to check what code is in the loop (must be at least 1) |
| 176 | + <<[<+>>+<-]>[<+>-]+<< |
| 177 | + - |
| 178 | + [ |
| 179 | + -[ |
| 180 | + -[ |
| 181 | + -[ |
| 182 | + -[ |
| 183 | + -[ |
| 184 | + -[ |
| 185 | + -[ |
| 186 | + -[ |
| 187 | + -[ |
| 188 | + - |
| 189 | + <+> fall through & code as 16 (double skip left) |
| 190 | + ]<+++++++++++++>>[-]>->-<< code as 15 (double skip right) |
| 191 | + ] |
| 192 | + ] |
| 193 | + ]>>[->>>>>]<< |
| 194 | + ]>>[-<<<++++++++++++>>[-]>>-]<< code as 14 (zero) |
| 195 | + ]>>[->>>>>]<< |
| 196 | + ]>>[-<<<+++++++++++>>[-]>>-]<< code as 13 (skip left) |
| 197 | + ]>>[-<<<++++++++++>>[-]>>-]<< code as 12 (skip right) |
| 198 | + ] |
| 199 | + ]>>[->>>>>]<< |
| 200 | + ] |
| 201 | + < |
| 202 | + ] |
| 203 | + ]>[>>]< |
| 204 | + << |
| 205 | + ] |
| 206 | + >>+>>> |
| 207 | + ] |
| 208 | + << |
| 209 | + ] |
| 210 | + >> [->+>] << end of input so clear "done" and set data mark and |
| 211 | + finally position to a zero cell ready for next phase |
| 212 | + |
| 213 | + < move to "more input" flag |
| 214 | + |
| 215 | +] |
| 216 | +
|
| 217 | +<<[<<]>> go to the first instruction |
| 218 | +
|
| 219 | + ******** MAIN INTERPRETER LOOPS STARTS HERE ******** |
| 220 | +
|
| 221 | +[ start on current instruction code |
| 222 | + setup a big switch statement to decode instructions |
| 223 | + [<+>>+<-] move/copy instruction code and set "done" flag to |
| 224 | + +<- start with '(i less 1) (1) (i) for i = instruction |
| 225 | + [ |
| 226 | + -[ |
| 227 | + -[ |
| 228 | + -[ |
| 229 | + -[ |
| 230 | + -[ |
| 231 | + -[ |
| 232 | + -[ |
| 233 | + -[ |
| 234 | + -[ |
| 235 | + -[ |
| 236 | + -[ |
| 237 | + -[ |
| 238 | + -[ |
| 239 | + -[ |
| 240 | + - can't be anything but 1 so bracketing not needed |
| 241 | + >->> [>>] >> [>>]< [<-<<-<] <[<<] << [<<]< double skip left (code 16) |
| 242 | + ] |
| 243 | + >[->> [>>] >> [>>]< [>+>>+>] <[<<] << [<<]]< double skip right (code 15) |
| 244 | + ] |
| 245 | + >[->> [>>] >> [>>] <[-]< [<<] << [<<]]< zero (code 14) |
| 246 | + ] |
| 247 | + >[->> [>>] >> [>>]< [<-<] <[<<] << [<<]]< skip left (code 13) |
| 248 | + ] |
| 249 | + >[->> [>>] >> [>>]< [>+>] <[<<] << [<<]]< skip right (code 12) |
| 250 | + ] |
| 251 | + >[->> [>>] >> [>>]< <-<<-< <[<<] << [<<]]< double move left (code 11) |
| 252 | + ] |
| 253 | + >[->> [>>] >> [>>] +>>+ [<<] << [<<]]< double move right (code 10) |
| 254 | + ] |
| 255 | + >[->> [>>] >> [>>]< ++ <[<<] << [<<]]< add 2 (code 9) |
| 256 | + ] |
| 257 | + >[->> [>>] >> [>>]< + <[<<] << [<<]]< increment |
| 258 | + ] |
| 259 | + >[->> [>>] >> [>>]< , <[<<] << [<<]]< input |
| 260 | + ] |
| 261 | + >[->> [>>] >> [>>]< - <[<<] << [<<]]< decrement |
| 262 | + ] |
| 263 | + >[->> [>>] >> [>>]< . <[<<] << [<<]]< output |
| 264 | + ] |
| 265 | + >[->> [>>] >> [>>] <<-<< [<<] << [<<]]< move left |
| 266 | + ] |
| 267 | + >[->> [>>] >> [>>] + [<<] << [<<]]< move right |
| 268 | + ] |
| 269 | + > |
| 270 | + [- left hand bracket |
| 271 | + >> [>>] >> [>>]< move to data cell |
| 272 | + [>+>>+<<<-]> make double copy and move to first |
| 273 | + [<+>-] restore original data cell value |
| 274 | + >>[<<+>>[-]]+ This and the following achieves |
| 275 | + <<[>>-<<-] x = not x |
| 276 | + >> go to flag cell (0 or 1) |
| 277 | +
|
| 278 | + Some tricky stuff here: set up (not flag) also so we can later choose |
| 279 | + appropriate instruction sequence to get back to code area in one pass |
| 280 | + In one case we set flags at the other end (data greater than 0) but |
| 281 | + for the other we just go back without setting any flags (data equals 0) |
| 282 | +
|
| 283 | + [<<+>>>>+<<-] make two copies of flag |
| 284 | + >>[<<+>>-] |
| 285 | + <<[>>+<<-]+ This and the following achieves |
| 286 | + >>[<<->>-]<< x = not x |
| 287 | +
|
| 288 | + << so we now have (data) '(flag) (?) (not flag) |
| 289 | +
|
| 290 | + [ if flag set then |
| 291 | + -<< [<<] << [<<]< clear and return to code section where we save |
| 292 | + << << ++ a 2 meaning we need (later) to match left bracket |
| 293 | + >> stop in zero cell for now |
| 294 | + ] |
| 295 | +
|
| 296 | + >> if we executed code above then now at switch flag |
| 297 | + else it will put us ready to return from data area |
| 298 | +
|
| 299 | + [-<<<<<<[<<]<<[<<]<] move back to switch flag without setting anything |
| 300 | +
|
| 301 | + > |
| 302 | + ] |
| 303 | + < |
| 304 | + ] |
| 305 | + > |
| 306 | + [- right hand bracket |
| 307 | + >> [>>] >> [>>]< move to data cell |
| 308 | + [>+>>+<<<-]> make double copy and move to first |
| 309 | + [[<+>-]>>[-]+<<] restore data from one then zero second and set flag |
| 310 | + >> go to flag cell (0 or 1) |
| 311 | +
|
| 312 | + Some tricky stuff here: set up (not flag) also so we can later choose |
| 313 | + appropriate instruction sequence to get back to code area in one pass |
| 314 | + In one case we set flags at the other end (data greater than 0) but |
| 315 | + for the other we just go back without setting any flags (data equals 0) |
| 316 | +
|
| 317 | + [<<+>>>>+<<-] make two copes of flag |
| 318 | + >>[<<+>>-] |
| 319 | + <<[>>+<<-]+ This and the following achieves |
| 320 | + >>[<<->>-]<< x = not x |
| 321 | + |
| 322 | + << so we now have (data) '(flag) (?) (not flag) |
| 323 | + |
| 324 | + [ if flag set then |
| 325 | + -<< [<<] << [<<]< clear and return to code section where we save |
| 326 | + << << + a 1 meaning we need (later) to match right bracket |
| 327 | + >> stop in zero cell for now |
| 328 | + ] |
| 329 | +
|
| 330 | + >> if we executed code above then now at switch flag |
| 331 | + else it will put us ready to return from data area |
| 332 | + |
| 333 | + [-<<<<<<[<<]<<[<<]<] move back to switch flag without setting anything |
| 334 | + |
| 335 | + > |
| 336 | + ] |
| 337 | +
|
| 338 | + >[<+>-] restore original instruction code |
| 339 | +
|
| 340 | + *** We are positioned in the cell immediately to the right of the *** |
| 341 | + *** instruction that has just been "executed" in the switch above *** |
| 342 | + *** The following code is to handle finding matching brackets *** |
| 343 | + *** because code above has only set a cell value to 1 or 2 to show *** |
| 344 | + *** what kind of loop scanning is required (1=scan left 2=right) *** |
| 345 | + |
| 346 | + << << << position to cell showing if matching required |
| 347 | + [ if non zero we need to find a matching bracket |
| 348 | + >> + set up "done" flag for switch and |
| 349 | + << - decrement switch value so now is 0 or 1 |
| 350 | + [ if 1 we are looking for matching right bracket |
| 351 | + - >> - >> + clear switch value & "done" & set level to 1 |
| 352 | + [ while level is more than 0 |
| 353 | + >>>[-<+>>+<] make double copy of instruction code |
| 354 | + +<- set flag and prepare for switch |
| 355 | + [ |
| 356 | + -[ |
| 357 | + [-] clear whatever is left of code |
| 358 | + > - < do nothing except clear flag |
| 359 | + ] |
| 360 | + > [- <<< + >>>] < increment level |
| 361 | + ] |
| 362 | + > [- <<< - >>>] decrement level |
| 363 | +
|
| 364 | + >[-<+>]<< restore instruction code |
| 365 | +
|
| 366 | + << go to level |
| 367 | + [>>+<<-] if level then move right one instruction |
| 368 | + >> |
| 369 | + ] |
| 370 | + << << << go back to switch value cell |
| 371 | + ] |
| 372 | + >> go to switch done flag and if still set then |
| 373 | + [ we must be looking for a matching left bracket |
| 374 | + - << + clear switch value & "done" & set level to 1 |
| 375 | + [ repeat while level is more than 0 |
| 376 | + >>>[-<+>>+<] make double copy of instruction code |
| 377 | + +<- set flag and prepare for switch |
| 378 | + [ |
| 379 | + -[ |
| 380 | + [-] clear whatever is left of code |
| 381 | + > - < do nothing except clear flag |
| 382 | + ] |
| 383 | + > [- <<< - >>>] < decrement level |
| 384 | + ] |
| 385 | + > [- <<< + >>>] increment level |
| 386 | +
|
| 387 | + >[-<+>]<< restore instruction code |
| 388 | +
|
| 389 | + << go to level |
| 390 | + [<<+>>-] if level then move left one instruction |
| 391 | + << |
| 392 | + ] |
| 393 | + ] |
| 394 | + ] |
| 395 | +
|
| 396 | + >> >> >> |
| 397 | +
|
| 398 | + > move forward to next instruction |
| 399 | +] |
0 commit comments