A statement for the ScriptProcessor to execute.
Пример #1
0
        private SObject ExecuteVar(ScriptStatement statement)
        {
            var exp = statement.Code;

            var identifier = exp.Remove(0, "var ".Length).Trim();
            var data       = Undefined;

            if (identifier.Contains("="))
            {
                var assignment = identifier.Remove(0, identifier.IndexOf("=") + 1).Trim();
                identifier = identifier.Remove(identifier.IndexOf("=")).Trim();

                data = SObject.Unbox(ExecuteStatement(new ScriptStatement(assignment)));
            }

            if (!IsValidIdentifier(identifier))
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_VAR_NAME));
            }

            var variable = new SVariable(identifier, data);

            Context.AddVariable(variable);

            return(variable);
        }
Пример #2
0
        private SObject ExecuteImport(ScriptStatement statement)
        {
            // import apiClass from "moduleName"

            var exp   = statement.Code;
            var parts = exp.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

            if (parts.Length < 4 || parts[0] != "import" || parts[2] != "from")
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_INVALID_IMPORT_STATEMENT));
            }

            var apiClass   = parts[1];
            var moduleName = exp.Remove(0, exp.IndexOf("\""));

            moduleName = moduleName.Trim('\"');

            if (!IsValidIdentifier(apiClass))
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_VAR_NAME));
            }

            var apiUsing = new SAPIUsing(apiClass, moduleName);

            Context.AddAPIUsing(apiUsing);
            return(apiUsing);
        }
Пример #3
0
        private SObject ExecuteClass(ScriptStatement statement)
        {
            var exp = statement.Code;

            // The function's body is the next statement:

            _index++;

            if (_index < _statements.Length)
            {
                var classBodyStatement = _statements[_index];

                if (classBodyStatement.IsCompoundStatement)
                {
                    exp += classBodyStatement.Code;

                    var prototype = (Prototype)Prototype.Parse(this, exp);
                    Context.AddPrototype(prototype);

                    return(prototype);
                }
                else
                {
                    return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_COMPOUND, classBodyStatement.Code[0]));
                }
            }
            else
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script"));
            }
        }
Пример #4
0
        private SObject ExecuteAsync(ScriptStatement statement)
        {
            // statement inside async block gets executed in its own thread.
            // cannot rely on any variables from outside being set on time.

            string taskName = statement.Code.Remove(0, statement.Code.IndexOf("(") + 1);

            taskName = taskName.Remove(taskName.LastIndexOf(")")).Trim();

            if (string.IsNullOrWhiteSpace(taskName))
            {
                taskName = Guid.NewGuid().ToString();
            }

            _index++;
            var nextStatement = _statements[_index];

            var processor = new ScriptProcessor(Context, GetLineNumber());

            lock (Context.AsyncTasks)
                Context.AsyncTasks.Add(taskName);

            Console.WriteLine($"Start async task ({taskName})");

            Task.Run(() =>
            {
                processor.ExecuteStatement(nextStatement);

                lock (Context.AsyncTasks)
                    Context.AsyncTasks.Remove(taskName);
            });

            return(Undefined);
        }
Пример #5
0
        private SObject ExecuteAsync(ScriptStatement statement)
        {
            // statement inside async block gets executed in its own thread.
            // cannot rely on any variables from outside being set on time.

            string taskName = statement.Code.Remove(0, statement.Code.IndexOf("(") + 1);
            taskName = taskName.Remove(taskName.LastIndexOf(")")).Trim();

            if (string.IsNullOrWhiteSpace(taskName))
                taskName = Guid.NewGuid().ToString();

            _index++;
            var nextStatement = _statements[_index];

            var processor = new ScriptProcessor(Context, GetLineNumber());

            lock (Context.AsyncTasks)
                Context.AsyncTasks.Add(taskName);

            Console.WriteLine($"Start async task ({taskName})");

            Task.Run(() =>
            {
                processor.ExecuteStatement(nextStatement);

                lock (Context.AsyncTasks)
                    Context.AsyncTasks.Remove(taskName);
            });

            return Undefined;
        }
Пример #6
0
        private SObject ExecuteElse(ScriptStatement statement)
        {
            // Search for an if statement:
            var searchIndex = _index - 2;
            var foundIf     = false;

            while (searchIndex >= 0 && !foundIf)
            {
                if (_statements[searchIndex].StatementType == StatementType.If)
                {
                    foundIf = true;
                }

                searchIndex -= 2;
            }

            if (!foundIf)
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "keyword \'else\'"));
            }

            _index++;

            if (_statements.Length > _index)
            {
                var executeStatement = _statements[_index];
                return(ExecuteStatement(executeStatement));
            }
            else
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script"));
            }
        }
Пример #7
0
        private SObject ExecuteLink(ScriptStatement statement)
        {
            if (Context.HasCallback(CallbackType.ScriptPipeline))
            {
                var exp = statement.Code;
                exp = exp.Remove(0, "link ".Length).Trim();

                var callback = (DScriptPipeline)Context.GetCallback(CallbackType.ScriptPipeline);
                var task     = Task <string> .Factory.StartNew(() => callback(this, exp));

                task.Wait();

                var code = task.Result;

                var statements = StatementProcessor.GetStatements(this, code);

                // Convert the current statements into a list, so we can modify them.
                var tempStatements = _statements.ToList();
                // Remove the "link" statement, because we don't want to step into it again if we are in a loop.
                tempStatements.RemoveAt(_index);

                // Insert class, using and link statements right after the current statement.
                var insertIndex = _index;

                for (var i = 0; i < statements.Length; i++)
                {
                    if (statements[i].StatementType == StatementType.Class)
                    {
                        // The class statement needs its body, so we add the class statement and the one afterwards:
                        if (statements.Length > i + 1)
                        {
                            tempStatements.Insert(insertIndex, statements[i]);
                            tempStatements.Insert(insertIndex + 1, statements[i + 1]);

                            insertIndex += 2;
                        }
                        else
                        {
                            ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
                        }
                    }
                    else if (statements[i].StatementType == StatementType.Import || statements[i].StatementType == StatementType.Link)
                    {
                        tempStatements.Insert(insertIndex, statements[i]);
                        insertIndex += 1;
                    }
                }

                // Convert the temp statement list back and reduce the index by one, because we deleted the current statement.
                _statements = tempStatements.ToArray();
                _index--;

                return(Undefined);
            }
            else
            {
                return(ErrorHandler.ThrowError(ErrorType.APIError, ErrorHandler.MESSAGE_API_NOT_SUPPORTED));
            }
        }
