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

m
no edit summary
No edit summary
imported>Arakov
mNo edit summary
 
(14 intermediate revisions by 3 users not shown)
Line 1:
ELENA 6.x:
<lang elena>#define system.
<syntaxhighlight lang="elena">import system'collections;
#define extensions'text.
import system'routines;
import system'dynamic'expressions;
 
import extensions;
// --- Tape ---
import extensions'scripting;
 
const bf_program = "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.";
#class Tape
{
#field theArray.
#field thePointer.
 
class TapeAssembler
#constructor new &type'length:aLength
{ [
Stack thePointer := Integer new:0. _brackets;
List<Expression> _tape;
 
theArray := Array new &type'length:aLength &function: &&:n [ Integer new:0 ].
]
 
#method type'tape = $self.
 
#method append
[
(theArray@thePointer) += 1.
]
#method reduceconstructor()
[{
_brackets := new Stack();
(theArray@thePointer) -= 1.
_tape := new List<Expression>();
]
_tape.append(Expression.DeclareAndAssigning(
"ptr",
Expression.Constant(0)));
}
constructor load(assembly_program)
#method next
[{
thePointer += 1.assembly_program(self)
]}
 
#method previous
[
thePointer -= 1.
]
#method inputopen()
[{
_brackets.push(_tape);
(theArray@thePointer) write &type'int:(console readChar).
_tape := new List<Expression>();
]
}
#method outputclose()
[{
var loop := Expression.Loop(
console write:(CharValue new:(theArray@thePointer)).
Expression.MessageCall(
]
new Message("notequal[2]"),
Expression.MessageCall(
new Message("at[2]"),
Expression.Variable("tape"),
Expression.Variable("ptr")
),
Expression.Constant($0)
),
CodeblockExpression.new(_tape.Value));
_tape := _brackets.pop();
_tape.append(loop)
}
input()
#method get = theArray@thePointer.
{
}
_tape.append(
 
Expression.MessageCall(
// --- LoopInterpreter ---
new Message("setAt[3]"),
 
Expression.Variable("tape"),
#class LoopInterpreter
Expression.Variable("ptr"),
{
Expression.MessageCall(
#field theLoopBody.
new Message("readChar[1]"),
#field theTape.
Expression.Constant(console)
)
)
)
}
output()
#constructor new &tape:aTape
[{
theTape := aTape_tape.append(
theLoopBody := String new Expression.MessageCall(
new Message("write[2]"),
]
Expression.Constant(console),
Expression.MessageCall(
new Message("at[2]"),
Expression.Variable("tape"),
Expression.Variable("ptr")
)
)
)
}
next()
#method type'tape = theTape type'tape.
{
 
#method _tape.append(
Expression.Assigning(
[
theLoopBody += "+ptr".,
Expression.MessageCall(
]
new Message("add[2]"),
Expression.Variable("ptr"),
Expression.Constant(1))))
}
#method reduceprevious()
[{
theLoopBody += "-"_tape.append(
Expression.Assigning(
]
"ptr",
Expression.MessageCall(
new Message("subtract[2]"),
Expression.Variable("ptr"),
Expression.Constant(1))))
}
#method nextincrease()
[{
theLoopBody += ">"_tape.append(
Expression.MessageCall(
]
new Message("setAt[3]"),
 
Expression.Variable("tape"),
#method previous
Expression.Variable("ptr"),
[
theLoopBody += "<" Expression.MessageCall(
new Message("load[2]"),
]
Expression.Constant(CharValue),
Expression.MessageCall(
#method input
new Message("add[2]"),
[
Expression.MessageCall(
theLoopBody += ",".
new Message("toInt[2]"),
]
Expression.Constant(intConvertExt),
Expression.MessageCall(
new Message("at[2]"),
Expression.Variable("tape"),
Expression.Variable("ptr")
)
),
Expression.Constant(1)
)
)
));
}
#method outputdecrease()
[{
theLoopBody += "."_tape.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(intConvertExt),
Expression.MessageCall(
new Message("at[2]"),
Expression.Variable("tape"),
Expression.Variable("ptr")
)
),
Expression.Constant(1)
)
)
));
}
#method runcompiled()
[{
controlvar program while:[0= < theTape get ] &do:DynamicSingleton.load(
Expression.Method(
[ interpreter'Interpreter new:(theTape type'tape) eval:theLoopBody. ].
"eval",
CodeblockExpression.new(_tape.Value),
^ theTape.
ScopeIdentifier.Variable("tape"))
]
).compile();
^(tape){ program.eval(tape) }
}
}
 
public program()
// --- Interpreter ---
 
#class Interpreter
{
var bfAssemblyProgram := new ScriptEngine()
#field theTape.
.loadPath("asmrules.es")
.buildScript(bf_program);
 
var bfProgram := TapeAssembler.load(bfAssemblyProgram).compiled();
#constructor new : aTape
[
theTape := aTape.
]
 
var bfTape := Array.allocate(1024).populate::(n => $0);
#method eval : anObject
[
$self eval::anObject.
]
#method eval &type'widestr:aLiteral
[
control foreach:aLiteral &do:$self.
]
 
console.writeLine(bf_program);
#method eval &widechar:aChar
[
aChar =>
">" ? [ theTape next ]
"<" ? [ theTape previous ]
"+" ? [ theTape append ]
"-" ? [ theTape reduce ]
"." ? [ theTape output. ]
"," ? [ theTape input. ]
"[" ? [ theTape := LoopInterpreter new &tape:theTape. ]
"]" ? [ theTape := theTape run. ].
]
}
 
bfProgram(bfTape)
// --- Program ---
}</syntaxhighlight>
The grammar:
<syntaxhighlight lang="elena">[[
#grammar build
#grammar cf
 
#define start ::=
#symbol program =
<=
[
system'dynamic'DynamicTape (
('program'arguments Count == 1)?
system'dynamic'AllocFunction ( "1" )
[ console write:"Please provide the path to the file to interpret". #throw BreakException new. ].
system'dynamic'LocalFunction ( "2" ) => command commands
<= ) =>;
textFileControl forEachLine:('program'arguments@1) &do:(Interpreter new:(Tape new &type'length:1024)).
 
].
#define start ::= $eof;
</lang>
 
#define commands ::= command commands;
#define commands ::= comment commands;
#define commands ::= $eof;
 
#define command ::= <= system'dynamic'MessageFunction ( "output[1]" ) => ".";
#define command ::= <= system'dynamic'MessageFunction ( "input[1]" ) => ",";
#define command ::= <= system'dynamic'MessageFunction ( "previous[1]" ) => "<";
#define command ::= <= system'dynamic'MessageFunction ( "next[1]" ) => ">";
#define command ::= <= system'dynamic'MessageFunction ( "increase[1]" ) => "+";
#define command ::= <= system'dynamic'MessageFunction ( "decrease[1]" ) => "-";
#define command ::= <= system'dynamic'MessageFunction ( "open[1]" ) => "[";
#define command ::= <= system'dynamic'MessageFunction ( "close[1]" ) => "]";
 
#define comment ::= " " comments;
#define comment ::= "'" comments;
#define comment ::= "!" comments;
#define comment ::= $eol;
 
#define comments ::= $chr comments;
#define comments ::= $eps;
 
#mode symbolic;
]]</syntaxhighlight>
{{out}}
<pre>
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
Hello World!
</pre>
Anonymous user