public static Parser.Variable sum(Parser.Variable left, Parser.Variable right)
        {
            left  = GetVariableValue(left);
            right = GetVariableValue(right);

            if (left.type == "string" || right.type == "string")
            {
                return(new Parser.Variable(left.value + right.value, "string"));
            }

            if (left.IsNaN() || right.IsNaN())
            {
                return(new Parser.Variable("NaN", "number"));
            }

            if (!left.CanBeConvertedTo("number") || !right.CanBeConvertedTo("number"))
            {
                return(new Parser.Variable("NaN", "number"));
            }

            left  = left.ConvertTo("number");
            right = right.ConvertTo("number");

            return(new Parser.Variable(Parse(left.value) + Parse(right.value)));
        }
Exemple #2
0
        public static Parser.Variable RegisterObject(string name)
        {
            var value = new Parser.Variable("", "object");

            Interpreter.SetVariable(Interpreter.variables, new Parser.Variable(name, "variable"), "object", value);
            value.constant = true;
            return(value);
        }
 public static Parser.Variable GetVariableValue(Parser.Variable var)
 {
     if (var.type == "variable")
     {
         var gvar = Interpreter.GetVariableByName(Interpreter.variables, var.value);
         if (gvar == null)
         {
             return(new Parser.Variable("undefined", "undefined"));
         }
         return(new Parser.Variable(gvar.value.value, gvar.value.type));
     }
     return(var);
 }
        public static Parser.Variable GetVariableByName(Parser.Variable prototype, Parser.Variable right)
        {
            foreach (var field in prototype.fields)
            {
                if (field.Key.IsDeepEqualTo(right))
                {
                    return(field.Value as Parser.Variable ?? new Parser.Variable());
                }
            }

            if (prototype.prototype != null)
            {
                return(GetVariableByName(prototype.prototype, right));
            }

            return(new Parser.Variable());
        }
        internal static Parser.Variable res(Parser.Variable left, Parser.Variable right)
        {
            left  = GetVariableValue(left);
            right = GetVariableValue(right);

            if (left.IsNaN() || right.IsNaN())
            {
                return(new Parser.Variable("NaN", "number"));
            }
            if (!left.CanBeConvertedTo("number") || !right.CanBeConvertedTo("number"))
            {
                return(new Parser.Variable("NaN", "number"));
            }

            left  = left.ConvertTo("number");
            right = right.ConvertTo("number");

            return(new Parser.Variable(Parse(left.value) % Parse(right.value)));
        }
        public static Parser.Variable div(Parser.Variable left, Parser.Variable right)
        {
            left  = GetVariableValue(left);
            right = GetVariableValue(right);

            if (left.IsNaN() || right.IsNaN())
            {
                return(new Parser.Variable("NaN", "number"));
            }
            if (!left.CanBeConvertedTo("number") || !right.CanBeConvertedTo("number"))
            {
                return(new Parser.Variable("NaN", "number"));
            }

            left  = left.ConvertTo("number");
            right = right.ConvertTo("number");

            if (Parse(right.value) == 0)
            {
                return(new Parser.Variable(0));
            }

            return(new Parser.Variable(Parse(left.value) / Parse(right.value)));
        }
        public static void SetVariable(List <Variable> vars, Node variable, string type, Parser.Variable value)
        {
            var normal = variable as Parser.Variable;

            if (normal != null)
            {
                SetVariable(vars, variable.value, type, value.Clone());
                return;
            }

            var varop = variable as Operation;

            if (varop != null)
            {
                var left = GetVariableByName(vars, varop.left);
                if (left.constant)
                {
                    ShowError("left isde of exppression is constant");
                    return;
                }

                if (left.type == "undefined")
                {
                    ShowError("Can not read property of undefined");
                }
                else
                {
                    var  right = CalculateTree(varop.right, vars);
                    bool found = false;

                    if (right.value == "prototype")
                    {
                        if (value.type == "object")
                        {
                            left.prototype = value;
                        }
                        else
                        {
                            ShowError($"Prototype need to be object, but {value.type} were given");
                        }
                        return;
                    }

                    foreach (var key in left.fields)
                    {
                        if (key.Key.IsDeepEqualTo(right))
                        {
                            (key.Value as Parser.Variable)?.Set(value.Clone());
                            found = true;
                        }
                    }

                    if (!found)
                    {
                        left.fields.Add(right.Clone(), value.Clone());
                    }
                }
            }
        }
        public static void SetVariable(List <Variable> vars, string name, string type, Parser.Variable value)
        {
            for (var now = vars.Count - 1; now != -1; --now)
            {
                if (vars[now].name == name)
                {
                    if (vars[now].value.constant)
                    {
                        ShowError("left isde of exppression is constant");
                        return;
                    }

                    vars[now].value      = value.Clone();
                    vars[now].value.type = type;
                    return;
                }
            }

            vars.Add(new Variable(name, type, value));
        }
        private static Parser.Variable ExecuteFunction(FunctionNode func, List <Parser.Variable> args, Parser.Variable caller)
        {
            ++depth;

            Parser.Variable var;

            var context = new List <Variable>(10);

            for (int now = 0; now < func.parameters.Count; ++now)
            {
                if (args.Count >= now)
                {
                    context.Add(new Variable(func.parameters[now], args[now].type, args[now]));
                }
            }
            context.Add(new Variable("this", caller.type, caller));

            foreach (Node line in func.code.code)
            {
                var = CalculateTree(line, context);
                if (isReturn)
                {
                    isReturn = false;
                    --depth;
                    return(var);
                }
                if (isBreak)
                {
                    ShowError("break operator need to be placed in cycle");
                    isBreak = false;
                }
            }

            --depth;
            return(new Parser.Variable());
        }
        public static Parser.Variable CalculateTree(Node tree, List <Variable> context)
        {
            var varnode = tree as Parser.Variable;

            if (varnode != null)
            {
                Variable var = null;

                if (varnode.type != "variable")
                {
                    if (varnode.type == "functionCall")
                    {
                        Parser.Variable left = CalculateTree(varnode.expression, context);

                        Parser.Variable caller;
                        var             objectOp = varnode.expression as Operation;

                        if (objectOp == null || objectOp.op.symbol != ".")
                        {
                            caller = new Parser.Variable();
                        }
                        else
                        {
                            caller = GetVariableByName(context, objectOp.left);
                        }

                        if (left.type == "function")
                        {
                            var = new Variable("anonymous", "function", left);
                        }
                        else
                        {
                            ShowError(left.type + " is not a function");
                            return(new Parser.Variable());
                        }

                        if (varnode.args != null)
                        {
                            var func = var.value as FunctionNode;

                            var args = new List <Parser.Variable>(Math.Max(varnode.args.Count, func.parameters.Count));

                            for (int now = 0; now < args.Capacity; ++now)
                            {
                                if (now < varnode.args.Count)
                                {
                                    args.Add(CalculateTree(varnode.args[now], context));
                                }
                                else
                                {
                                    args.Add(new Parser.Variable());
                                }
                            }

                            if (func.native)
                            {
                                return(func.function(args));
                            }
                            else
                            {
                                return(ExecuteFunction(func, args, caller));
                            }
                        }

                        return(new Parser.Variable());
                    }
                    return(varnode);
                }

                var = GetVariableByName(context, varnode.value);

                if (var != null)
                {
                    return(var.value);
                }
                else
                {
                    return(new Parser.Variable());
                }
            }

            var opnode = tree as Operation;

            if (opnode != null)
            {
                Parser.Variable left = null, right = null;
                if (opnode.op.symbol != ".")
                {
                    if (opnode.op.symbol != "=")
                    {
                        left = CalculateTree(opnode.left, context);
                    }
                    right = CalculateTree(opnode.right, context);
                }

                switch (opnode.op.symbol)
                {
                case "+": return(VariableOperations.sum(left, right));

                case "-": return(VariableOperations.sub(left, right));

                case "*": return(VariableOperations.mul(left, right));

                case "/": return(VariableOperations.div(left, right));

                case "%": return(VariableOperations.res(left, right));

                case ".":
                    var lnode = opnode.left as Parser.Variable;
                    if (lnode != null && lnode.type != "function" && lnode.type != "functionCall")
                    {
                        return(GetVariableByName(context, opnode));
                    }
                    else
                    {
                        opnode = new Parser.Operation(operators[0], CalculateTree(opnode.left, context), opnode.right);
                        return(GetVariableByName(context, opnode));
                    }

                case "=":
                    if (right.fields.Count != 0)
                    {
                        var fields = new Dictionary <Parser.Variable, Parser.Node>(right.fields.Count);
                        foreach (var key in right.fields)
                        {
                            fields.Add(key.Key, CalculateTree(key.Value, context));
                        }
                        right.fields = fields;
                    }

                    SetVariable(context, opnode.left, right.type, right);

                    return(right);

                case "+=":
                    var sum = VariableOperations.sum(left, right);

                    SetVariable(context, opnode.left, sum.type, sum);

                    return(sum);

                case "-=":
                    var sub = VariableOperations.sub(left, right);

                    SetVariable(context, opnode.left, sub.type, sub);

                    return(sub);

                case "*=":
                    var mult = VariableOperations.mul(left, right);

                    SetVariable(context, opnode.left, mult.type, mult);

                    return(mult);

                case "/=":
                    var div = VariableOperations.div(left, right);

                    SetVariable(context, opnode.left, div.type, div);

                    return(div);

                case "==": return(new Parser.Variable(left.IsEqualTo(right)));

                case "!=": return(new Parser.Variable(!left.IsEqualTo(right)));

                case "===": return(new Parser.Variable(left.IsDeepEqualTo(right)));

                case "!==": return(new Parser.Variable(!left.IsDeepEqualTo(right)));

                case ">": return(new Parser.Variable(left.IsGreaterThan(right)));

                case ">=": return(new Parser.Variable(left.IsGreaterOrEqualTo(right)));

                case "<": return(new Parser.Variable(right.IsGreaterThan(left)));

                case "<=": return(new Parser.Variable(right.IsGreaterOrEqualTo(left)));

                case "&":
                case "&&":
                    return(new Parser.Variable(left.IsEqualTo(new Parser.Variable(true)) && right.IsEqualTo(new Parser.Variable(true))));

                case "|":
                case "||":
                    return(left.IsEqualTo(new Parser.Variable(true)) ? left : right);
                }
            }

            var conditionalNode = tree as ConditionalBlock;

            if (conditionalNode != null)
            {
                if (conditionalNode.type == "if")
                {
                    if (CalculateTree(conditionalNode.condition, context).IsEqualTo(new Parser.Variable(true)))
                    {
                        return(CalculateTree(conditionalNode.code, context));
                    }
                    else if (conditionalNode.oppositeCode != null)
                    {
                        return(CalculateTree(conditionalNode.oppositeCode, context));
                    }
                }

                if (conditionalNode.type == "for")
                {
                    CalculateTree(conditionalNode.init, context);

                    while (CalculateTree(conditionalNode.condition, context).IsEqualTo(new Parser.Variable(true)))
                    {
                        varnode = CalculateTree(conditionalNode.code, context);
                        if (isReturn)
                        {
                            return(varnode);
                        }
                        if (isBreak)
                        {
                            isBreak = false;
                            break;
                        }

                        CalculateTree(conditionalNode.post, context);
                    }
                }

                if (conditionalNode.type == "while")
                {
                    while (CalculateTree(conditionalNode.condition, context).IsEqualTo(new Parser.Variable(true)))
                    {
                        varnode = CalculateTree(conditionalNode.code, context);
                        if (isReturn)
                        {
                            return(varnode);
                        }
                        if (isBreak)
                        {
                            isBreak = false;
                            break;
                        }
                    }
                }

                return(new Parser.Variable());
            }

            var blocknode = tree as Block;

            if (blocknode != null)
            {
                foreach (var exp in blocknode.code)
                {
                    varnode = CalculateTree(exp, context);
                    if (isReturn)
                    {
                        return(varnode);
                    }
                    if (isBreak)
                    {
                        break;
                    }
                }
            }

            if (tree?.value == "return")
            {
                isReturn = true;
                return(CalculateTree((tree as ReturnNode).expression, context));
            }
            if (tree?.value == "break")
            {
                isBreak = true;
            }

            return(new Parser.Variable());
        }
 public Variable(string name, string type, Parser.Variable value)
 {
     this.name       = name;
     this.value      = value;
     this.value.type = type;
 }