Пример #8
0
        private SObject ExecuteWhile(ScriptStatement statement)
        {
            var exp = statement.Code;

            var condition = exp.Remove(0, exp.IndexOf("while") + "while".Length).Trim().Remove(0, 1); // Remove "while" and "(".

            condition = condition.Remove(condition.Length - 1, 1).Trim();                             // Remove ")".

            if (condition.Length == 0)
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, ")"));
            }

            _index++;

            if (_statements.Length > _index)
            {
                var stayInWhile      = true;
                var executeStatement = _statements[_index];
                var returnObject     = Undefined;

                while (stayInWhile)
                {
                    var conditionResult = ExecuteStatement(new ScriptStatement(condition));

                    if (conditionResult is SBool)
                    {
                        stayInWhile = ((SBool)conditionResult).Value;
                    }
                    else
                    {
                        stayInWhile = conditionResult.ToBool(this).Value;
                    }

                    if (stayInWhile)
                    {
                        returnObject = ExecuteStatement(executeStatement);

                        if (_returnIssued || _breakIssued)
                        {
                            _breakIssued = false;
                            stayInWhile  = false;
                        }
                    }
                }

                return(returnObject);
            }
            else
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script"));
            }
        }
Пример #9
0
        internal SObject ExecuteStatement(ScriptStatement statement)
        {
            switch (statement.StatementType)
            {
                case StatementType.Executable:
                    return ExecuteExecutable(statement);
                case StatementType.If:
                    return ExecuteIf(statement);
                case StatementType.Else:
                    return ExecuteElse(statement);
                case StatementType.ElseIf:
                    return ExecuteElseIf(statement);
                case StatementType.Import:
                    return ExecuteImport(statement);
                case StatementType.Var:
                    return ExecuteVar(statement);
                case StatementType.While:
                    return ExecuteWhile(statement);
                case StatementType.Return:
                    return ExecuteReturn(statement);
                case StatementType.Assignment:
                    return ExecuteAssignment(statement);
                case StatementType.For:
                    return ExecuteFor(statement);
                case StatementType.Function:
                    return ExecuteFunction(statement);
                case StatementType.Class:
                    return ExecuteClass(statement);
                case StatementType.Link:
                    return ExecuteLink(statement);
                case StatementType.Continue:
                    return ExecuteContinue(statement);
                case StatementType.Break:
                    return ExecuteBreak(statement);
                case StatementType.Throw:
                    return ExecuteThrow(statement);
                case StatementType.Try:
                    return ExecuteTry(statement);
                case StatementType.Catch:
                    return ExecuteCatch(statement);
                case StatementType.Finally:
                    return ExecuteFinally(statement);
                case StatementType.Async:
                    return ExecuteAsync(statement);
            }

            return null;
        }
Пример #10
0
        private SObject ExecuteReturn(ScriptStatement statement)
        {
            var exp = statement.Code;

            if (exp == "return")
            {
                _returnIssued = true;
                return(Undefined);
            }
            else
            {
                exp = exp.Remove(0, "return".Length);

                var returnObject = ExecuteStatement(new ScriptStatement(exp));
                _returnIssued = true;

                return(returnObject);
            }
        }
Пример #11
0
        private SObject ExecuteElseIf(ScriptStatement statement)
        {
            // Search for an if statement:
            var searchIndex = _index - 2;
            var foundIf     = false;

            while (searchIndex >= 0 && !foundIf)
            {
                if (_statements[searchIndex].StatementType == StatementType.If)
                {
                    foundIf = true;
                }

                searchIndex -= 2;
            }

            return(foundIf ?
                   ExecuteIf(statement) :
                   ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "keyword \'else if\'"));
        }
Пример #12
0
        private SObject ExecuteFunction(ScriptStatement statement)
        {
            // function <name> ()
            var exp = statement.Code;

            exp = exp.Remove(0, "function".Length).Trim();
            var functionName = exp.Remove(exp.IndexOf("("));

            if (!IsValidIdentifier(functionName))
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_VAR_NAME));
            }

            var functionExpression = "function " + exp.Remove(0, exp.IndexOf("("));

            // The function's body is the next statement:

            _index++;

            if (_index < _statements.Length)
            {
                var functionBodyStatement = _statements[_index];

                var functionBody = functionBodyStatement.Code;
                if (!functionBodyStatement.IsCompoundStatement)
                {
                    functionBody = "{" + functionBody + "}";
                }

                functionExpression += functionBody;

                var function = new SFunction(this, functionExpression);
                Context.AddVariable(functionName, function);

                return(function);
            }
            else
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script"));
            }
        }
Пример #13
0
        private SObject ExecuteThrow(ScriptStatement statement)
        {
            var exp = statement.Code;

            if (exp == "throw")
            {
                return(ErrorHandler.ThrowError(ErrorType.UserError, ErrorHandler.MESSAGE_USER_ERROR));
            }
            else
            {
                exp = exp.Remove(0, "throw ".Length).Trim();

                var errorObject = ExecuteStatement(new ScriptStatement(exp));

                // Set the line number if the object is an error object:
                if (errorObject.TypeOf() == SObject.LITERAL_TYPE_ERROR)
                {
                    ((SError)errorObject).SetMember(ErrorPrototype.MEMBER_NAME_LINE, CreateNumber(GetLineNumber()));
                }

                return(ErrorHandler.ThrowError(errorObject));
            }
        }
Пример #14
0
        private SObject ExecuteIf(ScriptStatement statement)
        {
            var exp = statement.Code;

            var condition = exp.Remove(0, exp.IndexOf("if") + "if".Length).Trim().Remove(0, 1); // Remove "if" and "(".
            condition = condition.Remove(condition.Length - 1, 1).Trim(); // Remove ")".

            if (condition.Length == 0)
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, ")");

            var conditionResult = ExecuteStatement(new ScriptStatement(condition));
            statement.StatementResult = conditionResult;

            bool conditionEval;
            if (conditionResult is SBool)
                conditionEval = ((SBool)conditionResult).Value;
            else
                conditionEval = conditionResult.ToBool(this).Value;

            _index++;

            if (_statements.Length > _index)
            {
                var executeStatement = _statements[_index];

                if (conditionEval)
                {
                    var returnObject = ExecuteStatement(executeStatement);

                    // Jump over all "else if" and "else" statements that follow this if / else if:

                    var searchIndex = _index + 1;
                    var foundIfs = true;

                    while (searchIndex < _statements.Length && foundIfs)
                    {
                        if (_statements[searchIndex].StatementType == StatementType.ElseIf || _statements[searchIndex].StatementType == StatementType.Else)
                            _index += 2;
                        else
                            foundIfs = false;

                        searchIndex += 2;
                    }

                    return returnObject;
                }
                else
                {
                    return Undefined;
                }
            }
            else
            {
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
            }
        }
