Execute Brain****/E

From Rosetta Code
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.

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)
}

Example usage:

? def incr3 := bfCompiler(",>,>,><<<[+.>]")
# value: <BF function>
 
? incr3("abc")
# value: "bcd"