示例#1
0
        /// <summary>
        /// Splits a <see cref="ForStatement"/> into a set of cases
        /// </summary>
        /// <returns>The number of new fragments.</returns>
        /// <param name="statement">The statement(s) to split.</param>
        /// <param name="collected">The currently collected statements.</param>
        /// <param name="fragments">The currently collected fragments.</param>
        private int SplitStatement(ForStatement statement, List <Statement> collected, List <List <Statement> > fragments)
        {
            if (!statement.All().OfType <AwaitExpression>().Any())
            {
                try
                {
                    statement.GetStaticForLoopValues();

                    // If this is a basic static loop, just treat it as a normal
                    collected.Add(statement);
                    return(0);
                }
                catch
                {
                    throw new Exception($"Cannot process a non-static for loop without await calls in the body");
                }
            }

            collected.Add(
                new ExpressionStatement(
                    new AssignmentExpression(
                        new IdentifierExpression(statement.LoopIndex), statement.Initializer)));
            EndFragment(collected, fragments, fragments.Count + 2, true);

            collected.Add(new ExpressionStatement(statement.Increment));
            EndFragment(collected, fragments, fragments.Count + 1, true);

            var ifs = new IfElseStatement(statement.Condition, new EmptyStatement(), new EmptyStatement());

            collected.Add(ifs);
            var selflabel = fragments.Count;

            EndFragment(collected, fragments, -1, true);

            var extras = SplitStatement(statement.LoopBody, collected, fragments);
            List <Statement> trueStatements;

            // Build the loop body into a list
            if (extras == 0)
            {
                trueStatements = new List <Statement>(collected);
                collected.Clear();
            }
            else
            {
                trueStatements = fragments[selflabel + 1];
                fragments.RemoveAt(selflabel + 1);
                extras--;
            }

            // TODO: Handle if we fall out of the loop
            if (!(trueStatements.Last() is CaseGotoStatement))
            {
                trueStatements.Add(new CaseGotoStatement(selflabel - 1, true));
            }
            // Jump to self, not next at the end of the loop
            else
            {
                trueStatements[trueStatements.Count - 1] = new CaseGotoStatement(selflabel - 1, false);
            }

            ifs.TrueStatement  = ToBlockStatement(trueStatements);
            ifs.FalseStatement = new CaseGotoStatement(fragments.Count, true);

            return(extras + 3);
        }