Пример #15
0
        private SObject ExecuteIf(ScriptStatement statement)
        {
            var exp = statement.Code;

            var condition = exp.Remove(0, exp.IndexOf("if") + "if".Length).Trim().Remove(0, 1); // Remove "if" and "(".

            condition = condition.Remove(condition.Length - 1, 1).Trim();                       // Remove ")".

            if (condition.Length == 0)
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, ")"));
            }

            var conditionResult = ExecuteStatement(new ScriptStatement(condition));

            statement.StatementResult = conditionResult;

            bool conditionEval;

            if (conditionResult is SBool)
            {
                conditionEval = ((SBool)conditionResult).Value;
            }
            else
            {
                conditionEval = conditionResult.ToBool(this).Value;
            }

            _index++;

            if (_statements.Length > _index)
            {
                var executeStatement = _statements[_index];

                if (conditionEval)
                {
                    var returnObject = ExecuteStatement(executeStatement);

                    // Jump over all "else if" and "else" statements that follow this if / else if:

                    var searchIndex = _index + 1;
                    var foundIfs    = true;

                    while (searchIndex < _statements.Length && foundIfs)
                    {
                        if (_statements[searchIndex].StatementType == StatementType.ElseIf || _statements[searchIndex].StatementType == StatementType.Else)
                        {
                            _index += 2;
                        }
                        else
                        {
                            foundIfs = false;
                        }

                        searchIndex += 2;
                    }

                    return(returnObject);
                }
                else
                {
                    return(Undefined);
                }
            }
            else
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script"));
            }
        }
Пример #16
0
        private SObject ExecuteExecutable(ScriptStatement statement)
        {
            if (statement.IsCompoundStatement)
            {
                var processor = new ScriptProcessor(Context, GetLineNumber());

                // Remove { and }:
                var code = statement.Code.Remove(0, 1);
                code = code.Remove(code.Length - 1, 1);

                var returnObject = processor.Run(code);

                _breakIssued    = processor._breakIssued;
                _continueIssued = processor._continueIssued;
                _returnIssued   = processor._returnIssued;

                return(returnObject);
            }
            else
            {
                var exp = ResolveParentheses(statement.Code).Trim();

                #region QuickConvert

                // have quick conversions for small statements here
                // parameter statements are much faster that way:
                if (exp == SObject.LITERAL_BOOL_TRUE)
                {
                    return(CreateBool(true));
                }
                else if (exp == SObject.LITERAL_BOOL_FALSE)
                {
                    return(CreateBool(false));
                }
                else if (exp == SObject.LITERAL_UNDEFINED || exp == "")
                {
                    return(Undefined);
                }
                else if (exp == SObject.LITERAL_NULL)
                {
                    return(Null);
                }
                else if (exp.StartsWith("\"") && exp.EndsWith("\"") && !exp.Remove(exp.Length - 1, 1).Remove(0, 1).Contains("\""))
                {
                    return(CreateString(exp.Remove(exp.Length - 1, 1).Remove(0, 1)));
                }
                else if (exp.All(char.IsDigit))
                {
                    double num;
                    SNumber.TryParse(exp, out num);
                    return(CreateNumber(num));
                }

                #endregion

                if (exp.Contains("=>"))
                {
                    exp = EvaluateLambda(exp);
                }
                if (exp.Contains("."))
                {
                    exp = EvaluateOperator(exp, ".");
                }
                if (exp.Contains("++"))
                {
                    exp = EvaluateOperator(exp, "++");
                }
                if (exp.Contains("--"))
                {
                    exp = EvaluateOperator(exp, "--");
                }
                if (exp.Contains("!"))
                {
                    exp = EvaluateReverseBool(exp);
                }
                if (exp.Contains("**"))
                {
                    exp = EvaluateOperator(exp, "**");
                }
                if (exp.Contains("*"))
                {
                    exp = EvaluateOperator(exp, "*");
                }
                if (exp.Contains("/"))
                {
                    exp = EvaluateOperator(exp, "/");
                }
                if (exp.Contains("%"))
                {
                    exp = EvaluateOperator(exp, "%");
                }
                if (exp.Contains("+"))
                {
                    exp = EvaluateOperator(exp, "+");
                }
                if (exp.Contains("-"))
                {
                    exp = EvaluateOperator(exp, "-");
                }
                if (exp.Contains("<="))
                {
                    exp = EvaluateOperator(exp, "<=");
                }
                if (exp.Contains(">="))
                {
                    exp = EvaluateOperator(exp, ">=");
                }
                if (exp.Contains("<"))
                {
                    exp = EvaluateOperator(exp, "<");
                }
                if (exp.Contains(">"))
                {
                    exp = EvaluateOperator(exp, ">");
                }
                if (exp.Contains("==="))
                {
                    exp = EvaluateOperator(exp, "===");
                }
                if (exp.Contains("!=="))
                {
                    exp = EvaluateOperator(exp, "!==");
                }
                if (exp.Contains("=="))
                {
                    exp = EvaluateOperator(exp, "==");
                }
                if (exp.Contains("!="))
                {
                    exp = EvaluateOperator(exp, "!=");
                }
                if (exp.Contains("&&"))
                {
                    exp = EvaluateOperator(exp, "&&");
                }
                if (exp.Contains("||"))
                {
                    exp = EvaluateOperator(exp, "||");
                }

                return(ToScriptObject(exp));
            }
        }
Пример #17
0
        private SObject ExecuteFor(ScriptStatement statement)
        {
            var exp = statement.Code;

            var forCode = exp.Remove(0, exp.IndexOf("for") + "for".Length).Trim().Remove(0, 1); // Remove "for" and "(".

            forCode = forCode.Remove(forCode.Length - 1, 1);                                    // Remove ")".

            var forStatements = StatementProcessor.GetStatements(this, forCode);

            if (forStatements.Length == 0)
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, ")"));
            }
            else if (forStatements.Length == 1)
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_FOR_INITIALIZER));
            }
            else if (forStatements.Length == 2)
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_FOR_CONDITION));
            }
            else if (forStatements.Length > 3)
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_FOR_CONTROL));
            }

            var processor = new ScriptProcessor(Context, GetLineNumber());

            var forInitializer = forStatements[0];
            var forCondition   = forStatements[1];
            var forControl     = forStatements[2];

            if (forInitializer.Code.Length > 0)
            {
                processor.ExecuteStatement(forInitializer);
            }

            _index++;

            if (_statements.Length > _index)
            {
                var stayInFor        = true;
                var executeStatement = _statements[_index];
                var returnObject     = Undefined;

                while (stayInFor)
                {
                    if (forCondition.Code.Length > 0)
                    {
                        var conditionResult = processor.ExecuteStatement(forCondition);

                        if (conditionResult is SBool)
                        {
                            stayInFor = ((SBool)conditionResult).Value;
                        }
                        else
                        {
                            stayInFor = conditionResult.ToBool(this).Value;
                        }
                    }

                    if (stayInFor)
                    {
                        returnObject = processor.ExecuteStatement(executeStatement);

                        if (processor._returnIssued || processor._breakIssued)
                        {
                            _breakIssued  = false;
                            _returnIssued = processor._returnIssued;
                            stayInFor     = false;
                        }
                        else if (forControl.Code.Length > 0)
                        {
                            processor.ExecuteStatement(forControl);
                        }
                    }
                }

                return(returnObject);
            }
            else
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script"));
            }
        }
Пример #18
0
 private SObject ExecuteContinue(ScriptStatement statement)
 {
     _continueIssued = true;
     return Undefined;
 }
