Example #1
0
        /// <summary>
        ///     Executes a while statement node.
        /// </summary>
        public void ExecuteWhileStatement(Node node, ScopeContext scopeContext)
        {
            // Loop until an exit condition is reached.
            while (true)
            {
                var conditionResult = CheckCondition(node.Nodes[0].Nodes[0], scopeContext);

                // Exit when the condition is false.
                if (!conditionResult)
                {
                    break;
                }

                var scope = ExecuteBlock(node.Nodes[1], scopeContext, ScopeProperties.InLoop);

                // Exit when a break expression was reached.
                if ((scope.Properties & ScopeProperties.BrokeLoop) != 0)
                {
                    break;
                }

                if (scope.ReturnObject != null)
                {
                    scopeContext.ReturnObject = scope.ReturnObject;
                    break;
                }
            }
        }
Example #2
0
        /// <summary>
        ///     Executes an index opeation.
        /// </summary>
        public SkryptObject ExecuteIndex(IndexNode node, ScopeContext scopeContext)
        {
            var arguments = new List <SkryptObject>();

            foreach (var subNode in node.Arguments)
            {
                var result = ExecuteExpression(subNode, scopeContext);

                arguments.Add(result);
            }

            var Object = ExecuteExpression(node.Getter, scopeContext);

            // Dynamically change type so we can get it's actual operations.
            dynamic left = Convert.ChangeType(Object, Object.GetType());

            Operation opLeft = SkryptObject.GetOperation(Operators.Index, Object.GetType(), arguments[0].GetType(), left.Operations);

            OperationDelegate operation = null;

            if (opLeft != null)
            {
                operation = opLeft.OperationDelegate;
            }
            else
            {
                _engine.ThrowError("No such operation as index " + left.Name + "!", node.Getter.Token);
            }

            var inputArray = new List <SkryptObject>(arguments);

            inputArray.Insert(0, Object);

            return(operation(inputArray.ToArray(), _engine));
        }
Example #3
0
        /// <summary>
        ///     Solves an expression and returns its boolean result.
        /// </summary>
        private bool CheckCondition(Node node, ScopeContext scopeContext)
        {
            var conditionResult = false;

            conditionResult = _engine.Executor.ExecuteExpression(node, scopeContext).ToBoolean();

            return(conditionResult);
        }
Example #4
0
        /// <summary>
        ///     Executes a for statement node.
        /// </summary>
        public void ExecuteForStatement(Node node, ScopeContext scopeContext)
        {
            var initNode = node.Nodes[0];
            var condNode = node.Nodes[1];
            var modiNode = node.Nodes[2];
            var block    = node.Nodes[3];

            ScopeContext loopScope = new ScopeContext();

            loopScope.StrictlyLocal = true;

            if (scopeContext != null)
            {
                loopScope.ParentScope = scopeContext;
                scopeContext.SubScopes.Add(loopScope);
            }

            var initResult = ExecuteExpression(initNode, loopScope);

            if (scopeContext != null)
            {
                loopScope.Properties = scopeContext.Properties;
            }

            loopScope.Properties |= ScopeProperties.InLoop;

            loopScope.StrictlyLocal = false;

            // Loop until an exit condition is reached.
            while (true)
            {
                var conditionResult = CheckCondition(condNode, loopScope);

                // Exit when the condition is false.
                if (!conditionResult)
                {
                    break;
                }

                var scope = ExecuteBlock(block, loopScope);

                // Exit when a break expression was reached.
                if ((scope.Properties & ScopeProperties.BrokeLoop) != 0)
                {
                    break;
                }

                if (scope.ReturnObject != null)
                {
                    scopeContext.ReturnObject = scope.ReturnObject;
                    break;
                }

                var modiResult = ExecuteExpression(modiNode, loopScope);
            }
        }
