Exemple #1
0
        ParseResult monomod()
        {
            ParseResult res = new ParseResult();
            PNode       node;

            if (current.type == TokenType.INC || current.type == TokenType.DEC)
            {
                LToken op = current;
                res.Register(Next());
                node = res.Register(call(newer()));
                if (res.error != null)
                {
                    return(res);
                }
                if (op.type == TokenType.INC)
                {
                    op.type = TokenType.ADD;
                }
                else
                {
                    op.type = TokenType.SUB;
                }
                PNode exp = PNode.GetBinOP(node, op, new PNode(new LToken(TokenType.VALUE, new Value(1), op.position)));

                if (node.TYPE == "VarGet")
                {
                    return(res.Succes(new PNode("VarAsign", node.val, exp)));
                }

                if (!res.isInnnerCall)
                {
                    return(res.Failure(new InvalidSyntaxError(op.position, "Increment and decrement operators can only edit immediate variables")));
                }

                List <PNode> pns = new List <PNode>(node.PNodes);
                pns.RemoveAt(0);
                pns.Add(exp);
                return(res.Succes(PNode.GetCall("InnerAsign", node.PNodes[0], pns)));
            }
            node = res.Register(call(newer()));
            if (current.type == TokenType.INC || current.type == TokenType.DEC)
            {
                LToken op = current;
                LToken ed = current.Copy(false);
                if (!res.isInnnerCall && node.TYPE != "VarGet")
                {
                    return(res.Failure(new InvalidSyntaxError(op.position, "Increment and decrement operators can only edit immediate variables")));
                }
                res.Register(Next());

                if (op.type == TokenType.INC)
                {
                    ed.type = TokenType.ADD;
                }
                else
                {
                    ed.type = TokenType.SUB;
                }
                PNode exp = PNode.GetBinOP(node, ed, new PNode(new LToken(TokenType.VALUE, new Value(1), op.position)));

                if (node.TYPE == "VarGet")
                {
                    exp = new PNode("VarAsign", node.val, exp);
                }
                else
                {
                    List <PNode> pns = new List <PNode>(node.PNodes);
                    pns.RemoveAt(0);
                    pns.Add(exp);
                    exp = PNode.GetCall("InnerAsign", node.PNodes[0], pns);
                }
                return(res.Succes(new PNode("UnarOp", new List <PNode>()
                {
                    node, exp
                }, op)));
            }
            return(res.Succes(node, true));
        }