Пример #19
0
 private SObject ExecuteBreak(ScriptStatement statement)
 {
     _breakIssued = true;
     return(Undefined);
 }
Пример #20
0
        private SObject ExecuteWhile(ScriptStatement statement)
        {
            var exp = statement.Code;

            var condition = exp.Remove(0, exp.IndexOf("while") + "while".Length).Trim().Remove(0, 1); // Remove "while" and "(".
            condition = condition.Remove(condition.Length - 1, 1).Trim(); // Remove ")".

            if (condition.Length == 0)
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, ")");

            _index++;

            if (_statements.Length > _index)
            {
                var stayInWhile = true;
                var executeStatement = _statements[_index];
                var returnObject = Undefined;

                while (stayInWhile)
                {
                    var conditionResult = ExecuteStatement(new ScriptStatement(condition));

                    if (conditionResult is SBool)
                        stayInWhile = ((SBool)conditionResult).Value;
                    else
                        stayInWhile = conditionResult.ToBool(this).Value;

                    if (stayInWhile)
                    {
                        returnObject = ExecuteStatement(executeStatement);

                        if (_returnIssued || _breakIssued)
                        {
                            _breakIssued = false;
                            stayInWhile = false;
                        }
                    }
                }

                return returnObject;
            }
            else
            {
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
            }
        }
Пример #21
0
 private SObject ExecuteCatch(ScriptStatement statement)
 {
     // The script processor can only reach this, when a catch statement exists without a try statement:
     return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_CATCH_WITHOUT_TRY);
 }
Пример #22
0
        private SObject ExecuteVar(ScriptStatement statement)
        {
            var exp = statement.Code;

            var identifier = exp.Remove(0, "var ".Length).Trim();
            var data = Undefined;

            if (identifier.Contains("="))
            {
                var assignment = identifier.Remove(0, identifier.IndexOf("=") + 1).Trim();
                identifier = identifier.Remove(identifier.IndexOf("=")).Trim();

                data = SObject.Unbox(ExecuteStatement(new ScriptStatement(assignment)));
            }

            if (!IsValidIdentifier(identifier))
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_VAR_NAME);

            var variable = new SVariable(identifier, data);
            Context.AddVariable(variable);

            return variable;
        }
Пример #23
0
        private SObject ExecuteImport(ScriptStatement statement)
        {
            // import apiClass from "moduleName"

            var exp = statement.Code;
            var parts = exp.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

            if (parts.Length < 4 || parts[0] != "import" || parts[2] != "from")
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_INVALID_IMPORT_STATEMENT);

            var apiClass = parts[1];
            var moduleName = exp.Remove(0, exp.IndexOf("\""));
            moduleName = moduleName.Trim('\"');

            if (!IsValidIdentifier(apiClass))
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_VAR_NAME);

            var apiUsing = new SAPIUsing(apiClass, moduleName);

            Context.AddAPIUsing(apiUsing);
            return apiUsing;
        }
Пример #24
0
        private SObject ExecuteElseIf(ScriptStatement statement)
        {
            // Search for an if statement:
            var searchIndex = _index - 2;
            var foundIf = false;

            while (searchIndex >= 0 && !foundIf)
            {
                if (_statements[searchIndex].StatementType == StatementType.If)
                    foundIf = true;

                searchIndex -= 2;
            }

            return foundIf ?
                ExecuteIf(statement) :
                ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "keyword \'else if\'");
        }
Пример #25
0
        private SObject ExecuteElse(ScriptStatement statement)
        {
            // Search for an if statement:
            var searchIndex = _index - 2;
            var foundIf = false;

            while (searchIndex >= 0 && !foundIf)
            {
                if (_statements[searchIndex].StatementType == StatementType.If)
                    foundIf = true;

                searchIndex -= 2;
            }

            if (!foundIf)
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "keyword \'else\'");

            _index++;

            if (_statements.Length > _index)
            {
                var executeStatement = _statements[_index];
                return ExecuteStatement(executeStatement);
            }
            else
            {
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
            }
        }
Пример #26
0
        private SObject ExecuteTry(ScriptStatement statement)
        {
            var exp = statement.Code;

            if (exp != "try")
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_BEFORE_TRY));
            }

            _index++;
            if (_statements.Length > _index)
            {
                var     executeStatement   = _statements[_index];
                var     encounteredError   = false;
                var     foundCatch         = false;
                var     foundFinally       = false;
                var     foundMatchingCatch = false;
                SObject errorObject        = null;
                var     returnObject       = Undefined;

                try
                {
                    returnObject = ExecuteStatement(executeStatement);
                }
                catch (ScriptException ex)
                {
                    encounteredError = true;
                    errorObject      = ex.ErrorObject;
                }

                if (encounteredError)
                {
                    var endedCatchSearch = false;
                    var findCatchIndex   = _index + 1;
                    while (findCatchIndex < _statements.Length && !endedCatchSearch)
                    {
                        if (_statements[findCatchIndex].StatementType == StatementType.Catch)
                        {
                            _index = findCatchIndex + 1;

                            if (_statements.Length > _index)
                            {
                                if (!foundMatchingCatch)
                                {
                                    var catchExecuteStatement = _statements[_index];
                                    foundCatch = true;

                                    var catchCode    = _statements[findCatchIndex].Code;
                                    var errorVarName = "";

                                    if (catchCode != "catch")
                                    {
                                        catchCode    = catchCode.Remove(0, "catch".Length).Trim().Remove(0, 1);
                                        catchCode    = catchCode.Remove(catchCode.Length - 1, 1);
                                        errorVarName = catchCode.Trim();
                                    }

                                    if (Regex.IsMatch(catchCode, REGEX_CATCHCONDITION))
                                    {
                                        errorVarName = catchCode.Remove(catchCode.IndexOf(" "));
                                        string conditionCode = catchCode.Remove(0, catchCode.IndexOf("if") + 3);

                                        var processor = new ScriptProcessor(Context, GetLineNumber());
                                        processor.Context.AddVariable(errorVarName, errorObject);

                                        var conditionResult = processor.ExecuteStatement(new ScriptStatement(conditionCode));

                                        if (conditionResult is SBool)
                                        {
                                            foundMatchingCatch = ((SBool)conditionResult).Value;
                                        }
                                        else
                                        {
                                            foundMatchingCatch = conditionResult.ToBool(this).Value;
                                        }

                                        if (foundMatchingCatch)
                                        {
                                            returnObject = processor.ExecuteStatement(catchExecuteStatement);
                                        }
                                    }
                                    else
                                    {
                                        foundMatchingCatch = true;
                                        var processor = new ScriptProcessor(Context, GetLineNumber());
                                        processor.Context.AddVariable(errorVarName, errorObject);
                                        returnObject = processor.ExecuteStatement(catchExecuteStatement);
                                    }
                                }
                            }
                            else
                            {
                                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script"));
                            }
                        }
                        else
                        {
                            // end search if different statement type appears:
                            endedCatchSearch = true;
                        }

                        findCatchIndex += 2;
                    }
                }
                else
                {
                    var findCatchIndex = _index + 1;
                    while (findCatchIndex < _statements.Length)
                    {
                        if (_statements[findCatchIndex].StatementType == StatementType.Catch)
                        {
                            foundCatch = true;
                            _index     = findCatchIndex + 1;
                        }
                        else
                        {
                            findCatchIndex = _statements.Length;
                        }

                        findCatchIndex += 2;
                    }
                }

                // if no matching catch was found when an error occurred, it was not caught: throw it!
                if (encounteredError && !foundMatchingCatch)
                {
                    return(ErrorHandler.ThrowError(errorObject));
                }

                // now, try to find finally statement:
                var findFinallyIndex = _index + 1;
                while (findFinallyIndex < _statements.Length && !foundFinally)
                {
                    if (_statements[findFinallyIndex].StatementType == StatementType.Finally)
                    {
                        _index = findFinallyIndex + 1;

                        if (_statements.Length > _index)
                        {
                            var finallyExecuteStatement = _statements[_index];
                            foundFinally = true;

                            returnObject = ExecuteStatement(finallyExecuteStatement);
                        }
                        else
                        {
                            return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script"));
                        }
                    }
                    else
                    {
                        findFinallyIndex = _statements.Length;
                    }

                    findFinallyIndex += 2;
                }

                if (!foundCatch && !foundFinally) // when no catch or finally block has been found, throw an error.
                {
                    return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_CATCH_OR_FINALLY));
                }
                else
                {
                    return(returnObject);
                }
            }
            else
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script"));
            }
        }