Example #5
0
        /// <summary>
        ///     Executes an if statement node.
        /// </summary>
        public void ExecuteIfStatement(Node node, ScopeContext scopeContext)
        {
            var conditionResult = CheckCondition(node.Nodes[0].Nodes[0], scopeContext);

            // Execute body of statement if its evaluated to true.
            if (conditionResult)
            {
                var scope = ExecuteBlock(node.Nodes[1], scopeContext);

                if (scope.ReturnObject != null)
                {
                    scopeContext.ReturnObject = scope.ReturnObject;
                }

                return;
            }

            // Execute elseif/else statements proceeding the current statement.
            if (node.Nodes.Count > 2)
            {
                for (var i = 2; i < node.Nodes.Count; i++)
                {
                    var elseNode = node.Nodes[i];

                    // Execute elseif statement as if statement.
                    if (elseNode.Body == "elseif")
                    {
                        conditionResult = _engine.Executor.ExecuteExpression(elseNode.Nodes[0].Nodes[0], scopeContext).ToBoolean();

                        if (conditionResult)
                        {
                            var scope = ExecuteBlock(elseNode.Nodes[1], scopeContext);

                            if (scope.ReturnObject != null)
                            {
                                scopeContext.ReturnObject = scope.ReturnObject;
                            }

                            return;
                        }
                    }
                    // Execute remaining else statement.
                    else
                    {
                        var scope = ExecuteBlock(elseNode, scopeContext);

                        if (scope.ReturnObject != null)
                        {
                            scopeContext.ReturnObject = scope.ReturnObject;
                        }
                    }
                }
            }
        }
Example #6
0
        /// <summary>
        ///     Executes a using statement.
        /// </summary>
        public ScopeContext ExecuteUsing(ImportNode node, ScopeContext scopeContext)
        {
            var Object = ExecuteExpression(node.Getter, scopeContext);

            // Add all public variables from object as variables to scope.
            foreach (var property in Object.Properties)
            {
                if ((property.Modifiers & Modifier.Public) != 0)
                {
                    scopeContext.SetVariable(property.Name, property.Value, Modifier.Const);
                }
            }

            return(scopeContext);
        }
Example #7
0
        /// <summary>
        ///     Recursively fetches a variable from the given scope.
        /// </summary>
        public Variable GetVariable(string name, ScopeContext scopeContext)
        {
            Variable foundVar = null;

            if (scopeContext.Variables.ContainsKey(name))
            {
                foundVar = scopeContext.Variables[name];
            }
            else if (scopeContext.ParentScope != null)
            {
                foundVar = GetVariable(name, scopeContext.ParentScope);
            }

            return(foundVar);
        }
Example #8
0
        /// <summary>
        ///     Executes a function definition node.
        /// </summary>
        public UserFunction ExecuteFunctionDeclaration(Node node, ScopeContext scopeContext)
        {
            UserFunction result = new UserFunction {
                Name      = node.Body,
                Signature = node.Body,
                BlockNode = node.Nodes[0],
                CallName  = node.Body,
                Path      = _engine.CurrentExecutingFile
            };

            // Create parameters.
            foreach (Node snode in node.Nodes[1].Nodes)
            {
                result.Parameters.Add(snode.Body);
            }

            return(result);
        }
Example #9
0
        /// <summary>
        ///     Recursively fetches a type from the given scope.
        /// </summary>
        public SkryptObject GetType(string name, ScopeContext scopeContext)
        {
            SkryptObject foundVar = null;

            if (scopeContext.Types.ContainsKey(name))
            {
                foundVar = scopeContext.Types[name];
            }
            else if (scopeContext.ParentScope != null)
            {
                foundVar = GetType(name, scopeContext.ParentScope);
            }

            if (foundVar == null)
            {
                _engine.ThrowError("Could not find type: " + name);
            }

            return(foundVar);
        }
