Ejemplo n.º 1
0
        public override void EnterForStatement(ForStatement forStatement)
        {
            var block           = (BlockStatement)forStatement.Parent;
            var addedStatements = new List <IStatement>();

            var allowedConditionOperators = new[] { "==", "!=", "<", ">", "<=", ">=" };
            var allowedUpdateOperators    = new[] { "+", "-", "*", "/", "%" };

            if (forStatement.Variables.Count() == 1 &&
                forStatement.Variables.Single() is VariableDeclaration singleVariable &&
                singleVariable.Type is NumberType &&
                singleVariable.InitExpression is NumberLiteral initLiteral &&
                !forStatement.InitExpressions.Any() &&
                forStatement.Condition is BinaryExpression condition &&
                condition.Left is SimpleNameExpression conditionVar &&
                conditionVar.Declaration == singleVariable &&
                condition.Right is NumberLiteral &&
                allowedConditionOperators.Contains(condition.Operator.Text) &&
                forStatement.NextExpressions.Count() == 1 &&
                forStatement.NextExpressions.Single() is AssignmentExpression update &&
                update.Left is SimpleNameExpression updateVarWrite &&
                updateVarWrite.Declaration == singleVariable &&
                update.Right is BinaryExpression updateBinaryExpression &&
                allowedUpdateOperators.Contains(updateBinaryExpression.Operator.Text) &&
                updateBinaryExpression.Left is SimpleNameExpression updateVarRead &&
                updateVarRead.Declaration == singleVariable &&
                updateBinaryExpression.Right is NumberLiteral &&
                CountIterations(initLiteral, condition, updateBinaryExpression) is List <double> iterations)
            {
                var breakGotoTarget = new GotoTargetStatement(forStatement.Context);
                foreach (var iteration in iterations)
                {
                    var continueGotoTarget = new GotoTargetStatement(forStatement.Context);
                    var clone = AstCloner.Clone(forStatement);
                    ReplaceContinueAndBreakStatements(
                        clone,
                        new GotoStatement(clone.Context, breakGotoTarget),
                        new GotoStatement(clone.Context, continueGotoTarget));

                    var variable = clone.Variables.Single();
                    variable.InitExpression.ReplaceWith(new NumberLiteral(variable.Context, iteration));
                    var variableDeclarationStatement = new VariableDeclarationStatement(variable.Context, variable);
                    block.AddChildBefore(forStatement, variableDeclarationStatement);
                    block.AddChildBefore(forStatement, clone.Body);
                    block.AddChildBefore(forStatement, continueGotoTarget);


                    addedStatements.Add(variableDeclarationStatement);
                    addedStatements.Add(clone.Body);
                    addedStatements.Add(continueGotoTarget);
                }
                block.AddChildBefore(forStatement, breakGotoTarget);
                addedStatements.Add(breakGotoTarget);

                forStatement.Remove();
            }