Пример #27
0
        internal SObject ExecuteStatement(ScriptStatement statement)
        {
            switch (statement.StatementType)
            {
            case StatementType.Executable:
                return(ExecuteExecutable(statement));

            case StatementType.If:
                return(ExecuteIf(statement));

            case StatementType.Else:
                return(ExecuteElse(statement));

            case StatementType.ElseIf:
                return(ExecuteElseIf(statement));

            case StatementType.Import:
                return(ExecuteImport(statement));

            case StatementType.Var:
                return(ExecuteVar(statement));

            case StatementType.While:
                return(ExecuteWhile(statement));

            case StatementType.Return:
                return(ExecuteReturn(statement));

            case StatementType.Assignment:
                return(ExecuteAssignment(statement));

            case StatementType.For:
                return(ExecuteFor(statement));

            case StatementType.Function:
                return(ExecuteFunction(statement));

            case StatementType.Class:
                return(ExecuteClass(statement));

            case StatementType.Link:
                return(ExecuteLink(statement));

            case StatementType.Continue:
                return(ExecuteContinue(statement));

            case StatementType.Break:
                return(ExecuteBreak(statement));

            case StatementType.Throw:
                return(ExecuteThrow(statement));

            case StatementType.Try:
                return(ExecuteTry(statement));

            case StatementType.Catch:
                return(ExecuteCatch(statement));

            case StatementType.Finally:
                return(ExecuteFinally(statement));

            case StatementType.Async:
                return(ExecuteAsync(statement));
            }

            return(null);
        }
Пример #28
0
        private SObject ExecuteReturn(ScriptStatement statement)
        {
            var exp = statement.Code;

            if (exp == "return")
            {
                _returnIssued = true;
                return Undefined;
            }
            else
            {
                exp = exp.Remove(0, "return".Length);

                var returnObject = ExecuteStatement(new ScriptStatement(exp));
                _returnIssued = true;

                return returnObject;
            }
        }
Пример #29
0
 private SObject ExecuteContinue(ScriptStatement statement)
 {
     _continueIssued = true;
     return(Undefined);
 }
Пример #30
0
        private SObject ExecuteAssignment(ScriptStatement statement)
        {
            var exp = statement.Code;

            var leftSide = "";
            var rightSide = "";
            var assignmentOperator = "";

            // Get left and right side of the assignment:
            {
                var depth = 0;
                var index = 0;
                StringEscapeHelper escaper = new LeftToRightStringEscapeHelper(exp, 0);

                while (index < exp.Length && assignmentOperator.Length == 0)
                {
                    var t = exp[index];
                    escaper.CheckStartAt(index);

                    if (!escaper.IsString)
                    {
                        if (t == '(' || t == '[' || t == '{')
                        {
                            depth++;
                        }
                        else if (t == ')' || t == ']' || t == '}')
                        {
                            depth--;
                        }
                        else if (t == '=' && depth == 0)
                        {
                            var previous = ' ';
                            if (index > 0)
                                previous = exp[index - 1];

                            if (previous == '+' || previous == '-' || previous == '/' || previous == '*')
                            {
                                assignmentOperator = previous.ToString();
                                leftSide = exp.Substring(0, index - 1).TrimEnd();
                            }
                            else
                            {
                                assignmentOperator = "=";
                                leftSide = exp.Substring(0, index).TrimEnd();
                            }

                            rightSide = exp.Substring(index + 1).TrimStart();
                        }
                    }

                    index++;
                }
            }

            // This means it's a function call, which cannot be assigned to:
            if (leftSide.EndsWith(")") || leftSide.Length == 0)
                return ErrorHandler.ThrowError(ErrorType.ReferenceError, ErrorHandler.MESSAGE_REFERENCE_INVALID_ASSIGNMENT_LEFT);

            SObject memberHost = null;
            SObject accessor = null;
            SObject value = null;
            var isIndexer = false;
            var host = "";
            var member = "";

            if (leftSide.EndsWith("]"))
            {
                var indexerStartIndex = 0;
                var index = leftSide.Length - 1;
                var depth = 0;

                StringEscapeHelper escaper = new RightToLeftStringEscapeHelper(leftSide, index);
                while (index > 0 && !isIndexer)
                {
                    var t = leftSide[index];
                    escaper.CheckStartAt(index);

                    if (!escaper.IsString)
                    {
                        if (t == '(' || t == '{')
                        {
                            depth--;
                        }
                        else if (t == ')' || t == ']' || t == '}')
                        {
                            depth++;
                        }
                        else if (t == '[')
                        {
                            depth--;
                            if (depth == 0 && index > 0)
                            {
                                isIndexer = true;
                                indexerStartIndex = index;
                            }
                        }
                    }

                    index--;
                }

                if (isIndexer)
                {
                    member = leftSide.Substring(indexerStartIndex + 1);
                    member = member.Remove(member.Length - 1, 1);
                    host = leftSide.Remove(indexerStartIndex);
                }
            }
            else
            {
                var foundMember = false;

                if (leftSide.Contains("."))
                {
                    var index = leftSide.Length - 1;
                    var depth = 0;
                    StringEscapeHelper escaper = new RightToLeftStringEscapeHelper(leftSide, index);

                    while (index > 0 && !foundMember)
                    {
                        var t = leftSide[index];
                        escaper.CheckStartAt(index);

                        if (!escaper.IsString)
                        {
                            if (t == '(' || t == '[' || t == '{')
                            {
                                depth--;
                            }
                            else if (t == ')' || t == ']' || t == '}')
                            {
                                depth++;
                            }
                            else if (t == '.' && depth == 0)
                            {
                                foundMember = true;
                                host = leftSide.Substring(0, index);
                                member = leftSide.Remove(0, index + 1);
                            }
                        }

                        index--;
                    }
                }

                if (!foundMember)
                {
                    host = SObject.LITERAL_THIS;
                    member = leftSide;
                }
            }

            // When it's an indexer, we parse it as statement:
            accessor = isIndexer ? SObject.Unbox(ExecuteStatement(new ScriptStatement(member))) : CreateString(member);

            memberHost = ExecuteStatement(new ScriptStatement(host));
            value = SObject.Unbox(ExecuteStatement(new ScriptStatement(rightSide)));

            if (assignmentOperator == "=")
            {
                memberHost.SetMember(this, accessor, isIndexer, value);
            }
            else
            {
                var memberContent = memberHost.GetMember(this, accessor, isIndexer);

                var result = "";

                switch (assignmentOperator)
                {
                    case "+":
                        result = ObjectOperators.AddOperator(this, memberContent, value);
                        break;
                    case "-":
                        result = ObjectOperators.SubtractOperator(this, memberContent, value);
                        break;
                    case "*":
                        result = ObjectOperators.MultiplyOperator(this, memberContent, value);
                        break;
                    case "/":
                        result = ObjectOperators.DivideOperator(this, memberContent, value);
                        break;
                }

                memberHost.SetMember(this, accessor, isIndexer, ToScriptObject(result));
            }

            return value;
        }
