Execute Brain****/D

From Rosetta Code
Revision as of 10:16, 27 November 2015 by rosettacode>Bearophile (Removed first D entry, faster second entry)
Execute Brain****/D is an implementation of Brainf***. Other implementations of Brainf***.
Execute Brain****/D is part of RCBF. You may find other members of RCBF at Category:RCBF.

Version 1

<lang d>import core.stdc.stdio, core.stdc.stdlib, std.conv;

void brainfuckRun(in dstring code) nothrow {

   static int[int] matchBraces(in dstring code) pure nothrow
   out(result) {
       foreach (immutable k, immutable v; result) {
           assert(k >=0 && k < code.length);
           assert(v >=0 && v < code.length);
       }
   } body {
       int[int] loops;
       int[] loopStack;
       foreach (immutable i, immutable instruction; code) {
           if (instruction == '[')
               loopStack ~= i;
           else if (instruction == ']') {
               loops[loopStack[$ - 1]] = i;
               loopStack.length -= 1;
           }
       }
       assert(!loopStack.length);
       return loops;
   }
   static void runCode(in dstring code, in int[int] loops) nothrow {
       enum char empty = '\0';
       char[30_000] tape = empty;
       int cell, index;
       int[10_000] stack; // Bracket stack
       size_t stack_pos = 0; // Bracket stack position
       while (index < code.length.signed) {
           immutable int instruction = code[index];
           switch (instruction) {
               case '>': cell++; assert(cell < tape.length); break;
               case '<': cell--; assert(cell >= 0); break;
               case '+': tape[cell]++; break;
               case '-': tape[cell]--; break;
               case '.': putchar(tape[cell]); break;
               case ',':
                   immutable int c = getchar;
                   if (c == EOF)
                       exit(1);
                   tape[cell] = cast(char)c;
                   break;
               case '[':
                   if (tape[cell] == empty)
                       index = loops[index];
                   else {
                       stack[stack_pos] = index;
                       stack_pos++;
                   }
                   break;
               case ']':
                   immutable matching = stack[stack_pos - 1];
                   stack_pos -= 1;
                   if (tape[cell] != empty)
                       index = matching - 1;
                   break;
               default:
                   break;
           }
           index++;
       }
   }
   int[int] loops = matchBraces(code);
   runCode(code, loops);

}

void main(in string[] args) {

   import std.file;
   // if no argument, demo code will be run, else the first
   // argument is treated as filename of bf source and executed.
   if (args.length > 1) {
       args[1].readText.dtext.brainfuckRun;
   } else {
       brainfuckRun("++++++++++[>+++++++>++++++++++>+++>+<<<<-]
                     >++.>+.+++++++..+++.>++.<<+++++++++++++++.>.
                     +++.------.--------.>+.>.");
   }

}</lang>

Version 2

Much faster version, code generated at compile-time, run at run-time: <lang d>string ctbf(in string code) pure nothrow {

   string r;
   foreach (immutable c; code)
       switch (c) {
           case '>': r ~= "i++; assert(i < m.length);"; break;
           case '<': r ~= "i--; assert(i >= 0);";       break;
           case '+': r ~= "m[i]++;";                    break;
           case '-': r ~= "m[i]--;";                    break;
           case '[': r ~= "while (m[i]) {";             break;
           case ']': r ~= "}";                          break;
           case '.': r ~= "m[i].putchar;";              break;
           case ',': r ~= "{ int d = getchar;
                             if (d == EOF) exit(1);
                             m[i] = cast(char)d; }";    break;
           default:                                     break;
       }
   return r;

}

void main() {

   import core.stdc.stdio, core.stdc.stdlib;
   char[30_000] m = '\0';
   size_t i;
   mixin(ctbf("++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++
      ++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."));

}</lang>