Search in sources :

Example 1 with EnhancedForIntermediate

use of org.candle.decompiler.intermediate.code.loop.EnhancedForIntermediate in project candle-decompiler by bradsdavis.

the class ArrayForToEnhancedFor method visitForIntermediate.

@Override
public void visitForIntermediate(ForIntermediate line) {
    // we need to look at the previous 2 statements and the first statement child.
    AbstractIntermediate arrayLenthCandidate = getForExteriorPredecessor(line);
    // check that the array length candidate's declared length variable is used in the for's condition.
    AbstractIntermediate tempArrayCandidate = null;
    AbstractIntermediate firstChild = igc.getTrueTarget(line);
    if (arrayLenthCandidate != null) {
        tempArrayCandidate = getSinglePredecessor(arrayLenthCandidate);
    }
    // if either of these are null, then this doesn't match.
    if (arrayLenthCandidate == null || tempArrayCandidate == null) {
        return;
    }
    GeneratedVariable generatedArrayLength = extractGeneratedVariableDeclaration(arrayLenthCandidate);
    GeneratedVariable generatedArrayReference = extractGeneratedVariableDeclaration(tempArrayCandidate);
    GeneratedVariable arrayIteratorValue = extractGeneratedVariableDeclaration(line.getInit());
    if (generatedArrayLength == null || generatedArrayReference == null || arrayIteratorValue == null) {
        return;
    }
    if (generatedArrayLength.getType() != Type.INT) {
        if (!(generatedArrayReference.getType() instanceof ArrayType)) {
            return;
        }
        if (arrayIteratorValue.getType() != Type.INT) {
            return;
        }
    }
    // great; at this point we know the pattern matches.  check the next statement to see if the transformation is possible.
    // format should be: 40 : GENERATED_ARRAY_REFERENCE_TYPE i = GENERATED_ARRAY_REFERENCE[ARRAY_ITERATOR_VALUE] |
    StatementIntermediate childDeclarationStatement = ((StatementIntermediate) firstChild);
    Declaration childDeclaration = (Declaration) childDeclarationStatement.getExpression();
    if (firstMatchesGeneratedVariables(childDeclarationStatement, generatedArrayReference, arrayIteratorValue)) {
        LOG.debug("Likely a enhanced for loop for array: " + generatedArrayLength + " , " + generatedArrayReference);
        // we are good to go here.  Now we just need to reorganize the graph.  Start by creating the new enhanced for loop.
        EnhancedForIntermediate efl = new EnhancedForIntermediate(line.getInstruction(), line.getConditionalIntermediate(), childDeclaration.getVariable(), extractExpressionFromGeneratedArrayAssignment(tempArrayCandidate));
        // efl.setTrueBranch(line.getTrueBranch());
        // efl.setFalseBranch(line.getFalseBranch());
        // add the new node...
        this.igc.getGraph().addVertex(efl);
        // now, we just need to redirect.
        igc.redirectPredecessors(tempArrayCandidate, efl);
        igc.redirectPredecessors(line, efl);
        igc.redirectSuccessors(line, efl);
        AbstractIntermediate nextChild = getSingleSuccessor(firstChild);
        igc.redirectPredecessors(firstChild, nextChild);
        // remove line.
        igc.getGraph().removeVertex(line);
        igc.getGraph().removeVertex(tempArrayCandidate);
        igc.getGraph().removeVertex(firstChild);
        igc.getGraph().removeVertex(arrayLenthCandidate);
    }
}
Also used : AbstractIntermediate(org.candle.decompiler.intermediate.code.AbstractIntermediate) ArrayType(org.apache.bcel.generic.ArrayType) GeneratedVariable(org.candle.decompiler.intermediate.expression.GeneratedVariable) EnhancedForIntermediate(org.candle.decompiler.intermediate.code.loop.EnhancedForIntermediate) StatementIntermediate(org.candle.decompiler.intermediate.code.StatementIntermediate) Declaration(org.candle.decompiler.intermediate.expression.Declaration)

Example 2 with EnhancedForIntermediate

use of org.candle.decompiler.intermediate.code.loop.EnhancedForIntermediate in project candle-decompiler by bradsdavis.

the class WhileToForLoopIterator method visitWhileIntermediate.

