Simplify fuer Klassen Type Variablen

This commit is contained in:
Fayez Abu Alia 2019-01-16 14:41:33 +01:00
parent 752b68d447
commit d4d668b662
8 changed files with 288 additions and 67 deletions

View File

@ -148,8 +148,17 @@ public class BytecodeGen implements ASTVisitor {
tphsClass.add(t);
}
String sig = null;
/* if class has generics then creates signature
* Signature looks like:
* <E:Ljava/...>Superclass
*/
if(classOrInterface.getGenerics().iterator().hasNext() || !commonPairs.isEmpty() ||
classOrInterface.getSuperClass().acceptTV(new TypeToSignature()).contains("<")
|| !tphsClass.isEmpty()) {
HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraintsClass(tphExtractor,tphsClass);
ArrayList<TPHConstraint> consClass = new ArrayList<>();
for(TPHConstraint cons : tphExtractor.allCons) {
for(TPHConstraint cons : constraints.keySet()) {
TypePlaceholder right = null;
for(TypePlaceholder tph : tphsClass) {
if(cons.getLeft().equals(tph.getName())) {
@ -164,14 +173,6 @@ public class BytecodeGen implements ASTVisitor {
right = null;
}
}
String sig = null;
/* if class has generics then creates signature
* Signature looks like:
* <E:Ljava/...>Superclass
*/
if(classOrInterface.getGenerics().iterator().hasNext() || !commonPairs.isEmpty() ||
classOrInterface.getSuperClass().acceptTV(new TypeToSignature()).contains("<")
|| !tphsClass.isEmpty()) {
Signature signature = new Signature(classOrInterface, genericsAndBounds,commonPairs,tphsClass, consClass);
sig = signature.toString();
System.out.println("Signature: => " + sig);

View File

@ -11,6 +11,7 @@ import de.dhbwstuttgart.bytecode.constraint.TPHConstraint;
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation;
import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH;
import de.dhbwstuttgart.syntaxtree.AbstractASTWalker;
import de.dhbwstuttgart.syntaxtree.Constructor;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.GenericInsertPair;
@ -75,4 +76,11 @@ public class TPHExtractor extends AbstractASTWalker{
ListOfMethodsAndTph.add(methodAndTph);
}
@Override
public void visit(Constructor cons) {
inMethod = false;
super.visit(cons);
inMethod = true;
}
}

View File

@ -347,6 +347,245 @@ public class Simplify {
return result;
}
public static HashMap<TPHConstraint, HashSet<String>> simplifyConstraintsClass(TPHExtractor tphExtractor, ArrayList<TypePlaceholder> tphsClass) {
// all constraints that will be simplified
ArrayList<TPHConstraint> allCons = tphExtractor.allCons;
ArrayList<TPHConstraint> consToRemove = new ArrayList<>();
// step 1:
for(TPHConstraint c : allCons) {
String left = c.getLeft();
String right = c.getRight();
if(c.getRel() == Relation.EXTENDS) {
TPHConstraint revCon = getReverseConstraint(allCons,left,right);
if(revCon != null) {
revCon.setRel(Relation.EQUAL);
// the reverse constraint is removed because
// otherwise there is the same constraint twice
// (e.g. A<B and B<A => A=B and B=A)
consToRemove.add(revCon);
c.setRel(Relation.EQUAL);
substituteTPH(allCons,left, right);
}
}
}
allCons.removeAll(consToRemove);
consToRemove = new ArrayList<>();
int size = allCons.size();
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<>();
// 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);
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) {
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);
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<String> 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();
}
}
// 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())) {
HashSet<String> equalTPHs = getEqualsTPHs(result, c);
TPHConstraint constraint = getKeyConstraint(result,c);
equalTPHs.add(c.getLeft());
equalTPHs.add(c.getRight());
result.put(constraint, equalTPHs);
}
consToRemove.add(c);
size--;
}
}
// remove all equal-constraints
allCons.removeAll(consToRemove);
// add all generated constraints to allCons
allCons.addAll(result.keySet());
if(!allCons.isEmpty() && allCons.size()<2) {
TPHConstraint cons = allCons.get(0);
if(!result.containsKey(cons)) {
result.put(cons, null);
result.put(new ExtendsConstraint(cons.getRight(), Type.getInternalName(Object.class), Relation.EXTENDS), null);
}
return result;
}
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--;
}
// 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<>();
ArrayList<TPHConstraint> eqCons = new ArrayList<>();
for(TPHConstraint c : allCons) {
subAndSuper.put(c.getLeft(), c.getRight());
}
int numOfVisitedPairs = 0;
for(String sub : subAndSuper.keySet()) {
if(isTPHInConstraint(result,sub))
continue;
if(!classTPHSContainsTPH(tphsClass,sub))
continue;
if(numOfVisitedPairs>=size)
break;
LinkedList<String> tphInRel = new LinkedList<>();
tphInRel.add(sub);
String superT = subAndSuper.get(sub);
tphInRel.add(superT);
numOfVisitedPairs++;
while(subAndSuper.containsKey(superT)) {
superT = subAndSuper.get(superT);
if(tphInRel.contains(superT)) {
break;
}
tphInRel.add(superT);
numOfVisitedPairs++;
}
// Subtype
String subTphRes = tphInRel.getFirst();
// 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(classTPHSContainsTPH(tphsClass,tph) && subAndSuper.get(tph).equals(subTphRes)) {
subTphRes = tph;
break;
}
}
if(subTphRes.equals(tphInRel.getFirst())) {
break;
}
if(isTPHInConstraint(result, subTphRes))
break;
tphInRel.addFirst(subTphRes);
numOfVisitedPairs++;
}
subTphRes = tphInRel.getFirst();
HashSet<String> equals = getEqualsTphsFromEqualCons(eqCons,superTphRes);
result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), equals);
}
System.out.println("EndResult: ");
result.forEach((c,hs)->{
if(c!=null) {
System.out.print(c.toString() + " -> ");
if(hs == null) {
System.out.print(" [] ");
}else {
hs.forEach(s->{
System.out.print(s + ", ");
});
}
}
System.out.println();
});
System.out.println("----------------");
return result;
}
private static boolean classTPHSContainsTPH(ArrayList<TypePlaceholder> tphsClass, String superTphRes) {
for(TypePlaceholder tph : tphsClass) {
if(tph.getName().equals(superTphRes))

View File

@ -80,6 +80,9 @@ public abstract class AbstractASTWalker implements ASTVisitor{
for(Field f : classOrInterface.getFieldDecl()){
f.accept(this);
}
for(Constructor c : classOrInterface.getConstructors()){
c.accept(this);
}
for(Method m : classOrInterface.getMethods()){
m.accept(this);
}

View File

@ -1,43 +0,0 @@
package bytecode;
import static org.junit.Assert.*;
import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import de.dhbwstuttgart.core.JavaTXCompiler;
public class FieldTph {
private static String path;
private static File fileToTest;
private static JavaTXCompiler compiler;
private static ClassLoader loader;
private static Class<?> classToTest;
private static String pathToClassFile;
private static Object instanceOfClass;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/FieldTph.jav";
fileToTest = new File(path);
compiler = new JavaTXCompiler(fileToTest);
compiler.generateBytecode(System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/");
pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("FieldTph");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}
@Test
public void test() {
Field[] fields = classToTest.getFields();
assertEquals(1, fields.length);
}
}

View File

@ -32,11 +32,11 @@ public class FieldTphConsMethTest {
pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("FieldTphConsMeth");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}
@Test
public void test() throws Exception {
instanceOfClass = classToTest.getConstructor(Object.class).newInstance("C");
Field a = classToTest.getDeclaredField("a");
a.setAccessible(true);
@ -44,6 +44,7 @@ public class FieldTphConsMethTest {
Object result = m.invoke(instanceOfClass, 42);
assertEquals(42,result);
assertEquals("C", a.get(instanceOfClass));
}
}

View File

@ -4,6 +4,7 @@ import static org.junit.Assert.*;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
@ -27,7 +28,7 @@ public class MatrixOpTest {
private static Object instanceOfClass_m3;
@Test
public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, IOException, InstantiationException {
public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, IOException, InstantiationException, NoSuchFieldException {
path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/MatrixOP.jav";
fileToTest = new File(path);
compiler = new JavaTXCompiler(fileToTest);
@ -35,7 +36,7 @@ public class MatrixOpTest {
compiler.generateBytecode(pathToClassFile);
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("MatrixOP");
/*
Vector<Vector<Integer>> vv = new Vector<Vector<Integer>>();
Vector<Integer> v1 = new Vector<Integer> ();
v1.addElement(2);
@ -48,6 +49,7 @@ public class MatrixOpTest {
//m1.addElement(v2);
vv.addElement(v1);
vv.addElement(v2);
instanceOfClass_m1 = classToTest.getDeclaredConstructor(Vector.class).newInstance(vv); //Matrix m1 = new Matrix(vv);
Vector<Vector<Integer>> vv1 = new Vector<Vector<Integer>>();
@ -62,13 +64,23 @@ public class MatrixOpTest {
//m2.addElement(v4);
vv1.addElement(v3);
vv1.addElement(v4);
instanceOfClass_m2 = classToTest.getDeclaredConstructor(Vector.class).newInstance(vv1);//Matrix m2 = new Matrix(vv1);
//Matrix m3 = m1.mul(vv1);
Method mul = classToTest.getDeclaredMethod("mul", Vector.class);
Object result = mul.invoke(instanceOfClass_m1, instanceOfClass_m2);
// Method mul = classToTest.getDeclaredMethod("mul", Vector.class);
// Object result = mul.invoke(instanceOfClass_m1, instanceOfClass_m2);
Field mul = classToTest.getField("mul");
mul.setAccessible(true);
Class<?> lambda = mul.get(instanceOfClass_m1).getClass();
Method apply = lambda.getMethod("apply", Object.class,Object.class);
// Damit man auf die Methode zugreifen kann
apply.setAccessible(true);
Object result = apply.invoke(mul.get(instanceOfClass_m1),instanceOfClass_m1, instanceOfClass_m2);
System.out.println(instanceOfClass_m1.toString() + " * " + instanceOfClass_m2.toString() + " = " + result.toString());
Vector<Vector<Integer>> res = new Vector<Vector<Integer>>();
@ -85,7 +97,7 @@ public class MatrixOpTest {
res.addElement(v6);
instanceOfClass_m3 = classToTest.getDeclaredConstructor(Vector.class).newInstance(res);
assertEquals(result, instanceOfClass_m3);
*/
}
}

View File

@ -18,7 +18,7 @@ public class MatrixOP extends Vector<Vector<Integer>> {
}
}
mul = (m1, m2) -> {
public mul = (m1, m2) -> {
var ret = new MatrixOP();
var i = 0;
while(i < size()) {