bool ForStatementUsesVariable(ForStatement statement, IL.ILVariable variable) { if (statement.Condition.DescendantsAndSelf.OfType <IdentifierExpression>().Any(ie => ie.GetILVariable() == variable)) { return(true); } if (statement.Iterators.Any(i => i.DescendantsAndSelf.OfType <IdentifierExpression>().Any(ie => ie.GetILVariable() == variable))) { return(true); } return(false); }
bool MatchLowerBound(int indexNum, out IL.ILVariable index, IL.ILVariable collection, Statement statement) { index = null; var m = variableAssignLowerBoundPattern.Match(statement); if (!m.Success) { return(false); } if (!int.TryParse(m.Get <PrimitiveExpression>("index").Single().Value.ToString(), out int i) || indexNum != i) { return(false); } index = m.Get <IdentifierExpression>("variable").Single().GetILVariable(); return(m.Get <IdentifierExpression>("collection").Single().GetILVariable() == collection); }
bool MatchForeachOnMultiDimArray(IL.ILVariable[] upperBounds, IL.ILVariable collection, Statement firstInitializerStatement, out IdentifierExpression foreachVariable, out IList <Statement> statements, out IL.ILVariable[] lowerBounds) { int i = 0; foreachVariable = null; statements = null; lowerBounds = new IL.ILVariable[upperBounds.Length]; Statement stmt = firstInitializerStatement; Match m = default(Match); while (i < upperBounds.Length && MatchLowerBound(i, out IL.ILVariable indexVariable, collection, stmt)) { m = forOnArrayMultiDimPattern.Match(stmt.GetNextStatement()); if (!m.Success) { return(false); } var upperBound = m.Get <IdentifierExpression>("upperBoundVariable").Single().GetILVariable(); if (upperBounds[i] != upperBound) { return(false); } stmt = m.Get <Statement>("lowerBoundAssign").Single(); lowerBounds[i] = indexVariable; i++; } var m2 = foreachVariableOnMultArrayAssignPattern.Match(stmt); if (!m2.Success) { return(false); } var collection2 = m2.Get <IdentifierExpression>("collection").Single().GetILVariable(); if (collection2 != collection) { return(false); } foreachVariable = m2.Get <IdentifierExpression>("variable").Single(); statements = m.Get <Statement>("statements").ToList(); return(true); }
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); }