Execute Brain****/E

From Rosetta Code
Revision as of 18:14, 19 May 2009 by rosettacode>Kevin Reid (New page: {{implementation|Brainf***}}{{collection|RCBF}}Category:E This BF implementation compiles BF programs into functions (from strings to strings) in the host language, E. It has a fixed...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Execute Brain****/E is an implementation of Brainf***. Other implementations of Brainf***.
Execute Brain****/E is part of RCBF. You may find other members of RCBF at Category:RCBF.

This BF implementation compiles BF programs into functions (from strings to strings) in the host language, E.

It has a fixed-size memory defined in terms of characters, not bytes, and initialized to the null character. It does not permit the BF program to notice EOF.

<lang e>pragma.syntax("0.9") pragma.enable("accumulator")

def makeLiteralExpr := <elang:evm.makeLiteralExpr> def makeSeqExpr  := <elang:evm.makeSeqExpr>

def simpleInstructions := [

 '>' => e`ptr        +=        1`,
 '<' => e`ptr        -=        1`,
 '+' => e`array[ptr] next=     ()`,
 '-' => e`array[ptr] previous= ()`,
 '.' => e`out        +=        E.toString(array[ptr])`,
 ',' => e`array[ptr] :=        inputString[inPtr += 1]`,

]

def bfCompile(prog) {

 # Stack holding nested loop bodies collected so far
 def stack := [[]].diverge()
 
 for ch in prog {
   switch (ch) {
     
     match =='[' {
       stack.push([])
     }
     
     match ==']' {
       # take enclosed program off top of stack and append to next down inside a loop
       stack[stack.size() - 2] with= e`
         while (array[ptr] != '\u0000') {
           ${makeSeqExpr(null, stack.pop(), null)}
         }
       `
     }
     
     match _ ? (simpleInstructions.maps(ch)) {
       # XXX the {} will be unnecessary once e`` goes to using selfish temps
       stack[stack.size() - 1] with= e`{${simpleInstructions[ch]}}`
     }
     match _ {}
   }
 }
 
 # Take the one remaining stack item
 def [bodyExprs] exit fn _{throw("Too few right brackets")} \
                 := stack.snapshot()
 
 # How the BF function object will appear
 def printDesc := makeLiteralExpr(null, "<BF " + if (prog.indexOf(",") != -1) {"function"} else {"thunk"} + ">", null)
 
 return e`
   pragma.syntax("0.9")
   def bfo := def _ {
     to __printOn(out :TextWriter) {
       out.print($printDesc)
     }
     
     /** Equivalent to passing the empty string */
     to run() { return bfo("") }
     
     to run(inputString) {
       def array := ("\u0000" * 30000).diverge(char)
       var ptr := 0
       var inPtr := -1
       var out := ""
       
       ${makeSeqExpr(null, bodyExprs, null)}
       
       return out
     }
   }
 `.eval(safeScope)

}</lang>

Example usage:

<lang e>? def incr3 := bfCompiler(",>,>,><<<[+.>]")

  1. value: <BF function>

? incr3("abc")

  1. value: "bcd"</lang>