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