Execute Brain****/Elena: Difference between revisions
Content added Content deleted
No edit summary |
imported>Arakov mNo edit summary |
||
(12 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
ELENA 6.x: |
|||
<lang elena>#define system. |
|||
<syntaxhighlight lang="elena">import system'collections; |
|||
#define system'routines. |
|||
import system'routines; |
|||
#define extensions'text. |
|||
import system'dynamic'expressions; |
|||
import extensions; |
|||
// --- Tape --- |
|||
import extensions'scripting; |
|||
const bf_program = "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."; |
|||
#class BFTape |
|||
{ |
|||
#field theArray. |
|||
#field thePointer. |
|||
class TapeAssembler |
|||
#constructor new &length:aLength |
|||
{ |
|||
Stack _brackets; |
|||
List<Expression> _tape; |
|||
theArray := arrayControl new &length:aLength &each: n [ Integer new:0 ]. |
|||
] |
|||
#method bf_tape = $self. |
|||
#method append |
|||
[ |
|||
(theArray@thePointer) += 1. |
|||
] |
|||
constructor() |
|||
{ |
|||
_brackets := new Stack(); |
|||
(theArray@thePointer) -= 1. |
|||
_tape := new List<Expression>(); |
|||
] |
|||
_tape.append(Expression.DeclareAndAssigning( |
|||
"ptr", |
|||
Expression.Constant(0))); |
|||
} |
|||
constructor load(assembly_program) |
|||
#method next |
|||
{ |
|||
assembly_program(self) |
|||
} |
|||
#method previous |
|||
[ |
|||
thePointer -= 1. |
|||
] |
|||
open() |
|||
{ |
|||
_brackets.push(_tape); |
|||
(theArray@thePointer) write &int:(console readChar). |
|||
_tape := new List<Expression>(); |
|||
] |
|||
} |
|||
close() |
|||
{ |
|||
var loop := Expression.Loop( |
|||
console write:(CharValue new:(theArray@thePointer)). |
|||
Expression.MessageCall( |
|||
] |
|||
new Message("notequal[2]"), |
|||
Expression.MessageCall( |
|||
#method run : aLoop |
|||
new Message("at[2]"), |
|||
[ |
|||
Expression.Variable("tape"), |
|||
control while:[ 0 < (theArray@thePointer) ] &do: [ aLoop eval:self ]. |
|||
Expression.Variable("ptr") |
|||
] |
|||
), |
|||
Expression.Constant($0) |
|||
#method get = theArray@thePointer. |
|||
), |
|||
} |
|||
CodeblockExpression.new(_tape.Value)); |
|||
// --- LoopInterpreter --- |
|||
_tape := _brackets.pop(); |
|||
_tape.append(loop) |
|||
#class LoopInterpreter |
|||
} |
|||
{ |
|||
#field theLoopBody. |
|||
#field theTape. |
|||
input() |
|||
#constructor new &tape:aTape |
|||
{ |
|||
_tape.append( |
|||
Expression.MessageCall( |
|||
new Message("setAt[3]"), |
|||
] |
|||
Expression.Variable("tape"), |
|||
Expression.Variable("ptr"), |
|||
Expression.MessageCall( |
|||
new Message("readChar[1]"), |
|||
Expression.Constant(console) |
|||
) |
|||
) |
|||
) |
|||
} |
|||
output() |
|||
#method bf_tape = theTape bf_tape. |
|||
{ |
|||
_tape.append( |
|||
Expression.MessageCall( |
|||
[ |
|||
new Message("write[2]"), |
|||
Expression.Constant(console), |
|||
] |
|||
Expression.MessageCall( |
|||
new Message("at[2]"), |
|||
Expression.Variable("tape"), |
|||
Expression.Variable("ptr") |
|||
) |
|||
) |
|||
) |
|||
} |
|||
next() |
|||
{ |
|||
_tape.append( |
|||
Expression.Assigning( |
|||
] |
|||
"ptr", |
|||
Expression.MessageCall( |
|||
new Message("add[2]"), |
|||
Expression.Variable("ptr"), |
|||
Expression.Constant(1)))) |
|||
} |
|||
previous() |
|||
{ |
|||
_tape.append( |
|||
Expression.Assigning( |
|||
] |
|||
"ptr", |
|||
Expression.MessageCall( |
|||
#method previous |
|||
new Message("subtract[2]"), |
|||
[ |
|||
Expression.Variable("ptr"), |
|||
Expression.Constant(1)))) |
|||
] |
|||
} |
|||
increase() |
|||
{ |
|||
_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("add[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) |
|||
) |
|||
) |
|||
)); |
|||
} |
|||
decrease() |
|||
{ |
|||
_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) |
|||
) |
|||
) |
|||
)); |
|||
} |
|||
compiled() |
|||
#method repeatUntil |
|||
{ |
|||
var program := DynamicSingleton.load( |
|||
theTape run: aTape [ interpreter'Interpreter new:aTape eval:theLoopBody ]. |
|||
Expression.Method( |
|||
"eval", |
|||
CodeblockExpression.new(_tape.Value), |
|||
] |
|||
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 &literal:aLiteral |
|||
[ |
|||
control foreach:aLiteral &do:$self. |
|||
] |
|||
console.writeLine(bf_program); |
|||
#method eval &char:aChar |
|||
[ |
|||
aChar => |
|||
">" ? [ theTape next ] |
|||
"<" ? [ theTape previous ] |
|||
"+" ? [ theTape append ] |
|||
"-" ? [ theTape reduce ] |
|||
"." ? [ theTape output. ] |
|||
"," ? [ theTape input. ] |
|||
"[" ? [ theTape := LoopInterpreter new &tape:theTape. ] |
|||
"]" ? [ theTape := theTape repeatUntil. ]. |
|||
] |
|||
} |
|||
bfProgram(bfTape) |
|||
// --- Program --- |
|||
}</syntaxhighlight> |
|||
The grammar: |
|||
<syntaxhighlight lang="elena">[[ |
|||
#grammar build |
|||
#grammar cf |
|||
#define start ::= |
|||
#symbol program = |
|||
<= |
|||
[ |
|||
system'dynamic'DynamicTape ( |
|||
('program'arguments length == 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:(BFTape new &length:1024)). |
|||
].</lang> |
|||
#define start ::= $eof; |
|||
#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> |
Latest revision as of 10:41, 25 January 2024
ELENA 6.x:
import system'collections;
import system'routines;
import system'dynamic'expressions;
import extensions;
import extensions'scripting;
const bf_program = "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.";
class TapeAssembler
{
Stack _brackets;
List<Expression> _tape;
constructor()
{
_brackets := new Stack();
_tape := new List<Expression>();
_tape.append(Expression.DeclareAndAssigning(
"ptr",
Expression.Constant(0)));
}
constructor load(assembly_program)
{
assembly_program(self)
}
open()
{
_brackets.push(_tape);
_tape := 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)
),
CodeblockExpression.new(_tape.Value));
_tape := _brackets.pop();
_tape.append(loop)
}
input()
{
_tape.append(
Expression.MessageCall(
new Message("setAt[3]"),
Expression.Variable("tape"),
Expression.Variable("ptr"),
Expression.MessageCall(
new Message("readChar[1]"),
Expression.Constant(console)
)
)
)
}
output()
{
_tape.append(
Expression.MessageCall(
new Message("write[2]"),
Expression.Constant(console),
Expression.MessageCall(
new Message("at[2]"),
Expression.Variable("tape"),
Expression.Variable("ptr")
)
)
)
}
next()
{
_tape.append(
Expression.Assigning(
"ptr",
Expression.MessageCall(
new Message("add[2]"),
Expression.Variable("ptr"),
Expression.Constant(1))))
}
previous()
{
_tape.append(
Expression.Assigning(
"ptr",
Expression.MessageCall(
new Message("subtract[2]"),
Expression.Variable("ptr"),
Expression.Constant(1))))
}
increase()
{
_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("add[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)
)
)
));
}
decrease()
{
_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)
)
)
));
}
compiled()
{
var program := DynamicSingleton.load(
Expression.Method(
"eval",
CodeblockExpression.new(_tape.Value),
ScopeIdentifier.Variable("tape"))
).compile();
^(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);
console.writeLine(bf_program);
bfProgram(bfTape)
}
The grammar:
[[
#grammar build
#grammar cf
#define start ::=
<=
system'dynamic'DynamicTape (
system'dynamic'AllocFunction ( "1" )
system'dynamic'LocalFunction ( "2" ) => command commands
<= ) =>;
#define start ::= $eof;
#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;
]]
- Output:
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. Hello World!