Exemple #2
0
        static public RTResult Visit(PNode node, Context context)
        {
            RTResult res = new RTResult();
            LToken   Ot;
            Function f;
            Value    v;

            switch (node.TYPE)
            {
            case "VALUE":
                return(res.Succes(node.val.SetContext(context)));

            case "VarAsign":
            case "PublicVarMake":
            case "PublicPrototype":
            case "VarMake":
                Ot = res.Register(VisitVarAsign(node, context));
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(Ot));

            case "VarGet":
                f = context.GetFunction();
                if (f != null)
                {
                    if (f.InnerValues.ContainsKey(node.val.value.text))
                    {
                        return(res.Succes(f.InnerValues[node.val.value.text]));
                    }
                }
                if (!context.varlist.ContainsKey(node.val.value.text))
                {
                    return(res.Failure(new RuntimeError(node.val.position, $"{node.val.value.text} is not defined", context)));
                }
                return(res.Succes(context.varlist[node.val.value.text]));

            case "BinOp":
                Ot = res.Register(VisitBinOp(node, context));
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(Ot));

            case "UnarOp":
                Ot = res.Register(VisitUnarOp(node, context));
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(Ot));

            case "PublicFuncDeff":
                f = new Function(node.val, node.right, node.LTokens.ConvertAll(x => x.value.text), context);
                Function CF = context.GetFunction();
                f.InnerValues.parent = CF.InnerValues;
                CF.InnerValues[node.val.value.text] = new LToken(TokenType.VALUE, new Value(f), node.val.position).SetContext(context);;
                return(res.Succes(new LToken(TokenType.VALUE, new Value(f), node.val.position).SetContext(context)));

            case "FuncDef":
                f = new Function(node.val, node.right, node.LTokens.ConvertAll(x => x.value.text), context);
                if (node.val.value != null)
                {
                    context.varlist[node.val.value.text] = new LToken(TokenType.VALUE, new Value(f), node.val.position).SetContext(context);
                }
                return(res.Succes(new LToken(TokenType.VALUE, new Value(f), node.val.position).SetContext(context)));

            case "CallFunc":
                Ot = res.Register(VisitCall(node, context));
                if (res.error != null)
                {
                    return(res);
                }
                Ot.type = TokenType.VALUE;
                return(res.Succes(Ot));

            case "MakeList":
                List <Value> values = new List <Value>();
                foreach (PNode n in node.PNodes)
                {
                    values.Add(res.Register(Visit(n, context)).value);
                    if (res.error != null)
                    {
                        return(res);
                    }
                }
                return(res.Succes(new LToken(TokenType.VALUE, new Value(values), node.val.position).SetContext(context)));

            case "Prototype":
                Ot = res.Register(Visit(node.PNodes[0], context));
                if (res.error != null)
                {
                    return(res);
                }
                if (Ot.value.type != "FUNC")
                {
                    return(res.Failure(new RuntimeError(Ot.position, "Value to prototype into has to be a function.", context)));
                }
                if (Compiler.forbidden.Contains(Ot.value.function.name.value.text))
                {
                    return(res.Failure(new RuntimeError(node.val.position, $"{Ot.value.function.name.value.text} is a predefined, unmutable variable", context)));
                }
                Ot.value.function.body.PNodes.Add(new PNode("PublicPrototype", node.val, node.PNodes[1]));
                return(res.Succes(Ot));

            case "GetProperty":
                Ot = res.Register(Visit(node.right, context));
                if (res.error != null)
                {
                    return(res);
                }
                v  = Ot.value.GetProperty(node.val.value.text);
                Ot = new LToken(TokenType.VALUE, v, Ot.position);
                return(res.Succes(Ot.SetContext(context)));

            case "PropertyAsign":
                Ot = res.Register(Visit(node.PNodes[1], context));
                v  = res.Register(Visit(node.PNodes[0].right, context)).value.SetProperty(node.PNodes[0].val.value.text, Ot);
                Ot = new LToken(TokenType.VALUE, v, Ot.position);
                return(res.Succes(Ot.SetContext(context)));

            case "CallProperty":
                LToken toCall = res.Register(Visit(node.PNodes[0], context));
                if (res.error != null)
                {
                    return(res);
                }
                List <LToken> args = new List <LToken>();
                for (int n = 1; n < node.PNodes.Count; n++)
                {
                    args.Add(res.Register(Visit(node.PNodes[n], context)));
                    if (res.error != null)
                    {
                        return(res);
                    }
                }
                LToken t = res.Register(toCall.value.CallProperty(node.val.value.text, args, context, toCall.position));
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(t.SetContext(context)));

            case "GetInner":
                Ot = res.Register(VisitGetInner(node, context));
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(Ot));

            case "InnerAsign":
                Ot = res.Register(VisitSetInner(node, context));
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(Ot));

            case "IF":
            {
                Context ctx = BracketContext(context);
                Ot = res.Register(Visit(node.PNodes[0], ctx));
                if (res.error != null)
                {
                    return(res);
                }
                if (Ot.value.boolean)
                {
                    Ot = res.Register(Visit(node.PNodes[1], ctx));
                    if (res.error != null)
                    {
                        return(res);
                    }
                    if ((Ot.type & (TokenType.BREAK | TokenType.CONTINUE | TokenType.RETURN)) != 0)
                    {
                        return(res.Succes(Ot));
                    }
                }
                else if (node.PNodes.Count == 3)
                {
                    Ot = res.Register(Visit(node.PNodes[2], ctx));
                    if (res.error != null)
                    {
                        return(res);
                    }
                    if ((Ot.type & (TokenType.BREAK | TokenType.CONTINUE | TokenType.RETURN)) != 0)
                    {
                        return(res.Succes(Ot));
                    }
                }
            }
                return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, node.val.position)));

            case "WHILE":
            {
                Context ctx = BracketContext(context);
                Ot = res.Register(Visit(node.PNodes[0], ctx));
                if (res.error != null)
                {
                    return(res);
                }
                while (Ot.value.boolean)
                {
                    Ot = res.Register(Visit(node.PNodes[1], ctx));
                    if (res.error != null)
                    {
                        return(res);
                    }
                    if (Ot.type == TokenType.BREAK)
                    {
                        break;
                    }
                    if (Ot.type == TokenType.RETURN)
                    {
                        return(res.Succes(Ot));
                    }
                    ctx = BracketContext(context);
                    Ot  = res.Register(Visit(node.PNodes[0], ctx));
                    if (res.error != null)
                    {
                        return(res);
                    }
                }
            }
                return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, node.val.position)));

            case "FOR":
            {
                Context CON = BracketContext(context);
                res.Register(Visit(node.PNodes[0], CON));
                Ot = res.Register(Visit(node.PNodes[1], CON));
                if (res.error != null)
                {
                    return(res);
                }
                Context ctx = BracketContext(CON);
                while (Ot.value.boolean)
                {
                    Ot = res.Register(Visit(node.PNodes[3], ctx));
                    if (res.error != null)
                    {
                        return(res);
                    }
                    if (Ot.type == TokenType.BREAK)
                    {
                        break;
                    }
                    if (Ot.type == TokenType.RETURN)
                    {
                        return(res.Succes(Ot));
                    }
                    ctx = BracketContext(CON);
                    res.Register(Visit(node.PNodes[2], ctx));
                    if (res.error != null)
                    {
                        return(res);
                    }
                    Ot = res.Register(Visit(node.PNodes[1], ctx));
                    if (res.error != null)
                    {
                        return(res);
                    }
                }
                return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, node.val.position)));
            }

            case "MultExpr":
                return(VisitBody(node, BracketContext(context)));

            case "Body":
                return(VisitBody(node, context));

            case "NEW":
                Ot = res.Register(Visit(node.right, context));
                if (res.error != null)
                {
                    return(res);
                }
                if (Ot.value.type != "FUNC")
                {
                    return(res.Failure(new RuntimeError(node.val.position, "'new' copy can be only aplied to functions.", context)));
                }
                return(res.Succes(Ot.Copy(false)));

            case "RETURN":
                Ot = res.Register(Visit(node.right, context));
                if (res.error != null)
                {
                    return(res);
                }
                Ot.type = TokenType.RETURN;
                return(res.Succes(Ot));

            case "BREAK":
                return(res.Succes(new LToken(TokenType.BREAK, Value.NULL, node.val.position)));

            case "CONTINUE":
                return(res.Succes(new LToken(TokenType.CONTINUE, Value.NULL, node.val.position)));

            case "SUPER":
                f = context.GetFunction();
                if (f == null)
                {
                    return(res.Failure(new RuntimeError(node.val.position, "Super can only be called inside a function.", context)));
                }
                Ot = res.Register(Visit(node.right, context));
                if (res.error != null)
                {
                    return(res);
                }
                if (Ot.value.type != "FUNC")
                {
                    return(res.Failure(new RuntimeError(Ot.position, "Function can only accept another function as a Super.", context)));
                }
                f.InnerValues.Merge(Ot.value.function.InnerValues, f);
                return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, node.val.position)));

            case "RUN":
                Ot = res.Register(Visit(node.right, context));
                if (res.error != null)
                {
                    return(res);
                }
                if (Ot.value.type != "STRING")
                {
                    return(res.Failure(new RuntimeError(node.val.position, "Run statement requires a string argument.", context)));
                }
                if (!System.IO.File.Exists(Ot.value.text))
                {
                    return(res.Failure(new RuntimeError(Ot.position, $"File {Ot.value.text} does not exist.", context)));
                }
                Ot = res.Register(Compiler.Run(System.IO.File.ReadAllText(Ot.value.text), new System.IO.FileInfo(Ot.value.text).Name));
                if (res.error != null)
                {
                    return(res);
                }
                return(res.Succes(Ot));

            default:
                throw new Exception("Visit not defined");
            }
        }