Beispiel #1
0
 public void Run(AstNode node)
 {
     Run(node, null);
     // Declare all the variables at the end, after all the logic has run.
     // This is done so that definite assignment analysis can work on a single representation and doesn't have to be updated
     // when we change the AST.
     foreach (var v in variablesToDeclare)
     {
         if (v.ReplacedAssignment == null)
         {
             BlockStatement block = (BlockStatement)v.InsertionPoint.Parent;
             var            decl  = new VariableDeclarationStatement(v.ILVariable != null && v.ILVariable.IsParameter ? TextTokenKind.Parameter : TextTokenKind.Local, (AstType)v.Type.Clone(), v.Name);
             if (v.ILVariable != null)
             {
                 decl.Variables.Single().AddAnnotation(v.ILVariable);
             }
             block.Statements.InsertBefore(
                 v.InsertionPoint,
                 decl);
         }
     }
     // First do all the insertions, then do all the replacements. This is necessary because a replacement might remove our reference point from the AST.
     foreach (var v in variablesToDeclare)
     {
         if (v.ReplacedAssignment != null)
         {
             // We clone the right expression so that it doesn't get removed from the old ExpressionStatement,
             // which might be still in use by the definite assignment graph.
             VariableInitializer          initializer = new VariableInitializer(v.ILVariable != null && v.ILVariable.IsParameter ? TextTokenKind.Parameter : TextTokenKind.Local, v.Name, v.ReplacedAssignment.Right.Detach()).CopyAnnotationsFrom(v.ReplacedAssignment).WithAnnotation(v.ILVariable);
             VariableDeclarationStatement varDecl     = new VariableDeclarationStatement {
                 Type      = (AstType)v.Type.Clone(),
                 Variables = { initializer }
             };
             ExpressionStatement es = v.ReplacedAssignment.Parent as ExpressionStatement;
             if (es != null)
             {
                 // Note: if this crashes with 'Cannot replace the root node', check whether two variables were assigned the same name
                 es.ReplaceWith(varDecl.CopyAnnotationsFrom(es));
                 varDecl.AddAnnotation(es.GetAllRecursiveILRanges());
             }
             else
             {
                 varDecl.AddAnnotation(v.ReplacedAssignment.GetAllRecursiveILRanges());
                 v.ReplacedAssignment.ReplaceWith(varDecl);
             }
         }
     }
     variablesToDeclare.Clear();
 }
Beispiel #2
0
 public void Run(AstNode node)
 {
     Run(node, null);
     // Declare all the variables at the end, after all the logic has run.
     // This is done so that definite assignment analysis can work on a single representation and doesn't have to be updated
     // when we change the AST.
     foreach (var v in variablesToDeclare)
     {
         if (v.ReplacedAssignment == null)
         {
             BlockStatement block = (BlockStatement)v.InsertionPoint.Parent;
             block.Statements.InsertBefore(
                 v.InsertionPoint,
                 new VariableDeclarationStatement((AstType)v.Type.Clone(), v.Name));
         }
     }
     // First do all the insertions, then do all the replacements. This is necessary because a replacement might remove our reference point from the AST.
     foreach (var v in variablesToDeclare)
     {
         if (v.ReplacedAssignment != null)
         {
             // We clone the right expression so that it doesn't get removed from the old ExpressionStatement,
             // which might be still in use by the definite assignment graph.
             VariableDeclarationStatement varDecl = new VariableDeclarationStatement {
                 Type      = (AstType)v.Type.Clone(),
                 Variables = { new VariableInitializer(v.Name, v.ReplacedAssignment.Right.Detach()).CopyAnnotationsFrom(v.ReplacedAssignment) }
             };
             ExpressionStatement es = v.ReplacedAssignment.Parent as ExpressionStatement;
             if (es != null)
             {
                 es.ReplaceWith(varDecl.CopyAnnotationsFrom(es));
             }
             else
             {
                 v.ReplacedAssignment.ReplaceWith(varDecl);
             }
         }
     }
     variablesToDeclare = null;
 }
        Statement TransformForeachOnMultiDimArray(ExpressionStatement expressionStatement)
        {
            if (!context.Settings.ForEachStatement)
            {
                return(null);
            }
            Match     m;
            Statement stmt = expressionStatement;

            IL.ILVariable    collection         = null;
            IL.ILVariable[]  upperBounds        = null;
            List <Statement> statementsToDelete = new List <Statement>();
            int i = 0;

            // first we look for all the upper bound initializations
            do
            {
                m = variableAssignUpperBoundPattern.Match(stmt);
                if (!m.Success)
                {
                    break;
                }
                if (upperBounds == null)
                {
                    collection = m.Get <IdentifierExpression>("collection").Single().GetILVariable();
                    if (!(collection?.Type is Decompiler.TypeSystem.ArrayType arrayType))
                    {
                        break;
                    }
                    upperBounds = new IL.ILVariable[arrayType.Dimensions];
                }
                else
                {
                    statementsToDelete.Add(stmt);
                }
                var nextCollection = m.Get <IdentifierExpression>("collection").Single().GetILVariable();
                if (nextCollection != collection)
                {
                    break;
                }
                if (!int.TryParse(m.Get <PrimitiveExpression>("index").Single().Value?.ToString() ?? "", out int index) || index != i)
                {
                    break;
                }
                upperBounds[i] = m.Get <IdentifierExpression>("variable").Single().GetILVariable();
                stmt           = stmt.GetNextStatement();
                i++;
            } while (stmt != null && i < upperBounds.Length);

            if (upperBounds?.LastOrDefault() == null || collection == null)
            {
                return(null);
            }
            if (!MatchForeachOnMultiDimArray(upperBounds, collection, stmt, out var foreachVariable, out var statements, out var lowerBounds))
            {
                return(null);
            }
            statementsToDelete.Add(stmt);
            statementsToDelete.Add(stmt.GetNextStatement());
            var itemVariable = foreachVariable.GetILVariable();

            if (itemVariable == null || !itemVariable.IsSingleDefinition ||
                !upperBounds.All(ub => ub.IsSingleDefinition && ub.LoadCount == 1) ||
                !lowerBounds.All(lb => lb.StoreCount == 2 && lb.LoadCount == 3 && lb.AddressCount == 0))
            {
                return(null);
            }
            var body = new BlockStatement();

            foreach (var statement in statements)
            {
                body.Statements.Add(statement.Detach());
            }
            var foreachStmt = new ForeachStatement {
                VariableType      = context.Settings.AnonymousTypes && itemVariable.Type.ContainsAnonymousType() ? new SimpleType("var") : context.TypeSystemAstBuilder.ConvertType(itemVariable.Type),
                VariableName      = itemVariable.Name,
                InExpression      = m.Get <IdentifierExpression>("collection").Single().Detach(),
                EmbeddedStatement = body
            };

            foreach (var statement in statementsToDelete)
            {
                statement.Detach();
            }
            //foreachStmt.CopyAnnotationsFrom(forStatement);
            itemVariable.Kind = IL.VariableKind.ForeachLocal;
            // Add the variable annotation for highlighting (TokenTextWriter expects it directly on the ForeachStatement).
            foreachStmt.AddAnnotation(new ILVariableResolveResult(itemVariable, itemVariable.Type));
            // TODO : add ForeachAnnotation
            expressionStatement.ReplaceWith(foreachStmt);
            return(foreachStmt);
        }