Execute Brain****/Elena

From Rosetta Code
Revision as of 11:17, 1 September 2022 by PureFox (talk | contribs) (Fixed syntax highlighting.)

ELENA 5.0:

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

The grammar:

[[
   #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;
]]
Output:
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
Hello World!