diff --git a/src/de/dhbwstuttgart/bytecode/utilities/Simplify.java b/src/de/dhbwstuttgart/bytecode/utilities/Simplify.java index 41357af06..c96d21e16 100644 --- a/src/de/dhbwstuttgart/bytecode/utilities/Simplify.java +++ b/src/de/dhbwstuttgart/bytecode/utilities/Simplify.java @@ -16,7 +16,7 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; public class Simplify { public static HashMap> simplifyConstraints(String name, TPHExtractor tphExtractor) { - // 1. check if there are any cycles like L set L=R and: // * remove both constraints // * substitute L with R in all constraint @@ -28,8 +28,10 @@ public class Simplify { // b) no // 3. is + // all constraints that will be simplified ArrayList allCons = tphExtractor.allCons; ArrayList consToRemove = new ArrayList<>(); + // step 1: for(TPHConstraint c : allCons) { @@ -39,12 +41,16 @@ public class Simplify { TPHConstraint revCon = getReverseConstraint(allCons,left,right); if(revCon != null) { revCon.setRel(Relation.EQUAL); + // the reverse constraint is removed because + // otherwise there is twice the same constraint + // (e.g. A A=B and B=A) consToRemove.add(revCon); c.setRel(Relation.EQUAL); substituteTPH(allCons,left, right); } } } + System.out.println(); System.out.println("NEW ALL CONST: " + allCons.size()); allCons.forEach(c->System.out.println(c.toString())); @@ -59,51 +65,75 @@ public class Simplify { System.out.println("----------------"); HashMap> result = new HashMap<>(); + // check if there is any long cycle (e.g. A allTypes = new LinkedList<>(); + // we will put all constraints which are in the cycle, in this ArrayList. + // Later these contraints will be converted to equal-constraints ArrayList constraints = new ArrayList<>(size); int visited = 0; + + // contains all constraints + HashMap ss1 = new HashMap<>(); + + for(TPHConstraint constr : allCons) { + ss1.put(constr.getLeft(), constr.getRight()); + } + for(TPHConstraint c : allCons) { + if(visited >= size) break; - + // Only extends-constraints will be checked if(c.getRel() == Relation.EXTENDS) { ++visited; String left = c.getLeft(); String right = c.getRight(); - + // put the types in linked list allTypes.add(left); allTypes.add(right); constraints.add(c); - HashMap ss1 = new HashMap<>(); - for(TPHConstraint constr : allCons) { - ss1.put(constr.getLeft(), constr.getRight()); - } - boolean isCycle = false; + boolean isCycle = false; + + // iterate through the map to check if there is a cycle while(ss1.containsKey(right)) { ++visited; String oldRight = right; right = ss1.get(right); + TPHConstraint toAdd = getConstraint(oldRight, right, allCons); + if(toAdd != null) constraints.add(toAdd); + if(left.equals(right)) { isCycle = true; break; } + allTypes.add(right); } + if(isCycle) { + // convert all constraints to equal constraints setAllEqual(constraints); + // these constraints will be removed from allCons consToRemove.addAll(constraints); + // all equal types will be substitute with one type substituteAllTPH(allCons,constraints,left); + HashSet eq = new HashSet<>(); + // put all equal types in a set for(String t:allTypes) { eq.add(t); } + // generate a new constraint (left < Object) TPHConstraint constraint = new ExtendsConstraint(left, Type.getInternalName(Object.class), Relation.EXTENDS); + // put the generated constraint and its equal set into result set result.put(constraint, eq); constraints.clear(); allTypes.clear(); @@ -111,7 +141,10 @@ public class Simplify { } } - + // build an equal set that contains all types + // which are equal and for each equal constraint put left side and right side + // in this set Then generate a constraint type < Object and put it + // with the equal set into the result. for(TPHConstraint c : allCons) { if(c.getRel()==Relation.EQUAL) { if(!isTPHInResEqual(result, c.getLeft())) { @@ -125,6 +158,7 @@ public class Simplify { size--; } } + System.out.println("Step 2 Result: "); result.forEach((c,hs)->{ System.out.print(c.toString() + " -> "); @@ -134,7 +168,9 @@ public class Simplify { System.out.println(); }); System.out.println("----------------"); + // remove all equal-constraints allCons.removeAll(consToRemove); + // add all generated constraints to allCons allCons.addAll(result.keySet()); if(!allCons.isEmpty() && allCons.size()<2) { @@ -146,11 +182,13 @@ public class Simplify { } size += result.keySet().size(); - + // all constraints which have Object on the right side will + // be ignored, because they are simplified and can not be changed. for(TPHConstraint c : allCons) { if(c.getRight().equals(Type.getInternalName(Object.class))) size--; } + // get all tph of the method ArrayList methodTphs = new ArrayList<>(); for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { if(m.getName().equals(name)) { @@ -158,7 +196,9 @@ public class Simplify { break; } } - + // check if there are multiple constraint with the same left side. + // if yes => check if the super type in the method, if not + // then ignore it. HashMap subAndSuper = new HashMap<>(); for(TPHConstraint c : allCons) { if(subAndSuper.containsKey(c.getLeft())) { @@ -210,6 +250,8 @@ public class Simplify { // Die größte Supertype String superTphRes = tphInRel.getLast(); + // if there is any constraint X < subTph, then + // add X at the beginning of the list. while(subAndSuper.containsValue(subTphRes)) { for(String tph : subAndSuper.keySet()) { if(containTPH(methodTphs,tph) && subAndSuper.get(tph).equals(subTphRes)) { @@ -220,12 +262,18 @@ public class Simplify { if(subTphRes.equals(tphInRel.getFirst())) { break; } + + if(isTPHInConstraint(result, subTphRes)) + break; + tphInRel.addFirst(subTphRes); numOfVisitedPairs++; } subTphRes = tphInRel.getFirst(); - + // if the last type in the list not a type in method-types + // then find the last type in front of this type, which is + // a type in method-types int i = 2; while(!containTPH(methodTphs,superTphRes) && (tphInRel.size()-i) >0) { superTphRes = tphInRel.get(tphInRel.size()-i); @@ -236,7 +284,8 @@ public class Simplify { result.put(new ExtendsConstraint(subTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); } else { result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), null); - result.put(new ExtendsConstraint(superTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); + if(!isTPHInConstraint(result, superTphRes)) + result.put(new ExtendsConstraint(superTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); } } diff --git a/test/bytecode/simplifyalgo/SameLeftSide.java b/test/bytecode/simplifyalgo/SameLeftSide.java index 5cb807ea2..b5c4e875f 100644 --- a/test/bytecode/simplifyalgo/SameLeftSide.java +++ b/test/bytecode/simplifyalgo/SameLeftSide.java @@ -2,14 +2,19 @@ package bytecode.simplifyalgo; import static org.junit.Assert.*; +import java.util.HashMap; +import java.util.HashSet; + import org.junit.BeforeClass; import org.junit.Test; +import org.objectweb.asm.Type; import de.dhbwstuttgart.bytecode.TPHExtractor; import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint; import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; +import de.dhbwstuttgart.bytecode.utilities.Simplify; import de.dhbwstuttgart.typedeployment.TypeInsertPlacer; /** @@ -22,6 +27,7 @@ public class SameLeftSide { // private ist => Test geht nicht private static TPHExtractor tphExtractor; private static String methName; + private static String methName2; @BeforeClass public static void setUpBeforeClass() throws Exception { @@ -38,11 +44,54 @@ public class SameLeftSide { methName = "m1"; MethodAndTPH m1 = new MethodAndTPH("m1"); -// tphExtractor.ListOfMethodsAndTph.add(e) + methName2 = "m2"; + MethodAndTPH m2 = new MethodAndTPH("m2"); + + m1.getTphs().add("A"); + m1.getTphs().add("B"); + m1.getTphs().add("D"); + + m2.getTphs().add("C"); + m2.getTphs().add("E"); + + tphExtractor.ListOfMethodsAndTph.add(m1); + tphExtractor.ListOfMethodsAndTph.add(m2); + tphExtractor.allCons.add(c1); tphExtractor.allCons.add(c2); + tphExtractor.allCons.add(c3); + tphExtractor.allCons.add(c4); } + @Test + public void testM1() { + HashMap> result = new HashMap<>(); + + TPHConstraint d = new ExtendsConstraint("D", Type.getInternalName(Object.class), Relation.EXTENDS); + TPHConstraint a = new ExtendsConstraint("A", "D", Relation.EXTENDS); + TPHConstraint b = new ExtendsConstraint("B", "D", Relation.EXTENDS); + result.put(d, null); + result.put(a, null); + result.put(b, null); + + HashMap> sim = Simplify.simplifyConstraints(methName, tphExtractor); + boolean areEquals = SimpleCycle.areMapsEqual(result, sim); + assertTrue(areEquals); + } + @Test + public void testM2() { + HashMap> result = new HashMap<>(); + + TPHConstraint e = new ExtendsConstraint("E", Type.getInternalName(Object.class), Relation.EXTENDS); + TPHConstraint c = new ExtendsConstraint("C", "E", Relation.EXTENDS); + + result.put(e, null); + result.put(c, null); + + HashMap> sim = Simplify.simplifyConstraints(methName2, tphExtractor); + boolean areEquals = SimpleCycle.areMapsEqual(result, sim); + assertTrue(areEquals); + } } diff --git a/test/bytecode/simplifyalgo/SimpleCycle.java b/test/bytecode/simplifyalgo/SimpleCycle.java index ac05117e5..636eb026d 100644 --- a/test/bytecode/simplifyalgo/SimpleCycle.java +++ b/test/bytecode/simplifyalgo/SimpleCycle.java @@ -58,16 +58,17 @@ public class SimpleCycle { HashSet eq1 = m1.get(c); HashSet eq2 = m2.get(c2); - if(eq1.size() != eq2.size()) + if((eq1 == null && eq2 != null) || (eq1 != null && eq2 == null)) return false; - - for(String tph:eq1) { - if(!eq2.contains(tph)) + if(eq1 != null) { + if(eq1.size() != eq2.size()) return false; + + for(String tph:eq1) { + if(!eq2.contains(tph)) + return false; + } } - - }else { - return false; } }