forked from JavaTX/JavaCompilerCore
Bug in Simplify-Algo gefixt
This commit is contained in:
parent
a269ee9690
commit
7bfc222037
@ -16,7 +16,7 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
|||||||
public class Simplify {
|
public class Simplify {
|
||||||
|
|
||||||
public static HashMap<TPHConstraint, HashSet<String>> simplifyConstraints(String name, TPHExtractor tphExtractor) {
|
public static HashMap<TPHConstraint, HashSet<String>> simplifyConstraints(String name, TPHExtractor tphExtractor) {
|
||||||
// 1. check if there are any cycles like L<R and R<L:
|
// 1. check if there are any simple cycles like L<R and R<L:
|
||||||
// a) yes => set L=R and:
|
// a) yes => set L=R and:
|
||||||
// * remove both constraints
|
// * remove both constraints
|
||||||
// * substitute L with R in all constraint
|
// * substitute L with R in all constraint
|
||||||
@ -28,8 +28,10 @@ public class Simplify {
|
|||||||
// b) no
|
// b) no
|
||||||
// 3. is
|
// 3. is
|
||||||
|
|
||||||
|
// all constraints that will be simplified
|
||||||
ArrayList<TPHConstraint> allCons = tphExtractor.allCons;
|
ArrayList<TPHConstraint> allCons = tphExtractor.allCons;
|
||||||
ArrayList<TPHConstraint> consToRemove = new ArrayList<>();
|
ArrayList<TPHConstraint> consToRemove = new ArrayList<>();
|
||||||
|
|
||||||
// step 1:
|
// step 1:
|
||||||
for(TPHConstraint c : allCons) {
|
for(TPHConstraint c : allCons) {
|
||||||
|
|
||||||
@ -39,12 +41,16 @@ public class Simplify {
|
|||||||
TPHConstraint revCon = getReverseConstraint(allCons,left,right);
|
TPHConstraint revCon = getReverseConstraint(allCons,left,right);
|
||||||
if(revCon != null) {
|
if(revCon != null) {
|
||||||
revCon.setRel(Relation.EQUAL);
|
revCon.setRel(Relation.EQUAL);
|
||||||
|
// the reverse constraint is removed because
|
||||||
|
// otherwise there is twice the same constraint
|
||||||
|
// (e.g. A<B and B<A => A=B and B=A)
|
||||||
consToRemove.add(revCon);
|
consToRemove.add(revCon);
|
||||||
c.setRel(Relation.EQUAL);
|
c.setRel(Relation.EQUAL);
|
||||||
substituteTPH(allCons,left, right);
|
substituteTPH(allCons,left, right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println();
|
System.out.println();
|
||||||
System.out.println("NEW ALL CONST: " + allCons.size());
|
System.out.println("NEW ALL CONST: " + allCons.size());
|
||||||
allCons.forEach(c->System.out.println(c.toString()));
|
allCons.forEach(c->System.out.println(c.toString()));
|
||||||
@ -59,51 +65,75 @@ public class Simplify {
|
|||||||
System.out.println("----------------");
|
System.out.println("----------------");
|
||||||
HashMap<TPHConstraint, HashSet<String>> result = new HashMap<>();
|
HashMap<TPHConstraint, HashSet<String>> result = new HashMap<>();
|
||||||
|
|
||||||
|
// check if there is any long cycle (e.g. A<B<C<A)
|
||||||
|
|
||||||
|
// to save all types that are in relation
|
||||||
LinkedList<String> allTypes = new LinkedList<>();
|
LinkedList<String> 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<TPHConstraint> constraints = new ArrayList<>(size);
|
ArrayList<TPHConstraint> constraints = new ArrayList<>(size);
|
||||||
int visited = 0;
|
int visited = 0;
|
||||||
|
|
||||||
|
// contains all constraints
|
||||||
|
HashMap<String,String> ss1 = new HashMap<>();
|
||||||
|
|
||||||
|
for(TPHConstraint constr : allCons) {
|
||||||
|
ss1.put(constr.getLeft(), constr.getRight());
|
||||||
|
}
|
||||||
|
|
||||||
for(TPHConstraint c : allCons) {
|
for(TPHConstraint c : allCons) {
|
||||||
|
|
||||||
if(visited >= size)
|
if(visited >= size)
|
||||||
break;
|
break;
|
||||||
|
// Only extends-constraints will be checked
|
||||||
if(c.getRel() == Relation.EXTENDS) {
|
if(c.getRel() == Relation.EXTENDS) {
|
||||||
++visited;
|
++visited;
|
||||||
|
|
||||||
String left = c.getLeft();
|
String left = c.getLeft();
|
||||||
String right = c.getRight();
|
String right = c.getRight();
|
||||||
|
// put the types in linked list
|
||||||
allTypes.add(left);
|
allTypes.add(left);
|
||||||
allTypes.add(right);
|
allTypes.add(right);
|
||||||
|
|
||||||
constraints.add(c);
|
constraints.add(c);
|
||||||
HashMap<String,String> ss1 = new HashMap<>();
|
|
||||||
|
|
||||||
for(TPHConstraint constr : allCons) {
|
boolean isCycle = false;
|
||||||
ss1.put(constr.getLeft(), constr.getRight());
|
|
||||||
}
|
// iterate through the map to check if there is a cycle
|
||||||
boolean isCycle = false;
|
|
||||||
while(ss1.containsKey(right)) {
|
while(ss1.containsKey(right)) {
|
||||||
++visited;
|
++visited;
|
||||||
String oldRight = right;
|
String oldRight = right;
|
||||||
right = ss1.get(right);
|
right = ss1.get(right);
|
||||||
|
|
||||||
TPHConstraint toAdd = getConstraint(oldRight, right, allCons);
|
TPHConstraint toAdd = getConstraint(oldRight, right, allCons);
|
||||||
|
|
||||||
if(toAdd != null)
|
if(toAdd != null)
|
||||||
constraints.add(toAdd);
|
constraints.add(toAdd);
|
||||||
|
|
||||||
if(left.equals(right)) {
|
if(left.equals(right)) {
|
||||||
isCycle = true;
|
isCycle = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
allTypes.add(right);
|
allTypes.add(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isCycle) {
|
if(isCycle) {
|
||||||
|
// convert all constraints to equal constraints
|
||||||
setAllEqual(constraints);
|
setAllEqual(constraints);
|
||||||
|
// these constraints will be removed from allCons
|
||||||
consToRemove.addAll(constraints);
|
consToRemove.addAll(constraints);
|
||||||
|
// all equal types will be substitute with one type
|
||||||
substituteAllTPH(allCons,constraints,left);
|
substituteAllTPH(allCons,constraints,left);
|
||||||
|
|
||||||
HashSet<String> eq = new HashSet<>();
|
HashSet<String> eq = new HashSet<>();
|
||||||
|
// put all equal types in a set
|
||||||
for(String t:allTypes) {
|
for(String t:allTypes) {
|
||||||
eq.add(t);
|
eq.add(t);
|
||||||
}
|
}
|
||||||
|
// generate a new constraint (left < Object)
|
||||||
TPHConstraint constraint = new ExtendsConstraint(left, Type.getInternalName(Object.class), Relation.EXTENDS);
|
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);
|
result.put(constraint, eq);
|
||||||
constraints.clear();
|
constraints.clear();
|
||||||
allTypes.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) {
|
for(TPHConstraint c : allCons) {
|
||||||
if(c.getRel()==Relation.EQUAL) {
|
if(c.getRel()==Relation.EQUAL) {
|
||||||
if(!isTPHInResEqual(result, c.getLeft())) {
|
if(!isTPHInResEqual(result, c.getLeft())) {
|
||||||
@ -125,6 +158,7 @@ public class Simplify {
|
|||||||
size--;
|
size--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("Step 2 Result: ");
|
System.out.println("Step 2 Result: ");
|
||||||
result.forEach((c,hs)->{
|
result.forEach((c,hs)->{
|
||||||
System.out.print(c.toString() + " -> ");
|
System.out.print(c.toString() + " -> ");
|
||||||
@ -134,7 +168,9 @@ public class Simplify {
|
|||||||
System.out.println();
|
System.out.println();
|
||||||
});
|
});
|
||||||
System.out.println("----------------");
|
System.out.println("----------------");
|
||||||
|
// remove all equal-constraints
|
||||||
allCons.removeAll(consToRemove);
|
allCons.removeAll(consToRemove);
|
||||||
|
// add all generated constraints to allCons
|
||||||
allCons.addAll(result.keySet());
|
allCons.addAll(result.keySet());
|
||||||
|
|
||||||
if(!allCons.isEmpty() && allCons.size()<2) {
|
if(!allCons.isEmpty() && allCons.size()<2) {
|
||||||
@ -146,11 +182,13 @@ public class Simplify {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size += result.keySet().size();
|
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) {
|
for(TPHConstraint c : allCons) {
|
||||||
if(c.getRight().equals(Type.getInternalName(Object.class)))
|
if(c.getRight().equals(Type.getInternalName(Object.class)))
|
||||||
size--;
|
size--;
|
||||||
}
|
}
|
||||||
|
// get all tph of the method
|
||||||
ArrayList<String> methodTphs = new ArrayList<>();
|
ArrayList<String> methodTphs = new ArrayList<>();
|
||||||
for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) {
|
for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) {
|
||||||
if(m.getName().equals(name)) {
|
if(m.getName().equals(name)) {
|
||||||
@ -158,7 +196,9 @@ public class Simplify {
|
|||||||
break;
|
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<String, String> subAndSuper = new HashMap<>();
|
HashMap<String, String> subAndSuper = new HashMap<>();
|
||||||
for(TPHConstraint c : allCons) {
|
for(TPHConstraint c : allCons) {
|
||||||
if(subAndSuper.containsKey(c.getLeft())) {
|
if(subAndSuper.containsKey(c.getLeft())) {
|
||||||
@ -210,6 +250,8 @@ public class Simplify {
|
|||||||
// Die größte Supertype
|
// Die größte Supertype
|
||||||
String superTphRes = tphInRel.getLast();
|
String superTphRes = tphInRel.getLast();
|
||||||
|
|
||||||
|
// if there is any constraint X < subTph, then
|
||||||
|
// add X at the beginning of the list.
|
||||||
while(subAndSuper.containsValue(subTphRes)) {
|
while(subAndSuper.containsValue(subTphRes)) {
|
||||||
for(String tph : subAndSuper.keySet()) {
|
for(String tph : subAndSuper.keySet()) {
|
||||||
if(containTPH(methodTphs,tph) && subAndSuper.get(tph).equals(subTphRes)) {
|
if(containTPH(methodTphs,tph) && subAndSuper.get(tph).equals(subTphRes)) {
|
||||||
@ -220,12 +262,18 @@ public class Simplify {
|
|||||||
if(subTphRes.equals(tphInRel.getFirst())) {
|
if(subTphRes.equals(tphInRel.getFirst())) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(isTPHInConstraint(result, subTphRes))
|
||||||
|
break;
|
||||||
|
|
||||||
tphInRel.addFirst(subTphRes);
|
tphInRel.addFirst(subTphRes);
|
||||||
numOfVisitedPairs++;
|
numOfVisitedPairs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
subTphRes = tphInRel.getFirst();
|
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;
|
int i = 2;
|
||||||
while(!containTPH(methodTphs,superTphRes) && (tphInRel.size()-i) >0) {
|
while(!containTPH(methodTphs,superTphRes) && (tphInRel.size()-i) >0) {
|
||||||
superTphRes = tphInRel.get(tphInRel.size()-i);
|
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);
|
result.put(new ExtendsConstraint(subTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null);
|
||||||
} else {
|
} else {
|
||||||
result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), null);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,14 +2,19 @@ package bytecode.simplifyalgo;
|
|||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
import de.dhbwstuttgart.bytecode.TPHExtractor;
|
import de.dhbwstuttgart.bytecode.TPHExtractor;
|
||||||
import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint;
|
import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint;
|
||||||
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint;
|
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint;
|
||||||
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation;
|
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation;
|
||||||
import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH;
|
import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH;
|
||||||
|
import de.dhbwstuttgart.bytecode.utilities.Simplify;
|
||||||
import de.dhbwstuttgart.typedeployment.TypeInsertPlacer;
|
import de.dhbwstuttgart.typedeployment.TypeInsertPlacer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,6 +27,7 @@ public class SameLeftSide {
|
|||||||
// private ist => Test geht nicht
|
// private ist => Test geht nicht
|
||||||
private static TPHExtractor tphExtractor;
|
private static TPHExtractor tphExtractor;
|
||||||
private static String methName;
|
private static String methName;
|
||||||
|
private static String methName2;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setUpBeforeClass() throws Exception {
|
public static void setUpBeforeClass() throws Exception {
|
||||||
@ -38,11 +44,54 @@ public class SameLeftSide {
|
|||||||
methName = "m1";
|
methName = "m1";
|
||||||
MethodAndTPH m1 = new MethodAndTPH("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(c1);
|
||||||
tphExtractor.allCons.add(c2);
|
tphExtractor.allCons.add(c2);
|
||||||
|
tphExtractor.allCons.add(c3);
|
||||||
|
tphExtractor.allCons.add(c4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testM1() {
|
||||||
|
HashMap<TPHConstraint, HashSet<String>> 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<TPHConstraint, HashSet<String>> sim = Simplify.simplifyConstraints(methName, tphExtractor);
|
||||||
|
boolean areEquals = SimpleCycle.areMapsEqual(result, sim);
|
||||||
|
assertTrue(areEquals);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testM2() {
|
||||||
|
HashMap<TPHConstraint, HashSet<String>> 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<TPHConstraint, HashSet<String>> sim = Simplify.simplifyConstraints(methName2, tphExtractor);
|
||||||
|
boolean areEquals = SimpleCycle.areMapsEqual(result, sim);
|
||||||
|
assertTrue(areEquals);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -58,16 +58,17 @@ public class SimpleCycle {
|
|||||||
HashSet<String> eq1 = m1.get(c);
|
HashSet<String> eq1 = m1.get(c);
|
||||||
HashSet<String> eq2 = m2.get(c2);
|
HashSet<String> eq2 = m2.get(c2);
|
||||||
|
|
||||||
if(eq1.size() != eq2.size())
|
if((eq1 == null && eq2 != null) || (eq1 != null && eq2 == null))
|
||||||
return false;
|
return false;
|
||||||
|
if(eq1 != null) {
|
||||||
for(String tph:eq1) {
|
if(eq1.size() != eq2.size())
|
||||||
if(!eq2.contains(tph))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
for(String tph:eq1) {
|
||||||
|
if(!eq2.contains(tph))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user