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;
            }
        }
示例#2
0
 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));
        }