Exemplo n.º 1
0
        public SkryptObject ExecuteExpression(Node node, ScopeContext scopeContext)
        {
            Operator op = Operator.AllOperators.Find(o => o.OperationName == node.Body || o.Operation == node.Body);

            if (op != null)
            {
                if (op.OperationName == "return")
                {
                    if (!scopeContext.subContext.InMethod)
                    {
                        engine.throwError("Can't use return operator outside method!", node.SubNodes[0].Token);
                    }

                    SkryptObject result = null;

                    if (node.SubNodes.Count == 1)
                    {
                        result = ExecuteExpression(node.SubNodes[0], scopeContext);
                    }
                    else
                    {
                        result = new Library.Native.System.Void();
                    }

                    scopeContext.subContext.ReturnObject = result;
                    return(result);
                }

                if (op.OperationName == "access")
                {
                    SkryptObject Target = ExecuteExpression(node.SubNodes[1], scopeContext);
                    SkryptObject Result = ExecuteAccess(Target, node.SubNodes[0], scopeContext).Value;
                    return(Result);
                }

                if (op.OperationName == "assign")
                {
                    SkryptObject result = ExecuteExpression(node.SubNodes[1], scopeContext);

                    if (node.SubNodes[0].SubNodes.Count == 0 && node.SubNodes[0].TokenType == "Identifier")
                    {
                        Variable Variable = getVariable(node.SubNodes[0].Body, scopeContext);

                        if (Variable != null)
                        {
                            Variable.Value = result;
                        }
                        else
                        {
                            scopeContext.Variables[node.SubNodes[0].Body] = new Variable {
                                Name  = node.SubNodes[0].Body,
                                Value = result,
                                Scope = scopeContext
                            };
                        }
                    }
                    else if (node.SubNodes[0].Body == "access")
                    {
                        SkryptObject   Target       = ExecuteExpression(node.SubNodes[0].SubNodes[1], scopeContext);
                        SkryptProperty AccessResult = ExecuteAccess(Target, node.SubNodes[0].SubNodes[0], scopeContext);

                        AccessResult.Value = result;
                    }
                    else if (node.SubNodes[0].Body == "Index")
                    {
                        ExecuteIndexSet(result, node.SubNodes[0], scopeContext);
                    }
                    else
                    {
                        engine.throwError("Left hand side needs to be a variable or property!", node.SubNodes[0].Token);
                    }

                    return(result);
                }

                if (op.Members == 2)
                {
                    SkryptObject LeftResult  = ExecuteExpression(node.SubNodes[0], scopeContext);
                    SkryptObject RightResult = ExecuteExpression(node.SubNodes[1], scopeContext);

                    dynamic Left  = Convert.ChangeType(LeftResult, LeftResult.GetType());
                    dynamic Right = Convert.ChangeType(RightResult, RightResult.GetType());

                    Operation OpLeft  = Left.GetOperation(op.OperationName, LeftResult.GetType(), RightResult.GetType(), Left.Operations);
                    Operation OpRight = Right.GetOperation(op.OperationName, LeftResult.GetType(), RightResult.GetType(), Right.Operations);

                    OperationDelegate Operation = null;

                    if (OpLeft != null)
                    {
                        Operation = OpLeft.operation;
                    }
                    else if (OpRight != null)
                    {
                        Operation = OpRight.operation;
                    }
                    else
                    {
                        engine.throwError("No such operation as " + Left.Name + " " + op.Operation + " " + Right.Name, node.SubNodes[0].Token);
                    }

                    return(Operation(new SkryptObject[] { LeftResult, RightResult }));
                }
                else if (op.Members == 1)
                {
                    SkryptObject LeftResult = ExecuteExpression(node.SubNodes[0], scopeContext);

                    dynamic Left = Convert.ChangeType(LeftResult, LeftResult.GetType());

                    Operation OpLeft = Left.GetOperation(op.OperationName, LeftResult.GetType(), null, Left.Operations);

                    OperationDelegate Operation = null;

                    if (OpLeft != null)
                    {
                        Operation = OpLeft.operation;
                    }
                    else
                    {
                        engine.throwError("No such operation as " + Left.Name + " " + op.Operation, node.SubNodes[0].Token);
                    }

                    return(Operation(new SkryptObject[] { LeftResult }));
                }
            }
            else if (node.TokenType == "ArrayLiteral")
            {
                Library.Native.System.Array array = new Library.Native.System.Array();

                for (int i = 0; i < node.SubNodes.Count; i++)
                {
                    Node subNode = node.SubNodes[i];

                    SkryptObject Result = ExecuteExpression(subNode, scopeContext);

                    if (Result.Name == "void")
                    {
                        engine.throwError("Can't add void to array!", node.SubNodes[0].Token);
                    }

                    array.value["" + i] = Result;
                }

                return(array);
            }
            else if (node.SubNodes.Count == 0)
            {
                switch (node.TokenType)
                {
                case "NumericLiteral":
                    return(new Library.Native.System.Numeric(Double.Parse(node.Body)));

                case "StringLiteral":
                    return(new Library.Native.System.String(node.Body));

                case "BooleanLiteral":
                    return(new Library.Native.System.Boolean(node.Body == "true" ? true : false));

                case "NullLiteral":
                    return(new Library.Native.System.Null());
                }
            }
            else if (node.TokenType == "FunctionLiteral")
            {
                UserMethod result = new UserMethod();
                result.Name      = "method";
                result.Signature = node.Body;
                result.BlockNode = node.SubNodes[0];
                result.CallName  = node.Body.Split('_')[0];

                foreach (Node snode in node.SubNodes[1].SubNodes)
                {
                    result.Parameters.Add(snode.Body);
                }

                return(result);
            }

            if (node.TokenType == "Identifier")
            {
                if (engine.Constants.ContainsKey(node.Body))
                {
                    return(engine.Constants[node.Body]);
                }

                Variable foundVariable = getVariable(node.Body, scopeContext);

                if (foundVariable != null)
                {
                    return(foundVariable.Value);
                }
                else
                {
                    engine.throwError("Variable '" + node.Body + "' does not exist in the current context!", node.Token);
                }
            }

            if (node.TokenType == "Index")
            {
                return(ExecuteIndex(node, scopeContext));
            }

            if (node.TokenType == "Call")
            {
                List <SkryptObject> Arguments     = new List <SkryptObject>();
                ScopeContext        methodContext = new ScopeContext {
                    ParentScope = scopeContext
                };

                foreach (Node subNode in node.SubNodes[1].SubNodes)
                {
                    SkryptObject Result = ExecuteExpression(subNode, scopeContext);

                    if (Result.Name == "void")
                    {
                        engine.throwError("Can't pass void into arguments!", node.SubNodes[0].Token);
                    }

                    Arguments.Add(Result);
                }

                SkryptObject Method = ExecuteExpression(node.SubNodes[0].SubNodes[0], scopeContext);

                if (Method.GetType() != typeof(SharpMethod))
                {
                    var Find = Method.Properties.Find((x) => x.Name == "Constructor");

                    if (Find != null)
                    {
                        Method = Find.Value;
                    }
                }

                if (Method.GetType() == typeof(UserMethod))
                {
                    UserMethod method = (UserMethod)Method;

                    for (int i = 0; i < method.Parameters.Count; i++)
                    {
                        string       parName = method.Parameters[i];
                        SkryptObject input;

                        if (i < Arguments.Count)
                        {
                            input = Arguments[i];
                        }
                        else
                        {
                            input = new Library.Native.System.Null();
                        }

                        methodContext.Variables[parName] = new Variable {
                            Name  = parName,
                            Value = input,
                            Scope = methodContext
                        };
                    }

                    SkryptObject MethodResult = method.Execute(engine, Arguments.ToArray(), methodContext);

                    return(MethodResult);
                }
                else if (Method.GetType() == typeof(SharpMethod))
                {
                    SkryptObject MethodResult = ((SharpMethod)Method).Execute(engine, Arguments.ToArray(), methodContext);

                    return(MethodResult);
                }
                else
                {
                    engine.throwError("Cannot call value, as it is not a function!", node.SubNodes[0].SubNodes[0].Token);
                }
            }

            return(null);
        }