@Override
public void visitWhileIntermediate(WhileIntermediate line) {
    if (line.getExpression() instanceof SingleConditional) {
        if (((SingleConditional) line.getExpression()).getExpression() instanceof MethodInvocation) {
            MethodInvocation mi = (MethodInvocation) ((SingleConditional) line.getExpression()).getExpression();
            String iteratorName = null;
            if (mi.getTarget() instanceof Variable) {
                iteratorName = ((Variable) mi.getTarget()).getName();
            } else {
                return;
            }
            if (StringUtils.equals("hasNext", mi.getMethodName())) {
                // probably an iterator.
                List<AbstractIntermediate> predecessors = Graphs.predecessorListOf(igc.getGraph(), line);
                // look at the predecessor lines;  validate there are only 2 predecessors.
                if (predecessors.size() == 2) {
                    StatementIntermediate declaration = null;
                    for (AbstractIntermediate predecessor : predecessors) {
                        if (comparator.before(predecessor, line)) {
                            if (predecessor instanceof StatementIntermediate) {
                                declaration = (StatementIntermediate) predecessor;
                                break;
                            }
                        }
                    }
                    // check to see if the declaration is a temporary variable..
                    if (declaration == null) {
                        return;
                    }
                    // otherwise, let's see if the declaration is an iterator.
                    if (declaration.getExpression() instanceof Declaration) {
                        Declaration declarationExpression = (Declaration) declaration.getExpression();
                        Variable v = (Variable) declarationExpression.getAssignment().getLeftHandSide();
                        // check to see if the declaration is the same as the iterator's name.
                        if (StringUtils.equals(iteratorName, v.getName())) {
                            LOG.debug("Identified Likely Iterator: " + v.getName());
                            // get the ".next()" statement, which should be the first child.
                            AbstractIntermediate firstChild = igc.getTrueTarget(line);
                            // then check the right side to see if it is an invocation.. and the invocation has the method name "next"...
                            if (firstChild instanceof StatementIntermediate) {
                                StatementIntermediate nextStatement = (StatementIntermediate) firstChild;
                                if (nextStatement.getExpression() instanceof Declaration) {
                                    // the statement is indeed a declaration.
                                    Declaration nextDeclaration = (Declaration) nextStatement.getExpression();
                                    if (nextDeclaration.getAssignment().getRightHandSide() instanceof MethodInvocation) {
                                        MethodInvocation nextMethodInvocation = (MethodInvocation) nextDeclaration.getAssignment().getRightHandSide();
                                        if (StringUtils.equals("next", nextMethodInvocation.getMethodName())) {
                                            // check to see if the next method is on the candidate iterator.
                                            if (nextMethodInvocation.getTarget() instanceof Variable) {
                                                Variable nextMethodTarget = (Variable) nextMethodInvocation.getTarget();
                                                if (StringUtils.equals(iteratorName, nextMethodTarget.getName())) {
                                                    LOG.info("Definitely an enhanced for loop.");
                                                    if (declarationExpression.getAssignment().getRightHandSide() instanceof MethodInvocation) {
                                                        MethodInvocation iteratorInvocation = (MethodInvocation) declarationExpression.getAssignment().getRightHandSide();
                                                        if (StringUtils.equals("iterator", iteratorInvocation.getMethodName())) {
                                                            // now, we are pretty certain this is an enhanced for loop...  we can chop up the graph.
                                                            EnhancedForIntermediate enhancedFor = new EnhancedForIntermediate(line, nextDeclaration.getVariable(), iteratorInvocation.getTarget());
                                                            igc.getGraph().addVertex(enhancedFor);
                                                            igc.redirectSuccessors(line, enhancedFor);
                                                            igc.redirectPredecessors(line, enhancedFor);
                                                            igc.getGraph().removeVertex(line);
                                                            igc.redirectPredecessors(declaration, igc.getSingleSuccessor(declaration));
                                                            igc.getGraph().removeVertex(declaration);
                                                            igc.redirectPredecessors(firstChild, igc.getSingleSuccessor(firstChild));
                                                            igc.getGraph().removeVertex(firstChild);
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
Also used : AbstractIntermediate(org.candle.decompiler.intermediate.code.AbstractIntermediate) Variable(org.candle.decompiler.intermediate.expression.Variable) EnhancedForIntermediate(org.candle.decompiler.intermediate.code.loop.EnhancedForIntermediate) StatementIntermediate(org.candle.decompiler.intermediate.code.StatementIntermediate) SingleConditional(org.candle.decompiler.intermediate.expression.SingleConditional) MethodInvocation(org.candle.decompiler.intermediate.expression.MethodInvocation) Declaration(org.candle.decompiler.intermediate.expression.Declaration)

Aggregations

AbstractIntermediate (org.candle.decompiler.intermediate.code.AbstractIntermediate)2 StatementIntermediate (org.candle.decompiler.intermediate.code.StatementIntermediate)2 EnhancedForIntermediate (org.candle.decompiler.intermediate.code.loop.EnhancedForIntermediate)2 Declaration (org.candle.decompiler.intermediate.expression.Declaration)2 ArrayType (org.apache.bcel.generic.ArrayType)1 GeneratedVariable (org.candle.decompiler.intermediate.expression.GeneratedVariable)1 MethodInvocation (org.candle.decompiler.intermediate.expression.MethodInvocation)1 SingleConditional (org.candle.decompiler.intermediate.expression.SingleConditional)1 Variable (org.candle.decompiler.intermediate.expression.Variable)1