Пример #31
0
 private SObject ExecuteBreak(ScriptStatement statement)
 {
     _breakIssued = true;
     return Undefined;
 }
Пример #32
0
        private SObject ExecuteFor(ScriptStatement statement)
        {
            var exp = statement.Code;

            var forCode = exp.Remove(0, exp.IndexOf("for") + "for".Length).Trim().Remove(0, 1); // Remove "for" and "(".
            forCode = forCode.Remove(forCode.Length - 1, 1); // Remove ")".

            var forStatements = StatementProcessor.GetStatements(this, forCode);

            if (forStatements.Length == 0)
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, ")");
            else if (forStatements.Length == 1)
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_FOR_INITIALIZER);
            else if (forStatements.Length == 2)
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_FOR_CONDITION);
            else if (forStatements.Length > 3)
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_FOR_CONTROL);

            var processor = new ScriptProcessor(Context, GetLineNumber());

            var forInitializer = forStatements[0];
            var forCondition = forStatements[1];
            var forControl = forStatements[2];

            if (forInitializer.Code.Length > 0)
                processor.ExecuteStatement(forInitializer);

            _index++;

            if (_statements.Length > _index)
            {
                var stayInFor = true;
                var executeStatement = _statements[_index];
                var returnObject = Undefined;

                while (stayInFor)
                {
                    if (forCondition.Code.Length > 0)
                    {
                        var conditionResult = processor.ExecuteStatement(forCondition);

                        if (conditionResult is SBool)
                            stayInFor = ((SBool)conditionResult).Value;
                        else
                            stayInFor = conditionResult.ToBool(this).Value;
                    }

                    if (stayInFor)
                    {
                        returnObject = processor.ExecuteStatement(executeStatement);

                        if (processor._returnIssued || processor._breakIssued)
                        {
                            _breakIssued = false;
                            _returnIssued = processor._returnIssued;
                            stayInFor = false;
                        }
                        else if (forControl.Code.Length > 0)
                        {
                            processor.ExecuteStatement(forControl);
                        }
                    }
                }

                return returnObject;
            }
            else
            {
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
            }
        }
Пример #33
0
        private SObject ExecuteFunction(ScriptStatement statement)
        {
            // function <name> ()
            var exp = statement.Code;
            exp = exp.Remove(0, "function".Length).Trim();
            var functionName = exp.Remove(exp.IndexOf("("));

            if (!IsValidIdentifier(functionName))
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_VAR_NAME);

            var functionExpression = "function " + exp.Remove(0, exp.IndexOf("("));

            // The function's body is the next statement:

            _index++;

            if (_index < _statements.Length)
            {
                var functionBodyStatement = _statements[_index];

                var functionBody = functionBodyStatement.Code;
                if (!functionBodyStatement.IsCompoundStatement)
                    functionBody = "{" + functionBody + "}";

                functionExpression += functionBody;

                var function = new SFunction(this, functionExpression);
                Context.AddVariable(functionName, function);

                return function;
            }
            else
            {
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
            }
        }
Пример #34
0
        private SObject ExecuteClass(ScriptStatement statement)
        {
            var exp = statement.Code;

            // The function's body is the next statement:

            _index++;

            if (_index < _statements.Length)
            {
                var classBodyStatement = _statements[_index];

                if (classBodyStatement.IsCompoundStatement)
                {
                    exp += classBodyStatement.Code;

                    var prototype = (Prototype)Prototype.Parse(this, exp);
                    Context.AddPrototype(prototype);

                    return prototype;
                }
                else
                {
                    return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_COMPOUND, classBodyStatement.Code[0]);
                }
            }
            else
            {
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
            }
        }
