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("(", StringComparison.Ordinal) + 1); taskName = taskName.Remove(taskName.LastIndexOf(")", StringComparison.Ordinal)).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); }
private SObject ExecuteFor(ScriptStatement statement) { var exp = statement.Code; var forCode = exp.Remove(0, exp.IndexOf("for", StringComparison.Ordinal) + "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.MessageSyntaxExpectedExpression, ")")); } if (forStatements.Length == 1) { return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxMissingForInitializer)); } if (forStatements.Length == 2) { return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxMissingForCondition)); } if (forStatements.Length > 3) { return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxMissingForControl)); } 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); var conditionAsBool = conditionResult as SBool; stayInFor = conditionAsBool?.Value ?? 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.MessageSyntaxExpectedExpression, "end of script")); } }
private SObject ExecuteTry(ScriptStatement statement) { var exp = statement.Code; if (exp != "try") { return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxMissingBeforeTry)); } _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, RegexCatchcondition)) { errorVarName = catchCode.Remove(catchCode.IndexOf(" ", StringComparison.Ordinal)); var conditionCode = catchCode.Remove(0, catchCode.IndexOf("if", StringComparison.Ordinal) + 3); var processor = new ScriptProcessor(Context, GetLineNumber()); processor.Context.AddVariable(errorVarName, errorObject); var conditionResult = processor.ExecuteStatement(new ScriptStatement(conditionCode)); var conditionAsBool = conditionResult as SBool; foundMatchingCatch = conditionAsBool?.Value ?? 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.MessageSyntaxExpectedExpression, "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.MessageSyntaxExpectedExpression, "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.MessageSyntaxMissingCatchOrFinally)); } else { return(returnObject); } } else { return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxExpectedExpression, "end of script")); } }