Execute Brain****/Elena
<lang elena>import system'collections; import system'routines; import system'dynamic'expressions;
import extensions; import extensions'scripting;
const bf_program = "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.";
class TapeAssembler {
Stack theBrackets; List<Expression> theTape; constructor() { theBrackets := new Stack(); theTape := new List<Expression>(); theTape.append(Expression.DeclareAndAssigning( new ScopeVariable("ptr"), Expression.Constant(0))); } constructor load(assembly_program) { assembly_program(self) } open() { theBrackets.push(theTape); theTape := new List<Expression>(); } close() { var loop := Expression.Loop( Expression.MessageCall( new Message("notequal[2]"), Expression.MessageCall( new Message("at[2]"), Expression.Variable("tape"), Expression.Variable("ptr") ), Expression.Constant($0) ), Expression.CodeBlock(theTape.Value)); theTape := theBrackets.pop(); theTape.append(loop) } input() { theTape.append( Expression.MessageCall( new Message("setAt[3]"), Expression.Variable(new ScopeVariable("tape")), Expression.Variable(new ScopeVariable("ptr")), Expression.MessageCall( new Message("readChar[1]"), Expression.Constant(console) ) ) ) } output() { theTape.append( Expression.MessageCall( new Message("write[2]"), Expression.Constant(console), Expression.MessageCall( new Message("at[2]"), Expression.Variable(new ScopeVariable("tape")), Expression.Variable(new ScopeVariable("ptr")) ) ) ) } next() { theTape.append( Expression.Assigning( new ScopeVariable("ptr"), Expression.MessageCall( new Message("add[2]"), Expression.Variable(new ScopeVariable("ptr")), Expression.Constant(1)))) } previous() { theTape.append( Expression.Assigning( new ScopeVariable("ptr"), Expression.MessageCall( new Message("subtract[2]"), Expression.Variable(new ScopeVariable("ptr")), Expression.Constant(1)))) } increase() { theTape.append( Expression.MessageCall( new Message("setAt[3]"), Expression.Variable("tape"), Expression.Variable("ptr"), Expression.MessageCall( new Message("load[2]"), Expression.Constant(CharValue), Expression.MessageCall( new Message("add[2]"), Expression.MessageCall( new Message("toInt[2]"), Expression.Constant(convertor), Expression.MessageCall( new Message("at[2]"), Expression.Variable("tape"), Expression.Variable("ptr") ) ), Expression.Constant(1) ) ) )); } decrease() { theTape.append( Expression.MessageCall( new Message("setAt[3]"), Expression.Variable("tape"), Expression.Variable("ptr"), Expression.MessageCall( new Message("load[2]"), Expression.Constant(CharValue), Expression.MessageCall( new Message("subtract[2]"), Expression.MessageCall( new Message("toInt[2]"), Expression.Constant(convertor), Expression.MessageCall( new Message("at[2]"), Expression.Variable("tape"), Expression.Variable("ptr") ) ), Expression.Constant(1) ) ) )); } compiled() { var program := DynamicSingleton.new( Expression.Method( "eval", new ScopeVariable("tape"), Expression.CodeBlock(theTape.Value))).compiled(); ^(tape){ program.eval(tape) } }
}
public program() {
var bfAssemblyProgram := new ScriptEngine() .loadPath("asmrules.es") .buildScript(bf_program);
var bfProgram := TapeAssembler.load(bfAssemblyProgram).compiled();
var bfTape := Array.allocate(1024).populate:(n => $0);
bfProgram(bfTape)
}</lang> The grammar: <lang elena>[[
#grammar build #grammar cf
#define start ::= <= system'dynamic'ClosureTape ( => command commands <= ) =>; #define start ::= $eof;
#define commands ::= command commands; #define commands ::= comment commands; #define commands ::= $eof;
#define command ::= <= system'dynamic'MessageClosure ( "output[1]" ) => "."; #define command ::= <= system'dynamic'MessageClosure ( "input[1]" ) => ","; #define command ::= <= system'dynamic'MessageClosure ( "previous[1]" ) => "<"; #define command ::= <= system'dynamic'MessageClosure ( "next[1]" ) => ">"; #define command ::= <= system'dynamic'MessageClosure ( "increase[1]" ) => "+"; #define command ::= <= system'dynamic'MessageClosure ( "decrease[1]" ) => "-"; #define command ::= <= system'dynamic'MessageClosure ( "open[1]" ) => "["; #define command ::= <= system'dynamic'MessageClosure ( "close[1]" ) => "]";
#define comment ::= " " comments; #define comment ::= "'" comments; #define comment ::= "!" comments; #define comment ::= $eol;
#define comments ::= $chr comments; #define comments ::= $eps;
#mode symbolic;
]]</lang>
- Output:
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. Hello World!