Пример #35
0
        private SObject ExecuteAssignment(ScriptStatement statement)
        {
            var exp = statement.Code;

            var leftSide           = "";
            var rightSide          = "";
            var assignmentOperator = "";

            // Get left and right side of the assignment:
            {
                var depth = 0;
                var index = 0;
                StringEscapeHelper escaper = new LeftToRightStringEscapeHelper(exp, 0);

                while (index < exp.Length && assignmentOperator.Length == 0)
                {
                    var t = exp[index];
                    escaper.CheckStartAt(index);

                    if (!escaper.IsString)
                    {
                        if (t == '(' || t == '[' || t == '{')
                        {
                            depth++;
                        }
                        else if (t == ')' || t == ']' || t == '}')
                        {
                            depth--;
                        }
                        else if (t == '=' && depth == 0)
                        {
                            var previous = ' ';
                            if (index > 0)
                            {
                                previous = exp[index - 1];
                            }

                            if (previous == '+' || previous == '-' || previous == '/' || previous == '*')
                            {
                                assignmentOperator = previous.ToString();
                                leftSide           = exp.Substring(0, index - 1).TrimEnd();
                            }
                            else
                            {
                                assignmentOperator = "=";
                                leftSide           = exp.Substring(0, index).TrimEnd();
                            }

                            rightSide = exp.Substring(index + 1).TrimStart();
                        }
                    }

                    index++;
                }
            }

            // This means it's a function call, which cannot be assigned to:
            if (leftSide.EndsWith(")") || leftSide.Length == 0)
            {
                return(ErrorHandler.ThrowError(ErrorType.ReferenceError, ErrorHandler.MESSAGE_REFERENCE_INVALID_ASSIGNMENT_LEFT));
            }

            SObject memberHost = null;
            SObject accessor   = null;
            SObject value      = null;
            var     isIndexer  = false;
            var     host       = "";
            var     member     = "";

            if (leftSide.EndsWith("]"))
            {
                var indexerStartIndex = 0;
                var index             = leftSide.Length - 1;
                var depth             = 0;

                StringEscapeHelper escaper = new RightToLeftStringEscapeHelper(leftSide, index);
                while (index > 0 && !isIndexer)
                {
                    var t = leftSide[index];
                    escaper.CheckStartAt(index);

                    if (!escaper.IsString)
                    {
                        if (t == '(' || t == '{')
                        {
                            depth--;
                        }
                        else if (t == ')' || t == ']' || t == '}')
                        {
                            depth++;
                        }
                        else if (t == '[')
                        {
                            depth--;
                            if (depth == 0 && index > 0)
                            {
                                isIndexer         = true;
                                indexerStartIndex = index;
                            }
                        }
                    }

                    index--;
                }

                if (isIndexer)
                {
                    member = leftSide.Substring(indexerStartIndex + 1);
                    member = member.Remove(member.Length - 1, 1);
                    host   = leftSide.Remove(indexerStartIndex);
                }
            }
            else
            {
                var foundMember = false;

                if (leftSide.Contains("."))
                {
                    var index = leftSide.Length - 1;
                    var depth = 0;
                    StringEscapeHelper escaper = new RightToLeftStringEscapeHelper(leftSide, index);

                    while (index > 0 && !foundMember)
                    {
                        var t = leftSide[index];
                        escaper.CheckStartAt(index);

                        if (!escaper.IsString)
                        {
                            if (t == '(' || t == '[' || t == '{')
                            {
                                depth--;
                            }
                            else if (t == ')' || t == ']' || t == '}')
                            {
                                depth++;
                            }
                            else if (t == '.' && depth == 0)
                            {
                                foundMember = true;
                                host        = leftSide.Substring(0, index);
                                member      = leftSide.Remove(0, index + 1);
                            }
                        }

                        index--;
                    }
                }

                if (!foundMember)
                {
                    host   = SObject.LITERAL_THIS;
                    member = leftSide;
                }
            }

            // When it's an indexer, we parse it as statement:
            accessor = isIndexer ? SObject.Unbox(ExecuteStatement(new ScriptStatement(member))) : CreateString(member);

            memberHost = ExecuteStatement(new ScriptStatement(host));
            value      = SObject.Unbox(ExecuteStatement(new ScriptStatement(rightSide)));

            if (assignmentOperator == "=")
            {
                memberHost.SetMember(this, accessor, isIndexer, value);
            }
            else
            {
                var memberContent = memberHost.GetMember(this, accessor, isIndexer);

                var result = "";

                switch (assignmentOperator)
                {
                case "+":
                    result = ObjectOperators.AddOperator(this, memberContent, value);
                    break;

                case "-":
                    result = ObjectOperators.SubtractOperator(this, memberContent, value);
                    break;

                case "*":
                    result = ObjectOperators.MultiplyOperator(this, memberContent, value);
                    break;

                case "/":
                    result = ObjectOperators.DivideOperator(this, memberContent, value);
                    break;
                }

                memberHost.SetMember(this, accessor, isIndexer, ToScriptObject(result));
            }

            return(value);
        }
Пример #36
0
        private SObject ExecuteLink(ScriptStatement statement)
        {
            if (Context.HasCallback(CallbackType.ScriptPipeline))
            {
                var exp = statement.Code;
                exp = exp.Remove(0, "link ".Length).Trim();

                var callback = (DScriptPipeline)Context.GetCallback(CallbackType.ScriptPipeline);
                var task = Task<string>.Factory.StartNew(() => callback(this, exp));
                task.Wait();

                var code = task.Result;

                var statements = StatementProcessor.GetStatements(this, code);

                // Convert the current statements into a list, so we can modify them.
                var tempStatements = _statements.ToList();
                // Remove the "link" statement, because we don't want to step into it again if we are in a loop.
                tempStatements.RemoveAt(_index);

                // Insert class, using and link statements right after the current statement.
                var insertIndex = _index;

                for (var i = 0; i < statements.Length; i++)
                {
                    if (statements[i].StatementType == StatementType.Class)
                    {
                        // The class statement needs its body, so we add the class statement and the one afterwards:
                        if (statements.Length > i + 1)
                        {
                            tempStatements.Insert(insertIndex, statements[i]);
                            tempStatements.Insert(insertIndex + 1, statements[i + 1]);

                            insertIndex += 2;
                        }
                        else
                        {
                            ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
                        }
                    }
                    else if (statements[i].StatementType == StatementType.Import || statements[i].StatementType == StatementType.Link)
                    {
                        tempStatements.Insert(insertIndex, statements[i]);
                        insertIndex += 1;
                    }
                }

                // Convert the temp statement list back and reduce the index by one, because we deleted the current statement.
                _statements = tempStatements.ToArray();
                _index--;

                return Undefined;
            }
            else
            {
                return ErrorHandler.ThrowError(ErrorType.APIError, ErrorHandler.MESSAGE_API_NOT_SUPPORTED);
            }
        }
Пример #37
0
        private SObject ExecuteThrow(ScriptStatement statement)
        {
            var exp = statement.Code;

            if (exp == "throw")
            {
                return ErrorHandler.ThrowError(ErrorType.UserError, ErrorHandler.MESSAGE_USER_ERROR);
            }
            else
            {
                exp = exp.Remove(0, "throw ".Length).Trim();

                var errorObject = ExecuteStatement(new ScriptStatement(exp));

                // Set the line number if the object is an error object:
                if (errorObject.TypeOf() == SObject.LITERAL_TYPE_ERROR)
                    ((SError)errorObject).SetMember(ErrorPrototype.MEMBER_NAME_LINE, CreateNumber(GetLineNumber()));

                return ErrorHandler.ThrowError(errorObject);
            }
        }
Пример #38
0
 private SObject ExecuteFinally(ScriptStatement statement)
 {
     // The script processor can only reach this, when a finally statement exists without a try statement:
     return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_FINALLY_WITHOUT_TRY));
 }
