Execute Brain****/D: Difference between revisions

From Rosetta Code
Content added Content deleted
(Move 2 alternate implementations from Execute Brain****. http://rosettacode.org/mw/index.php?title=Execute_Brain****&action=history)
Line 1: Line 1:
{{implementation|Brainf***}}{{collection|RCBF}}
{{implementation|Brainf***}}{{collection|RCBF}}

== Implementation 1 ==
{{works with|D|2.007+}}
{{works with|D|2.007+}}
An implementation of Rosetta Code [[Brainfuck|BrainF*ck]] interpreter in [[D]].
An implementation of Rosetta Code [[Brainfuck|BrainF*ck]] interpreter in [[D]].
Line 70: Line 72:
}
}
</lang>
</lang>

== Implementation 2 ==
Alternative version, simpler and faster:
<lang d>import core.stdc.stdio: getchar, putchar, EOF;
import core.stdc.stdlib: exit;

void brainfuckRun(const string code) {
static pure int[int] matchBraces(const string code)
out(result) {
foreach (k, v; result) {
assert(k >=0 && k < code.length);
assert(v >=0 && v < code.length);
assert(v in result);
}
} body {
int[int] loops;
int[] loopStack;

foreach (i, instruction; code) {
if (instruction == '[')
loopStack ~= i;
else if (instruction == ']') {
assert(loopStack.length);
loops[i] = loopStack[$ - 1];
loopStack.length -= 1;
loops[loops[i]] = i;
}
}

assert(!loopStack.length);
return loops;
}

static void runCode(const string code, const int[int] loops) {
enum char empty = '\0';
char[30_000] tape = empty;
int cell, index;

while (index < cast(int)code.length) {
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 ',':
int c = getchar();
if (c == EOF)
exit(1);
tape[cell] = cast(char)c;
break;
case '[':
if (tape[cell] == empty)
index = loops[index];
break;
case ']':
if (tape[cell] != empty)
index = loops[index];
break;
default: break;
}

index++;
}
}

int[int] loops = matchBraces(code);
runCode(code, loops);
}

