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 virtual JsStatement VisitForStatement(JsForStatement statement, TData data)
        {
            var initStatement = statement.InitStatement != null?VisitStatement(statement.InitStatement, data)        : null;

            var condition = statement.ConditionExpression != null?VisitExpression(statement.ConditionExpression, data) : null;

            var iterator = statement.IteratorExpression != null?VisitExpression(statement.IteratorExpression, data)  : null;

            var body = VisitStatement(statement.Body, data);

            return(ReferenceEquals(initStatement, statement.InitStatement) && ReferenceEquals(condition, statement.ConditionExpression) && ReferenceEquals(iterator, statement.IteratorExpression) && ReferenceEquals(body, statement.Body)
                             ? statement
                             : JsStatement.For(initStatement, condition, iterator, body));
        }
Exemplo n.º 3
0
        public override JsStatement VisitForStatement(JsForStatement statement, object data)
        {
            var initStatement = statement.InitStatement != null?VisitStatement(statement.InitStatement, data)        : null;

            var condition = statement.ConditionExpression != null?VisitExpression(statement.ConditionExpression, data) : null;

            var iterator = statement.IteratorExpression != null?VisitExpression(statement.IteratorExpression, data)  : null;

            var body = VisitStatement(statement.Body, data);

            if (initStatement is JsBlockStatement)                      // Will happen if the init statement is a variable declaration without initializers.
            {
                Debug.Assert(((JsBlockStatement)initStatement).Statements.Count == 0);
                initStatement = JsStatement.Empty;
            }

            return(ReferenceEquals(initStatement, statement.InitStatement) && ReferenceEquals(condition, statement.ConditionExpression) && ReferenceEquals(iterator, statement.IteratorExpression) && ReferenceEquals(body, statement.Body)
                             ? statement
                             : JsStatement.For(initStatement, condition, iterator, body));
        }
        public void ForStatementsAreCorrectlyOutput()
        {
            AssertCorrect(JsStatement.For(JsStatement.Var("i", JsExpression.Number(0)),
                                          JsExpression.Lesser(JsExpression.Identifier("i"), JsExpression.Number(10)),
                                          JsExpression.PostfixPlusPlus(JsExpression.Identifier("i")),
                                          JsStatement.EmptyBlock),
                          "for(var i=0;i<10;i++){}");

            AssertCorrect(JsStatement.For(JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(0)),
                                          JsExpression.Lesser(JsExpression.Identifier("i"), JsExpression.Number(10)),
                                          JsExpression.PostfixPlusPlus(JsExpression.Identifier("i")),
                                          JsStatement.EmptyBlock),
                          "for(i=0;i<10;i++){}");

            AssertCorrect(JsStatement.For(JsStatement.Var(JsStatement.Declaration("i", JsExpression.Number(0)), JsStatement.Declaration("j", JsExpression.Number(1))),
                                          JsExpression.Lesser(JsExpression.Identifier("i"), JsExpression.Number(10)),
                                          JsExpression.Comma(JsExpression.PostfixPlusPlus(JsExpression.Identifier("i")), JsExpression.PostfixPlusPlus(JsExpression.Identifier("j"))),
                                          JsStatement.EmptyBlock),
                          "for(var i=0,j=1;i<10;i++,j++){}");

            AssertCorrect(JsStatement.For(JsStatement.Empty, null, null, JsStatement.EmptyBlock), "for(;;){}");
        }
        public override JsStatement VisitForStatement(JsForStatement statement, object data)
        {
            var body = VisitLoopBody(statement.Body, data);

            return(ReferenceEquals(body, statement.Body) ? statement : JsStatement.For(statement.InitStatement, statement.ConditionExpression, statement.IteratorExpression, body));
        }