diff --git a/pom.xml b/pom.xml index 6f54967a..b90b76e2 100644 --- a/pom.xml +++ b/pom.xml @@ -1,88 +1,175 @@ - - - 4.0.0 - de.dhbwstuttgart - JavaTXcompiler - jar - 0.1 - JavaTXcompiler - http://maven.apache.org - - - junit - junit - 4.0 - test - - - org.antlr - antlr4 - 4.7 - - - commons-io - commons-io - 2.6 - - -com.google.guava - guava - 22.0 - - - org.reflections - reflections - 0.9.11 - - - org.ow2.asm - asm-all - [4.0.0,) - - - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 +http://maven.apache.org/maven-v4_0_0.xsd"> + 4.0.0 + de.dhbwstuttgart + JavaTXcompiler + jar - - target - target/classes - ${artifactId}-${version} - target/test-classes - src/ - test/ - - - org.antlr - antlr4-maven-plugin - 4.7 - - - antlr - - antlr4 - - - src/de/dhbwstuttgart/parser/antlr/ - src/de/dhbwstuttgart/parser/antlr/ - - -package - de.dhbwstuttgart.parser.antlr - - - - - - - - - 1.8 - 1.8 - + 0.1 + JavaTXcompiler + http://maven.apache.org + + + junit + junit + 4.0 + test + + + org.antlr + antlr4 + 4.7 + + + commons-io + commons-io + 2.6 + + + com.google.guava + guava + 22.0 + + + org.reflections + reflections + 0.9.11 + + + + org.ow2.asm + asm + 7.0 + + + + + + + target + target/classes + ${project.artifactId}-${project.version} + target/test-classes + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M3 + + true + + + + org.antlr + antlr4-maven-plugin + 4.7 + + + antlr + + antlr4 + + + src/main/antlr4/java8 + ${project.basedir}/target/generated-sources/antlr4/de/dhbwstuttgart/parser/antlr + + -package + de.dhbwstuttgart.parser.antlr + + + + + aspParser + + antlr4 + + + src/main/antlr4/sat + ${project.basedir}/target/generated-sources/antlr4/de/dhbwstuttgart/sat/asp/parser/antlr + + -package + de.dhbwstuttgart.sat.asp.parser.antlr + + + + + + + + maven-assembly-plugin + + + package + + single + + + + + + jar-with-dependencies + + + + + org.reficio + p2-maven-plugin + 1.1.2-SNAPSHOT + + + default-cli + + + + + + de.dhbwstuttgart:JavaTXcompiler:0.1 + + + org.reflections:reflections:0.9.11 + + + com.google.guava:guava:22.0 + + + javax.annotation:javax.annotation-api:1.3.1 + + + org.glassfish:javax.annotation:3.1.1 + + + + + + + + + + + reficio + http://repo.reficio.org/maven/ + + + + + maven-repository + file:///${project.basedir}/target + + + + 1.8 + 1.8 + 0.23.0 + + + + maven-repository + MyCo Internal Repository + file:///${project.basedir}/maven-repository/ + + diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java index 0dea801d..fec01c10 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -147,23 +147,7 @@ public class BytecodeGen implements ASTVisitor { if(!tphExtractor.allTPHS.get(t)) tphsClass.add(t); } - - ArrayList consClass = new ArrayList<>(); - for(TPHConstraint cons : tphExtractor.allCons) { - TypePlaceholder right = null; - for(TypePlaceholder tph : tphsClass) { - if(cons.getLeft().equals(tph.getName())) { - - consClass.add(cons); - right = getTPH(cons.getRight()); - } - } - if(right != null) { - tphsClass.add(right); - removeFromMethod(right.getName()); - right = null; - } - } + String sig = null; /* if class has generics then creates signature * Signature looks like: @@ -172,6 +156,23 @@ public class BytecodeGen implements ASTVisitor { if(classOrInterface.getGenerics().iterator().hasNext() || !commonPairs.isEmpty() || classOrInterface.getSuperClass().acceptTV(new TypeToSignature()).contains("<") || !tphsClass.isEmpty()) { + HashMap> constraints = Simplify.simplifyConstraintsClass(tphExtractor,tphsClass); + ArrayList consClass = new ArrayList<>(); + for(TPHConstraint cons : constraints.keySet()) { + TypePlaceholder right = null; + for(TypePlaceholder tph : tphsClass) { + if(cons.getLeft().equals(tph.getName())) { + + consClass.add(cons); + right = getTPH(cons.getRight()); + } + } + if(right != null) { + tphsClass.add(right); + removeFromMethod(right.getName()); + right = null; + } + } Signature signature = new Signature(classOrInterface, genericsAndBounds,commonPairs,tphsClass, consClass); sig = signature.toString(); System.out.println("Signature: => " + sig); diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index d4670289..b1ea614f 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -140,7 +140,8 @@ public class BytecodeGenMethod implements StatementVisitor { } public BytecodeGenMethod(LambdaExpression lambdaExpression, ArrayList usedVars, ResultSet resultSet, MethodVisitor mv, - int indexOfFirstParamLam, boolean isInterface, HashMap classFiles, String path, int lamCounter, SourceFile sf) { + int indexOfFirstParamLam, boolean isInterface, HashMap classFiles, String path, int lamCounter, SourceFile sf,HashMap genericsAndBoundsMethod, + HashMap genericsAndBounds) { this.resultSet = resultSet; this.mv = mv; @@ -149,6 +150,9 @@ public class BytecodeGenMethod implements StatementVisitor { this.path = path; this.lamCounter = lamCounter; this.sf = sf; + this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.genericsAndBounds = genericsAndBounds; + Iterator itr = lambdaExpression.params.iterator(); int i = indexOfFirstParamLam; @@ -644,7 +648,8 @@ public class BytecodeGenMethod implements StatementVisitor { ArrayList usedVars = kindOfLambda.getUsedVars(); new BytecodeGenMethod(lambdaExpression, usedVars,this.resultSet, mvLambdaBody, indexOfFirstParamLam, isInterface, - classFiles,this.path, lamCounter, sf); + classFiles,this.path, lamCounter, sf, genericsAndBoundsMethod, + genericsAndBounds); mvLambdaBody.visitMaxs(0, 0); mvLambdaBody.visitEnd(); @@ -744,6 +749,13 @@ public class BytecodeGenMethod implements StatementVisitor { statement = new IfStatement(ifStmt.expr, ifStmt.then_block, ifStmt.else_block); isBinaryExp = statement.isExprBinary(); ifStmt.expr.accept(this); + if(!(ifStmt.expr instanceof BinaryExpr)) { + doUnboxing(getResolvedType(ifStmt.expr.getType())); + Label branchLabel = new Label(); + Label endLabel = new Label(); + mv.visitJumpInsn(Opcodes.IFEQ, branchLabel); + statement.genBCForRelOp(mv, branchLabel, endLabel, this); + } statement = null; } @@ -758,84 +770,90 @@ public class BytecodeGenMethod implements StatementVisitor { System.out.println("In MethodCall = " + methodCall.name); String receiverName = getResolvedType(methodCall.receiver.getType()); System.out.println("Methods of " + receiverName + " "); - ClassLoader cLoader = ClassLoader.getSystemClassLoader(); - // This will be used if the class is not standard class (not in API) - ClassLoader cLoader2; java.lang.reflect.Method methodRefl = null; String clazz = receiverName.replace("/", "."); - String methCallType = resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor()); - String[] typesOfParams = getTypes(methodCall.arglist.getArguments()); - try { - if(receiverName.contains("<")) { - clazz = clazz.substring(0, receiverName.indexOf("<")); - } +// if(!receiverName.equals(className)) { + ClassLoader cLoader = ClassLoader.getSystemClassLoader(); + // This will be used if the class is not standard class (not in API) + ClassLoader cLoader2; - java.lang.reflect.Method[] methods = cLoader.loadClass(clazz).getMethods(); - System.out.println("Methods of " + receiverName + " "); - methodRefl = getMethod(methodCall.name,methodCall.arglist.getArguments().size(),methods); - - } catch (Exception e) { -// try { -// cLoader2 = new URLClassLoader(new URL[] {new URL("file://"+path)}); -// java.lang.reflect.Method[] methods = cLoader2.loadClass(clazz).getMethods(); -// System.out.println("Methods of " + receiverName + " "); -// for(int i = 0; i Refl != null"); receiverRefl = methodRefl.getAnnotatedReceiverType().getType().toString(); for(Parameter p:methodRefl.getParameters()) { System.out.println(p.getName() + " und is Primitive = " + p.getType().isPrimitive()); @@ -863,7 +882,7 @@ public class BytecodeGenMethod implements StatementVisitor { } } - System.out.println("Methodcall Desc : " + mDesc); + System.out.println("Methodcall ("+ methodCall.name +") Desc : " + mDesc); // methodCall.arglist.accept(this); @@ -1195,6 +1214,7 @@ public class BytecodeGenMethod implements StatementVisitor { break; case "java/lang/Boolean": + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false); break; case "java/lang/Byte": mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false); diff --git a/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java b/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java index d9a95311..c100eb4a 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java @@ -5,13 +5,19 @@ package de.dhbwstuttgart.bytecode; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; 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.syntaxtree.AbstractASTWalker; +import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.FormalParameter; import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.statement.LocalVar; +import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.result.GenericInsertPair; import de.dhbwstuttgart.typeinference.result.ResultSet; @@ -20,36 +26,42 @@ import de.dhbwstuttgart.typeinference.result.ResultSet; * @author Fayez Abu Alia * */ -public class TPHExtractor extends AbstractASTWalker{ +public class TPHExtractor extends AbstractASTWalker { // Alle TPHs der Felder werden iKopf der Klasse definiert // alle TPHs der Klasse: (TPH, is in Method?) - final HashMap allTPHS = new HashMap<>(); + final HashMap allTPHS = new HashMap<>(); MethodAndTPH methodAndTph; + Boolean inMethod = false; + boolean inLocalOrParam = false; + public final ArrayList ListOfMethodsAndTph = new ArrayList<>(); final ArrayList allPairs = new ArrayList<>(); public final ArrayList allCons = new ArrayList<>(); private ResultSet resultSet; - + public TPHExtractor() { - + } - + public void setResultSet(ResultSet resultSet) { this.resultSet = resultSet; } - + @Override public void visit(TypePlaceholder tph) { - if(resultSet.resolveType(tph).resolvedType instanceof TypePlaceholder) { + if (resultSet.resolveType(tph).resolvedType instanceof TypePlaceholder) { TypePlaceholder resolvedTPH = (TypePlaceholder) resultSet.resolveType(tph).resolvedType; - if(inMethod) + if (inMethod) { methodAndTph.getTphs().add(resolvedTPH.getName()); - - allTPHS.put(resolvedTPH,inMethod); - resultSet.resolveType(tph).additionalGenerics.forEach(ag ->{ - if(ag.contains(resolvedTPH)&&ag.TA1.equals(resolvedTPH)&&!contains(allPairs,ag)) { - if(inMethod) + if (inLocalOrParam) + methodAndTph.getLocalTphs().add(resolvedTPH.getName()); + } + + allTPHS.put(resolvedTPH, inMethod); + resultSet.resolveType(tph).additionalGenerics.forEach(ag -> { + if (ag.contains(resolvedTPH) && ag.TA1.equals(resolvedTPH) && !contains(allPairs, ag)) { + if (inMethod) methodAndTph.getPairs().add(ag); allPairs.add(ag); TPHConstraint con = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); @@ -58,14 +70,16 @@ public class TPHExtractor extends AbstractASTWalker{ }); } } + private boolean contains(ArrayList pairs, GenericInsertPair genPair) { - for(int i=0; i allConstaints; + + public ConstraintsFinder(List allConstaints) { + super(); + this.allConstaints = allConstaints; + } + + public List> findConstraints() { + List> result = new ArrayList<>(); + + List visitedCons = new ArrayList<>(); + for(TPHConstraint c : allConstaints) { + if(c.getRel() == Relation.EXTENDS) { + // get constraints with the same left side + List cons = getConstraints(c,visitedCons); + if(cons.size()>1) + result.add(cons); + } + } + + return result; + } + + private List getConstraints(TPHConstraint c, List visitedCons) { + List res = new ArrayList<>(); + for(TPHConstraint cons : allConstaints) { + if(!isVisited(cons,visitedCons) && cons.getLeft().equals(c.getLeft())) { + res.add(cons); + visitedCons.add(cons); + } + } + return res; + } + + private boolean isVisited(TPHConstraint cons, List visitedCons) { + for(TPHConstraint c : visitedCons) { + if(c.getLeft().equals(cons.getLeft()) && c.getRight().equals(cons.getRight())) + return true; + } + return false; + } +} diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java index 7175f108..e21f974c 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java @@ -10,6 +10,8 @@ public class MethodAndTPH { private String name; private final ArrayList tphs = new ArrayList<>(); private final ArrayList pairs = new ArrayList<>(); + // tphs of local variables and parameters + private final ArrayList localTphs = new ArrayList<>(); public MethodAndTPH(String name) { this.name = name; @@ -26,4 +28,9 @@ public class MethodAndTPH { public String getName() { return name; } + + public ArrayList getLocalTphs() { + return localTphs; + } + } diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/NameReplacer.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/NameReplacer.java new file mode 100644 index 00000000..bc3c1b98 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/bytecode/utilities/NameReplacer.java @@ -0,0 +1,49 @@ +package de.dhbwstuttgart.bytecode.utilities; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; + +public class NameReplacer { + private List constraints; + private List allConstraints; + private List tphs; + private List localTphs; + + public NameReplacer(List constraints, List allConstraints,List tphs, ArrayList localTphs) { + super(); + this.constraints = constraints; + this.allConstraints = allConstraints; + this.tphs = tphs; + this.localTphs = localTphs; + } + + public Map> replaceNames() { + String newName = NameGenerator.makeNewName(); + ArrayList names = new ArrayList<>(); + for(TPHConstraint cons : constraints) { + names.add(cons.getRight()); + cons.setRight(newName); + } + + for(TPHConstraint cons : allConstraints) { + if(names.contains(cons.getLeft())) + cons.setLeft(newName); + if(names.contains(cons.getRight())) + cons.setRight(newName); + } + + tphs.removeAll(names); + tphs.add(newName); + localTphs.removeAll(names); + localTphs.add(newName); + + HashMap> res = new HashMap<>(); + res.put(newName, names); + return res; + } +} diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/Simplify.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/Simplify.java index d19d38dc..89b55efb 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/utilities/Simplify.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/utilities/Simplify.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; +import java.util.List; +import java.util.Map; import org.objectweb.asm.Type; @@ -15,125 +17,145 @@ import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; public class Simplify { - - public static HashMap> simplifyConstraints(String name, TPHExtractor tphExtractor, ArrayList tphsClass) { + + public static HashMap> simplifyConstraints(String name, TPHExtractor tphExtractor, + ArrayList tphsClass) { // 1. check if there are any simple cycles like L set L=R and: - // * remove both constraints - // * substitute L with R in all constraint - // b)no => go to next step - // 2. check the result of step 1 if there are any equal-constraints like L=R, M=R .. - // a) yes => put all such TPhs in a map and define "key-Cons" - // -- key-Cons = TPH < Object -- - // put this Constraint and the - // b) no + // a) yes => set L=R and: + // * remove both constraints + // * substitute L with R in all constraint + // b)no => go to next step + // 2. check the result of step 1 if there are any equal-constraints like L=R, + // M=R .. + // a) yes => put all such TPhs in a map and define "key-Cons" + // -- key-Cons = TPH < Object -- + // put this Constraint and the + // b) no // 3. is - + // all constraints that will be simplified - ArrayList allCons = tphExtractor.allCons; +// ArrayList allCons = tphExtractor.allCons; + ArrayList allCons = new ArrayList<>(); + + for(TPHConstraint c : tphExtractor.allCons) { + TPHConstraint nc = new TPHConstraint(c.getLeft(), c.getRight(), c.getRel()); + allCons.add(nc); + } ArrayList consToRemove = new ArrayList<>(); - + + // get all tph of the method + ArrayList methodTphs = new ArrayList<>(); + ArrayList localTphs = new ArrayList<>(); + for (MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { + if (m.getName().equals(name)) { + methodTphs = m.getTphs(); + localTphs = m.getLocalTphs(); + break; + } + } + // step 1: - for(TPHConstraint c : allCons) { - + 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) { + 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 A=B and B=A) + // the reverse constraint is removed because + // otherwise there is the same constraint twice + // (e.g. A A=B and B=A) consToRemove.add(revCon); c.setRel(Relation.EQUAL); - substituteTPH(allCons,left, right); + substituteTPH(allCons, left, right); } } } - + System.out.println(); System.out.println("NEW ALL CONST: " + allCons.size()); - allCons.forEach(c->System.out.println(c.toString())); + allCons.forEach(c -> System.out.println(c.toString())); System.out.println("----------------"); allCons.removeAll(consToRemove); consToRemove = new ArrayList<>(); - + int size = allCons.size(); - + System.out.println("AFTER DELETE ALL CONST: " + allCons.size()); - allCons.forEach(c->System.out.println(c.toString())); + allCons.forEach(c -> System.out.println(c.toString())); 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) { + HashMap ss1 = new HashMap<>(); + + for (TPHConstraint constr : allCons) { ss1.put(constr.getLeft(), constr.getRight()); } - - for(TPHConstraint c : allCons) { - - if(visited >= size) + + for (TPHConstraint c : allCons) { + + if (visited >= size) break; // Only extends-constraints will be checked - if(c.getRel() == Relation.EXTENDS) { + 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)) { + while (ss1.containsKey(right)) { ++visited; String oldRight = right; right = ss1.get(right); - + TPHConstraint toAdd = getConstraint(oldRight, right, allCons); - - if(toAdd != null) + + if (toAdd != null) constraints.add(toAdd); - - if(left.equals(right)) { + + if (left.equals(right)) { isCycle = true; break; } - + allTypes.add(right); } - - if(isCycle) { + + 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); - + substituteAllTPH(allCons, constraints, left); + HashSet eq = new HashSet<>(); // put all equal types in a set - for(String t:allTypes) { + for (String t : allTypes) { 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); constraints.clear(); @@ -141,15 +163,260 @@ public class Simplify { allTypes.clear(); } } + + for (TPHConstraint ec : allCons) { + + if(ec.getRel() == Relation.EQUAL) { + if(!localTphs.contains(ec.getRight())) { + localTphs.add(ec.getRight()); + } + if(!methodTphs.contains(ec.getRight())) { + methodTphs.add(ec.getRight()); + } + + } + } // build an equal set that contains all types - // which are equal and for each equal constraint put left side and right side + // 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())) { +// for(TPHConstraint c : allCons) { +// if(c.getRel()==Relation.EQUAL) { +// if(!isTPHInResEqual(result, c.getLeft())) { +// HashSet 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--; +// } +// } + + System.out.println("Step 2 Result: "); + result.forEach((c, hs) -> { + System.out.print(c.toString() + " -> "); + hs.forEach(s -> { + System.out.print(s + ", "); + }); + System.out.println(); + }); + System.out.println("----------------"); + + if (!allCons.isEmpty() && allCons.size() < 2) { + TPHConstraint cons = allCons.get(0); + if (!result.containsKey(cons)) { + result.put(cons, null); + if (!cons.getRight().equals(Type.getInternalName(Object.class))) + 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--; + } + + // finder looks for constraints that have the same left hand side + // and put them in a list + ConstraintsFinder finder = new ConstraintsFinder(allCons); + List> foundCons = finder.findConstraints(); + + ArrayList eqCons = new ArrayList<>(); + + for (List list : foundCons) { + // generate a new name and replace the right hand side for each constraint + // in list with the new name + NameReplacer replacer = new NameReplacer(list, allCons, methodTphs, localTphs); + // new name -> [all old names] + Map> replRes = replacer.replaceNames(); + // create an equal constraint for each value in repres + String key = replRes.keySet().iterator().next(); + for (String val : replRes.values().iterator().next()) { + EqualConstraint ec = new EqualConstraint(val, key, Relation.EQUAL); + eqCons.add(ec); + } + for (TPHConstraint c : allCons) { + if (c.getRel() == Relation.EQUAL && key.equals(c.getRight())) { + eqCons.add(c); + } + } + updateEqualCons(replRes, eqCons); + + TPHConstraint c = list.get(0); + allCons.removeAll(list); + allCons.add(c); + } + + // 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<>(); +// ArrayList eqCons = new ArrayList<>(); +// for(TPHConstraint c : allCons) { +// if(subAndSuper.containsKey(c.getLeft())) { +// LinkedList all = new LinkedList<>(); +// all.add(c.getLeft()); +// String sup =c.getRight(); +// all.add(sup); +// HashMap ss = new HashMap<>(); +// for(TPHConstraint constr : allCons) { +// ss.put(constr.getLeft(), constr.getRight()); +// } +// while(ss.containsKey(sup)) { +// sup = ss.get(sup); +// all.add(sup); +// } +// if(!containTPH(methodTphs, all.getLast())) +// continue; +// } +// if(subAndSuper.containsKey(c.getLeft())) { +// System.out.println(c.getLeft()); +// String r = c.getRight(); +// String r2 = subAndSuper.get(c.getLeft()); +// EqualConstraint eq = new EqualConstraint(r2, r, Relation.EQUAL); +// eqCons.add(eq); +// substituteInMap(subAndSuper,eqCons,allCons,r,r2); +// } +// subAndSuper.put(c.getLeft(), c.getRight()); +// } +// +// System.out.println("SAME LEFT SIDE: "); +// subAndSuper.forEach((c,hs)->{ +// if(c!=null) { +// System.out.print(c+ " -> " + hs); +// +// } +// +// +// System.out.println(); +// }); +// System.out.println("----------------"); + HashMap subAndSuper = new HashMap<>(); + + for (TPHConstraint c : allCons) { + if (c.getRel() == Relation.EXTENDS) + subAndSuper.put(c.getLeft(), c.getRight()); + } + + for (TPHConstraint ec : allCons) { + if(ec.getRel() == Relation.EQUAL) { + methodTphs.remove(ec.getLeft()); + localTphs.remove(ec.getLeft()); + if(!localTphs.contains(ec.getRight())) { + localTphs.add(ec.getRight()); + } + if(!methodTphs.contains(ec.getRight())) { + methodTphs.add(ec.getRight()); + } + } + + } + + int numOfVisitedPairs = 0; + for (String sub : subAndSuper.keySet()) { + if (isTPHInConstraint(result, sub)) + continue; + + if (!containTPH(methodTphs, sub)) + continue; + + if (numOfVisitedPairs >= size) + break; + LinkedList tphInRel = new LinkedList<>(); + tphInRel.add(sub); + String superT = subAndSuper.get(sub); + tphInRel.add(superT); + + numOfVisitedPairs++; + while (!localTphs.contains(superT) && 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 (!localTphs.contains(subTphRes) && subAndSuper.containsValue(subTphRes)) { + for (String tph : subAndSuper.keySet()) { + if (containTPH(methodTphs, 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(); + // 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); + i++; + } + + if (!containTPH(methodTphs, superTphRes)) { + HashSet equals = getEqualsTphsFromEqualCons(eqCons, superTphRes); + if (classTPHSContainsTPH(tphsClass, superTphRes)) { + result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), equals); + } else { + result.put(new ExtendsConstraint(subTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), + equals); + } + + } else { + HashSet equals = getEqualsTphsFromEqualCons(eqCons, subTphRes); + result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), equals); + if (!isTPHInConstraint(result, superTphRes) && !isTphInEqualSet(result, superTphRes)) { + HashSet equals2 = getEqualsTphsFromEqualCons(eqCons, superTphRes); + result.put(new ExtendsConstraint(superTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), + equals2); + } + } + } + +// for(String tph : methodTphs) { + for (String tph : localTphs) { + if (!isTPHInConstraint(result, tph) && !isTphInEqualSet(result, tph)) { + HashSet equals = getEqualsTphsFromEqualCons(eqCons, tph); + result.put(new ExtendsConstraint(tph, Type.getInternalName(Object.class), Relation.EXTENDS), equals); + } + } + + // 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 equalTPHs = getEqualsTPHs(result, c); - TPHConstraint constraint = getKeyConstraint(result,c); + TPHConstraint constraint = getKeyConstraint(result, c); equalTPHs.add(c.getLeft()); equalTPHs.add(c.getRight()); result.put(constraint, equalTPHs); @@ -158,206 +425,290 @@ public class Simplify { size--; } } - - System.out.println("Step 2 Result: "); - result.forEach((c,hs)->{ - System.out.print(c.toString() + " -> "); - hs.forEach(s->{ - System.out.print(s + ", "); - }); - System.out.println(); - }); - System.out.println("----------------"); + // remove all equal-constraints allCons.removeAll(consToRemove); - // add all generated constraints to allCons + // 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--; - } - // get all tph of the method - ArrayList methodTphs = new ArrayList<>(); - for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { - if(m.getName().equals(name)) { - methodTphs = m.getTphs(); - 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<>(); - ArrayList eqCons = new ArrayList<>(); - for(TPHConstraint c : allCons) { - if(subAndSuper.containsKey(c.getLeft())) { - LinkedList all = new LinkedList<>(); - all.add(c.getLeft()); - String sup =c.getRight(); - all.add(sup); - HashMap ss = new HashMap<>(); - for(TPHConstraint constr : allCons) { - ss.put(constr.getLeft(), constr.getRight()); - } - while(ss.containsKey(sup)) { - sup = ss.get(sup); - all.add(sup); - } - if(!containTPH(methodTphs, all.getLast())) - continue; - } - if(subAndSuper.containsKey(c.getLeft())) { - System.out.println(c.getLeft()); - String r = c.getRight(); - String r2 = subAndSuper.get(c.getLeft()); - EqualConstraint eq = new EqualConstraint(r2, r, Relation.EQUAL); - eqCons.add(eq); - substituteInMap(subAndSuper,eqCons,allCons,r,r2); - } - subAndSuper.put(c.getLeft(), c.getRight()); - } - - System.out.println("SAME LEFT SIDE: "); - subAndSuper.forEach((c,hs)->{ - if(c!=null) { - System.out.print(c+ " -> " + hs); - - } - - - System.out.println(); - }); - System.out.println("----------------"); - int numOfVisitedPairs = 0; - for(String sub : subAndSuper.keySet()) { - if(isTPHInConstraint(result,sub)) - continue; - - if(!containTPH(methodTphs,sub)) - continue; - - if(numOfVisitedPairs>=size) - break; - LinkedList 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(containTPH(methodTphs,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(); - // 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); - i++; - } - - if(!containTPH(methodTphs, superTphRes)) { - HashSet equals = getEqualsTphsFromEqualCons(eqCons,superTphRes); - if(classTPHSContainsTPH(tphsClass,superTphRes)) { - result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), equals); - } else { - result.put(new ExtendsConstraint(subTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), equals); - } - - } else { - HashSet equals = getEqualsTphsFromEqualCons(eqCons,subTphRes); - result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), equals); - if(!isTPHInConstraint(result, superTphRes) && !isTphInEqualSet(result,superTphRes)) { - HashSet equals2 = getEqualsTphsFromEqualCons(eqCons,superTphRes); - result.put(new ExtendsConstraint(superTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), equals2); - } - } - } - - for(String tph : methodTphs) { - if(!isTPHInConstraint(result, tph) && !isTphInEqualSet(result,tph)) { - HashSet equals = getEqualsTphsFromEqualCons(eqCons,tph); - result.put(new ExtendsConstraint(tph, Type.getInternalName(Object.class), Relation.EXTENDS), equals); - } - } - + System.out.println("EndResult: "); - result.forEach((c,hs)->{ - if(c!=null) { + result.forEach((c, hs) -> { + if (c != null) { System.out.print(c.toString() + " -> "); - if(hs == null) { + if (hs == null) { System.out.print(" [] "); - }else { - hs.forEach(s->{ + } else { + hs.forEach(s -> { System.out.print(s + ", "); }); } } - - + System.out.println(); }); System.out.println("----------------"); return result; } - + + private static void updateEqualCons(Map> replRes, ArrayList eqCons) { + List oldNames = replRes.values().iterator().next(); + String newName = replRes.keySet().iterator().next(); + for (TPHConstraint c : eqCons) { +// if(oldNames.contains(c.getLeft())) +// c.setLeft(newName); + if (oldNames.contains(c.getRight())) + c.setRight(newName); + } + + } + + public static HashMap> simplifyConstraintsClass(TPHExtractor tphExtractor, + ArrayList tphsClass) { + // all constraints that will be simplified + ArrayList allCons = tphExtractor.allCons; + ArrayList 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 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> 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); + + 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(); + } + } + // 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 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 subAndSuper = new HashMap<>(); + ArrayList 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 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 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 tphsClass, String superTphRes) { - for(TypePlaceholder tph : tphsClass) { - if(tph.getName().equals(superTphRes)) + for (TypePlaceholder tph : tphsClass) { + if (tph.getName().equals(superTphRes)) return true; } return false; } private static boolean isTphInEqualSet(HashMap> result, String tph) { - for(HashSet hs: result.values()) { - if(hs.contains(tph)) + for (HashSet hs : result.values()) { + if (hs.contains(tph)) return true; } return false; @@ -365,44 +716,44 @@ public class Simplify { private static HashSet getEqualsTphsFromEqualCons(ArrayList eqCons, String tph) { HashSet ee = new HashSet<>(); - for(TPHConstraint c : eqCons) { - if(c.getLeft().equals(tph)) + for (TPHConstraint c : eqCons) { + if (c.getLeft().equals(tph)) ee.add(c.getRight()); - if(c.getRight().equals(tph)) + if (c.getRight().equals(tph)) ee.add(c.getLeft()); } return ee; } - private static void substituteInMap(HashMap subAndSuper, ArrayList allCons,ArrayList eqCons, String toSubs, - String tph) { + private static void substituteInMap(HashMap subAndSuper, ArrayList allCons, + ArrayList eqCons, String toSubs, String tph) { substituteTPH(allCons, toSubs, tph); - if(subAndSuper.containsKey(toSubs) && subAndSuper.containsKey(tph)) { + if (subAndSuper.containsKey(toSubs) && subAndSuper.containsKey(tph)) { toSubs = subAndSuper.remove(toSubs); EqualConstraint eq = new EqualConstraint(subAndSuper.get(tph), toSubs, Relation.EQUAL); eqCons.add(eq); - substituteInMap(subAndSuper, allCons,eqCons,toSubs, subAndSuper.get(tph)); - } else if(subAndSuper.containsKey(toSubs) && !subAndSuper.containsKey(tph)) { + substituteInMap(subAndSuper, allCons, eqCons, toSubs, subAndSuper.get(tph)); + } else if (subAndSuper.containsKey(toSubs) && !subAndSuper.containsKey(tph)) { String val = subAndSuper.remove(toSubs); subAndSuper.put(tph, val); } else { - for(String k : subAndSuper.keySet()) { + for (String k : subAndSuper.keySet()) { subAndSuper.replace(k, toSubs, tph); } } } private static TPHConstraint getConstraint(String oldRight, String right, ArrayList allCons) { - for(TPHConstraint c : allCons) { - if(c.getLeft().equals(oldRight) && c.getRight().equals(right)) + for (TPHConstraint c : allCons) { + if (c.getLeft().equals(oldRight) && c.getRight().equals(right)) return c; } return null; } private static boolean isTPHInResEqual(HashMap> result, String left) { - for(HashSet eq : result.values()) { - if(eq.contains(left)) { + for (HashSet eq : result.values()) { + if (eq.contains(left)) { return true; } } @@ -411,75 +762,77 @@ public class Simplify { private static void substituteAllTPH(ArrayList allCons, ArrayList constraints, String first) { - for(TPHConstraint c : allCons) { - for(TPHConstraint c2 : constraints) { - if(c.getRel() == Relation.EXTENDS) { - if(c2.getLeft().equals(c.getLeft()) || c2.getRight().equals(c.getLeft())) + for (TPHConstraint c : allCons) { + for (TPHConstraint c2 : constraints) { + if (c.getRel() == Relation.EXTENDS) { + if (c2.getLeft().equals(c.getLeft()) || c2.getRight().equals(c.getLeft())) c.setLeft(first); - if(c2.getLeft().equals(c.getRight()) || c2.getRight().equals(c.getRight())) + if (c2.getLeft().equals(c.getRight()) || c2.getRight().equals(c.getRight())) c.setRight(first); } - + } } } private static void setAllEqual(ArrayList constraints) { - for(TPHConstraint c:constraints) { + for (TPHConstraint c : constraints) { c.setRel(Relation.EQUAL); } } - public static HashMap> simplifyContraints(HashMap> allConstraints) { + public static HashMap> simplifyContraints( + HashMap> allConstraints) { // 1. check if there are any cycles like L set L=R and: - // * remove both constraints - // * substitute L with R in all constraint - // b)no => go to next step - // 2. check the result of step 1 if there are any equal-constraints like L=R, M=R .. - // a) yes => put all such TPhs in a map and define "key-Cons" - // -- key-Cons = TPH < Object -- - // put this Constraint and the - // b) no + // a) yes => set L=R and: + // * remove both constraints + // * substitute L with R in all constraint + // b)no => go to next step + // 2. check the result of step 1 if there are any equal-constraints like L=R, + // M=R .. + // a) yes => put all such TPhs in a map and define "key-Cons" + // -- key-Cons = TPH < Object -- + // put this Constraint and the + // b) no // 3. is ArrayList allCons = new ArrayList<>(); - for(TPHConstraint tphCons : allConstraints.keySet()) { + for (TPHConstraint tphCons : allConstraints.keySet()) { allCons.add(tphCons); } ArrayList consToRemove = new ArrayList<>(); // step 1: - for(TPHConstraint c : allCons) { - + 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) { + if (c.getRel() == Relation.EXTENDS) { + TPHConstraint revCon = getReverseConstraint(allCons, left, right); + if (revCon != null) { revCon.setRel(Relation.EQUAL); consToRemove.add(revCon); c.setRel(Relation.EQUAL); - substituteTPH(allCons,left, right); + substituteTPH(allCons, left, right); } } } System.out.println(); System.out.println("NEW ALL CONST: " + allCons.size()); - allCons.forEach(c->System.out.println(c.toString())); + allCons.forEach(c -> System.out.println(c.toString())); System.out.println("----------------"); allCons.removeAll(consToRemove); consToRemove = new ArrayList<>(); - + // int size = allCons.size(); - + System.out.println("AFTER DELETE ALL CONST: " + allCons.size()); - allCons.forEach(c->System.out.println(c.toString())); + allCons.forEach(c -> System.out.println(c.toString())); System.out.println("----------------"); HashMap> result = new HashMap<>(); - - for(TPHConstraint c : allCons) { - if(c.getRel()==Relation.EQUAL) { + + for (TPHConstraint c : allCons) { + if (c.getRel() == Relation.EQUAL) { HashSet equalTPHs = getEqualsTPHs(result, c); - TPHConstraint constraint = getKeyConstraint(result,c); + TPHConstraint constraint = getKeyConstraint(result, c); equalTPHs.add(c.getLeft()); equalTPHs.add(c.getRight()); result.put(constraint, equalTPHs); @@ -488,9 +841,9 @@ public class Simplify { } } System.out.println("Step 2 Result: "); - result.forEach((c,hs)->{ + result.forEach((c, hs) -> { System.out.print(c.toString() + " -> "); - hs.forEach(s->{ + hs.forEach(s -> { System.out.print(s + ", "); }); System.out.println(); @@ -498,33 +851,33 @@ public class Simplify { System.out.println("----------------"); allCons.removeAll(consToRemove); allCons.addAll(result.keySet()); - - if(!allCons.isEmpty() && allCons.size()<2) { - if(!result.containsKey(allCons.get(0))) + if (!allCons.isEmpty() && allCons.size() < 2) { + + if (!result.containsKey(allCons.get(0))) result.put(allCons.get(0), null); - + return result; } - + // size += result.keySet().size(); - + // for(TPHConstraint c : allCons) { // if(c.getRight().equals(Type.getInternalName(Object.class))) // size--; // } - + HashMap subAndSuper = new HashMap<>(); - - for(TPHConstraint c : allCons) { + + for (TPHConstraint c : allCons) { subAndSuper.put(c.getLeft(), c.getRight()); } - + // int numOfVisitedPairs = 0; - for(String sub : subAndSuper.keySet()) { - if(isTPHInConstraint(result,sub)) + for (String sub : subAndSuper.keySet()) { + if (isTPHInConstraint(result, sub)) continue; - + // if(numOfVisitedPairs>=size) // break; @@ -532,118 +885,137 @@ public class Simplify { tphInRel.add(sub); String superT = subAndSuper.get(sub); tphInRel.add(superT); - + // numOfVisitedPairs++; - while(subAndSuper.containsKey(superT)) { + while (subAndSuper.containsKey(superT)) { superT = subAndSuper.get(superT); - if(tphInRel.contains(superT)) { + if (tphInRel.contains(superT)) { break; } tphInRel.add(superT); // numOfVisitedPairs++; } - + // Subtype String subTphRes = tphInRel.getFirst(); // Die größte Supertype String superTphRes = tphInRel.getLast(); - - while(subAndSuper.containsValue(subTphRes)) { - for(String tph : subAndSuper.keySet()) { - if(subAndSuper.get(tph).equals(subTphRes)) { + + while (subAndSuper.containsValue(subTphRes)) { + for (String tph : subAndSuper.keySet()) { + if (subAndSuper.get(tph).equals(subTphRes)) { subTphRes = tph; break; } } - if(subTphRes.equals(tphInRel.getFirst())) { + if (subTphRes.equals(tphInRel.getFirst())) { break; } tphInRel.addFirst(subTphRes); // numOfVisitedPairs++; } - + subTphRes = tphInRel.getFirst(); - + int i = 2; - while(superTphRes.equals(Type.getInternalName(Object.class)) && (tphInRel.size()-i) >0) { - superTphRes = tphInRel.get(tphInRel.size()-i); + while (superTphRes.equals(Type.getInternalName(Object.class)) && (tphInRel.size() - i) > 0) { + superTphRes = tphInRel.get(tphInRel.size() - i); i++; } - if(superTphRes.equals(Type.getInternalName(Object.class))) { - result.put(new ExtendsConstraint(subTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); + if (superTphRes.equals(Type.getInternalName(Object.class))) { + 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); + result.put(new ExtendsConstraint(superTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), + null); } - + } System.out.println("EndResult: "); - result.forEach((c,hs)->{ - if(c!=null) { + result.forEach((c, hs) -> { + if (c != null) { System.out.print(c.toString() + " -> "); - if(hs == null) { + if (hs == null) { System.out.print(" [] "); - }else { - hs.forEach(s->{ + } else { + hs.forEach(s -> { System.out.print(s + ", "); }); } } - - + System.out.println(); }); System.out.println("----------------"); return result; } - - private static void substituteTPH(ArrayList allCons,String left ,String right) { - allCons.forEach(c->{ - if(c.getRel() == Relation.EXTENDS) { - if(c.getLeft().equals(left)) + + private static void substituteTPH(ArrayList allCons, String left, String right) { + allCons.forEach(c -> { + if (c.getRel() == Relation.EXTENDS) { + if (c.getLeft().equals(left)) c.setLeft(right); - if(c.getRight().equals(left)) + if (c.getRight().equals(left)) c.setRight(right); } }); } private static TPHConstraint getReverseConstraint(ArrayList allCons, String left, String right) { - for(TPHConstraint c : allCons) { - if(c.getLeft().equals(right) && c.getRight().equals(left)){ + for (TPHConstraint c : allCons) { + if (c.getLeft().equals(right) && c.getRight().equals(left)) { return c; } } return null; } - + private static boolean isTPHInConstraint(HashMap> result, String sub) { - for(TPHConstraint c : result.keySet()) { - if(c.getLeft().equals(sub)) + for (TPHConstraint c : result.keySet()) { + if (c.getLeft().equals(sub)) return true; } return false; } private static boolean containTPH(ArrayList methodTphs, String sub) { - for(String tph : methodTphs) { - if(tph.equals(sub)) + for (String tph : methodTphs) { + if (tph.equals(sub)) return true; } return false; } - private static TPHConstraint getKeyConstraint(HashMap> result, TPHConstraint toFind) { - for(TPHConstraint c : result.keySet()) { - if(c.containTPH(toFind.getLeft()) || c.containTPH(toFind.getRight())) + private static TPHConstraint getKeyConstraint(HashMap> result, TPHConstraint toFind, + ArrayList allCons) { + + for (TPHConstraint c : result.keySet()) { + if (c.containTPH(toFind.getLeft())) return c; } + for (TPHConstraint c : allCons) { + if (toFind.getRight().equals(c.getLeft())) + return c; + } + return new ExtendsConstraint(toFind.getRight(), Type.getInternalName(Object.class), Relation.EXTENDS); } - private static HashSet getEqualsTPHs(HashMap> result, TPHConstraint toFind) { - for(TPHConstraint c : result.keySet()) { - if(c.containTPH(toFind.getLeft()) || c.containTPH(toFind.getRight())) + private static TPHConstraint getKeyConstraint(HashMap> result, + TPHConstraint toFind) { + + for (TPHConstraint c : result.keySet()) { + if (c.containTPH(toFind.getLeft()) || c.containTPH(toFind.getRight())) + return c; + } + + return new ExtendsConstraint(toFind.getRight(), Type.getInternalName(Object.class), Relation.EXTENDS); + } + + private static HashSet getEqualsTPHs(HashMap> result, TPHConstraint toFind) { + for (TPHConstraint c : result.keySet()) { + if (c.containTPH(toFind.getLeft()) || c.containTPH(toFind.getRight())) return result.get(c); } return new HashSet<>(); diff --git a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java index a860adf9..b84c9441 100644 --- a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -1,3 +1,4 @@ +//PL 2018-12-19: typeInferenceOld nach typeInference uebertragen package de.dhbwstuttgart.core; @@ -15,6 +16,7 @@ import de.dhbwstuttgart.syntaxtree.ParameterList; import de.dhbwstuttgart.syntaxtree.SourceFile; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; import de.dhbwstuttgart.typeinference.constraints.Constraint; @@ -25,26 +27,37 @@ import de.dhbwstuttgart.typeinference.typeAlgo.TYPE; import de.dhbwstuttgart.typeinference.unify.RuleSet; import de.dhbwstuttgart.typeinference.unify.TypeUnify; import de.dhbwstuttgart.typeinference.unify.distributeVariance; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure; import de.dhbwstuttgart.typeinference.unify.model.PairOperator; import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask; +import de.dhbwstuttgart.typeinference.unify.UnifyResultListener; +import de.dhbwstuttgart.typeinference.unify.UnifyResultListenerImpl; +import de.dhbwstuttgart.typeinference.unify.UnifyResultModel; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.antlr.v4.parse.ANTLRParser.throwsSpec_return; +import org.apache.commons.io.output.NullOutputStream; + public class JavaTXCompiler { final CompilationEnvironment environment; + Boolean resultmodel = true; public final Map sourceFiles = new HashMap<>(); - Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+"/test/logFiles/log" geschrieben werden soll? + Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+"src/test/java/logFiles" geschrieben werden soll? public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException { this(Arrays.asList(sourceFile)); @@ -103,7 +116,8 @@ public class JavaTXCompiler { return new ArrayList<>(allClasses); } - public List typeInference() throws ClassNotFoundException { +/* + public List typeInferenceOld() throws ClassNotFoundException { List allClasses = new ArrayList<>();//environment.getAllAvailableClasses(); //Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC for(SourceFile sf : this.sourceFiles.values()) { @@ -187,10 +201,7 @@ public class JavaTXCompiler { } } return x;//HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE JEWEILS ANDERE SEITE - }) - /* PL 2018-11-07 wird in varianceInheritance erledigt - .map( y -> { - + }).map( y -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { if (((PlaceholderType)y.getLhsType()).getVariance() != 0 && ((PlaceholderType)y.getRhsType()).getVariance() == 0) { ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType()).getVariance()); @@ -200,20 +211,16 @@ public class JavaTXCompiler { } } return y; } ) - */ .collect(Collectors.toCollection(HashSet::new)); - varianceInheritance(xConsSet); - - - - Set> result = unify.unifySequential(xConsSet, finiteClosure, logFile, log); - //Set> result = unify.unify(xConsSet, finiteClosure); - System.out.println("RESULT: " + result); - logFile.write("RES: " + result.toString()+"\n"); - logFile.flush(); - results.addAll(result); + varianceInheritance(xConsSet); + Set> result = unify.unifySequential(xConsSet, finiteClosure, logFile, log); + //Set> result = unify.unify(xConsSet, finiteClosure); + System.out.println("RESULT: " + result); + logFile.write("RES: " + result.toString()+"\n"); + logFile.flush(); + results.addAll(result); } - + results = results.stream().map(x -> { Optional> res = new RuleSet().subst(x.stream().map(y -> { if (y.getPairOp() == PairOperator.SMALLERDOTWC) y.setPairOp(PairOperator.EQUALSDOT); @@ -236,12 +243,14 @@ public class JavaTXCompiler { return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, generateTPHMap(cons))))).collect(Collectors.toList()); } - + */ /** - * Vererbt alle Variancen + * Vererbt alle Variancen bei Paaren (a <. theta) oder (Theta <. a) + * wenn a eine Variance !=0 hat auf alle Typvariablen in Theta. * @param eq The set of constraints */ - private void varianceInheritance(Set eq) { + /* + private void varianceInheritance(Set eq) { Set usedTPH = new HashSet<>(); Set phSet = eq.stream().map(x -> { Set pair = new HashSet<>(); @@ -267,20 +276,365 @@ public class JavaTXCompiler { phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x))); } } + */ + + public UnifyResultModel typeInferenceAsync(UnifyResultListener resultListener) throws ClassNotFoundException { + List allClasses = new ArrayList<>();//environment.getAllAvailableClasses(); + //Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC + for(SourceFile sf : this.sourceFiles.values()) { + allClasses.addAll(getAvailableClasses(sf)); + allClasses.addAll(sf.getClasses()); + } - private Map generateTPHMap(ConstraintSet constraints) { - HashMap ret = new HashMap<>(); - constraints.map((Pair p) -> { - if (p.TA1 instanceof TypePlaceholder) { - ret.put(((TypePlaceholder) p.TA1).getName(), (TypePlaceholder) p.TA1); - } - if (p.TA2 instanceof TypePlaceholder) { - ret.put(((TypePlaceholder) p.TA2).getName(), (TypePlaceholder) p.TA2); - } - return null; - }); - return ret; + final ConstraintSet cons = getConstraints(); + Set> results = new HashSet<>(); + UnifyResultModel urm = new UnifyResultModel(); + urm.addUnifyResultListener(resultListener); + try { + Writer logFile = new OutputStreamWriter(new NullOutputStream()); + //new FileWriter(new File("log_"+sourceFiles.keySet().iterator().next().getName())); + + IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses,logFile); + System.out.println(finiteClosure); + ConstraintSet unifyCons = UnifyTypeFactory.convert(cons); + + Function distributeInnerVars = + x -> { + UnifyType lhs, rhs; + if (((lhs = x.getLhsType()) instanceof PlaceholderType) + && ((rhs = x.getRhsType()) instanceof PlaceholderType) + && (((PlaceholderType)lhs).isInnerType() + || ((PlaceholderType)rhs).isInnerType())) + { + ((PlaceholderType)lhs).setInnerType(true); + ((PlaceholderType)rhs).setInnerType(true); + } + return x; + + }; + logFile.write(unifyCons.toString()); + unifyCons = unifyCons.map(distributeInnerVars); + logFile.write(unifyCons.toString()); + TypeUnify unify = new TypeUnify(); + //Set> results = new HashSet<>(); Nach vorne gezogen + logFile.write("FC:\\" + finiteClosure.toString()+"\n"); + for(SourceFile sf : this.sourceFiles.values()) { + logFile.write(ASTTypePrinter.print(sf)); + } + logFile.flush(); + + Set methodParaTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist() + .stream().filter(z -> z.getType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder)z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))) + .reduce(new HashSet(), (a,b) -> { a.addAll(b); return a;}, (a,b) -> { a.addAll(b); return a;} ) ) + .reduce(new HashSet(), (a,b) -> { a.addAll(b); return a;} ); + + Set constructorParaTypeVarNames = allClasses.stream().map(x -> x.getConstructors().stream().map(y -> y.getParameterList().getFormalparalist() + .stream().filter(z -> z.getType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder)z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))) + .reduce(new HashSet(), (a,b) -> { a.addAll(b); return a;}, (a,b) -> { a.addAll(b); return a;} ) ) + .reduce(new HashSet(), (a,b) -> { a.addAll(b); return a;} ); + + Set paraTypeVarNames = methodParaTypeVarNames; + paraTypeVarNames.addAll(constructorParaTypeVarNames); + + + Set returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get(); + + Set fieldTypeVarNames = allClasses.stream().map(x -> x.getFieldDecl().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get(); + + returnTypeVarNames.addAll(fieldTypeVarNames); + + unifyCons = unifyCons.map(x -> { + //Hier muss ueberlegt werden, ob + //1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs + // mit disableWildcardtable() werden. + //2. alle Typvariablen mit Argument- oder Retuntyp-Variablen + //in Beziehung auch auf disableWildcardtable() gesetzt werden muessen + //PL 2018-04-23 + if ((x.getLhsType() instanceof PlaceholderType)) { + if (paraTypeVarNames.contains(x.getLhsType().getName())) { + ((PlaceholderType)x.getLhsType()).setVariance((byte)1); + ((PlaceholderType)x.getLhsType()).disableWildcardtable(); + } + if (returnTypeVarNames.contains(x.getLhsType().getName())) { + ((PlaceholderType)x.getLhsType()).setVariance((byte)-1); + ((PlaceholderType)x.getLhsType()).disableWildcardtable(); + } + } + if ((x.getRhsType() instanceof PlaceholderType)) { + if (paraTypeVarNames.contains(x.getRhsType().getName())) { + ((PlaceholderType)x.getRhsType()).setVariance((byte)1); + ((PlaceholderType)x.getRhsType()).disableWildcardtable(); + } + if (returnTypeVarNames.contains(x.getRhsType().getName())) { + ((PlaceholderType)x.getRhsType()).setVariance((byte)-1); + ((PlaceholderType)x.getRhsType()).disableWildcardtable(); + } + } + return x;//HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE JEWEILS ANDERE SEITE + }); + Set varianceTPHold; + Set varianceTPH = new HashSet<>(); + varianceTPH = varianceInheritanceConstraintSet(unifyCons); + + /* PL 2018-11-07 wird in varianceInheritanceConstraintSet erledigt + do { //PL 2018-11-05 Huellenbildung Variance auf alle TPHs der Terme auf der jeweiligen + //anderen Seite übertragen + varianceTPHold = new HashSet<>(varianceTPH); + varianceTPH = varianceInheritanceConstraintSet(unifyCons); + unifyCons.map( y -> { + if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { + if (((PlaceholderType)y.getLhsType()).getVariance() != 0 && ((PlaceholderType)y.getRhsType()).getVariance() == 0) { + ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType()).getVariance()); + } + if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { + ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType()).getVariance()); + } + } + return y; } ); } + while (!varianceTPHold.equals(varianceTPH)); + */ + + //Set> result = unify.unifySequential(xConsSet, finiteClosure, logFile, log); + //Set> result = unify.unify(xConsSet, finiteClosure); + List>> oderConstraints = unifyCons.getOderConstraints().stream().map(x -> { + Set> ret = new HashSet<>(); + for (Constraint y : x) { + ret.add(new HashSet<>(y)); + } + return ret; + }).collect(Collectors.toCollection(ArrayList::new)); + unify.unifyAsync(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, cons, urm); + } + catch (IOException e) { + System.err.println("kein LogFile"); + } + return urm; } + + + public List typeInference() throws ClassNotFoundException { + List allClasses = new ArrayList<>();//environment.getAllAvailableClasses(); + //Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC + for(SourceFile sf : this.sourceFiles.values()) { + allClasses.addAll(getAvailableClasses(sf)); + allClasses.addAll(sf.getClasses()); + } + + final ConstraintSet cons = getConstraints(); + Set> results = new HashSet<>(); + try { + Writer logFile = new OutputStreamWriter(new NullOutputStream()); + //new FileWriter(new File("log_"+sourceFiles.keySet().iterator().next().getName())); + + IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses,logFile); + System.out.println(finiteClosure); + ConstraintSet unifyCons = UnifyTypeFactory.convert(cons); + + Function distributeInnerVars = + x -> { + UnifyType lhs, rhs; + if (((lhs = x.getLhsType()) instanceof PlaceholderType) + && ((rhs = x.getRhsType()) instanceof PlaceholderType) + && (((PlaceholderType)lhs).isInnerType() + || ((PlaceholderType)rhs).isInnerType())) + { + ((PlaceholderType)lhs).setInnerType(true); + ((PlaceholderType)rhs).setInnerType(true); + } + return x; + + }; + logFile.write(unifyCons.toString()); + unifyCons = unifyCons.map(distributeInnerVars); + logFile.write(unifyCons.toString()); + TypeUnify unify = new TypeUnify(); + //Set> results = new HashSet<>(); Nach vorne gezogen + logFile.write("FC:\\" + finiteClosure.toString()+"\n"); + for(SourceFile sf : this.sourceFiles.values()) { + logFile.write(ASTTypePrinter.print(sf)); + } + logFile.flush(); + + Set methodParaTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist() + .stream().filter(z -> z.getType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder)z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))) + .reduce(new HashSet(), (a,b) -> { a.addAll(b); return a;}, (a,b) -> { a.addAll(b); return a;} ) ) + .reduce(new HashSet(), (a,b) -> { a.addAll(b); return a;} ); + + Set constructorParaTypeVarNames = allClasses.stream().map(x -> x.getConstructors().stream().map(y -> y.getParameterList().getFormalparalist() + .stream().filter(z -> z.getType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder)z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))) + .reduce(new HashSet(), (a,b) -> { a.addAll(b); return a;}, (a,b) -> { a.addAll(b); return a;} ) ) + .reduce(new HashSet(), (a,b) -> { a.addAll(b); return a;} ); + + Set paraTypeVarNames = methodParaTypeVarNames; + paraTypeVarNames.addAll(constructorParaTypeVarNames); + + + Set returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get(); + + Set fieldTypeVarNames = allClasses.stream().map(x -> x.getFieldDecl().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get(); + + returnTypeVarNames.addAll(fieldTypeVarNames); + + unifyCons = unifyCons.map(x -> { + //Hier muss ueberlegt werden, ob + //1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs + // mit disableWildcardtable() werden. + //2. alle Typvariablen mit Argument- oder Retuntyp-Variablen + //in Beziehung auch auf disableWildcardtable() gesetzt werden muessen + //PL 2018-04-23 + if ((x.getLhsType() instanceof PlaceholderType)) { + if (paraTypeVarNames.contains(x.getLhsType().getName())) { + ((PlaceholderType)x.getLhsType()).setVariance((byte)1); + ((PlaceholderType)x.getLhsType()).disableWildcardtable(); + } + if (returnTypeVarNames.contains(x.getLhsType().getName())) { + ((PlaceholderType)x.getLhsType()).setVariance((byte)-1); + ((PlaceholderType)x.getLhsType()).disableWildcardtable(); + } + } + if ((x.getRhsType() instanceof PlaceholderType)) { + if (paraTypeVarNames.contains(x.getRhsType().getName())) { + ((PlaceholderType)x.getRhsType()).setVariance((byte)1); + ((PlaceholderType)x.getRhsType()).disableWildcardtable(); + } + if (returnTypeVarNames.contains(x.getRhsType().getName())) { + ((PlaceholderType)x.getRhsType()).setVariance((byte)-1); + ((PlaceholderType)x.getRhsType()).disableWildcardtable(); + } + } + return x;//HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE JEWEILS ANDERE SEITE + }); + Set varianceTPHold; + Set varianceTPH = new HashSet<>(); + varianceTPH = varianceInheritanceConstraintSet(unifyCons); + + /* PL 2018-11-07 wird in varianceInheritanceConstraintSet erledigt + do { //PL 2018-11-05 Huellenbildung Variance auf alle TPHs der Terme auf der jeweiligen + //anderen Seite übertragen + varianceTPHold = new HashSet<>(varianceTPH); + varianceTPH = varianceInheritanceConstraintSet(unifyCons); + unifyCons.map( y -> { + if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { + if (((PlaceholderType)y.getLhsType()).getVariance() != 0 && ((PlaceholderType)y.getRhsType()).getVariance() == 0) { + ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType()).getVariance()); + } + if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { + ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType()).getVariance()); + } + } + return y; } ); } + while (!varianceTPHold.equals(varianceTPH)); + */ + + //Set> result = unify.unifySequential(xConsSet, finiteClosure, logFile, log); + //Set> result = unify.unify(xConsSet, finiteClosure); + List>> oderConstraints = unifyCons.getOderConstraints().stream().map(x -> { + Set> ret = new HashSet<>(); + for (Constraint y : x) { + ret.add(new HashSet<>(y)); + } + return ret; + }).collect(Collectors.toCollection(ArrayList::new)); + if (resultmodel) { + /* UnifyResultModel Anfang */ + UnifyResultModel urm = new UnifyResultModel(); + UnifyResultListenerImpl li = new UnifyResultListenerImpl(); + urm.addUnifyResultListener(li); + unify.unifyParallel(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, cons, urm); + System.out.println("RESULT Final: " + li.getResults()); + logFile.write("RES_FINAL: " + li.getResults().toString()+"\n"); + logFile.flush(); + return li.getResults(); + } + /* UnifyResultModel End */ + else { + Set> result = unify.unify(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, cons); + //Set> result = unify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, cons); + System.out.println("RESULT: " + result); + logFile.write("RES: " + result.toString()+"\n"); + logFile.flush(); + results.addAll(result); + + + results = results.stream().map(x -> { + Optional> res = new RuleSet().subst(x.stream().map(y -> { + if (y.getPairOp() == PairOperator.SMALLERDOTWC) y.setPairOp(PairOperator.EQUALSDOT); + return y; //alle Paare a <.? b erden durch a =. b ersetzt + }).collect(Collectors.toCollection(HashSet::new))); + if (res.isPresent()) {//wenn subst ein Erg liefert wurde was veraendert + return new TypeUnifyTask().applyTypeUnificationRules(res.get(), finiteClosure); + } + else return x; //wenn nichts veraendert wurde wird x zurueckgegeben + }).collect(Collectors.toCollection(HashSet::new)); + System.out.println("RESULT Final: " + results); + logFile.write("RES_FINAL: " + results.toString()+"\n"); + logFile.flush(); + logFile.write("PLACEHOLDERS: " + PlaceholderType.EXISTING_PLACEHOLDERS); + logFile.flush(); + }} + catch (IOException e) { + System.err.println("kein LogFile"); + } + return results.stream().map((unifyPairs -> + new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons))))).collect(Collectors.toList()); + } + + + + /** + * Vererbt alle Variancen bei Paaren (a <. theta) oder (Theta <. a) + * wenn a eine Variance !=0 hat auf alle Typvariablen in Theta. + * @param eq The set of constraints + */ + private Set varianceInheritanceConstraintSet(ConstraintSet cons) { + Set eq = cons.getAll(); + Set usedTPH = new HashSet<>(); + Set phSet = eq.stream().map(x -> { + Set pair = new HashSet<>(); + if (x.getLhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getLhsType()); + if (x.getRhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getRhsType()); + return pair; + }).reduce(new HashSet<>(), (a,b) -> { a.addAll(b); return a;} , (c,d) -> { c.addAll(d); return c;}); + + ArrayList phSetVariance = new ArrayList<>(phSet); + phSetVariance.removeIf(x -> (x.getVariance() == 0)); + while(!phSetVariance.isEmpty()) { + PlaceholderType a = phSetVariance.remove(0); + usedTPH.add(a); + //HashMap ht = new HashMap<>(); + //ht.put(a, a.getVariance()); + //ConstraintSet eq1 = cons; + //eq1.removeIf(x -> !(x.getLhsType() instanceof PlaceholderType && ((PlaceholderType)x.getLhsType()).equals(a))); + //durch if-Abfrage im foreach geloest + cons.forEach(x -> { + if (x.getLhsType() instanceof PlaceholderType && ((PlaceholderType)x.getLhsType()).equals(a)) { + x.getRhsType().accept(new distributeVariance(), a.getVariance()); + } + }); + //` eq1 = new HashSet<>(eq); + //eq1.removeIf(x -> !(x.getRhsType() instanceof PlaceholderType && ((PlaceholderType)x.getRhsType()).equals(a))); + //durch if-Abfrage im foreach geloest + cons.forEach(x -> { + if (x.getRhsType() instanceof PlaceholderType && ((PlaceholderType)x.getRhsType()).equals(a)) { + x.getLhsType().accept(new distributeVariance(), a.getVariance()); + } + }); + phSetVariance = new ArrayList<>(phSet); //macht vermutlich keinen Sinn PL 2018-10-18, doch, es koennen neue TPHs mit Variancen dazugekommen sein PL 2018-11-07 + phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x))); + } + return usedTPH; + } + + + private SourceFile parse(File sourceFile) throws IOException, java.lang.ClassNotFoundException { CompilationUnitContext tree = JavaTXParser.parse(sourceFile); diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java b/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java index bf9fe263..6fd83f3b 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java @@ -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); } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java index 71985334..a764db6e 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java @@ -1,5 +1,7 @@ package de.dhbwstuttgart.syntaxtree.factory; +import java.io.FileWriter; +import java.io.Writer; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -29,7 +31,7 @@ public class UnifyTypeFactory { private static ArrayList PLACEHOLDERS = new ArrayList<>(); - public static FiniteClosure generateFC(List fromClasses) throws ClassNotFoundException { + public static FiniteClosure generateFC(List fromClasses, Writer logFile) throws ClassNotFoundException { /* Die transitive Hülle muss funktionieren. Man darf schreiben List extends AL @@ -40,7 +42,7 @@ public class UnifyTypeFactory { Generell dürfen sie immer die gleichen Namen haben. TODO: die transitive Hülle bilden */ - return new FiniteClosure(FCGenerator.toUnifyFC(fromClasses)); + return new FiniteClosure(FCGenerator.toUnifyFC(fromClasses), logFile); } public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr){ @@ -63,26 +65,26 @@ public class UnifyTypeFactory { * Convert from * ASTType -> UnifyType */ - public static UnifyType convert(RefTypeOrTPHOrWildcardOrGeneric t){ + public static UnifyType convert(RefTypeOrTPHOrWildcardOrGeneric t, Boolean innerType){ if(t instanceof GenericRefType){ - return UnifyTypeFactory.convert((GenericRefType)t); + return UnifyTypeFactory.convert((GenericRefType)t, innerType); }else if(t instanceof FunN){ - return UnifyTypeFactory.convert((FunN)t); + return UnifyTypeFactory.convert((FunN)t, innerType); }else if(t instanceof TypePlaceholder){ - return UnifyTypeFactory.convert((TypePlaceholder)t); + return UnifyTypeFactory.convert((TypePlaceholder)t, innerType); }else if(t instanceof ExtendsWildcardType){ - return UnifyTypeFactory.convert((ExtendsWildcardType)t); + return UnifyTypeFactory.convert((ExtendsWildcardType)t, innerType); }else if(t instanceof SuperWildcardType){ - return UnifyTypeFactory.convert((SuperWildcardType)t); + return UnifyTypeFactory.convert((SuperWildcardType)t, innerType); }else if(t instanceof RefType){ - return UnifyTypeFactory.convert((RefType)t); + return UnifyTypeFactory.convert((RefType)t, innerType); } //Es wurde versucht ein Typ umzuwandeln, welcher noch nicht von der Factory abgedeckt ist throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden"); } - public static UnifyType convert(RefType t){ + public static UnifyType convert(RefType t, Boolean innerType){ //Check if it is a FunN Type: Pattern p = Pattern.compile("Fun(\\d+)"); Matcher m = p.matcher(t.getName().toString()); @@ -90,14 +92,14 @@ public class UnifyTypeFactory { if(b){ Integer N = Integer.valueOf(m.group(1)); if((N + 1) == t.getParaList().size()){ - return convert(new FunN(t.getParaList())); + return convert(new FunN(t.getParaList()), false); } } UnifyType ret; if(t.getParaList() != null && t.getParaList().size() > 0){ List params = new ArrayList<>(); for(RefTypeOrTPHOrWildcardOrGeneric pT : t.getParaList()){ - params.add(UnifyTypeFactory.convert(pT)); + params.add(UnifyTypeFactory.convert(pT, true)); } ret = new ReferenceType(t.getName().toString(),new TypeParams(params)); }else{ @@ -106,39 +108,45 @@ public class UnifyTypeFactory { return ret; } - public static UnifyType convert(FunN t){ + public static UnifyType convert(FunN t, Boolean innerType){ UnifyType ret; List params = new ArrayList<>(); if(t.getParaList() != null && t.getParaList().size() > 0){ for(RefTypeOrTPHOrWildcardOrGeneric pT : t.getParaList()){ - params.add(UnifyTypeFactory.convert(pT)); + params.add(UnifyTypeFactory.convert(pT, false)); } } ret = FunNType.getFunNType(new TypeParams(params)); return ret; } - public static UnifyType convert(TypePlaceholder tph){ + public static UnifyType convert(TypePlaceholder tph, Boolean innerType){ + if (tph.getName().equals("AFR")) { + System.out.println("XXX"+innerType); + } PlaceholderType ntph = new PlaceholderType(tph.getName()); int in = PLACEHOLDERS.indexOf(ntph); if (in == -1) { PLACEHOLDERS.add(ntph); + ntph.setInnerType(innerType); return ntph; } else { - return PLACEHOLDERS.get(in); + PlaceholderType oldpht = PLACEHOLDERS.get(in); + oldpht.setInnerType(oldpht.isInnerType() || innerType); + return oldpht; } } - public static UnifyType convert(GenericRefType t){ + public static UnifyType convert(GenericRefType t, Boolean innerType){ return new ReferenceType(t.getParsedName()); } - public static UnifyType convert(WildcardType t){ + public static UnifyType convert(WildcardType t, Boolean innerType){ if(t.isExtends()) - return new ExtendsType(UnifyTypeFactory.convert(t.getInnerType())); + return new ExtendsType(UnifyTypeFactory.convert(t.getInnerType(), false)); else if(t.isSuper()) - return new SuperType(UnifyTypeFactory.convert(t.getInnerType())); + return new SuperType(UnifyTypeFactory.convert(t.getInnerType(), false)); else throw new NotImplementedException(); } @@ -152,22 +160,42 @@ public class UnifyTypeFactory { } public static UnifyPair convert(Pair p) { + UnifyPair ret = null; if(p.GetOperator().equals(PairOperator.SMALLERDOT)) { - UnifyPair ret = generateSmallerDotPair(UnifyTypeFactory.convert(p.TA1) - , UnifyTypeFactory.convert(p.TA2)); - return ret; + ret = generateSmallerDotPair(UnifyTypeFactory.convert(p.TA1, false) + , UnifyTypeFactory.convert(p.TA2, false)); + //return ret; }else if(p.GetOperator().equals(PairOperator.SMALLERNEQDOT)) { - UnifyPair ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(p.TA1) - , UnifyTypeFactory.convert(p.TA2)); - return ret; + ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(p.TA1, false) + , UnifyTypeFactory.convert(p.TA2, false)); + //return ret; }else if(p.GetOperator().equals(PairOperator.EQUALSDOT)) { - UnifyPair ret = generateEqualDotPair(UnifyTypeFactory.convert(p.TA1) - , UnifyTypeFactory.convert(p.TA2)); - return ret; + ret = generateEqualDotPair(UnifyTypeFactory.convert(p.TA1, false) + , UnifyTypeFactory.convert(p.TA2, false)); + //return ret; }else if(p.GetOperator().equals(PairOperator.SMALLER)){ - return generateSmallerPair(UnifyTypeFactory.convert(p.TA1), - UnifyTypeFactory.convert(p.TA2)); + ret = generateSmallerPair(UnifyTypeFactory.convert(p.TA1, false), + UnifyTypeFactory.convert(p.TA2, false)); }else throw new NotImplementedException(); + UnifyType lhs, rhs; + if (((lhs = ret.getLhsType()) instanceof PlaceholderType) + && ((PlaceholderType)lhs).isWildcardable() + && (rhs = ret.getLhsType()) instanceof PlaceholderType) { + if (lhs.getName().equals("AQ")) { + System.out.println(""); + } + ((PlaceholderType)rhs).enableWildcardtable(); + } + + if (((rhs = ret.getLhsType()) instanceof PlaceholderType) + && ((PlaceholderType)rhs).isWildcardable() + && (lhs = ret.getLhsType()) instanceof PlaceholderType) { + if (rhs.getName().equals("AQ")) { + System.out.println(""); + } + ((PlaceholderType)lhs).enableWildcardtable(); + } + return ret; } /** diff --git a/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java b/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java index 01356fe9..581f9fbd 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java @@ -1,6 +1,7 @@ package de.dhbwstuttgart.typeinference.constraints; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.unify.GuavaSetOperations; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; diff --git a/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java b/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java index 98679f7d..0c8ad7a5 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java @@ -1,7 +1,10 @@ package de.dhbwstuttgart.typeinference.constraints; import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.unify.model.PairOperator; @@ -110,5 +113,20 @@ public class Pair implements Serializable public boolean OperatorSmallerDot() { return eOperator == PairOperator.SMALLERDOT; } + + + static public Map generateTPHMap(ConstraintSet constraints) { + HashMap ret = new HashMap<>(); + constraints.map((Pair p) -> { + if (p.TA1 instanceof TypePlaceholder) { + ret.put(((TypePlaceholder) p.TA1).getName(), (TypePlaceholder) p.TA1); + } + if (p.TA2 instanceof TypePlaceholder) { + ret.put(((TypePlaceholder) p.TA2).getName(), (TypePlaceholder) p.TA2); + } + return null; + }); + return ret; + } } // ino.end diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java index d4e6b551..e333bdfe 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java @@ -28,6 +28,7 @@ import de.dhbwstuttgart.typeinference.unify.distributeVariance; import java.io.FileWriter; import java.io.IOException; +import java.io.Writer; /** * Implementation of the type inference rules. @@ -36,13 +37,13 @@ import java.io.IOException; */ public class RuleSet implements IRuleSet{ - FileWriter logFile; + Writer logFile; public RuleSet() { super(); } - RuleSet(FileWriter logFile) { + RuleSet(Writer logFile) { this.logFile = logFile; } @@ -319,13 +320,21 @@ public class RuleSet implements IRuleSet{ UnifyType lhsType = pair.getLhsType(); ReferenceType lhsSType; + UnifyType rhsType = pair.getRhsType(); + ReferenceType rhsSType; - if(lhsType instanceof ReferenceType) + if ((lhsType instanceof ReferenceType) && (rhsType instanceof ReferenceType)) { lhsSType = (ReferenceType) lhsType; - else if(lhsType instanceof WildcardType) { + rhsSType = (ReferenceType) rhsType; + } + else if (((lhsType instanceof ExtendsType) && (rhsType instanceof ExtendsType)) + || ((lhsType instanceof SuperType) && (rhsType instanceof SuperType))) { UnifyType lhsSTypeRaw = ((WildcardType) lhsType).getWildcardedType(); - if(lhsSTypeRaw instanceof ReferenceType) + UnifyType rhsSTypeRaw = ((WildcardType) rhsType).getWildcardedType(); + if ((lhsSTypeRaw instanceof ReferenceType) && (rhsSTypeRaw instanceof ReferenceType)) { lhsSType = (ReferenceType) lhsSTypeRaw; + rhsSType = (ReferenceType) rhsSTypeRaw; + } else return Optional.empty(); } @@ -334,7 +343,8 @@ public class RuleSet implements IRuleSet{ if(lhsSType.getTypeParams().empty()) return Optional.empty(); - + + /* PL 2018-01-22 in obere Teil integriert UnifyType rhsType = pair.getRhsType(); ReferenceType rhsSType; @@ -349,6 +359,7 @@ public class RuleSet implements IRuleSet{ } else return Optional.empty(); + */ if(!rhsSType.getName().equals(lhsSType.getName())) return Optional.empty(); diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify.java index fa190cb7..974581a9 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify.java @@ -1,25 +1,54 @@ package de.dhbwstuttgart.typeinference.unify; import java.io.FileWriter; +import java.io.Writer; +import java.util.List; import java.util.Set; import java.util.concurrent.ForkJoinPool; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; public class TypeUnify { - public Set> unify(Set eq, IFiniteClosure fc, FileWriter logFile, Boolean log) { - TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, true, logFile, log); + public Set> unify(Set undConstrains, List>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, ConstraintSet cons) { + TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, new UnifyResultModel(), cons); ForkJoinPool pool = new ForkJoinPool(); pool.invoke(unifyTask); Set> res = unifyTask.join(); return res; } + public UnifyResultModel unifyAsync(Set undConstrains, List>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, ConstraintSet cons, UnifyResultModel ret) { + TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, cons); + ForkJoinPool pool = new ForkJoinPool(); + pool.invoke(unifyTask); + return ret; + } + + public UnifyResultModel unifyParallel(Set undConstrains, List>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, ConstraintSet cons, UnifyResultModel ret) { + TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, cons); + ForkJoinPool pool = new ForkJoinPool(); + pool.invoke(unifyTask); + Set> res = unifyTask.join(); + return ret; + } + + /* public Set> unifySequential(Set eq, IFiniteClosure fc, FileWriter logFile, Boolean log) { TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, false, logFile, log); Set> res = unifyTask.compute(); return res; } + */ + + public Set> unifyOderConstraints(Set undConstrains, List>> oderConstraints, IFiniteClosure fc, FileWriter logFile, Boolean log, ConstraintSet cons) { + TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, false, logFile, log, 0, new UnifyResultModel(), cons); + Set> res = unifyTask.compute(); + return res; + } } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify2Task.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify2Task.java new file mode 100644 index 00000000..ac6f04bb --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify2Task.java @@ -0,0 +1,38 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.io.FileWriter; +import java.io.Writer; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +public class TypeUnify2Task extends TypeUnifyTask { + + Set> setToFlatten; + + public TypeUnify2Task(Set> setToFlatten, Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, Writer logFile, Boolean log, int rekTiefe, UnifyResultModel urm, ConstraintSet cons) { + super(eq, oderConstraints, fc, parallel, logFile, log, rekTiefe, urm, cons); + this.setToFlatten = setToFlatten; + } + + @Override + protected Set> compute() { + if (one) { + System.out.println("two"); + } + one = true; + Set> res = unify2(setToFlatten, eq, oderConstraintsField, fc, parallel, rekTiefeField); + /*if (isUndefinedPairSetSet(res)) { + return new HashSet<>(); } + else + */ + noOfThread--; + return res; + } +} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java index 7910b079..43142773 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java @@ -1,3 +1,4 @@ +//PL 2018-12-19: Merge checken package de.dhbwstuttgart.typeinference.unify; import java.util.ArrayList; @@ -18,6 +19,10 @@ import java.util.function.BinaryOperator; import java.util.stream.Collectors; import java.util.stream.Stream; +import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.result.ResultSet; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet; import de.dhbwstuttgart.typeinference.unify.interfaces.ISetOperations; @@ -32,12 +37,14 @@ import de.dhbwstuttgart.typeinference.unify.model.TypeParams; import de.dhbwstuttgart.typeinference.unify.model.Unifier; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; import de.dhbwstuttgart.typeinference.unify.model.UnifyType; +import de.dhbwstuttgart.typeinference.unify.model.WildcardType; import de.dhbwstuttgart.typeinference.unify.model.OrderingUnifyPair; import de.dhbwstuttgart.typeinference.unify.model.Pair; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.io.Writer; import com.google.common.collect.Ordering; @@ -53,8 +60,19 @@ public class TypeUnifyTask extends RecursiveTask>> { private boolean printtag = false; Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+"/test/logFiles/log" geschrieben werden soll? + /** + * Fuer die Threads + */ + UnifyResultModel urm; + ConstraintSet cons; + protected static int noOfThread = 0; + private static int totalnoOfThread = 0; + int thNo; + protected boolean one = false; + Integer MaxNoOfThreads = 8; + public static final String rootDirectory = System.getProperty("user.dir")+"/test/logFiles/"; - FileWriter logFile; + Writer logFile; /** * The implementation of setOps that will be used during the unification @@ -71,7 +89,9 @@ public class TypeUnifyTask extends RecursiveTask>> { */ protected IRuleSet rules; - protected Set eq; + protected Set eq; //und-constraints + + protected List>> oderConstraintsField; protected IFiniteClosure fc; @@ -79,18 +99,23 @@ public class TypeUnifyTask extends RecursiveTask>> { protected boolean parallel; + int rekTiefeField; + Integer nOfUnify = 0; Integer noUndefPair = 0; Integer noAllErasedElements = 0; + static Integer noou = 0; + static int noBacktracking; public TypeUnifyTask() { rules = new RuleSet(); } + /* public TypeUnifyTask(Set eq, IFiniteClosure fc, boolean parallel, FileWriter logFile, Boolean log) { this.eq = eq; this.fc = fc; @@ -99,8 +124,42 @@ public class TypeUnifyTask extends RecursiveTask>> { this.logFile = logFile; this.log = log; rules = new RuleSet(logFile); + noOfThread++; + thNo = noOfThread; } + */ + public TypeUnifyTask(Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, Writer logFile, Boolean log, int rekTiefe, UnifyResultModel urm, ConstraintSet cons2) { + synchronized (this) { + this.eq = eq; + //this.oderConstraints = oderConstraints.stream().map(x -> x.stream().map(y -> new HashSet<>(y)).collect(Collectors.toSet(HashSet::new))).collect(Collectors.toList(ArrayList::new)); + this.oderConstraintsField = oderConstraints; /*.stream().map(x -> { + Set> ret = new HashSet<>(); + for (Constraint y : x) { + ret.add(new HashSet<>(y)); + } + return ret; + }).collect(Collectors.toCollection(ArrayList::new)); + */ + + //x.stream().map(y -> new HashSet<>(y)).collect(Collectors.toSet(HashSet::new))).collect(Collectors.toList(ArrayList::new)); + this.fc = fc; + this.oup = new OrderingUnifyPair(fc); + this.parallel = parallel; + this.logFile = logFile; + this.log = log; + rules = new RuleSet(logFile); + this.rekTiefeField = rekTiefe; + this.urm = urm; + this.cons = cons2; + + noOfThread++; + totalnoOfThread++; + writeLog("thNo1 " + thNo); + thNo = totalnoOfThread; + writeLog("thNo2 " + thNo); + } + } /** * Vererbt alle Variancen @@ -134,12 +193,284 @@ public class TypeUnifyTask extends RecursiveTask>> { } } */ - @Override + protected Set> compute() { - Set> res = unify(eq, fc, parallel); + if (one) { + System.out.println("two"); + } + one = true; + Set neweq = new HashSet<>(eq); + /* 1-elementige Oder-Constraints werden in und-Constraints umgewandelt */ + oderConstraintsField.stream() + .filter(x -> x.size()==1) + .map(y -> y.stream().findFirst().get()).forEach(x -> neweq.addAll(x)); + ArrayList>> remainingOderconstraints = oderConstraintsField.stream() + .filter(x -> x.size()>1) + .collect(Collectors.toCollection(ArrayList::new)); + Set> res = unify(neweq, remainingOderconstraints, fc, parallel, rekTiefeField); + noOfThread--; if (isUndefinedPairSetSet(res)) { return new HashSet<>(); } else return res; } +/* + @Override + protected Set> compute() { + Set> fstElems = new HashSet<>(); + fstElems.add(eq); + Set> res = computeCartesianRecursiveOderConstraints(fstElems, oderConstraints, fc, parallel); + if (isUndefinedPairSetSet(res)) { return new HashSet<>(); } + else return res; + } +*/ + + + public Set> computeCartesianRecursiveOderConstraints(Set> fstElems, List>> topLevelSets, IFiniteClosure fc, boolean parallel, int rekTiefe) { + //ArrayList>> remainingSets = new ArrayList<>(topLevelSets); + fstElems.addAll(topLevelSets.stream() + .filter(x -> x.size()==1) + .map(y -> y.stream().findFirst().get()) + .collect(Collectors.toCollection(HashSet::new))); + ArrayList>> remainingSets = topLevelSets.stream() + .filter(x -> x.size()>1) + .collect(Collectors.toCollection(ArrayList::new)); + if (remainingSets.isEmpty()) {//Alle Elemente sind 1-elementig + Set eq = new HashSet<>(); + fstElems.stream().forEach(x -> eq.addAll(x)); + Set> result = unify(eq, new ArrayList<>(), fc, parallel, rekTiefe); + return result; + } + Set> nextSet = remainingSets.remove(0); + writeLog("nextSet: " + nextSet.toString()); + List> nextSetasList =new ArrayList<>(nextSet); + try { + //List> + //nextSetasList = oup.sortedCopy(nextSet);//new ArrayList<>(nextSet); + } + catch (java.lang.IllegalArgumentException e) { + System.out.print(""); + } + Set> result = new HashSet<>(); + int variance = 0; + Optional xi = nextSetasList.stream().map(x -> x.stream().filter(y -> y.getLhsType() instanceof PlaceholderType) + .filter(z -> ((PlaceholderType)z.getLhsType()).getVariance() != 0) + .map(c -> ((PlaceholderType)c.getLhsType()).getVariance()) + .reduce((a,b)-> {if (a==b) return a; else return 0; })) + .filter(d -> d.isPresent()) + .map(e -> e.get()) + .findAny(); + if (xi.isPresent()) { + variance = xi.get(); + } + //if (variance == 1 && nextSetasList.size() > 1) { + // List> al = new ArrayList<>(nextSetasList.size()); + // for (int ii = 0; ii < nextSetasList.size();ii++) { + // al.add(0,nextSetasList.get(ii)); + // } + // nextSetasList = al; + //} + //Set a = nextSetasListIt.next(); + /*if (nextSetasList.size()>1) {zu loeschen + if (nextSetasList.iterator().next().iterator().next().getLhsType().getName().equals("D")) + System.out.print(""); + if (variance == 1) { + a_next = oup.max(nextSetasList.iterator()); + } + else if (variance == -1) { + a_next = oup.min(nextSetasList.iterator()); + } + else if (variance == 0) { + a_next = nextSetasList.iterator().next(); + } + } + else { + a_next = nextSetasList.iterator().next(); + } + */ + if (!nextSetasList.iterator().hasNext()) + System.out.print(""); + if (nextSetasList.iterator().next().stream().filter(x -> x.getLhsType().getName().equals("D")).findFirst().isPresent() && nextSetasList.size()>1) + System.out.print(""); + writeLog("nextSetasList: " + nextSetasList.toString()); + while (nextSetasList.size() > 0) { //(nextSetasList.size() != 0) { + Set a = null; + if (variance == 1) { + a = oup.max(nextSetasList.iterator()); + nextSetasList.remove(a); + } + else if (variance == -1) { + a = oup.min(nextSetasList.iterator()); + nextSetasList.remove(a); + } + else if (variance == 0) { + a = nextSetasList.remove(0); + } + //writeLog("nextSet: " + nextSetasList.toString()+ "\n"); + //nextSetasList.remove(a); + /* zu loeschen + if (nextSetasList.size() > 0) { + if (nextSetasList.size()>1) { + if (variance == 1) { + a_next = oup.max(nextSetasList.iterator()); + } + else if (variance == -1) { + a_next = oup.min(nextSetasList.iterator()); + } + else { + a_next = nextSetasList.iterator().next(); + } + } + else { + a_next = nextSetasList.iterator().next(); + } + } + */ + //PL 2018-03-01 + //TODO: 1. Maximum und Minimum unterscheiden + //TODO: 2. compare noch für alle Elmemente die nicht X =. ty sind erweitern + //for(Set a : newSet) { + i++; + Set> elems = new HashSet>(fstElems); + elems.add(a); + Set> res = new HashSet<>(); + if (remainingSets.isEmpty()) { + noou++; + writeLog("Vor unify Aufruf: " + eq.toString()); + writeLog("No of Unify " + noou); + System.out.println(noou); + Set eq = new HashSet<>(); + elems.stream().forEach(x -> eq.addAll(x)); + res = unify(eq, new ArrayList<>(), fc, parallel, rekTiefe); + } + else {//duerfte gar nicht mehr vorkommen PL 2018-04-03 + res = computeCartesianRecursiveOderConstraints(elems, remainingSets, fc, parallel, rekTiefe); + + } + if (!isUndefinedPairSetSet(res) && isUndefinedPairSetSet(result)) { + //wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen + result = res; + } + else { + if ((isUndefinedPairSetSet(res) && isUndefinedPairSetSet(result)) + || (!isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result)) + || result.isEmpty()) { + //alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden + result.addAll(res); + } + //else { + //wenn Korrekte Ergebnisse da und Feherfälle dazukommen Fehlerfälle ignorieren + // if (isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result)) { + // result = result; + // } + //} + } + + + + + /* auskommentiert um alle Max und min Betrachtung auszuschalten ANFANG */ + if (!result.isEmpty() && !isUndefinedPairSetSet(res)) { + if (nextSetasList.iterator().hasNext() && nextSetasList.iterator().next().stream().filter(x -> x.getLhsType().getName().equals("B")).findFirst().isPresent() && nextSetasList.size()>1) + System.out.print(""); + Iterator> nextSetasListIt = new ArrayList>(nextSetasList).iterator(); + if (variance == 1) { + System.out.println(""); + while (nextSetasListIt.hasNext()) { + Set a_next = nextSetasListIt.next(); + if (a.equals(a_next) || + (oup.compare(a, a_next) == 1)) { + nextSetasList.remove(a_next); + } + else { + System.out.println(""); + } + } + } + else { if (variance == -1) { + System.out.println(""); + while (nextSetasListIt.hasNext()) { + Set a_next = nextSetasListIt.next(); + if (a.equals(a_next) || + (oup.compare(a, a_next) == -1)) { + nextSetasList.remove(0); + } + else { + System.out.println(""); + } + } + } + else if (variance == 0) { + //break; + }} + } + /* auskommentiert um alle Max und min Betrachtung auszuschalten ENDE */ + + /* PL 2018-11-05 wird falsch weil es auf der obersten Ebene ist. + if (isUndefinedPairSetSet(res)) { + int nofstred= 0; + Set abhSubst = res.stream() + .map(b -> + b.stream() + .map(x -> x.getAllSubstitutions()) + .reduce((y,z) -> { y.addAll(z); return y;}).get()) + .reduce((y,z) -> { y.addAll(z); return y;}).get(); + Set b = a;//effective final a + Set durchschnitt = abhSubst.stream() + .filter(x -> b.contains(x)) + //.filter(y -> abhSubst.contains(y)) + .collect(Collectors.toCollection(HashSet::new)); + //Set vars = durchschnitt.stream().map(x -> (PlaceholderType)x.getLhsType()).collect(Collectors.toCollection(HashSet::new)); + int len = nextSetasList.size(); + Set undefRes = res.stream().reduce((y,z) -> { y.addAll(z); return y;}).get(); //flatten aller undef results + Set, UnifyPair>> reducedUndefResSubstGroundedBasePair = undefRes.stream() + .map(x -> { Set su = x.getAllSubstitutions(); //alle benutzten Substitutionen + su.add(x.getGroundBasePair()); // urspruengliches Paar + su.removeAll(durchschnitt); //alle aktuell genänderten Paare entfernen + return new Pair<>(su, x.getGroundBasePair());}) + .collect(Collectors.toCollection(HashSet::new)); + if (res.size() > 1) { + System.out.println(); + } + nextSetasList = nextSetasList.stream().filter(x -> { + //Boolean ret = false; + //for (PlaceholderType var : vars) { + // ret = ret || x.stream().map(b -> b.getLhsType().equals(var)).reduce((c,d) -> c || d).get(); + //} + return (!x.containsAll(durchschnitt));//Was passiert wenn durchschnitt leer ist?? + })//.filter(y -> couldBecorrect(reducedUndefResSubstGroundedBasePair, y)) //fuer testzwecke auskommentiert um nofstred zu bestimmen PL 2018-10-10 + .collect(Collectors.toCollection(ArrayList::new)); + nofstred = nextSetasList.size(); + //NOCH NICHT korrekt PL 2018-10-12 + //nextSetasList = nextSetasList.stream().filter(y -> couldBecorrect(reducedUndefResSubstGroundedBasePair, y)) + // .collect(Collectors.toCollection(ArrayList::new)); + writeLog("res (undef): " + res.toString()); + writeLog("abhSubst: " + abhSubst.toString()); + writeLog("a: " + a.toString()); + writeLog("Durchschnitt: " + durchschnitt.toString()); + writeLog("nextSet: " + nextSet.toString()); + writeLog("nextSetasList: " + nextSetasList.toString()); + writeLog("Number first erased Elements (undef): " + (len - nofstred)); + writeLog("Number second erased Elements (undef): " + (nofstred- nextSetasList.size())); + writeLog("Number erased Elements (undef): " + (len - nextSetasList.size())); + noAllErasedElements = noAllErasedElements + (len - nextSetasList.size()); + writeLog("Number of all erased Elements (undef): " + noAllErasedElements.toString()); + noBacktracking++; + writeLog("Number of Backtracking: " + noBacktracking); + System.out.println(""); + } + */ + //if (nextSetasList.size() == 0 && isUndefinedPairSetSet(result) && nextSet.size() > 1) { + // return result; + //} + //else { + // result.removeIf(y -> isUndefinedPairSet(y)); + //} + //else result.stream().filter(y -> !isUndefinedPairSet(y)); + + + } // End of while (nextSetasList.size() > 0) + return result; + } + /** * Computes all principal type unifiers for a set of constraints. @@ -147,18 +478,22 @@ public class TypeUnifyTask extends RecursiveTask>> { * @param fc The finite closure * @return The set of all principal type unifiers */ - protected Set> unify(Set eq, IFiniteClosure fc, boolean parallel) { + protected Set> unify(final Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, int rekTiefe) { //Set aas = eq.stream().filter(x -> x.getLhsType().getName().equals("AA") //&& x.getPairOp().equals(PairOperator.SMALLERDOT) // ).collect(Collectors.toCollection(HashSet::new)); //writeLog(nOfUnify.toString() + " AA: " + aas.toString()); //if (aas.isEmpty()) { // System.out.println(""); //} + + //.collect(Collectors.toCollection(HashSet::new))); /* * Step 1: Repeated application of reduce, adapt, erase, swap */ + rekTiefe++; nOfUnify++; writeLog(nOfUnify.toString() + " Unifikation: " + eq.toString()); + writeLog(nOfUnify.toString() + " Oderconstraints: " + oderConstraints.toString()); //eq = eq.stream().map(x -> {x.setVariance((byte)-1); return x;}).collect(Collectors.toCollection(HashSet::new)); /* @@ -224,11 +559,13 @@ public class TypeUnifyTask extends RecursiveTask>> { Set undefinedPairs = new HashSet<>(); if (printtag) System.out.println("eq2s " + eq2s); //writeLog("BufferSet: " + bufferSet.toString()+"\n"); - Set>>> secondLevelSets = calculatePairSets(eq2s, fc, undefinedPairs); + List>> oderConstraintsOutput = new ArrayList<>();//new ArrayList<>(oderConstraints); + Set>>> secondLevelSets = calculatePairSets(eq2s, oderConstraints, fc, undefinedPairs, oderConstraintsOutput); //PL 2017-09-20: Im calculatePairSets wird möglicherweise O .< java.lang.Integer //nicht ausgewertet Faculty Beispiel im 1. Schritt //PL 2017-10-03 geloest, muesste noch mit FCs mit kleineren //Typen getestet werden. + writeLog(nOfUnify.toString() + " Oderconstraints2: " + oderConstraintsOutput.toString()); if (printtag) System.out.println("secondLevelSets:" +secondLevelSets); // If pairs occured that did not match one of the cartesian product cases, // those pairs are contradictory and the unification is impossible. @@ -280,12 +617,13 @@ public class TypeUnifyTask extends RecursiveTask>> { //Aufruf von computeCartesianRecursive ANFANG - return computeCartesianRecursive(new HashSet<>(), new ArrayList<>(topLevelSets), eq, fc, parallel); + //writeLog("topLevelSets: " + topLevelSets.toString()); + return computeCartesianRecursive(new HashSet<>(), new ArrayList<>(topLevelSets), eq, oderConstraintsOutput, fc, parallel, rekTiefe); } - Set> unify2(Set> setToFlatten, Set eq, IFiniteClosure fc, boolean parallel) { + Set> unify2(Set> setToFlatten, Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, int rekTiefe) { //Aufruf von computeCartesianRecursive ENDE //keine Ahnung woher das kommt @@ -312,14 +650,18 @@ public class TypeUnifyTask extends RecursiveTask>> { /* * Step 5: Substitution */ - //System.out.println("vor Subst: " + eqPrime); + //writeLog("vor Subst: " + eqPrime); Optional> eqPrimePrime = rules.subst(eqPrime); - + Set> unifyres1 = null; + Set> unifyres2 = null; + //writeLog("nach Subst: " + eqPrimePrime); /* * Step 6 a) Restart (fork) for pairs where subst was applied */ + /* if(parallel) { - if (eqPrime.equals(eq) && !eqPrimePrime.isPresent()) //PL 2017-09-29 //(!eqPrimePrime.isPresent()) auskommentiert und durch + if (eqPrime.equals(eq) && !eqPrimePrime.isPresent() + && oderConstraints.isEmpty()) //PL 2017-09-29 //(!eqPrimePrime.isPresent()) auskommentiert und durch //PL 2017-09-29 dies ersetzt //(!eqPrimePrime.isPresent()) //PL 2018-05-18 beide Bedingungen muessen gelten, da eqPrime Veränderungen in allem ausser subst //eqPrimePrime Veraenderungen in subst repraesentieren. @@ -337,28 +679,44 @@ public class TypeUnifyTask extends RecursiveTask>> { fork.fork(); } } - else { // sequentiell (Step 6b is included) + else */ + {// sequentiell (Step 6b is included) if (printtag) System.out.println("nextStep: " + eqPrimePrime); - if (eqPrime.equals(eq) && !eqPrimePrime.isPresent()) { //PL 2017-09-29 //(!eqPrimePrime.isPresent()) auskommentiert und durch + if (eqPrime.equals(eq) && !eqPrimePrime.isPresent() + && oderConstraints.isEmpty()) { //PL 2017-09-29 //(!eqPrimePrime.isPresent()) auskommentiert und durch //PL 2017-09-29 dies ersetzt //(!eqPrimePrime.isPresent()) //PL 2018-05-18 beide Bedingungen muessen gelten, da eqPrime Veränderungen in allem ausser subst //eqPrimePrime Veraenderungen in subst repraesentieren. try { if (isSolvedForm(eqPrime)) { - logFile.write(eqPrime.toString()+"\n"); + logFile.write("eqPrime:" + eqPrime.toString()+"\n"); logFile.flush(); } } - catch (IOException e) { } + catch (IOException e) { + System.err.println("log-File nicht vorhanden"); + } eqPrimePrimeSet.add(eqPrime); + Set> eqPrimePrimeSetRet = eqPrimePrimeSet.stream().map(x -> { + Optional> res = new RuleSet().subst(x.stream().map(y -> { + if (y.getPairOp() == PairOperator.SMALLERDOTWC) y.setPairOp(PairOperator.EQUALSDOT); + return y; //alle Paare a <.? b erden durch a =. b ersetzt + }).collect(Collectors.toCollection(HashSet::new))); + if (res.isPresent()) {//wenn subst ein Erg liefert wurde was veraendert + return new TypeUnifyTask().applyTypeUnificationRules(res.get(), fc); + } + else return x; //wenn nichts veraendert wurde wird x zurueckgegeben + }).collect(Collectors.toCollection(HashSet::new)); + urm.notify(eqPrimePrimeSetRet.stream().map((unifyPairs -> + new ResultSet(UnifyTypeFactory.convert(unifyPairs, de.dhbwstuttgart.typeinference.constraints.Pair.generateTPHMap(cons))))).collect(Collectors.toList())); } else if(eqPrimePrime.isPresent()) { - Set> unifyres = unify(eqPrimePrime.get(), fc, false); + Set> unifyres = unifyres1 = unify(eqPrimePrime.get(), oderConstraints, fc, parallel, rekTiefe); eqPrimePrimeSet.addAll(unifyres); } else { - Set> unifyres = unify(eqPrime, fc, false); + Set> unifyres = unifyres2 = unify(eqPrime, oderConstraints, fc, parallel, rekTiefe); eqPrimePrimeSet.addAll(unifyres); @@ -371,23 +729,26 @@ public class TypeUnifyTask extends RecursiveTask>> { /* * Step 6 b) Build the union over everything. */ + /* + * PL 2019-01-22: geloescht if(parallel) for(TypeUnifyTask fork : forks) eqPrimePrimeSet.addAll(fork.join()); - + */ /* * Step 7: Filter empty sets; */ eqPrimePrimeSet = eqPrimePrimeSet.stream().filter(x -> isSolvedForm(x) || this.isUndefinedPairSet(x)).collect(Collectors.toCollection(HashSet::new)); - if (!eqPrimePrimeSet.isEmpty() && !isUndefinedPairSetSet(eqPrimePrimeSet)) + if (!eqPrimePrimeSet.isEmpty() && !isUndefinedPairSetSet(eqPrimePrimeSet)) { writeLog("Result1 " + eqPrimePrimeSet.toString()); + } return eqPrimePrimeSet; } - Set> computeCartesianRecursive(Set> fstElems, ArrayList>> topLevelSets, Set eq, IFiniteClosure fc, boolean parallel) { + Set> computeCartesianRecursive(Set> fstElems, ArrayList>> topLevelSets, Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, int rekTiefe) { //ArrayList>> remainingSets = new ArrayList<>(topLevelSets); fstElems.addAll(topLevelSets.stream() .filter(x -> x.size()==1) @@ -397,7 +758,7 @@ public class TypeUnifyTask extends RecursiveTask>> { .filter(x -> x.size()>1) .collect(Collectors.toCollection(ArrayList::new)); if (remainingSets.isEmpty()) {//Alle Elemente sind 1-elementig - Set> result = unify2(fstElems, eq, fc, parallel); + Set> result = unify2(fstElems, eq, oderConstraints, fc, parallel, rekTiefe); return result; } Set> nextSet = remainingSets.remove(0); @@ -415,7 +776,7 @@ public class TypeUnifyTask extends RecursiveTask>> { Optional xi = nextSetasList.stream().map(x -> x.stream().filter(y -> y.getLhsType() instanceof PlaceholderType) .filter(z -> ((PlaceholderType)z.getLhsType()).getVariance() != 0) .map(c -> ((PlaceholderType)c.getLhsType()).getVariance()) - .reduce((a,b)-> {if (a==b) return a; else return 0; })) + .reduce((a,b)-> {if (a==b) return a; else return 2; })) //2 kommt insbesondere bei Oder-Constraints vor .filter(d -> d.isPresent()) .map(e -> e.get()) .findAny(); @@ -455,14 +816,73 @@ public class TypeUnifyTask extends RecursiveTask>> { Set a = null; while (nextSetasList.size() > 0) { //(nextSetasList.size() != 0) { Set a_last = a; + List> nextSetasListRest = new ArrayList<>(); + //List> nextSetasListRestMin = new ArrayList<>(); + //List> nextSetasListRestOder = new ArrayList<>(); if (variance == 1) { a = oup.max(nextSetasList.iterator()); nextSetasList.remove(a); + nextSetasListRest = new ArrayList<>(nextSetasList); + Iterator> nextSetasListItRest = new ArrayList>(nextSetasListRest).iterator(); + while (nextSetasListItRest.hasNext()) { + Set a_next = nextSetasListItRest.next(); + if (//a.equals(a_next) || + (oup.compare(a, a_next) == 1)) { + nextSetasListRest.remove(a_next); + } + } + //Alle maximale Elemente in nextSetasListRest bestimmen + List> nextSetasListRestTest; + do { + nextSetasListRestTest = new ArrayList>(nextSetasListRest); + if (!nextSetasListRest.isEmpty()) { + Set max = oup.max(nextSetasListRest.iterator()); + Iterator> nextSetasListItRest2 = new ArrayList>(nextSetasListRest).iterator(); + while (nextSetasListItRest2.hasNext()) { + Set a_nextRest = nextSetasListItRest2.next(); + if (//a.equals(a_next) || + (oup.compare(max, a_nextRest) == 1)) { + nextSetasListRest.remove(a_nextRest); + } + + }} + } while(!nextSetasListRestTest.equals(nextSetasListRest)); + } else if (variance == -1) { a = oup.min(nextSetasList.iterator()); nextSetasList.remove(a); + nextSetasListRest = new ArrayList<>(nextSetasList); + Iterator> nextSetasListItRest = new ArrayList>(nextSetasListRest).iterator(); + while (nextSetasListItRest.hasNext()) { + Set a_next = nextSetasListItRest.next(); + if (//a.equals(a_next) || + (oup.compare(a, a_next) == -1)) { + nextSetasListRest.remove(a_next); + } + } + //Alle minimalen Elemente in nextSetasListRest bestimmen + + List> nextSetasListRestTest; + do { + nextSetasListRestTest = new ArrayList>(nextSetasListRest); + if (!nextSetasListRest.isEmpty()) { + Set min = oup.min(nextSetasListRest.iterator()); + Iterator> nextSetasListItRest2 = new ArrayList>(nextSetasListRest).iterator(); + while (nextSetasListItRest2.hasNext()) { + Set a_nextRest = nextSetasListItRest2.next(); + if (//a.equals(a_next) || + (oup.compare(min, a_nextRest) == -1)) { + nextSetasListRest.remove(a_nextRest); + } + + }} + } while(!nextSetasListRestTest.equals(nextSetasListRest)); } + else if (variance == 2) { + a = nextSetasList.remove(0); + nextSetasListRest = new ArrayList<>(nextSetasList); + } else if (variance == 0) { a = nextSetasList.remove(0); } @@ -492,35 +912,217 @@ public class TypeUnifyTask extends RecursiveTask>> { //for(Set a : newSet) { i++; Set> elems = new HashSet>(fstElems); - elems.add(a); + writeLog("a1: " + rekTiefe + " "+ "variance: "+ variance + " " + a.toString()+ "\n"); + //elems.add(a); PL 2019-01-20 Muss weg, weil das in jeweiligen Thread erfolgen muss. Fuer den sequentiellen Fall + //im else-Zweig //if (remainingSets.isEmpty()) {//muss immer gegeben sein, weil nur 1 Element der topLevelSets mehr als ein Elemet enthaelt - //writeLog("Vor unify2 Aufruf: " + eq.toString()); - Set> res = unify2(elems, eq, fc, parallel); + //writeLog("Vor unify2 Aufruf: " + elems.toString()); + Set> res = new HashSet<>(); + Set>> add_res = new HashSet<>(); + if(parallel && (variance == 1) && noOfThread <= MaxNoOfThreads) { + Set forks = new HashSet<>(); + Set newEqOrig = new HashSet<>(eq); + Set> newElemsOrig = new HashSet<>(elems); + List>> newOderConstraintsOrig = new ArrayList<>(oderConstraints); + newElemsOrig.add(a); + + /* FORK ANFANG */ + TypeUnify2Task forkOrig = new TypeUnify2Task(newElemsOrig, newEqOrig, newOderConstraintsOrig, fc, parallel, logFile, log, rekTiefe, urm, cons); + //forks.add(forkOrig); + forkOrig.fork(); + /* FORK ENDE */ + + synchronized (this) { + writeLog("a in " + variance + " "+ a); + writeLog("nextSetasListRest: " + nextSetasListRest.toString()); + } + while (!nextSetasListRest.isEmpty()) { + Set nSaL = nextSetasListRest.remove(0); + synchronized (this) { nextSetasList.remove(nSaL); + writeLog("1 RM" + nSaL.toString()); + } + Set newEq = new HashSet<>(eq); + Set> newElems = new HashSet<>(elems); + List>> newOderConstraints = new ArrayList<>(oderConstraints); + newElems.add(nSaL); + TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, fc, parallel, logFile, log, rekTiefe, urm, cons); + forks.add(fork); + fork.fork(); + } + //res = unify2(newElemsOrig, newEqOrig, newOderConstraintsOrig, fc, parallel, rekTiefe); + + /* FORK ANFANG */ + synchronized (this) { + res = forkOrig.join(); + //Set> fork_res = forkOrig.join(); + writeLog("JoinOrig " + new Integer(forkOrig.thNo).toString()); + //noOfThread--; an das Ende von compute verschoben + //add_res.add(fork_res); + }; + /* FORK ENDE */ + + for(TypeUnifyTask fork : forks) { + synchronized (this) { + Set> fork_res = fork.join(); + writeLog("Join " + new Integer(fork.thNo).toString()); + //noOfThread--; an das Ende von compute verschoben + add_res.add(fork_res); + }; + } + } else { + if(parallel && (variance == -1) && noOfThread <= MaxNoOfThreads) { + Set forks = new HashSet<>(); + Set newEqOrig = new HashSet<>(eq); + Set> newElemsOrig = new HashSet<>(elems); + List>> newOderConstraintsOrig = new ArrayList<>(oderConstraints); + newElemsOrig.add(a); + + /* FORK ANFANG */ + TypeUnify2Task forkOrig = new TypeUnify2Task(newElemsOrig, newEqOrig, newOderConstraintsOrig, fc, parallel, logFile, log, rekTiefe, urm, cons); + //forks.add(forkOrig); + forkOrig.fork(); + /* FORK ENDE */ + + synchronized (this) { + writeLog("a in " + variance + " "+ a); + writeLog("nextSetasListRest: " + nextSetasListRest.toString()); + } + while (!nextSetasListRest.isEmpty()) { + Set nSaL = nextSetasListRest.remove(0); + synchronized (this) { nextSetasList.remove(nSaL); + writeLog("-1 RM" + nSaL.toString()); + } + Set newEq = new HashSet<>(eq); + Set> newElems = new HashSet<>(elems); + List>> newOderConstraints = new ArrayList<>(oderConstraints); + newElems.add(nSaL); + TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, fc, parallel, logFile, log, rekTiefe, urm, cons); + forks.add(fork); + fork.fork(); + } + //res = unify2(newElemsOrig, newEqOrig, newOderConstraintsOrig, fc, parallel, rekTiefe); + + /* FORK ANFANG */ + synchronized (this) { + res = forkOrig.join(); + //Set> fork_res = forkOrig.join(); + writeLog("JoinOrig " + new Integer(forkOrig.thNo).toString()); + //noOfThread--; an das Ende von compute verschoben + //add_res.add(fork_res); + }; + /* FORK ENDE */ + + for(TypeUnifyTask fork : forks) { + synchronized (this) { + Set> fork_res = fork.join(); + writeLog("Join " + new Integer(fork.thNo).toString()); + //noOfThread--; an das Ende von compute verschoben + add_res.add(fork_res); + }; + } + } else { + if(parallel && (variance == 2) && noOfThread <= MaxNoOfThreads) { + writeLog("var2einstieg"); + Set forks = new HashSet<>(); + Set newEqOrig = new HashSet<>(eq); + Set> newElemsOrig = new HashSet<>(elems); + List>> newOderConstraintsOrig = new ArrayList<>(oderConstraints); + newElemsOrig.add(a); + + /* FORK ANFANG */ + TypeUnify2Task forkOrig = new TypeUnify2Task(newElemsOrig, newEqOrig, newOderConstraintsOrig, fc, parallel, logFile, log, rekTiefe, urm, cons); + //forks.add(forkOrig); + forkOrig.fork(); + /* FORK ENDE */ + + synchronized (this) { + writeLog("a in " + variance + " "+ a); + writeLog("nextSetasListRest: " + nextSetasListRest.toString()); + } + while (!nextSetasListRest.isEmpty()) { + Set nSaL = nextSetasListRest.remove(0); + //nextSetasList.remove(nSaL); + Set newEq = new HashSet<>(eq); + Set> newElems = new HashSet<>(elems); + List>> newOderConstraints = new ArrayList<>(oderConstraints); + newElems.add(nSaL); + TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, fc, parallel, logFile, log, rekTiefe, urm, cons); + forks.add(fork); + fork.fork(); + } + //res = unify2(newElemsOrig, newEqOrig, newOderConstraintsOrig, fc, parallel, rekTiefe); + + /* FORK ANFANG */ + synchronized (this) { + res = forkOrig.join(); + //Set> fork_res = forkOrig.join(); + writeLog("JoinOrig " + new Integer(forkOrig.thNo).toString()); + //noOfThread--; an das Ende von compute verschoben + //add_res.add(fork_res); //vermutlich falsch + }; + /* FORK ENDE */ + + for(TypeUnifyTask fork : forks) { + synchronized (this) { + Set> fork_res = fork.join(); + writeLog("Join " + new Integer(fork.thNo).toString()); + //noOfThread--; an das Ende von compute verschoben + add_res.add(fork_res); + }; + }} + else { + //parallel = false; //Wenn MaxNoOfThreads erreicht ist, sequentiell weiterarbeiten + elems.add(a); //PL 2019-01-16 muss das wirklich hin steht schon in Zeile 859 ja braucht man siehe Zeile 859 + res = unify2(elems, eq, oderConstraints, fc, parallel, rekTiefe); + }}} if (!isUndefinedPairSetSet(res) && isUndefinedPairSetSet(result)) { //wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen result = res; + if (res.iterator().next() instanceof WildcardType) { + System.out.println(""); + } } else { if ((isUndefinedPairSetSet(res) && isUndefinedPairSetSet(result)) || (!isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result)) || result.isEmpty()) { - if (!result.isEmpty() && !res.isEmpty() && !isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result)) { + if ((!result.isEmpty() && !res.isEmpty() && !isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result)) //korrekte Loesungen aus und-constraints + && (a.stream().map(x-> (x.getBasePair() != null)).reduce(true, (x, y) -> (x && y)))) //bei oder-Constraints nicht ausfuehren + { + //TODO: PL 2019-01-15: Bug 129: Im Moment wird nur das Maximum und das Minimum des aktuellen Elements betrachtet. + //Die zu vereinigenden Mengen können mehrere Elemente enthalten. Das ist bisher nicht berücksichtigt //Alle Variablen bestimmen die nicht hinzugefügt wurden in a - List vars_a = a.stream().filter(x -> (x.getLhsType().getName().equals(x.getBasePair().getLhsType().getName()) - ||x.getLhsType().getName().equals(x.getBasePair().getRhsType().getName()))).map(y -> (PlaceholderType)y.getLhsType()).collect(Collectors.toCollection(ArrayList::new)); + //PL 2018-12-28: Hier gab es eine ClassCastException, war nicht reproduzierbar + System.out.println(""); + List vars_a = + a.stream().filter(x -> ((x.getLhsType().getName().equals(x.getBasePair().getLhsType().getName()) + && (x.getLhsType() instanceof PlaceholderType) && (x.getBasePair().getLhsType() instanceof PlaceholderType)) + || ((x.getLhsType().getName().equals(x.getBasePair().getRhsType().getName())) + && (x.getLhsType() instanceof PlaceholderType) && (x.getBasePair().getRhsType() instanceof PlaceholderType))) + ) + .map(y -> (PlaceholderType)y.getLhsType()).collect(Collectors.toCollection(ArrayList::new)); Set fstElemRes = res.iterator().next(); Set compRes = fstElemRes.stream().filter(x -> vars_a.contains(((PlaceholderType)x.getLhsType()))).collect(Collectors.toCollection(HashSet::new)); //Alle Variablen bestimmen die nicht hinzugefügt wurden in a_last - List varsLast_a = a_last.stream().filter(x -> (x.getLhsType().getName().equals(x.getBasePair().getLhsType().getName()) - ||x.getLhsType().getName().equals(x.getBasePair().getRhsType().getName()))).map(y -> (PlaceholderType)y.getLhsType()).collect(Collectors.toCollection(ArrayList::new)); + //System.out.println(a_last); + a_last.forEach(x -> {writeLog("a_last_elem:" + x + " basepair: " + x.getBasePair());}); + List varsLast_a = + a_last.stream().filter(x -> ((x.getLhsType().getName().equals(x.getBasePair().getLhsType().getName()) + && (x.getLhsType() instanceof PlaceholderType) && (x.getBasePair().getLhsType() instanceof PlaceholderType)) + || ((x.getLhsType().getName().equals(x.getBasePair().getRhsType().getName()))) + && (x.getLhsType() instanceof PlaceholderType) && (x.getBasePair().getRhsType() instanceof PlaceholderType))) + .map(y -> (PlaceholderType)y.getLhsType()).collect(Collectors.toCollection(ArrayList::new)); + //[(java.util.Vector <. gen_aq, , 1), (CEK =. ? extends gen_aq, 1)] KANN VORKOMMEN //erstes Element genügt, da vars immer auf die gleichen Elemente zugeordnet werden muessen Set fstElemResult = result.iterator().next(); Set compResult = fstElemResult.stream().filter(x -> varsLast_a.contains(((PlaceholderType)x.getLhsType()))).collect(Collectors.toCollection(HashSet::new));; - if (variance == 1) { + writeLog("a_last:" + a_last + " a: " + a); + writeLog("varsLast_a:" + varsLast_a + " vars_a: " + vars_a); + writeLog("compResult:" + compResult + " compRes: " + compRes); int resOfCompare = oup.compare(compResult, compRes); if (resOfCompare == -1) { writeLog("Geloescht result: " + result); @@ -534,6 +1136,9 @@ public class TypeUnifyTask extends RecursiveTask>> { //result = result; }}} else { if (variance == -1) { + writeLog("a_last:" + a_last + " a: " + a); + writeLog("varsLast_a:" + varsLast_a + " vars_a: " + vars_a); + writeLog("compResult:" + compResult + " compRes: " + compRes); int resOfCompare = oup.compare(compResult, compRes); if (resOfCompare == 1) { writeLog("Geloescht result: " + result); @@ -547,11 +1152,13 @@ public class TypeUnifyTask extends RecursiveTask>> { //result = result; }}}} else { if (variance == 0) { + writeLog("RES var=1 ADD:" + result.toString() + " " + res.toString()); result.addAll(res); - }}} - //alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden + }}} } else { + //alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden + writeLog("RES Fst:" + result.toString() + " " + res.toString()); result.addAll(res); } } @@ -567,6 +1174,27 @@ public class TypeUnifyTask extends RecursiveTask>> { //else {//duerfte gar nicht mehr vorkommen PL 2018-04-03 //result.addAll(computeCartesianRecursive(elems, remainingSets, eq, fc, parallel)); //} + if (parallel) { + for (Set> par_res : add_res) { + if (!isUndefinedPairSetSet(par_res) && isUndefinedPairSetSet(result)) { + //wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen + result = par_res; + if (par_res.iterator().next() instanceof WildcardType) { + System.out.println(""); + } + } + else { + if ((isUndefinedPairSetSet(par_res) && isUndefinedPairSetSet(result)) + || (!isUndefinedPairSetSet(par_res) && !isUndefinedPairSetSet(result)) + || result.isEmpty()) { + //alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden + writeLog("RES var1 ADD:" + result.toString() + " " + par_res.toString()); + result.addAll(par_res); + } + } + } + //break; + } /* auskommentiert um alle Max und min Betrachtung auszuschalten ANFANG */ if (!result.isEmpty() && !isUndefinedPairSetSet(res)) { @@ -574,34 +1202,119 @@ public class TypeUnifyTask extends RecursiveTask>> { System.out.print(""); Iterator> nextSetasListIt = new ArrayList>(nextSetasList).iterator(); if (variance == 1) { + /* vorgezogen vor das if + if (parallel) { + for (Set> par_res : add_res) { + if (!isUndefinedPairSetSet(par_res) && isUndefinedPairSetSet(result)) { + //wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen + result = par_res; + if (par_res.iterator().next() instanceof WildcardType) { + System.out.println(""); + } + } + else { + if ((isUndefinedPairSetSet(par_res) && isUndefinedPairSetSet(result)) + || (!isUndefinedPairSetSet(par_res) && !isUndefinedPairSetSet(result)) + || result.isEmpty()) { + //alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden + writeLog("RES var1 ADD:" + result.toString() + " " + par_res.toString()); + result.addAll(par_res); + } + } + } + //break; + */ + + /* nextSetasList = nextSetasListRest; */ + /* wird bereits vor den unify2-Aufruf durchgefuehrt und nextSetasListRest zugeordnet + */ + System.out.println(""); + writeLog("a: " + rekTiefe + " variance: " + variance + a.toString()); while (nextSetasListIt.hasNext()) { Set a_next = nextSetasListIt.next(); if (a.equals(a_next) || (oup.compare(a, a_next) == 1)) { + writeLog("Removed: " + a_next.toString()); nextSetasList.remove(a_next); } else { + writeLog("Not Removed: " + a_next.toString()); System.out.println(""); } } } else { if (variance == -1) { + /* vorgezogen vor das if + if (parallel) { + for (Set> par_res : add_res) { + if (!isUndefinedPairSetSet(par_res) && isUndefinedPairSetSet(result)) { + //wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen + result = par_res; + if (par_res.iterator().next() instanceof WildcardType) { + System.out.println(""); + } + } + else { + if ((isUndefinedPairSetSet(par_res) && isUndefinedPairSetSet(result)) + || (!isUndefinedPairSetSet(par_res) && !isUndefinedPairSetSet(result)) + || result.isEmpty()) { + //alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden + writeLog("RES var-1 ADD:" + result.toString() + " " + par_res.toString()); + result.addAll(par_res); + } + } + } + //break; + } + + } + */ + System.out.println(""); + writeLog("a: " + rekTiefe + " variance: " + variance + a.toString()); while (nextSetasListIt.hasNext()) { Set a_next = nextSetasListIt.next(); if (a.equals(a_next) || (oup.compare(a, a_next) == -1)) { - nextSetasList.remove(0); + writeLog("Removed: " + a_next.toString()); + nextSetasList.remove(a_next); //PL geaendert 2019-01-09 } else { System.out.println(""); + writeLog("Not Removed: " + a_next.toString()); } } } - else if (variance == 0) { - break; - } + else { if (variance == 0) { + writeLog("a: " + rekTiefe + " variance: " + variance + a.toString()); + break; } + else { if (variance == 2) { + /* vorgezogen vor das if + if (parallel) { + for (Set> par_res : add_res) { + if (!isUndefinedPairSetSet(par_res) && isUndefinedPairSetSet(result)) { + //wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen + result = par_res; + if (par_res.iterator().next() instanceof WildcardType) { + System.out.println(""); + } + } + else { + if ((isUndefinedPairSetSet(par_res) && isUndefinedPairSetSet(result)) + || (!isUndefinedPairSetSet(par_res) && !isUndefinedPairSetSet(result)) + || result.isEmpty()) { + //alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden + writeLog("RES var2 ADD:" + result.toString() + " " + par_res.toString()); + result.addAll(par_res); + } + } + } + //break; + } + */ + }}} + writeLog("a: " + rekTiefe + " variance: " + variance + a.toString()); } } /* auskommentiert um alle Max und min Betrachtung auszuschalten ENDE */ @@ -614,6 +1327,14 @@ public class TypeUnifyTask extends RecursiveTask>> { .map(x -> x.getAllSubstitutions()) .reduce((y,z) -> { y.addAll(z); return y;}).get()) .reduce((y,z) -> { y.addAll(z); return y;}).get(); + abhSubst.addAll( + res.stream() + .map(b -> + b.stream() + .map(x -> x.getAllBases()) + .reduce((y,z) -> { y.addAll(z); return y;}).get()) + .reduce((y,z) -> { y.addAll(z); return y;}).get() + ); Set b = a;//effective final a Set durchschnitt = abhSubst.stream() .filter(x -> b.contains(x)) @@ -645,7 +1366,7 @@ public class TypeUnifyTask extends RecursiveTask>> { // .collect(Collectors.toCollection(ArrayList::new)); writeLog("res (undef): " + res.toString()); writeLog("abhSubst: " + abhSubst.toString()); - writeLog("a: " + a.toString()); + writeLog("a2: " + rekTiefe + " " + a.toString()); writeLog("Durchschnitt: " + durchschnitt.toString()); writeLog("nextSet: " + nextSet.toString()); writeLog("nextSetasList: " + nextSetasList.toString()); @@ -665,7 +1386,10 @@ public class TypeUnifyTask extends RecursiveTask>> { // result.removeIf(y -> isUndefinedPairSet(y)); //} //else result.stream().filter(y -> !isUndefinedPairSet(y)); + writeLog("res: " + res.toString()); } + + writeLog("Return computeCR: " + result.toString()); return result; } @@ -942,15 +1666,18 @@ public class TypeUnifyTask extends RecursiveTask>> { * from the pairs that matched the case. Each generated set contains singleton sets or sets with few elements * (as in case 1 where sigma is added to the innermost set). */ - protected Set>>> calculatePairSets(Set eq2s, IFiniteClosure fc, Set undefined) { - List>>> result = new ArrayList<>(8); + protected Set>>> calculatePairSets(Set eq2s, List>> oderConstraintsInput, IFiniteClosure fc, Set undefined, List>> oderConstraintsOutput) { + oderConstraintsOutput.addAll(oderConstraintsInput); + List>>> result = new ArrayList<>(9); - // Init all 8 cases - for(int i = 0; i < 8; i++) + // Init all 8 cases + 9. Case: oderConstraints + for(int i = 0; i < 9; i++) result.add(new HashSet<>()); + ArrayList eq2sprime = new ArrayList<>(eq2s); Iterator eq2sprimeit = eq2sprime.iterator(); ArrayList eq2sAsList = new ArrayList<>(); + Boolean first = true; while(eq2sprimeit.hasNext()) {// alle mit Variance != 0 nach vorne schieben UnifyPair up = eq2sprimeit.next(); if ((up.getLhsType() instanceof PlaceholderType && ((PlaceholderType)up.getLhsType()).getVariance() != 0) @@ -959,8 +1686,45 @@ public class TypeUnifyTask extends RecursiveTask>> { eq2s.remove(up); } } + if (eq2sAsList.isEmpty()) { + List>> oderConstraintsVariance = oderConstraintsOutput.stream() //Alle Elemente rauswerfen, die Variance 0 haben oder keine TPH in LHS oder RHS sind + .filter(x -> x.stream() + .filter(y -> + y.stream().filter(z -> ((z.getLhsType() instanceof PlaceholderType) + && (((PlaceholderType)(z.getLhsType())).getVariance() != 0)) + || ((z.getRhsType() instanceof PlaceholderType) + && (((PlaceholderType)(z.getRhsType())).getVariance() != 0)) + ).findFirst().isPresent() + ).findFirst().isPresent()).collect(Collectors.toList()); + if (!oderConstraintsVariance.isEmpty()) { + Set> ret = oderConstraintsVariance.get(0); + oderConstraintsOutput.remove(ret); + //Set retFlat = new HashSet<>(); + //ret.stream().forEach(x -> retFlat.addAll(x)); + ret.stream().forEach(x -> x.stream().forEach(y -> y.addSubstitutions(x))); + result.get(8).add(ret); + first = false; + } + } + eq2sAsList.addAll(eq2s); - Boolean first = true; + + if (eq2sAsList.isEmpty() && first) {//Alle eq2s sind empty und alle oderConstraints mit Variance != 0 sind bearbeitet + if (!oderConstraintsOutput.isEmpty()) { + Set> ret = oderConstraintsOutput.remove(0); + //if (ret.iterator().next().iterator().next().getLhsType().getName().equals("M")) + // System.out.println("M"); + //Set retFlat = new HashSet<>(); + //ret.stream().forEach(x -> retFlat.addAll(x)); + ret.stream().forEach(x -> x.stream().forEach(y -> y.addSubstitutions(x))); + result.get(8).add(ret); + first = false; + } + } + /* + Bei allen die Abhaengigkeit der Elemente aus eq2sAsList als evtl. als Substitution + hinzufuegen + */ for(UnifyPair pair : eq2sAsList) { PairOperator pairOp = pair.getPairOp(); UnifyType lhsType = pair.getLhsType(); @@ -970,6 +1734,9 @@ public class TypeUnifyTask extends RecursiveTask>> { if (((pairOp == PairOperator.SMALLERDOT) || (pairOp == PairOperator.SMALLERNEQDOT)) && lhsType instanceof PlaceholderType) { //System.out.println(pair); if (first) { //writeLog(pair.toString()+"\n"); + if (((PlaceholderType)(pair.getLhsType())).getName().equals("AR")) { + System.out.println("AR"); + } Set> x1 = unifyCase1(pair, fc); if (pairOp == PairOperator.SMALLERNEQDOT) { Set remElem = new HashSet<>(); @@ -1112,11 +1879,16 @@ public class TypeUnifyTask extends RecursiveTask>> { allGen = false; break; } - + //if (thetaPrime.getName().equals("java.util.Vector") //Fuer Bug 127 + // && thetaPrime instanceof ReferenceType + // && ((ReferenceType)thetaPrime).getTypeParams().iterator().next() instanceof PlaceholderType) //.getName().equals("java.util.Vector")) + // && ((ReferenceType)((ReferenceType)thetaPrime).getTypeParams().iterator().next()).getTypeParams().iterator().next().getName().equals("java.lang.Integer")) { + // { + // System.out.println(""); + //} Set cs = fc.getAllTypesByName(thetaPrime.getName());//cs= [java.util.Vector, java.util.Vector>, ????java.util.Vector???] - //PL 18-02-06 entfernt, kommt durch unify wieder rein //cs.add(thetaPrime); //PL 18-02-06 entfernt @@ -1133,13 +1905,17 @@ public class TypeUnifyTask extends RecursiveTask>> { for(UnifyType c : csPHRenamed) { //PL 18-02-05 getChildren durch smaller ersetzt in getChildren werden die Varianlen nicht ersetzt. - Set thetaQs = fc.smaller(c, new HashSet<>()).stream().collect(Collectors.toCollection(HashSet::new)); + Set thetaQs = new HashSet<>(); + //TODO smaller wieder reinnehmen? + //thetaQs.add(c);// + thetaQs = fc.smaller(c, new HashSet<>()).stream().collect(Collectors.toCollection(HashSet::new)); //Set thetaQs = fc.getChildren(c).stream().collect(Collectors.toCollection(HashSet::new)); //thetaQs.add(thetaPrime); //PL 18-02-05 wieder geloescht //PL 2017-10-03: War auskommentiert habe ich wieder einkommentiert, //da children offensichtlich ein echtes kleiner und kein kleinergleich ist //PL 18-02-06: eingefuegt, thetaQs der Form V> <. V'> werden entfernt + //TODO PL 19-01-14 wieder reinnehmen kurzfristig auskommentiert thetaQs = thetaQs.stream().filter(ut -> ut.getTypeParams().arePlaceholders()).collect(Collectors.toCollection(HashSet::new)); //PL 18-02-06: eingefuegt @@ -1158,19 +1934,21 @@ public class TypeUnifyTask extends RecursiveTask>> { } for(UnifyType tqp : thetaQPrimes) { + Collection tphs = tqp.getInvolvedPlaceholderTypes(); Optional opt = stdUnify.unify(tqp, thetaPrime); if (!opt.isPresent()) { continue; } - Unifier unifier = opt.get(); unifier.swapPlaceholderSubstitutions(thetaPrime.getTypeParams()); Set substitutionSet = new HashSet<>(); for (Entry sigma : unifier) { - substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT, + if (!tphs.contains(sigma.getKey())) {//eingefuegt PL 2019-02-02 Bug 127 + substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT, //TODO: nochmals ueberlegen ob hier pair.getSubstitution() korrekt ist, oder ob leere Menge hin müsste //alle folgenden New UnifyPair ebenfalls ueberpruefen PL 2018-04-19 pair.getSubstitution(), pair)); + } } //List freshTphs = new ArrayList<>(); PL 18-02-06 in die For-Schleife verschoben for (UnifyType tq : thetaQs) { @@ -1195,19 +1973,23 @@ public class TypeUnifyTask extends RecursiveTask>> { for(int i = 0; !allGen && i < theta.getTypeParams().size(); i++) { if(freshTphs.size()-1 < i)//IST DAS RICHTIG??? PL 2018-12-12 freshTphs.add(PlaceholderType.freshPlaceholder()); + freshTphs.forEach(x -> ((PlaceholderType)x).setInnerType(true)); resultPrime.add(new UnifyPair(freshTphs.get(i), theta.getTypeParams().get(i), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair)); } if(allGen) { UnifyPair up = new UnifyPair(a, theta, PairOperator.EQUALSDOT, pair.getSubstitution(), pair); Iterator upit = up.getRhsType().getTypeParams().iterator(); - while (upit.hasNext()) ((PlaceholderType)upit.next()).setVariance(a.getVariance()); + //TODO PL 2019-01-24: upit.next() ist nicht unbedingt ein PlaceholderType -> Visitor erledigt + while (upit.hasNext()) upit.next().accept(new distributeVariance(), a.getVariance());//((PlaceholderType)upit.next()).setVariance(a.getVariance()); resultPrime.add(up); } else { UnifyPair up = new UnifyPair(a, theta.setTypeParams(new TypeParams(freshTphs.toArray(new UnifyType[0]))), PairOperator.EQUALSDOT, pair.getSubstitution(), pair); Iterator upit = up.getRhsType().getTypeParams().iterator(); - while (upit.hasNext()) ((PlaceholderType)upit.next()).setVariance(a.getVariance()); + distributeVariance dv = new distributeVariance(); + //TODO PL 2019-01-24: upit.next() ist nicht unbedingt ein PlaceholderType -> Visitor erledigt + while (upit.hasNext()) upit.next().accept(new distributeVariance(), a.getVariance()); //((PlaceholderType)upit.next()).setVariance(a.getVariance()); resultPrime.add(up); } resultPrime.addAll(substitutionSet); @@ -1236,6 +2018,7 @@ public class TypeUnifyTask extends RecursiveTask>> { UnifyType aPrime = PlaceholderType.freshPlaceholder(); ((PlaceholderType)aPrime).setVariance(((PlaceholderType)a).getVariance()); + ((PlaceholderType)aPrime).disableWildcardtable(); UnifyType extAPrime = new ExtendsType(aPrime); UnifyType thetaPrime = extThetaPrime.getExtendedType(); Set resultPrime = new HashSet<>(); @@ -1256,12 +2039,14 @@ public class TypeUnifyTask extends RecursiveTask>> { */ private Set> unifyCase3(UnifyPair pair, IFiniteClosure fc) { PlaceholderType a = (PlaceholderType) pair.getLhsType(); + a.reversVariance(); SuperType subThetaPrime = (SuperType) pair.getRhsType(); byte variance = pair.getVariance(); Set> result = new HashSet<>(); UnifyType aPrime = PlaceholderType.freshPlaceholder(); ((PlaceholderType)aPrime).setVariance(((PlaceholderType)a).getVariance()); + ((PlaceholderType)aPrime).disableWildcardtable(); UnifyType supAPrime = new SuperType(aPrime); UnifyType thetaPrime = subThetaPrime.getSuperedType(); Set resultPrime = new HashSet<>(); @@ -1295,7 +2080,27 @@ public class TypeUnifyTask extends RecursiveTask>> { break; } - for(UnifyType thetaS : fc.greater(theta, pair.getfBounded())) { + //eingefuegt PL 2019-01-03 ANFANG + //fc.setLogTrue(); + //writeLog("FBOUNDED: " + pair.getfBounded()); + //writeLog("Pair: " + pair); + Set greater = fc.greater(theta, pair.getfBounded()); + //writeLog("GREATER: " + greater + pair + "THETA: " + theta + "FBOUNDED: " + pair.getfBounded() + " "); + if (a.isWildcardable()) { + Set greater_ext = greater.stream().filter(x -> !(x instanceof ExtendsType) && !(x instanceof SuperType)) + .map(x -> { + //BinaryOperator> combiner = (aa,b) -> { aa.putAll(b); return aa;}; //Variablenumbenennung rausgenommen + //HashMap hm = x.getInvolvedPlaceholderTypes().stream() //Variablen muessen wahrscheinlich erhalten bleiben + // .reduce(new HashMap(), + // (aa, b)-> { aa.put(b,PlaceholderType.freshPlaceholder()); return aa; }, combiner); + return new SuperType (x);})//.accept(new freshPlaceholder(), hm));} + .collect(Collectors.toCollection(HashSet::new)); + greater.addAll(greater_ext); + } + //eingefuegt PL 2019-01-03 ENDE + + //for(UnifyType thetaS : fc.greater(theta, pair.getfBounded())) { + for(UnifyType thetaS : greater) { Set resultPrime = new HashSet<>(); Match match = new Match(); @@ -1303,7 +2108,7 @@ public class TypeUnifyTask extends RecursiveTask>> { for(int i = 0; !allGen && i < freshTphs.length; i++) { freshTphs[i] = PlaceholderType.freshPlaceholder(); ((PlaceholderType)freshTphs[i]).setVariance(((PlaceholderType)a).getVariance()); - Set fBounded = pair.getfBounded(); + Set fBounded = new HashSet<>(pair.getfBounded()); //PL 2019-01-09 new HashSet eingefuegt int i_ef = i; BiFunction f = (x,y) -> @@ -1317,7 +2122,7 @@ public class TypeUnifyTask extends RecursiveTask>> { //} BinaryOperator bo = (x,y) -> (x || y); if (fBounded.stream().reduce(false,f,bo)) { - resultPrime.add(new UnifyPair(thetaS.getTypeParams().get(i), freshTphs[i], PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(freshTphs[i], thetaS.getTypeParams().get(i), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); } else { fBounded.add(thetaS.getTypeParams().get(i)); @@ -1331,7 +2136,8 @@ public class TypeUnifyTask extends RecursiveTask>> { resultPrime.add(new UnifyPair(a, thetaS.setTypeParams(new TypeParams(freshTphs)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new)); result.add(resultPrime); - //writeLog(resultPrime.toString()); + //writeLog("FBOUNDED2: " + pair.getfBounded()); + //writeLog("resultPrime Theta < a: " + greater + pair + "THETA: " + theta + "FBOUNDED: " + pair.getfBounded() + " " + resultPrime.toString()); } return result; @@ -1354,6 +2160,7 @@ public class TypeUnifyTask extends RecursiveTask>> { UnifyType freshTph = PlaceholderType.freshPlaceholder(); ((PlaceholderType)freshTph).setVariance(a.getVariance()); + ((PlaceholderType)freshTph).disableWildcardtable(); resultPrime = new HashSet<>(); resultPrime.add(new UnifyPair(a, new ExtendsType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); resultPrime.add(new UnifyPair(theta, freshTph, PairOperator.SMALLERDOT, pair.getSubstitution(), pair, pair.getfBounded())); @@ -1405,15 +2212,20 @@ public class TypeUnifyTask extends RecursiveTask>> { } void writeLog(String str) { - /* + synchronized ( this ) { if (log) { try { - logFile.write(str+"\n"); + logFile.write("Thread no.:" + thNo + "\n"); + logFile.write("noOfThread:" + noOfThread + "\n"); + logFile.write("parallel:" + parallel + "\n"); + logFile.write(str+"\n\n"); logFile.flush(); } - catch (IOException e) { } + catch (IOException e) { + System.err.println("kein LogFile"); } - */ + } + } } } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultEvent.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultEvent.java new file mode 100644 index 00000000..a79e34ec --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultEvent.java @@ -0,0 +1,18 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.List; + +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class UnifyResultEvent { + + private List newTypeResult; + + public UnifyResultEvent(List newTypeResult) { + this.newTypeResult = newTypeResult; + } + + public List getNewTypeResult() { + return newTypeResult; + } +} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultListenerImpl.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultListenerImpl.java new file mode 100644 index 00000000..ea34728b --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultListenerImpl.java @@ -0,0 +1,21 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.List; + +import de.dhbwstuttgart.typeinference.result.ResultSet; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +public class UnifyResultListenerImpl implements UnifyResultListener { + + List results = new ArrayList<>(); + + public synchronized void onNewTypeResultFound(UnifyResultEvent evt) { + results.addAll(evt.getNewTypeResult()); + } + + public List getResults() { + return results; + } + +} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultModel.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultModel.java new file mode 100644 index 00000000..fe72bfea --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultModel.java @@ -0,0 +1,28 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class UnifyResultModel { + + private List listeners = new ArrayList<>(); + + public void addUnifyResultListener(UnifyResultListener listenerToAdd) { + listeners.add(listenerToAdd); + } + + public void removeUnifyResultListener(UnifyResultListener listenerToRemove) { + listeners.remove(listenerToRemove); + } + + public void notify(List newResult) { + UnifyResultEvent evt = new UnifyResultEvent(newResult); + + for (UnifyResultListener listener : listeners) { + listener.onNewTypeResultFound(evt); + } + } +} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java index 4aa769e5..29a0e198 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java @@ -1,5 +1,8 @@ package de.dhbwstuttgart.typeinference.unify.model; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -30,6 +33,11 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; public class FiniteClosure //extends Ordering //entfernt PL 2018-12-11 implements IFiniteClosure { + Writer logFile; + static Boolean log = false; + public void setLogTrue() { + log = true; + } /** * A map that maps every type to the node in the inheritance graph that contains that type. */ @@ -46,10 +54,21 @@ implements IFiniteClosure { */ private Set pairs; + /** + * Hastable fuer die greater-Werte, damit sie nicht doppelt berechnet werden muessen + */ + Hashtable> greaterHash = new Hashtable<>(); + + /** + * Hastable fuer die smaller-Werte, damit sie nicht doppelt berechnet werden muessen + */ + Hashtable> smallerHash = new Hashtable<>(); + /** * Creates a new instance using the inheritance tree defined in the pairs. */ - public FiniteClosure(Set pairs) { + public FiniteClosure(Set pairs, Writer logFile) { + this.logFile = logFile; this.pairs = new HashSet<>(pairs); inheritanceGraph = new HashMap>(); @@ -91,6 +110,18 @@ implements IFiniteClosure { strInheritanceGraph.get(key.getName()).add(inheritanceGraph.get(key)); } } + + void testSmaller() { + UnifyType tq1, tq2, tq3; + tq1 = new ExtendsType(PlaceholderType.freshPlaceholder()); + List l1 = new ArrayList<>(); + List l2 = new ArrayList<>(); + l1.add(tq1); + tq2 = new ReferenceType("java.util.Vector", new TypeParams(l1)); + l2.add(tq2); + tq3 = new ReferenceType("java.util.Vector", new TypeParams(l2)); + Set smaller = smaller(tq3, new HashSet<>()); + } /** * Returns all types of the finite closure that are subtypes of the argument. @@ -98,12 +129,29 @@ implements IFiniteClosure { */ @Override public Set smaller(UnifyType type, Set fBounded) { + + Set ret; + if ((ret = smallerHash.get(new hashKeyType(type))) != null) { + //System.out.println(greaterHash); + return new HashSet<>(ret); + } + if(type instanceof FunNType) return computeSmallerFunN((FunNType) type, fBounded); Set>> ts = new HashSet<>(); ts.add(new Pair<>(type, fBounded)); - return computeSmaller(ts); + Set result = computeSmaller(ts); + smallerHash.put(new hashKeyType(type), result); + /* + try { + logFile.write("\ntype: " + type + "\nret: " + ret + "\nresult: " + result);//"smallerHash: " + greaterHash.toString()); + logFile.flush(); + } + catch (IOException e) { + System.err.println("no LogFile"); + }*/ + return result; } /** @@ -197,6 +245,13 @@ implements IFiniteClosure { //Eingefuegt PL 2018-05-24 F-Bounded Problematik public Set greater(UnifyType type, Set fBounded) { + Set ret; + if ((ret = greaterHash.get(new hashKeyType(type))) != null) { + //System.out.println(greaterHash); + return new HashSet<>(ret); + } + + if(type instanceof FunNType) { return computeGreaterFunN((FunNType) type, fBounded); } @@ -214,6 +269,17 @@ implements IFiniteClosure { // if T <* T' then sigma(T) <* sigma(T') Set> candidates = strInheritanceGraph.get(type.getName()); + + /* + try { + if (log) logFile.write(candidates.toString()); + //log = false; + } + catch (IOException e) { + System.err.println("no LogFile"); + } + */ + for(Node candidate : candidates) { UnifyType theta1 = candidate.getContent(); @@ -222,9 +288,9 @@ implements IFiniteClosure { termList.add(new UnifyPair(theta1,type, PairOperator.EQUALSDOT)); Optional optSigma = match.match(termList); //PL 18-04-05 Unifier durch Matcher ersetzt ENDE - if(!optSigma.isPresent()) + if(!optSigma.isPresent()) { continue; - + } Unifier sigma = optSigma.get(); sigma.swapPlaceholderSubstitutionsReverse(theta1.getTypeParams()); @@ -237,7 +303,15 @@ implements IFiniteClosure { PairResultFBounded.add(new Pair<>(theta2.apply(sigma), fBoundedNew)); } } - + /* + try { + if (log) logFile.write(PairResultFBounded.toString()); + log = false; + } + catch (IOException e) { + System.err.println("no LogFile"); + } + */ for(Pair> pt : PairResultFBounded) { UnifyType t = pt.getKey(); Set lfBounded = pt.getValue().get(); @@ -273,6 +347,16 @@ implements IFiniteClosure { //System.out.println(""); } } + + greaterHash.put(new hashKeyType(type), result); + /* + try { + logFile.write("\ntype: " + type + "\nret: " + ret + "\nresult: " + result);//"greaterHash: " + greaterHash.toString()); + logFile.flush(); + } + catch (IOException e) { + System.err.println("no LogFile"); + }*/ return result; } @@ -487,7 +571,7 @@ implements IFiniteClosure { result.add(type); return result; } - + @Override public Set getAllTypesByName(String typeName) { if(!strInheritanceGraph.containsKey(typeName)) @@ -570,8 +654,7 @@ implements IFiniteClosure { */ public int compare (UnifyType left, UnifyType right, PairOperator pairop) { - if ((left instanceof ExtendsType && right instanceof ReferenceType) - || (right instanceof ExtendsType && left instanceof ReferenceType)) + if (left.getName().equals("Matrix") || right.getName().equals("Matrix")) System.out.println(""); /* List al = new ArrayList<>(); @@ -607,14 +690,28 @@ implements IFiniteClosure { return 0; } } - if ((right instanceof PlaceholderType) && (left instanceof WildcardType)) { - return 0; + if (right instanceof PlaceholderType) {//&& (left instanceof WildcardType)) {PL geloescht 2019-01-15 analog zu oben + if ((left instanceof WildcardType) //PL eingefuegt 2019-01-15 analog zu oben + && ((ex = ((WildcardType)left).wildcardedType) instanceof PlaceholderType) + && ((PlaceholderType)right).getName().equals(((PlaceholderType)ex).getName())) {// ? extends a <. a oder ? super a <. a + return 1; + } + else { + return 0; + } } UnifyPair up = new UnifyPair(left, right, pairop); TypeUnifyTask unifyTask = new TypeUnifyTask(); HashSet hs = new HashSet<>(); hs.add(up); Set smallerRes = unifyTask.applyTypeUnificationRules(hs, this); + if (left.getName().equals("Matrix") || right.getName().equals("Matrix")) + {try { + logFile.write("\nsmallerRes: " + smallerRes);//"smallerHash: " + greaterHash.toString()); + logFile.flush(); + } + catch (IOException e) { + System.err.println("no LogFile");}} //Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok. long smallerLen = smallerRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)).count(); if (smallerLen == 0) return -1; @@ -624,6 +721,13 @@ implements IFiniteClosure { hs = new HashSet<>(); hs.add(up); Set greaterRes = unifyTask.applyTypeUnificationRules(hs, this); + if (left.getName().equals("Matrix") || right.getName().equals("Matrix")) + {try { + logFile.write("\ngreaterRes: " + greaterRes);//"smallerHash: " + greaterHash.toString()); + logFile.flush(); + } + catch (IOException e) { + System.err.println("no LogFile");}} //Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok. long greaterLen = greaterRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)).count(); if (greaterLen == 0) return 1; diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/OrderingUnifyPair.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/OrderingUnifyPair.java index c655e6fd..1916712e 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/OrderingUnifyPair.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/OrderingUnifyPair.java @@ -183,7 +183,7 @@ public class OrderingUnifyPair extends Ordering> { if (leftlewc.iterator().next().getLhsType() instanceof PlaceholderType) { hm = rsleuni.stream().reduce(new HashMap(), (x, y)-> { x.put(y.getLhsType(),y); return x; }, combiner); Stream lslewcstr = lsleuni.stream().filter(x -> !(hm.get(x.getLhsType()) == null)); - si = lslewcstr.map(x -> fc.compare(x.getRhsType(), hm.get(x.getLhsType()).getRhsType(), PairOperator.SMALLERDOTWC)).reduce((x,y)-> { if (x == y) return x; else return 0; } ); + si = lslewcstr.map(x -> fc.compare(x.getRhsType(), hm.get(x.getLhsType()).getRhsType(), PairOperator.SMALLERDOTWC)).reduce((x,y)-> { if (x == y) return x; else return 0; } ); } //4. Fall else { diff --git a/src/test/java/bytecode/FieldTphConsMethTest.java b/src/test/java/bytecode/FieldTphConsMethTest.java index ecf992d0..382c31e4 100644 --- a/src/test/java/bytecode/FieldTphConsMethTest.java +++ b/src/test/java/bytecode/FieldTphConsMethTest.java @@ -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)); } } diff --git a/src/test/java/bytecode/FieldTphMMethTest.java b/src/test/java/bytecode/FieldTphMMethTest.java new file mode 100644 index 00000000..f21adefe --- /dev/null +++ b/src/test/java/bytecode/FieldTphMMethTest.java @@ -0,0 +1,66 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class FieldTphMMethTest { + + 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; + private static Object instanceOfClass2; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/FieldTphMMeth.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("FieldTphMMeth"); + instanceOfClass = classToTest.getConstructor(Object.class,Object.class,Boolean.class).newInstance("C",42,true); + instanceOfClass2 = classToTest.getConstructor(Object.class,Object.class,Boolean.class).newInstance("C",42,false); + } + + @Test + public void testM() throws Exception { + + Method m = classToTest.getDeclaredMethod("m", Object.class,Object.class,Boolean.class); + Object result = m.invoke(instanceOfClass, "C",42,false); + + assertEquals(42,result); + } + + @Test + public void testWithTrue() throws Exception { + Field a = classToTest.getDeclaredField("a"); + a.setAccessible(true); + + assertEquals("C", a.get(instanceOfClass)); + + } + + @Test + public void testWithFalse() throws Exception { + Field a = classToTest.getDeclaredField("a"); + a.setAccessible(true); + + assertEquals(42, a.get(instanceOfClass2)); + } + +} diff --git a/src/test/java/bytecode/FieldTph.java b/src/test/java/bytecode/InfTest.java similarity index 68% rename from src/test/java/bytecode/FieldTph.java rename to src/test/java/bytecode/InfTest.java index 65c7f291..75608bfe 100644 --- a/src/test/java/bytecode/FieldTph.java +++ b/src/test/java/bytecode/InfTest.java @@ -3,7 +3,7 @@ package bytecode; import static org.junit.Assert.*; import java.io.File; -import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; @@ -12,8 +12,8 @@ import org.junit.Test; import de.dhbwstuttgart.core.JavaTXCompiler; -public class FieldTph { - +public class InfTest { + private static String path; private static File fileToTest; private static JavaTXCompiler compiler; @@ -22,22 +22,16 @@ public class FieldTph { 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"; + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/Inf.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/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); - classToTest = loader.loadClass("FieldTph"); + classToTest = loader.loadClass("Inf"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); } - @Test - public void test() { - Field[] fields = classToTest.getFields(); - assertEquals(1, fields.length); - } - } diff --git a/src/test/java/bytecode/KompTphTest.java b/src/test/java/bytecode/KompTphTest.java new file mode 100644 index 00000000..8fca0c0b --- /dev/null +++ b/src/test/java/bytecode/KompTphTest.java @@ -0,0 +1,37 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class KompTphTest { + + 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; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/KompTph.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("KompTph"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + +} diff --git a/src/test/java/bytecode/MatrixOpTest.java b/src/test/java/bytecode/MatrixOpTest.java index 11018701..ea906853 100644 --- a/src/test/java/bytecode/MatrixOpTest.java +++ b/src/test/java/bytecode/MatrixOpTest.java @@ -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> vv = new Vector>(); Vector v1 = new Vector (); 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> vv1 = new Vector>(); @@ -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> res = new Vector>(); @@ -85,7 +97,7 @@ public class MatrixOpTest { res.addElement(v6); instanceOfClass_m3 = classToTest.getDeclaredConstructor(Vector.class).newInstance(res); assertEquals(result, instanceOfClass_m3); -*/ + } } diff --git a/src/test/java/bytecode/simplifyalgo/FinderTest.java b/src/test/java/bytecode/simplifyalgo/FinderTest.java new file mode 100644 index 00000000..edf43605 --- /dev/null +++ b/src/test/java/bytecode/simplifyalgo/FinderTest.java @@ -0,0 +1,64 @@ +package bytecode.simplifyalgo; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + +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.ConstraintsFinder; +import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; +import de.dhbwstuttgart.bytecode.utilities.Simplify; +import de.dhbwstuttgart.typedeployment.TypeInsertPlacer; + +/** + * + * @author Fayez Abu Alia + * + */ +public class FinderTest { + + @Test + public void testM1() { + List allCons = new ArrayList<>(); + // L < M + TPHConstraint c1 = new ExtendsConstraint("L", "M", Relation.EXTENDS); + // L < N + TPHConstraint c2 = new ExtendsConstraint("L", "N", Relation.EXTENDS); + // M < O + TPHConstraint c3 = new ExtendsConstraint("M", "O", Relation.EXTENDS); + // M < P + TPHConstraint c4 = new ExtendsConstraint("M", "P", Relation.EXTENDS); + + allCons.add(c1); + allCons.add(c2); + allCons.add(c3); + allCons.add(c4); + List> res = new ArrayList<>(); + List l1 = new ArrayList<>(); + List l2 = new ArrayList<>(); + + l1.add(c1); + l1.add(c2); + + l2.add(c3); + l2.add(c4); + + res.add(l1); + res.add(l2); + + ConstraintsFinder finder = new ConstraintsFinder(allCons); + + assertEquals(finder.findConstraints(), res); + } + +} diff --git a/src/test/resources/bytecode/javFiles/FieldTphMMeth.jav b/src/test/resources/bytecode/javFiles/FieldTphMMeth.jav new file mode 100644 index 00000000..ad97edc4 --- /dev/null +++ b/src/test/resources/bytecode/javFiles/FieldTphMMeth.jav @@ -0,0 +1,27 @@ +import java.lang.Boolean; + +public class FieldTphMMeth { + a; + + public FieldTphMMeth(c,d,e) { + a = m(c,d,e); + } + + m(b,d,e) { + if(e) { + return m3(b); + } else{ + return m3(d); + } + + } + + m2(b) { + a = m3(b); + } + + m3(b){ + return b; + } + +} \ No newline at end of file diff --git a/src/test/resources/bytecode/javFiles/Inf.jav b/src/test/resources/bytecode/javFiles/Inf.jav new file mode 100644 index 00000000..3c785a6e --- /dev/null +++ b/src/test/resources/bytecode/javFiles/Inf.jav @@ -0,0 +1,19 @@ +public class Inf { + m(x,y,a){ + var z; + var v; + var w; + var b; + y=x; + z=x; + v=y; + w=y; + y=a; + b=a; + } +} +// v w +// \ / +// z y b +// \ / \ / +// x a \ No newline at end of file diff --git a/src/test/resources/bytecode/javFiles/KompTph.jav b/src/test/resources/bytecode/javFiles/KompTph.jav new file mode 100644 index 00000000..ec34e154 --- /dev/null +++ b/src/test/resources/bytecode/javFiles/KompTph.jav @@ -0,0 +1,13 @@ +public class KompTph { + public m(a, b, c) { + var d = a; + var e = a; + a = b; + c = b; + m2(a,c); + } + + public m2(a,b){ + m(a,a,b); + } +} \ No newline at end of file diff --git a/src/test/resources/bytecode/javFiles/MatrixOP.jav b/src/test/resources/bytecode/javFiles/MatrixOP.jav index 828a270b..0daef9bd 100644 --- a/src/test/resources/bytecode/javFiles/MatrixOP.jav +++ b/src/test/resources/bytecode/javFiles/MatrixOP.jav @@ -18,7 +18,7 @@ public class MatrixOP extends Vector> { } } - mul = (m1, m2) -> { + public mul = (m1, m2) -> { var ret = new MatrixOP(); var i = 0; while(i < size()) {