Esempio n. 1
0
        private bool Call(RhoAstNode node)
        {
            var children = node.Children;
            var args     = children[1].Children;
            var name     = children[0];

            foreach (var a in args.ToList())
            {
                Generate(a);
            }

            Generate(name);

            // TODO: add Replace/Suspend/Resume to children
            if (children.Count > 2 && children[2].Token.Type == ERhoToken.Replace)
            {
                Append(EOperation.Replace);
            }
            else
            {
                Append(EOperation.Suspend);
            }

            return(true);
        }
Esempio n. 2
0
        private bool Assign(RhoAstNode node)
        {
            var ch = node.Children;

            Generate(ch[0]);    // the r-value

            switch (ch[1].Type)
            {
            case ERhoAst.TokenType:
                switch (ch[1].Token.Type)
                {
                case ERhoToken.Ident:
                    return(AppendQuoted(ch[1]) && Append(EOperation.Assign));
                }
                break;

            case ERhoAst.GetMember:
                ch = ch[1].Children;
                var subject = ch[0];
                var member  = ch[1];

                AppendQuoted(member);
                Generate(subject);

                return(Append(EOperation.SetMember));
            }

            return(false);
        }
Esempio n. 3
0
        private bool BinaryOp(RhoAstNode node, EOperation op)
        {
            Generate(node.GetChild(0));
            Generate(node.GetChild(1));

            return(Append(op));
        }
Esempio n. 4
0
        private bool GetMember(RhoAstNode node)
        {
            var ch      = node.Children;
            var subject = ch[0];
            var member  = ch[1];

            AppendQuoted(member);
            Generate(subject);

            return(Append(EOperation.GetMember));
        }
Esempio n. 5
0
        private bool PiSlice(RhoAstNode rhoNode)
        {
            if (!(rhoNode.Value is PiAstNode piNode))
            {
                return(InternalFail("PiAstNode type expected"));
            }

            // TODO: store a private _piTranslator that is re-used
            return(new PiTranslator(_reg).TranslateNode(piNode, Top().Code) ||
                   Fail("Couldn't translate pi"));
        }
Esempio n. 6
0
        private bool GenerateChildren(RhoAstNode node)
        {
            foreach (var st in node.Children)
            {
                if (!Generate(st))
                {
                    return(InternalFail($"Failed to generate code for '{st}' from {node}"));
                }
            }

            return(true);
        }
Esempio n. 7
0
        /// <summary>
        /// Generate executable pi-code from given node.
        /// </summary>
        private bool Generate(RhoAstNode node)
        {
            if (node == null)
            {
                return(InternalFail("Unexpected empty RhoAstNode"));
            }

            switch (node.Type)
            {
            case ERhoAst.Suspend:
                return(Append(EOperation.Suspend));

            case ERhoAst.Pathname:
                return(Token(node));

            case ERhoAst.Assignment:
                Generate(node.GetChild(0));
                AppendQuoted(node.GetChild(1));
                return(Append(EOperation.Store));

            case ERhoAst.IndexOp:
                return(BinaryOp(node, EOperation.At));

            case ERhoAst.Call:
                return(Call(node));

            case ERhoAst.GetMember:
                return(GetMember(node));

            case ERhoAst.Conditional:
                return(If(node));

            case ERhoAst.Block:
                return(PushNew() && Block(node) && Append(Pop()));

            case ERhoAst.List:
                return(List(node));

            case ERhoAst.For:
                return(For(node));

            case ERhoAst.Program:
                return(Block(node));

            default:
                return(Token(node));
            }
        }
Esempio n. 8
0
        private bool For(RhoAstNode node)
        {
            var ch = node.Children;

            if (ch.Count == 3)
            {
                // for (a in b) ...
                AppendQuoted(ch[0]);
                Generate(ch[1]);
                Generate(ch[2]);
                return(Append(EOperation.ForEachIn));
            }

            // for (a = 0; a < 10; ++a) ...
            Generate(ch[0]);
            Generate(ch[1]);
            Generate(ch[2]);
            Generate(ch[3]);
            return(Append(EOperation.ForLoop));
        }
Esempio n. 9
0
        private bool If(RhoAstNode node)
        {
            var ch        = node.Children;
            var test      = ch[0];
            var thenBlock = ch[1];
            var elseBlock = ch.Count > 2 ? ch[2] : null;
            var hasElse   = elseBlock != null;

            Generate(thenBlock);
            if (hasElse)
            {
                Generate(elseBlock);
            }

            Generate(test);
            Append(hasElse ? EOperation.IfElse : EOperation.If);

            // TODO: Allow for if! and if... as well as if&
            return(Append(EOperation.Suspend));
        }
Esempio n. 10
0
        private bool Function(RhoAstNode node)
        {
            var ch    = node.Children;
            var args  = ch[1].Children;
            var block = ch[2].Children;

            PushNew();
            foreach (var obj in block)
            {
                Generate(obj);
            }

            var cont = Pop();

            foreach (var arg in args)
            {
                cont.AddArg(arg.Token.Text);
            }

            return(Append(cont));
        }
