private Tuple <List <JsStatement>, int> ProcessInner(JsBlockStatement statement, ImmutableStack <Tuple <string, State> > breakStack, ImmutableStack <Tuple <string, State> > continueStack, ImmutableStack <Tuple <int, string> > finallyStack, int?parentState) { var oldLoopLabel = _currentLoopLabel; var oldRemainingBlocks = _remainingBlocks; try { _currentLoopLabel = _allocateLoopLabel(); _remainingBlocks = new Queue <RemainingBlock>(); _remainingBlocks.Enqueue(new RemainingBlock(ImmutableStack <StackEntry> .Empty.Push(new StackEntry(statement, 0)), breakStack, continueStack, CreateNewStateValue(finallyStack), new State(_currentLoopLabel, -1, finallyStack))); if (_exitState == null) { _exitState = new State(_currentLoopLabel, -1, ImmutableStack <Tuple <int, string> > .Empty); } var sections = new List <Section>(); int iterationCount = 0; while (_remainingBlocks.Count > 0) { var current = _remainingBlocks.Dequeue(); var list = Handle(current.Stack, current.BreakStack, current.ContinueStack, current.StateValue, current.ReturnState, _isIteratorBlock || _isAsync, true); // Merge all top-level blocks that should be merged with their parents. list = list.SelectMany(stmt => (stmt is JsBlockStatement && ((JsBlockStatement)stmt).MergeWithParent) ? ((JsBlockStatement)stmt).Statements : (IList <JsStatement>) new[] { stmt }).ToList(); sections.Add(new Section(current.StateValue, list)); if (iterationCount++ > 100000) { throw new Exception("Infinite loop when rewriting method to a state machine"); } } if (parentState != null && _isAsync) { List <int> childStates; if (!_childStates.TryGetValue(parentState.Value, out childStates)) { _childStates[parentState.Value] = childStates = new List <int>(); } childStates.AddRange(sections.Select(s => s.State.StateValue)); } var body = new List <JsStatement> { JsStatement.Label(_currentLoopLabel, JsStatement.For(JsStatement.Empty, null, null, JsStatement.Switch(JsExpression.Identifier(_stateVariableName), sections.Select(b => JsStatement.SwitchSection( GetAllContainedStateValues(b.State.StateValue).OrderBy(v => v).Select(v => JsExpression.Number(v)), JsStatement.Block(b.Statements))) .Concat(new[] { JsStatement.SwitchSection(new JsExpression[] { null }, JsStatement.Break(_currentLoopLabel)) })))) }; return(Tuple.Create(body, sections[0].State.StateValue)); } finally { _currentLoopLabel = oldLoopLabel; _remainingBlocks = oldRemainingBlocks; } }
public void LabelledStatementIsCorrectlyOutput() { AssertCorrect(JsStatement.Block(JsStatement.Label("lbl", JsExpression.Identifier("X"))), "{\n\tlbl:\n\tX;\n}\n"); }
public virtual JsStatement VisitLabelledStatement(JsLabelledStatement statement, TData data) { var stmt = VisitStatement(statement.Statement, data); return(ReferenceEquals(stmt, statement.Statement) ? statement : JsStatement.Label(statement.Label, stmt)); }