Example #10
0
        /// <summary>
        ///     Executes a block.
        /// </summary>
        public ScopeContext ExecuteBlock(Node node, ScopeContext scopeContext, ScopeProperties properties = 0)
        {
            _engine.State = EngineState.Executing;

            ScopeContext scope = new ScopeContext();

            // Copy settings from previous scope.
            if (scopeContext != null)
            {
                scope.Properties  = scopeContext.Properties;
                scope.ParentScope = scopeContext;
                scope.Types       = scopeContext.Types;
                scope.CallStack   = scopeContext.CallStack;
                scope.ParentClass = scopeContext.ParentClass;

                scopeContext.SubScopes.Add(scope);
            }

            if (properties != 0)
            {
                scope.Properties |= scopeContext.Properties;
            }

            if ((scope.Properties & ScopeProperties.InClassDeclaration) == 0)
            {
                if ((node.Modifiers & Modifier.Instance) != 0 || (node.Modifiers & Modifier.Public) != 0 || (node.Modifiers & Modifier.Private) != 0)
                {
                    _engine.ThrowError("Property modifiers cannot be used outside class", node.Token);
                }
            }

            _engine.CurrentScope = scope;
            var oldStack = _engine.CurrentStack;
            var oldPath  = _engine.CurrentExecutingFile;

            foreach (var subNode in node.Nodes)
            {
                if (subNode.Type == TokenTypes.Statement)
                {
                    switch (subNode.Body)
                    {
                    case "while":
                        ExecuteWhileStatement(subNode, scope);
                        break;

                    case "if":
                        ExecuteIfStatement(subNode, scope);
                        break;

                    case "for":
                        ExecuteForStatement(subNode, scope);
                        break;
                    }

                    if ((scope.Properties & ScopeProperties.SkippedLoop) != 0)
                    {
                        return(scope);
                    }
                    if ((scope.Properties & ScopeProperties.BrokeLoop) != 0)
                    {
                        return(scope);
                    }
                    if (scope.ReturnObject != null)
                    {
                        return(scope);
                    }
                }
                else if (subNode.Type == TokenTypes.Include)
                {
                    _engine.CurrentExecutingFile = ((IncludeNode)subNode).Path;
                    scope = ExecuteBlock(subNode, scope);
                }
                else if (subNode.Type == TokenTypes.MethodDeclaration)
                {
                    var result = ExecuteFunctionDeclaration(subNode, scope);

                    scope.SetVariable(result.CallName, result, subNode.Modifiers);
                }
                else if (subNode.Type == TokenTypes.ClassDeclaration)
                {
                    var createdClass = ExecuteClassDeclaration((ClassNode)subNode, scope);

                    scope.SetVariable(createdClass.Name, createdClass, subNode.Modifiers);
                }
                else if (subNode.Type == TokenTypes.Import)
                {
                    var _scope = ExecuteUsing((ImportNode)subNode, scope);
                }
                else
                {
                    var result = _engine.Executor.ExecuteExpression(subNode, scope);

                    if ((scope.Properties & ScopeProperties.SkippedLoop) != 0)
                    {
                        return(scope);
                    }
                    if ((scope.Properties & ScopeProperties.BrokeLoop) != 0)
                    {
                        return(scope);
                    }
                    if (scope.ReturnObject != null)
                    {
                        return(scope);
                    }
                }

                // Reset current stack and scope variables.
                _engine.CurrentScope         = scope;
                _engine.CurrentStack         = oldStack;
                _engine.CurrentExecutingFile = oldPath;
            }

            return(scope);
        }