Esempio n. 11
0
 private bool AppendChildOp(RhoAstNode node, EOperation op)
 => Generate(node.GetChild(0)) && Append(op);
Esempio n. 12
0
 private bool Block(RhoAstNode node)
 => GenerateChildren(node);
Esempio n. 13
0
 private bool List(RhoAstNode node)
 => PushNew() && GenerateChildren(node) && Append(Pop().Code);
Esempio n. 14
0
 private bool AppendQuoted(RhoAstNode node)
 => Append(new Label(node.Text, true));
Esempio n. 15
0
 private static bool While(RhoAstNode node)
 => throw new NotImplementedException("while loops");
Esempio n. 16
0
        /// <summary>
        /// Translate given node into pi-code.
        /// </summary>
        private bool Token(RhoAstNode node)
        {
            switch (node.RhoToken.Type)
            {
            case ERhoToken.New:
                return(GenNew(node));

            case ERhoToken.Assign:
                return(Assign(node));

            case ERhoToken.Fun:
            case ERhoToken.Class:
                return(Function(node));

            case ERhoToken.Assert:
                return(AppendChildOp(node, EOperation.Assert));

            case ERhoToken.If:
                return(If(node));

            case ERhoToken.Write:
                return(AppendChildOp(node, EOperation.Write));

            case ERhoToken.WriteLine:
                return(AppendChildOp(node, EOperation.WriteLine));

            case ERhoToken.OpenParan:
                return(node.Children.All(Generate));

            case ERhoToken.Not:
                return(AppendChildOp(node, EOperation.Not));

            case ERhoToken.True:
                return(Append(true));

            case ERhoToken.False:
                return(Append(false));

            case ERhoToken.While:
                return(While(node));

            case ERhoToken.DivAssign:
                return(BinaryOp(node, EOperation.DivEquals));

            case ERhoToken.MulAssign:
                return(BinaryOp(node, EOperation.MulEquals));

            case ERhoToken.MinusAssign:
                return(BinaryOp(node, EOperation.MinusEquals));

            case ERhoToken.PlusAssign:
                return(BinaryOp(node, EOperation.PlusEquals));

            case ERhoToken.Retrieve:
                return(Append(EOperation.Retrieve));

            case ERhoToken.Self:
                return(Append(EOperation.Self));

            case ERhoToken.NotEquiv:
                return(BinaryOp(node, EOperation.NotEquiv));

            case ERhoToken.Equiv:
                return(BinaryOp(node, EOperation.Equiv));

            case ERhoToken.Less:
                return(BinaryOp(node, EOperation.Less));

            case ERhoToken.Greater:
                return(BinaryOp(node, EOperation.Greater));

            case ERhoToken.GreaterEquiv:
                return(BinaryOp(node, EOperation.GreaterOrEquiv));

            case ERhoToken.LessEquiv:
                return(BinaryOp(node, EOperation.LessOrEquiv));

            case ERhoToken.Minus:
                return(BinaryOp(node, EOperation.Minus));

            case ERhoToken.Plus:
                return(BinaryOp(node, EOperation.Plus));

            case ERhoToken.Multiply:
                return(BinaryOp(node, EOperation.Multiply));

            case ERhoToken.Divide:
                return(BinaryOp(node, EOperation.Divide));

            case ERhoToken.Or:
                return(BinaryOp(node, EOperation.LogicalOr));

            case ERhoToken.And:
                return(BinaryOp(node, EOperation.LogicalAnd));

            case ERhoToken.Xor:
                return(BinaryOp(node, EOperation.LogicalXor));

            case ERhoToken.Int:
                return(Append(int.Parse(node.Text)));

            case ERhoToken.Float:
                return(Append(float.Parse(node.Text)));

            case ERhoToken.String:
                return(Append(node.Text));

            case ERhoToken.Ident:
                return(Append(new Label(node.Text)));

            case ERhoToken.Pathname:
                throw new NotImplementedException("Translate pathname");

            case ERhoToken.Yield:
                return(Append(EOperation.Suspend));

            case ERhoToken.Return:
                // DO NOT REFACTOR INTO LINQ.
                // In fact, don't use Linq anywhere in this library.
                foreach (var child in node.Children)
                {
                    if (!Generate(child))
                    {
                        return(false);
                    }
                }
                return(Append(EOperation.Resume));

            case ERhoToken.For:
                return(For(node));

            case ERhoToken.PiSlice:
                return(PiSlice(node));
            }

            return(Fail($"Unsupported RhoToken {node.Token.Type}"));
        }
Esempio n. 17
0
 private bool GenNew(RhoAstNode node)
 {
     Append(new Label(node.Children[0].Text, true));
     return(Append(EOperation.New));
 }