void main() {
brainfuckRun("++++++++++[>+++++++>++++++++++>+++>+<<<<-]
>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.");
}</lang>

== Implementation 3 ==
Faster partially compile-time version (code generated at compile-time, run at run time):
<lang d>import core.stdc.stdio, core.stdc.stdlib;

pure string ctbf(in string code) {
string r;
foreach (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 ~= "putchar(m[i]);"; break;
case ',': r ~= "int d = getchar();
if (d == EOF) exit(1);
m[i] = cast(char)d;"; break;
default: break;
}
return r;
}

void main() {
char[30_000] m = '\0';
size_t i;
mixin(ctbf("++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++
++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."));
}</lang>

Revision as of 17:51, 29 September 2011

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.

Implementation 1

Works with: D version 2.007+

An implementation of Rosetta Code BrainF*ck interpreter in D.

Implement notes:

  • Needs D version 2.007+, because closure support is required (it should compile in D1, but will run abnormally if brackets/loop-commands are in the BF source).
  • Memory is represented by an associative array, so that negative addresses are allowed, though it is not efficient.
  • Input and output are in character mode, rather than in numerical.
  • Nesting level is checked during parsing, and if loops/brackets are not matched, an error is thrown before executing the code.

<lang d>module rcbf ; import std.file, std.c.stdio ;

alias void delegate() Act ;

char[int] mem ; // memory Act[char] cmd ; // bf command except loop-control int ptr ; // mem pointer

static this() {

 cmd['>'] = { if(!(++ptr in mem)) mem[ptr] = 0 ; } ;
 cmd['<'] = { if(!(--ptr in mem)) mem[ptr] = 0 ; } ;
 cmd['+'] = { mem[ptr] += 1 ; } ;
 cmd['-'] = { mem[ptr] -= 1 ; } ;
 cmd['.'] = { printf("%c", mem[ptr]) ; } ;
 cmd[','] = { printf("%c", mem[ptr] = getch()) ; flushall ; } ;

}

void bf(string code) {

 int cp = 0  ;     // code pointer 
 int nested = 0 ;  // nested loop level
 Act bfAct() { 
   Act[] acts ;    // store commands of current nesting level
   char cc ;       
   while(cp < code.length)
     switch(cc = code[cp++]) { // cc get next command and code pointer cp is advanced 
       case '[':
         nested++ ;
         acts ~= bfAct() ;     // begin inner loop
         break ;
       case ']':                    
         if(--nested < 0) throw new Exception("Unmatched Loops") ;
         return { while(mem[ptr]) { foreach(x ; acts){x();} } } ;
       default:
         if(cc in cmd)
           acts ~= cmd[cc] ;
       //else ignore other non-command char
     }   
   return { foreach(x ; acts){x();} } ;
 }
 
 mem = null ;  mem[0] = 0 ;  ptr = 0 ; // reset memory
 Act run = bfAct() ;
 if(nested != 0) throw new Exception("Unmatched Loops") ;
 run() ; // execute the whole bf program
 printf("\n") ;

}

void main(string[] args) { // if no argument, demo code will be run, else

 if(args.length > 1)           // the arguments are treated as filenames of bf source
     foreach(f ; args[1..$])   // and executed one by one.
       try bf(cast(string)read(f)) ;
       catch (Exception e) printf("%*s",e.msg) ;
 else 
   bf(">+++++++++[<+++++++++>-]<+.>+++[<----->-]"
      "<.-.++++.>++++++[<------>-]<--.>++++++++["
      "<+++++++++>-]<+.>++[<++>-]<+.>++++++++[<-"
      "-------->-]<------.>++++++[<++++++>-]<.>+"
      "++++[<------->-]<.") ;    

} </lang>

Implementation 2

Alternative version, simpler and faster: <lang d>import core.stdc.stdio: getchar, putchar, EOF; import core.stdc.stdlib: exit;

void brainfuckRun(const string code) {

   static pure int[int] matchBraces(const string code)
       out(result) {
           foreach (k, v; result) {
               assert(k >=0 && k < code.length);
               assert(v >=0 && v < code.length);
               assert(v in result);
           }
       } body {
           int[int] loops;
           int[] loopStack;
           foreach (i, instruction; code) {
               if (instruction == '[')
                   loopStack ~= i;
               else if (instruction == ']') {
                   assert(loopStack.length);
                   loops[i] = loopStack[$ - 1];
                   loopStack.length -= 1;
                   loops[loops[i]] = i;
               }
           }
           assert(!loopStack.length);
           return loops;
       }
   static void runCode(const string code, const int[int] loops) {
       enum char empty = '\0';
       char[30_000] tape = empty;
       int cell, index;
       while (index < cast(int)code.length) {
           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 ',':
                   int c = getchar();
                   if (c == EOF)
                       exit(1);
                   tape[cell] = cast(char)c;
                   break;
               case '[':
                   if (tape[cell] == empty)
                       index = loops[index];
                   break;
               case ']':
                   if (tape[cell] != empty)
                       index = loops[index];
                   break;
               default: break;
           }
           index++;
       }
   }
   int[int] loops = matchBraces(code);
   runCode(code, loops);

}

void main() {

   brainfuckRun("++++++++++[>+++++++>++++++++++>+++>+<<<<-]
     >++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.");

}</lang>

Implementation 3

Faster partially compile-time version (code generated at compile-time, run at run time): <lang d>import core.stdc.stdio, core.stdc.stdlib;

pure string ctbf(in string code) {

 string r;
 foreach (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 ~= "putchar(m[i]);";             break;
     case ',': r ~= "int d = getchar();
                     if (d == EOF) exit(1);
                     m[i] = cast(char)d;";        break;
     default:                                     break;
   }
 return r;

}

void main() {

 char[30_000] m = '\0';
 size_t i;
 mixin(ctbf("++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++
   ++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."));

}</lang>