Example #11
0
        /// <summary>
        ///     Executes a class definition node.
        /// </summary>
        public SkryptObject ExecuteClassDeclaration(ClassNode node, ScopeContext scopeContext)
        {
            string ClassName   = node.Name;
            var    ParentClass = scopeContext.ParentClass;

            if (ParentClass != null)
            {
                ClassName = ParentClass.Name + "." + ClassName;
            }

            // The static object.
            SkryptObject Object = new SkryptObject {
                Name = ClassName,
            };

            // The object base that gets instantiated.
            SkryptType TypeObject = new SkryptType {
                Name = ClassName,
            };

            scopeContext.AddType(ClassName, TypeObject);

            // Give objects a value displaying their type.
            Object.Properties.Add(new SkryptProperty {
                Name      = "TypeName",
                Value     = new Library.Native.System.String(ClassName),
                Modifiers = Parsing.Modifier.Const
            });

            TypeObject.Properties.Add(new SkryptProperty {
                Name      = "TypeName",
                Value     = new Library.Native.System.String(ClassName),
                Modifiers = Parsing.Modifier.Const
            });

            // Give instance object a value pointing to its base type.
            TypeObject.Properties.Add(new SkryptProperty {
                Name      = "Type",
                Value     = Object,
                Modifiers = Parsing.Modifier.Const
            });

            // Execute class body.
            var scope = ExecuteBlock(node.BodyNode, scopeContext, ScopeProperties.InClassDeclaration);

            // Add variables with modifiers to instance and base objects.
            foreach (var v in scope.Variables)
            {
                if (v.Value.Modifiers != Modifier.None)
                {
                    var property = new SkryptProperty {
                        Name      = v.Key,
                        Value     = v.Value.Value,
                        Modifiers = v.Value.Modifiers
                    };

                    if ((v.Value.Modifiers & Modifier.Instance) == 0)
                    {
                        var find = TypeObject.Properties.Find(x => x.Name == v.Key);

                        if (find != null)
                        {
                            find = property;
                        }
                        else
                        {
                            Object.Properties.Add(property);
                        }
                    }
                    else
                    {
                        var find = TypeObject.Properties.Find(x => x.Name == v.Key);

                        if (find != null)
                        {
                            find = property;
                        }
                        else
                        {
                            TypeObject.Properties.Add(property);
                        }
                    }
                }
            }

            // Add variables from inherited classes to objects.
            foreach (var inheritNode in node.InheritNode.Nodes)
            {
                var value = ExecuteExpression(inheritNode, scopeContext);

                var BaseType = GetType(((Library.Native.System.String)value.GetProperty("TypeName")).Value, scopeContext);
                var instance = (SkryptType)Activator.CreateInstance(BaseType.GetType());
                instance.ScopeContext = _engine.CurrentScope;
                instance.Engine       = _engine;
                instance.GetPropertiesFrom(BaseType);

                if (value.GetType() != typeof(SkryptObject) || BaseType.GetType() != typeof(SkryptType))
                {
                    _engine.ThrowError("Can only inherit from Skrypt-based objects");
                }

                foreach (var p in value.Properties)
                {
                    var find = Object.Properties.Find(x => {
                        if (x.IsGetter != p.IsGetter)
                        {
                            return(false);
                        }
                        if (x.IsSetter != p.IsSetter)
                        {
                            return(false);
                        }
                        if (x.Name != p.Name)
                        {
                            return(false);
                        }

                        return(true);
                    });

                    if (find == null)
                    {
                        Object.Properties.Add(new SkryptProperty {
                            Name      = p.Name,
                            Value     = p.Value,
                            Modifiers = p.Modifiers,
                            IsGetter  = p.IsGetter,
                            IsSetter  = p.IsSetter
                        });
                    }
                }

                foreach (var p in instance.Properties)
                {
                    var find = TypeObject.Properties.Find(x => {
                        if (x.IsGetter != p.IsGetter)
                        {
                            return(false);
                        }
                        if (x.IsSetter != p.IsSetter)
                        {
                            return(false);
                        }
                        if (x.Name != p.Name)
                        {
                            return(false);
                        }

                        return(true);
                    });

                    if (find == null)
                    {
                        TypeObject.Properties.Add(new SkryptProperty {
                            Name      = p.Name,
                            Value     = p.Value,
                            Modifiers = p.Modifiers,
                            IsGetter  = p.IsGetter,
                            IsSetter  = p.IsSetter
                        });
                    }
                }
            }

            foreach (var p in Object.Properties)
            {
                SetFunctionOwner(p.Value, Object);
            }

            Object.Name = node.Name;

            return(Object);
        }
Example #12
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);
        }