private async Task <DynValue> ExecuteStatementList(List <AstNode> statements, CancellationToken token) { var retVal = DynValue.Zero; if (BreakExecution) { BreakExecution = false; throw new ScriptTerminationException("Execution stopped by user."); } foreach (var statement in statements) { do { token.ThrowIfCancellationRequested(); } while (SuspendExecution); if (BreakExecution) { BreakExecution = false; throw new ScriptTerminationException("Execution stopped by user."); } if (LoopStack.Count > 0) { var loopStackTop = LoopStack.Peek(); if (loopStackTop.BreakLoop || loopStackTop.SkipThisIteration) { break; } } if (CallStack.Count > 0) { var callStackTop = CallStack.Peek(); if (callStackTop.ReturnNow) { retVal = callStackTop.ReturnValue; break; } } retVal = Visit(statement); } return(retVal); }
public override DynValue Visit(ForLoopNode forLoopNode) { _ = Visit(forLoopNode.Assignment).Number; DynValue step = new DynValue(1); var targetValue = Visit(forLoopNode.TargetValue); if (forLoopNode.Step != null) { step = Visit(forLoopNode.Step); } var isLocalScope = false; var assignmentNode = (forLoopNode.Assignment as AssignmentNode); var iteratorName = assignmentNode.Variable.Name; if (assignmentNode.LocalScope) { isLocalScope = true; } try { LoopStack.Push(new LoopStackItem()); while (true) { ExecuteStatementList(forLoopNode.StatementList).GetAwaiter().GetResult(); double iterator; if (isLocalScope) { var callStackTop = CallStack.Peek(); iterator = callStackTop.LocalVariableScope[iteratorName].Number; } else { iterator = Environment.Globals[iteratorName].Number; } if (step.Number < 0) { if (iterator < targetValue.Number) { break; } else { iterator -= step.Number; } } else { if (iterator >= targetValue.Number) { break; } else { iterator += step.Number; } } if (isLocalScope) { // no throw on localvar token, so // guaranteed we're inside a function var callStackTop = CallStack.Peek(); callStackTop.LocalVariableScope[iteratorName] = new DynValue(iterator); } else { Environment.Globals[iteratorName] = new DynValue(iterator); } var loopStackTop = LoopStack.Peek(); if (loopStackTop.BreakLoop) { break; } if (loopStackTop.SkipThisIteration) { loopStackTop.SkipThisIteration = false; continue; } } } catch { throw; } finally { LoopStack.Pop(); } return(DynValue.Zero); }