Exemplo n.º 2
0
        /// <summary>
        ///     Allows you to invoke a function from the engine's global scope.
        /// </summary>
        public SkryptObject Invoke(string name, params object[] arguments)
        {
            var parameters    = new SkryptObject[arguments.Length];
            var foundMethod   = GetVariable(name, _engine.GlobalScope).Value;
            var input         = new List <SkryptObject>();
            var methodContext = new ScopeContext {
                ParentScope = _engine.GlobalScope
            };

            for (int i = 0; i < arguments.Length; i++)
            {
                object arg = arguments[i];

                if (arg.GetType() == typeof(int) || arg.GetType() == typeof(float) || arg.GetType() == typeof(double))
                {
                    parameters[i] = new Library.Native.System.Numeric(Convert.ToDouble(arg));
                }
                else if (arg.GetType() == typeof(string))
                {
                    parameters[i] = new Library.Native.System.String((string)arg);
                }
                else if (arg.GetType() == typeof(bool))
                {
                    parameters[i] = new Library.Native.System.Boolean((bool)arg);
                }
                else if (arg == null)
                {
                    parameters[i] = new Library.Native.System.Null();
                }

                parameters[i].GetPropertiesFrom(GetType(((SkryptType)parameters[i]).TypeName, _engine.GlobalScope));

                input.Add(parameters[i]);
            }

            ScopeContext methodScopeResult = null;

            if (foundMethod.GetType() == typeof(UserFunction))
            {
                UserFunction method = (UserFunction)foundMethod;

                for (var i = 0; i < method.Parameters.Count; i++)
                {
                    var          parName = method.Parameters[i];
                    SkryptObject inp;

                    inp = i < input.Count ? input[i] : new Library.Native.System.Null();

                    methodContext.Variables[parName] = new Variable {
                        Name  = parName,
                        Value = inp,
                        Scope = methodContext
                    };
                }

                methodScopeResult = method.Execute(_engine, null, input.ToArray(), methodContext);
            }
            else if (foundMethod.GetType() == typeof(SharpMethod))
            {
                methodScopeResult = ((SharpMethod)foundMethod).Execute(_engine, null, input.ToArray(), methodContext);
            }
            else
            {
                _engine.ThrowError("Cannot call value, as it is not a function!");
            }

            return(methodScopeResult.ReturnObject);
        }