Пример #39
0
        private SObject ExecuteTry(ScriptStatement statement)
        {
            var exp = statement.Code;

            if (exp != "try")
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_BEFORE_TRY);

            _index++;
            if (_statements.Length > _index)
            {
                var executeStatement = _statements[_index];
                var encounteredError = false;
                var foundCatch = false;
                var foundFinally = false;
                var foundMatchingCatch = false;
                SObject errorObject = null;
                var returnObject = Undefined;

                try
                {
                    returnObject = ExecuteStatement(executeStatement);
                }
                catch (ScriptException ex)
                {
                    encounteredError = true;
                    errorObject = ex.ErrorObject;
                }

                if (encounteredError)
                {
                    var endedCatchSearch = false;
                    var findCatchIndex = _index + 1;
                    while (findCatchIndex < _statements.Length && !endedCatchSearch)
                    {
                        if (_statements[findCatchIndex].StatementType == StatementType.Catch)
                        {
                            _index = findCatchIndex + 1;

                            if (_statements.Length > _index)
                            {
                                if (!foundMatchingCatch)
                                {
                                    var catchExecuteStatement = _statements[_index];
                                    foundCatch = true;

                                    var catchCode = _statements[findCatchIndex].Code;
                                    var errorVarName = "";

                                    if (catchCode != "catch")
                                    {
                                        catchCode = catchCode.Remove(0, "catch".Length).Trim().Remove(0, 1);
                                        catchCode = catchCode.Remove(catchCode.Length - 1, 1);
                                        errorVarName = catchCode.Trim();
                                    }

                                    if (Regex.IsMatch(catchCode, REGEX_CATCHCONDITION))
                                    {
                                        errorVarName = catchCode.Remove(catchCode.IndexOf(" "));
                                        string conditionCode = catchCode.Remove(0, catchCode.IndexOf("if") + 3);

                                        var processor = new ScriptProcessor(Context, GetLineNumber());
                                        processor.Context.AddVariable(errorVarName, errorObject);

                                        var conditionResult = processor.ExecuteStatement(new ScriptStatement(conditionCode));

                                        if (conditionResult is SBool)
                                            foundMatchingCatch = ((SBool)conditionResult).Value;
                                        else
                                            foundMatchingCatch = conditionResult.ToBool(this).Value;

                                        if (foundMatchingCatch)
                                            returnObject = processor.ExecuteStatement(catchExecuteStatement);
                                    }
                                    else
                                    {
                                        foundMatchingCatch = true;
                                        var processor = new ScriptProcessor(Context, GetLineNumber());
                                        processor.Context.AddVariable(errorVarName, errorObject);
                                        returnObject = processor.ExecuteStatement(catchExecuteStatement);
                                    }
                                }
                            }
                            else
                            {
                                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
                            }
                        }
                        else
                        {
                            // end search if different statement type appears:
                            endedCatchSearch = true;
                        }

                        findCatchIndex += 2;
                    }
                }
                else
                {
                    var findCatchIndex = _index + 1;
                    while (findCatchIndex < _statements.Length)
                    {
                        if (_statements[findCatchIndex].StatementType == StatementType.Catch)
                        {
                            foundCatch = true;
                            _index = findCatchIndex + 1;
                        }
                        else
                        {
                            findCatchIndex = _statements.Length;
                        }

                        findCatchIndex += 2;
                    }
                }

                // if no matching catch was found when an error occurred, it was not caught: throw it!
                if (encounteredError && !foundMatchingCatch)
                    return ErrorHandler.ThrowError(errorObject);

                // now, try to find finally statement:
                var findFinallyIndex = _index + 1;
                while (findFinallyIndex < _statements.Length && !foundFinally)
                {
                    if (_statements[findFinallyIndex].StatementType == StatementType.Finally)
                    {
                        _index = findFinallyIndex + 1;

                        if (_statements.Length > _index)
                        {
                            var finallyExecuteStatement = _statements[_index];
                            foundFinally = true;

                            returnObject = ExecuteStatement(finallyExecuteStatement);
                        }
                        else
                        {
                            return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
                        }
                    }
                    else
                    {
                        findFinallyIndex = _statements.Length;
                    }

                    findFinallyIndex += 2;
                }

                if (!foundCatch && !foundFinally) // when no catch or finally block has been found, throw an error.
                    return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_CATCH_OR_FINALLY);
                else
                    return returnObject;
            }
            else
            {
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
            }
        }
Пример #40
0
        private SObject ExecuteExecutable(ScriptStatement statement)
        {
            if (statement.IsCompoundStatement)
            {
                var processor = new ScriptProcessor(Context, GetLineNumber());

                // Remove { and }:
                var code = statement.Code.Remove(0, 1);
                code = code.Remove(code.Length - 1, 1);

                var returnObject = processor.Run(code);

                _breakIssued = processor._breakIssued;
                _continueIssued = processor._continueIssued;
                _returnIssued = processor._returnIssued;

                return returnObject;
            }
            else
            {
                var exp = ResolveParentheses(statement.Code).Trim();

                #region QuickConvert

                // have quick conversions for small statements here
                // parameter statements are much faster that way:
                if (exp == SObject.LITERAL_BOOL_TRUE)
                {
                    return CreateBool(true);
                }
                else if (exp == SObject.LITERAL_BOOL_FALSE)
                {
                    return CreateBool(false);
                }
                else if (exp == SObject.LITERAL_UNDEFINED || exp == "")
                {
                    return Undefined;
                }
                else if (exp == SObject.LITERAL_NULL)
                {
                    return Null;
                }
                else if (exp.StartsWith("\"") && exp.EndsWith("\"") && !exp.Remove(exp.Length - 1, 1).Remove(0, 1).Contains("\""))
                {
                    return CreateString(exp.Remove(exp.Length - 1, 1).Remove(0, 1));
                }
                else if (exp.All(char.IsDigit))
                {
                    double num;
                    SNumber.TryParse(exp, out num);
                    return CreateNumber(num);
                }

                #endregion

                if (exp.Contains("=>"))
                    exp = EvaluateLambda(exp);
                if (exp.Contains("."))
                    exp = EvaluateOperator(exp, ".");
                if (exp.Contains("++"))
                    exp = EvaluateOperator(exp, "++");
                if (exp.Contains("--"))
                    exp = EvaluateOperator(exp, "--");
                if (exp.Contains("!"))
                    exp = EvaluateReverseBool(exp);
                if (exp.Contains("**"))
                    exp = EvaluateOperator(exp, "**");
                if (exp.Contains("*"))
                    exp = EvaluateOperator(exp, "*");
                if (exp.Contains("/"))
                    exp = EvaluateOperator(exp, "/");
                if (exp.Contains("%"))
                    exp = EvaluateOperator(exp, "%");
                if (exp.Contains("+"))
                    exp = EvaluateOperator(exp, "+");
                if (exp.Contains("-"))
                    exp = EvaluateOperator(exp, "-");
                if (exp.Contains("<="))
                    exp = EvaluateOperator(exp, "<=");
                if (exp.Contains(">="))
                    exp = EvaluateOperator(exp, ">=");
                if (exp.Contains("<"))
                    exp = EvaluateOperator(exp, "<");
                if (exp.Contains(">"))
                    exp = EvaluateOperator(exp, ">");
                if (exp.Contains("==="))
                    exp = EvaluateOperator(exp, "===");
                if (exp.Contains("!=="))
                    exp = EvaluateOperator(exp, "!==");
                if (exp.Contains("=="))
                    exp = EvaluateOperator(exp, "==");
                if (exp.Contains("!="))
                    exp = EvaluateOperator(exp, "!=");
                if (exp.Contains("&&"))
                    exp = EvaluateOperator(exp, "&&");
                if (exp.Contains("||"))
                    exp = EvaluateOperator(exp, "||");

                return ToScriptObject(exp);
            }
        }