diff --git a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java index 37aef9d1..bfc543d5 100644 --- a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -46,9 +46,6 @@ 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; @@ -372,8 +369,6 @@ public class JavaTXCompiler { if (resultmodel) { /* UnifyResultModel Anfang */ UnifyResultModel urm = new UnifyResultModel(cons, finiteClosure); - UnifyResultListenerImpl li = new UnifyResultListenerImpl(); - urm.addUnifyResultListener(li); unify.unifyParallel(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, urm); System.out.println("RESULT Final: " + li.getResults()); logFile.write("RES_FINAL: " + li.getResults().toString() + "\n"); @@ -537,6 +532,10 @@ public class JavaTXCompiler { /** * @param path - can be null, then class file output is in the same directory as the parsed source files */ + List typeinferenceResult = this.typeInference(); + List simplifyResultsForAllSourceFiles = getGeneratedGenericResultsForAllSourceFiles( + typeinferenceResult); + generateBytecode(path, typeinferenceResult, simplifyResultsForAllSourceFiles); public void generateBytecode(File path) throws ClassNotFoundException, IOException, BytecodeGeneratorError { List typeinferenceResult = this.typeInference(); List simplifyResultsForAllSourceFiles = getGeneratedGenericResultsForAllSourceFiles( diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify2Future.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify2Future.java new file mode 100644 index 00000000..acd207ae --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify2Future.java @@ -0,0 +1,30 @@ +package de.dhbwstuttgart.typeinference.unify; + +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +import java.io.Writer; +import java.util.List; +import java.util.Set; + +public class TypeUnify2Future { + + Set> setToFlatten; + + public TypeUnify2Future(Set> setToFlatten, Set eq, List>> oderConstraints, Set nextSetElement, IFiniteClosure fc, boolean parallel, Writer logFile, Boolean log, int rekTiefe, UnifyResultModel urm) { + super(eq, oderConstraints, fc, parallel, logFile, log, rekTiefe, urm); + this.setToFlatten = setToFlatten; + this.nextSetElement = nextSetElement; + } + + Set getNextSetElement() { + return nextSetElement; + } + + @Override + protected Set> compute() { + Set> res = unify2(setToFlatten, eq, oderConstraintsField, fc, parallel, rekTiefeField, true); + return res; + } +} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyFuture.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyFuture.java new file mode 100644 index 00000000..9bbaed97 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyFuture.java @@ -0,0 +1,1849 @@ +package de.dhbwstuttgart.typeinference.unify; + +import de.dhbwstuttgart.exceptions.TypeinferenceException; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.unify.interfaces.*; +import de.dhbwstuttgart.typeinference.unify.model.*; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.*; +import java.util.concurrent.RecursiveTask; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; +import java.util.stream.Collectors; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.RecursiveTask; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.io.output.NullOutputStream; + +import de.dhbwstuttgart.exceptions.TypeinferenceException; +import de.dhbwstuttgart.parser.NullToken; +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.IMatch; +import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet; +import de.dhbwstuttgart.typeinference.unify.interfaces.ISetOperations; +import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +import de.dhbwstuttgart.typeinference.unify.model.OrderingExtend; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; +import de.dhbwstuttgart.typeinference.unify.model.SuperType; +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.OutputStreamWriter; +import java.io.Writer; + +import com.google.common.collect.Ordering; + +public class TypeUnifyFuture { + + private static final long serialVersionUID = 1L; + private static int i = 0; + private boolean printtag = false; + Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+"/test/logFiles/log" geschrieben werden soll? + + /** + * Element, das aus dem nextSet den Gleichunen dieses Threads hinzugefuegt wurde + */ + Set nextSetElement; + + /** + * Fuer die Threads + */ + UnifyResultModel urm; + 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/"; + Writer logFile; + + /** + * The implementation of setOps that will be used during the unification + */ + protected ISetOperations setOps = new GuavaSetOperations(); + + /** + * The implementation of the standard unify that will be used during the unification + */ + protected IUnify stdUnify = new MartelliMontanariUnify(); + + /** + * The implementation of the rules that will be used during the unification. + */ + protected IRuleSet rules; + + protected Set eq; //und-rulesconstraints + + protected List>> oderConstraintsField; + + protected IFiniteClosure fc; + + protected OrderingExtend> oup; + + protected boolean parallel; + + int rekTiefeField; + + Integer nOfUnify = 0; + + Integer noUndefPair = 0; + + Integer noAllErasedElements = 0; + + static Integer noou = 0; + + static int noBacktracking; + + static Integer noShortendElements = 0; + + Boolean myIsCanceled = false; + + volatile UnifyTaskModel usedTasks; + + + + //TODO: Future: + protected Set> compute() { + 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, true); + 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; + } +*/ + + + + + /** + * Computes all principal type unifiers for a set of constraints. + * @param eq The set of constraints + * @param fc The finite closure + * @return The set of all principal type unifiers + */ + protected static Optional>> unify(final Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, int rekTiefe, Boolean finalresult) { + Set doubleExt = eq.stream().filter(x -> (x.wrongWildcard())).map(x -> { x.setUndefinedPair(); return x;}) + .collect(Collectors.toCollection(HashSet::new)); + if (doubleExt.size() > 0) { + Set> ret = new HashSet<>(); + ret.add(doubleExt); + return ret; + } + + Set eq0; + Set eq0Prime; + Optional> eqSubst = Optional.of(eq); + do { + eq0Prime = eqSubst.get(); + eq0 = applyTypeUnificationRules(eq0Prime, fc); + eqSubst = new RuleSet().subst(eq0, oderConstraints); + } while (eqSubst.isPresent()); + + eq0.forEach(x -> x.disableCondWildcards()); + + /* + * Step 2 and 3: Create a subset eq1s of pairs where both sides are TPH and eq2s of the other pairs + */ + Set eq1s = new HashSet<>(); + Set eq2s = new HashSet<>(); + for(UnifyPair pair : eq) + if(pair.getLhsType() instanceof PlaceholderType && pair.getRhsType() instanceof PlaceholderType) + eq1s.add(pair); + else + eq2s.add(pair); + + /* + * Step 4: Create possible typings + * + * "Manche Autoren identifizieren die Paare (a, (b,c)) und ((a,b),c) + * mit dem geordneten Tripel (a,b,c), wodurch das kartesische Produkt auch assoziativ wird." - Wikipedia + */ + + // There are up to 10 toplevel set. 8 of 10 are the result of the + // cartesian product of the sets created by pattern matching. + List>> topLevelSets = new ArrayList<>(); + + //System.out.println(eq2s); + + if(eq1s.size() != 0) { // Do not add empty sets or the cartesian product will always be empty. + Set> wrap = new HashSet<>(); + wrap.add(eq1s); + topLevelSets.add(wrap); // Add Eq1' + } + + // Add the set of [a =. Theta | (a=. Theta) in Eq2'] + //TODO: Occurscheck anwenden als Fehler identifizieren + Set bufferSet = eq2s.stream() + .filter(x -> x.getPairOp() == PairOperator.EQUALSDOT && x.getLhsType() instanceof PlaceholderType) + .collect(Collectors.toSet()); + + if(bufferSet.size() != 0) { // Do not add empty sets or the cartesian product will always be empty. + Set> wrap = new HashSet<>(); + wrap.add(bufferSet); + topLevelSets.add(wrap); + eq2s.removeAll(bufferSet); + } + + // Sets that originate from pair pattern matching + // Sets of the "second level" + List>> oderConstraintsOutput = new ArrayList<>();//new ArrayList<>(oderConstraints); + Optional>>>> secondLevelSets = calculatePairSets(eq2s, oderConstraints, fc, oderConstraintsOutput); + + if(!secondLevelSets.isPresent())return secondLevelSets; + + //Alternative KEIN KARTESISCHES PRODUKT der secondlevel Ebene bilden + for(Set>> secondLevelSet : secondLevelSets.get()) { + for (Set> secondlevelelem : secondLevelSet) { + topLevelSets.add(secondlevelelem); + } + } + return computeCartesianRecursive(new HashSet<>(), new ArrayList<>(topLevelSets), eq, oderConstraintsOutput, fc, parallel, rekTiefe, finalresult); + + } + + + static Set> unify2(Set> setToFlatten, Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, int rekTiefe) { + Set> eqPrimePrimeSet = new HashSet<>(); + + Set forks = new HashSet<>(); + + //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG + //for(Set> setToFlatten : eqPrimeSet) { + // Flatten the cartesian product + //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE + Set eqPrime = new HashSet<>(); + setToFlatten.stream().forEach(x -> eqPrime.addAll(x)); + + /* + * Step 5: Substitution + */ + //writeLog("vor Subst: " + eqPrime); + String ocString = oderConstraints.toString(); + List>> newOderConstraints = new ArrayList<>(oderConstraints); + Optional> eqPrimePrime = new RuleSet().subst(eqPrime, newOderConstraints); + Set> unifyres1 = null; + Set> unifyres2 = null; + + {// sequentiell (Step 6b is included) + if (eqPrime.equals(eq) && !eqPrimePrime.isPresent() + && oderConstraints.isEmpty()) { + eqPrimePrimeSet.add(eqPrime); + + //TODO: Hier sollte es zwei verschiedene Funktionen geben. Einmal unify2Iterate oder so und einmal das Finale + if (finalresult && isSolvedForm(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)); + List newResult = eqPrimePrimeSetRet.stream().map(unifyPairs -> + new ResultSet(UnifyTypeFactory.convert(unifyPairs, de.dhbwstuttgart.typeinference.constraints.Pair.generateTPHMap(cons)))) + .collect(Collectors.toList()); + return newResult; + } + } + else if(eqPrimePrime.isPresent()) { + Set> unifyres = unifyres1 = unify(eqPrimePrime.get(), newOderConstraints, fc, parallel, rekTiefe, finalresult); + + eqPrimePrimeSet.addAll(unifyres); + } + else { + Set> unifyres = unifyres2 = unify(eqPrime, newOderConstraints, fc, parallel, rekTiefe, finalresult); + + + eqPrimePrimeSet.addAll(unifyres); + } + } + //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG + //} + //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE + + /* + * 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)); + + return eqPrimePrimeSet; + } + + + static Set> computeCartesianRecursive(Set> fstElems, ArrayList>> topLevelSets, Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, int rekTiefe, Boolean finalresult) { + + 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> result = unify2(fstElems, eq, oderConstraints, fc, parallel, rekTiefe, finalresult); + return result; + } + Set> nextSet = remainingSets.remove(0); + List> nextSetasList =new ArrayList<>(nextSet); + + Set> result = new HashSet<>(); + int variance = 0; + + ArrayList zeroNextElem = new ArrayList<>(nextSetasList.get(0)); + UnifyPair fstBasePair = zeroNextElem.remove(0).getBasePair(); + Boolean oderConstraint = false; + + if (fstBasePair != null) { + Boolean sameBase = true; + for (UnifyPair ele : nextSetasList.get(0)) {//check ob a <. ty base oder ob Ueberladung + sameBase = sameBase && ele.getBasePair() != null && ele.getBasePair().equals(fstBasePair); + } + if (sameBase) { //angefuegt PL 2020-02-30 + Optional xi = nextSetasList.stream().map(x -> x.stream().filter(y -> (y.getLhsType() instanceof PlaceholderType && !(y.getRhsType() 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; })) //2 kommt insbesondere bei Oder-Constraints vor + .filter(d -> d.isPresent()) + .map(e -> e.get()) + .findAny(); + if (xi.isPresent()) { + variance = xi.get(); + } + } + else { + //variance = 2; + oderConstraint = true; + } + } + else { + //variance = 2; + oderConstraint = true; + } + + if (oderConstraint) {//Varianz-Bestimmung Oder-Constraints + Optional optVariance = + nextSetasList.iterator() + .next() + .stream() + .filter(x -> x.getGroundBasePair().getLhsType() instanceof PlaceholderType && + ! (x.getRhsType() instanceof PlaceholderType) && + x.getPairOp() == PairOperator.EQUALSDOT) + .map(x -> + ((PlaceholderType)x.getGroundBasePair().getLhsType()).getVariance()) + .findAny(); + //Fuer Operatorenaufrufe wird variance auf 2 gesetzt. + //da kein Receiver existiert also keon x.getGroundBasePair().getLhsType() instanceof PlaceholderType + //Es werden alle Elemente des Kartesischen Produkts abgearbeitet + variance = optVariance.isPresent() ? optVariance.get() : 2; + } + + Set nextSetElem = nextSetasList.get(0); + + /* sameEqSet-Bestimmung: Wenn a = ty \in nextSet dann enthaelt sameEqSet alle Paare a < ty1 oder ty2 < a aus fstElems */ + Set sameEqSet = new HashSet<>(); + Optional optOrigPair = null; + if (!oderConstraint) { + optOrigPair = nextSetElem.stream().filter(x -> ( + (x.getPairOp().equals(PairOperator.EQUALSDOT) + ))).filter(x -> //Sicherstellen, dass bei a = ty a auch wirklich die gesuchte Typvariable ist + x.getLhsType().equals(x.getBasePair().getLhsType()) || + x.getLhsType().equals(x.getBasePair().getRhsType()) + ).findFirst(); + if (optOrigPair.isPresent()) { + UnifyPair origPair = optOrigPair.get(); + UnifyType tyVar; + if (!((tyVar = origPair.getLhsType()) instanceof PlaceholderType)) { + tyVar = origPair.getRhsType(); + } + UnifyType tyVarEF = tyVar; + sameEqSet = fstElems.stream().map(xx -> xx.iterator().next()) + .filter(x -> (((x.getLhsType().equals(tyVarEF) && !(x.getRhsType() instanceof PlaceholderType)) + || (x.getRhsType().equals(tyVarEF) && !(x.getLhsType() instanceof PlaceholderType))))) + .collect(Collectors.toCollection(HashSet::new)); + } + } + /* sameEqSet-Bestimmung Ende */ + OrderingUnifyPair oup = new OrderingUnifyPair(fc); + Set a = null; + while (nextSetasList.size() > 0) { //(nextSetasList.size() != 0) { + Set a_last = a; + + //Liste der Faelle für die parallele Verarbeitung + List> nextSetasListRest = new ArrayList<>(); + + //Liste der Faelle, bei dem Receiver jeweils "? extends" enthaelt bzw. nicht enthaelt + //In der Regel ein Element + List> nextSetasListOderConstraints = new ArrayList<>(); + + if (variance == 1) { + a = oup.max(nextSetasList.iterator()); + nextSetasList.remove(a); + if (oderConstraint) { + nextSetasListOderConstraints.add(((Constraint)a).getExtendConstraint()); + } + 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 + nextSetasListRest = oup.maxElements(nextSetasListRest); + } + else if (variance == -1) { + a = oup.min(nextSetasList.iterator()); + if (oderConstraint) { + nextSetasListOderConstraints.add(((Constraint)a).getExtendConstraint()); + } + 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 + nextSetasListRest = oup.minElements(nextSetasListRest); + } + else if (variance == 2) { + a = nextSetasList.remove(0); + nextSetasListRest = new ArrayList<>(nextSetasList); + } + else if (variance == 0) { + //wenn a <. theta dann ist ein maximales Element sehr wahrscheinlich + //wenn theta <. a dann ist ein minimales Element sehr wahrscheinlich + if (!oderConstraint && optOrigPair != null && optOrigPair.isPresent()) { + if (optOrigPair.get().getBasePair().getLhsType() instanceof PlaceholderType) { + a = oup.max(nextSetasList.iterator()); + } + else { + a = oup.min(nextSetasList.iterator()); + } + nextSetasList.remove(a); + } + else { + if (oderConstraint) { + a = oup.max(nextSetasList.iterator()); + nextSetasList.remove(a); + nextSetasListOderConstraints.add(((Constraint)a).getExtendConstraint()); + } + else { + a = nextSetasList.remove(0); + } + } + } + //writeLog("nextSet: " + nextSetasList.toString()+ "\n"); + //nextSetasList.remove(a); + + //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); + Set> res = new HashSet<>(); + Set>> add_res = new HashSet<>(); + Set> aParDef = new HashSet<>(); + + /* PL 2019-03-11 Anfang eingefuegt Vergleich mit anderen Paaren ggf. loeschen */ + if (!oderConstraint && !sameEqSet.isEmpty()) { + Optional optAPair = a.stream().filter(x -> ( + //x.getBasePair() != null && ist gegeben wenn variance != 2 + //x.getBasePair().getPairOp().equals(PairOperator.SMALLERDOT) && + (x.getPairOp().equals(PairOperator.EQUALSDOT) + /* + (x.getBasePair().getLhsType() instanceof PlaceholderType + && x.getLhsType().equals(x.getBasePair().getLhsType())) + || (x.getBasePair().getRhsType() instanceof PlaceholderType + && x.getLhsType().equals(x.getBasePair().getRhsType()) + */ + ))).filter(x -> //Sicherstellen, dass bei a = ty a auch wirklich die gesuchte Typvariable ist + x.getLhsType().equals(x.getBasePair().getLhsType()) || + x.getLhsType().equals(x.getBasePair().getRhsType()) + ).findFirst(); + + if (optAPair.isPresent()) {//basepair ist entweder a <. Ty oder ty <. a + UnifyPair aPair = optAPair.get(); + if (!checkA(aPair, sameEqSet, elems, result)) { + a = null; + noShortendElements++; + continue; + } + } + } + /* PL 2019-03-11 Ende eingefuegt Vergleich mit anderen Paaren ggf. loeschen */ + + if(parallel && (variance == 1)) { + Set forks = new HashSet<>(); + Set newEqOrig = new HashSet<>(eq); + Set> newElemsOrig = new HashSet<>(elems); + List>> newOderConstraintsOrig = new ArrayList<>(oderConstraints); + newElemsOrig.add(a); + + //TODO: + unify2(newElemsOrig, newEqOrig, newOderConstraintsOrig, fc, parallel, rekTiefe, true); + //TypeUnify2Task forkOrig = new TypeUnify2Future(newElemsOrig, newEqOrig, newOderConstraintsOrig, a, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); + + //forkOrig.fork(); + + while (!nextSetasListRest.isEmpty()) { + Set nSaL = nextSetasListRest.remove(0); + nextSetasList.remove(nSaL); + + + /* PL 2019-03-13 Anfang eingefuegt Vergleich mit anderen Paaren ggf. loeschen */ + if (!oderConstraint) {//weiss nicht ob das wirklich stimmt + Optional optAPair = nSaL.stream().filter(x -> ( + (x.getPairOp().equals(PairOperator.EQUALSDOT) + ))).filter(x -> //Sicherstellen, dass bei a = ty a auch wirklich die gesuchte Typvariable ist + x.getLhsType().equals(x.getBasePair().getLhsType()) || + x.getLhsType().equals(x.getBasePair().getRhsType()) + ).findFirst(); + + if (optAPair.isPresent()) {//basepair ist entweder a <. Ty oder ty <. a + UnifyPair aPair = optAPair.get(); + //writeLog("optOrigPair: " + optOrigPair + " " + "aPair: " + aPair+ " " + "aPair.basePair(): " + aPair.getBasePair()); + if (!sameEqSet.isEmpty() && !checkA(aPair, sameEqSet, elems, result)) { + nSaL = null; + noShortendElements++; + continue; + } + } + } + /* PL 2019-03-13 Ende eingefuegt Vergleich mit anderen Paaren ggf. loeschen */ + else { + nextSetasListOderConstraints.add(((Constraint)nSaL).getExtendConstraint()); + } + Set newEq = new HashSet<>(eq); + Set> newElems = new HashSet<>(elems); + List>> newOderConstraints = new ArrayList<>(oderConstraints); + newElems.add(nSaL); + + unify2() + TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, nSaL, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); + forks.add(fork); + fork.fork(); + } + //res = unify2(newElemsOrig, newEqOrig, newOderConstraintsOrig, fc, parallel, rekTiefe); + + /* FORK ANFANG */ + res = forkOrig.join(); + + /* FORK ENDE */ + for(TypeUnify2Task fork : forks) { + synchronized (this) { + noOfThread--; + Set> fork_res = fork.join(); + add_res.add(fork_res); + if (!isUndefinedPairSetSet(fork_res)) { + aParDef.add(fork.getNextSetElement()); + } + }; + } + //noOfThread++; + } 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, a, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); + //forks.add(forkOrig); + synchronized(usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + forkOrig.fork(); + } + /* FORK ENDE */ + + while (!nextSetasListRest.isEmpty()) { + Set nSaL = nextSetasListRest.remove(0); + synchronized (this) { nextSetasList.remove(nSaL); + writeLog("-1 RM" + nSaL.toString()); + } + + if (!oderConstraint) {//weiss nicht ob das wirklich stimmt + /* PL 2019-03-13 Anfang eingefuegt Vergleich mit anderen Paaren ggf. loeschen */ + Optional optAPair = nSaL.stream().filter(x -> ( + (x.getPairOp().equals(PairOperator.EQUALSDOT) + ))).filter(x -> //Sicherstellen, dass bei a = ty a auch wirklich die gesuchte Typvariable ist + x.getLhsType().equals(x.getBasePair().getLhsType()) || + x.getLhsType().equals(x.getBasePair().getRhsType()) + ).findFirst(); + + if (optAPair.isPresent()) {//basepair ist entweder a <. Ty oder ty <. a + UnifyPair aPair = optAPair.get(); + //writeLog("optOrigPair: " + optOrigPair + " " + "aPair: " + aPair+ " " + "aPair.basePair(): " + aPair.getBasePair()); + writeLog("variance: " + new Integer(variance).toString() + "sameEqSet:" + sameEqSet); + if (!sameEqSet.isEmpty() && !checkA(aPair, sameEqSet, elems, result)) { + nSaL = null; + noShortendElements++; + continue; + } + } + } + /* PL 2019-03-13 Ende eingefuegt Vergleich mit anderen Paaren ggf. loeschen */ + else { + nextSetasListOderConstraints.add(((Constraint)nSaL).getExtendConstraint()); + } + 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, nSaL, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); + forks.add(fork); + synchronized(usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + fork.fork(); + } + } + //res = unify2(newElemsOrig, newEqOrig, newOderConstraintsOrig, fc, parallel, rekTiefe); + + /* FORK ANFANG */ + synchronized (this) { + writeLog("wait "+ forkOrig.thNo); + noOfThread--; + res = forkOrig.join(); + synchronized (usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + } + //noOfThread++; + forkOrig.writeLog("final Orig -1"); + forkOrig.closeLogFile(); + //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(TypeUnify2Task fork : forks) { + synchronized (this) { + noOfThread--; + Set> fork_res = fork.join(); + add_res.add(fork_res); + if (!isUndefinedPairSetSet(fork_res)) { + aParDef.add(fork.getNextSetElement()); + } + fork.writeLog("final -1"); + }; + } + //noOfThread++; + } 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, a, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); + //forks.add(forkOrig); + synchronized(usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + 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); //PL einkommentiert 20-02-03 + 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, nSaL, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); + forks.add(fork); + synchronized(usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + fork.fork(); + } + } + //res = unify2(newElemsOrig, newEqOrig, newOderConstraintsOrig, fc, parallel, rekTiefe); + + /* FORK ANFANG */ + synchronized (this) { + writeLog("wait "+ forkOrig.thNo); + noOfThread--; + res = forkOrig.join(); + synchronized (usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + } + //noOfThread++; + forkOrig.writeLog("final Orig 2"); + forkOrig.closeLogFile(); + //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(TypeUnify2Task fork : forks) { + synchronized (this) { + noOfThread--; + Set> fork_res = fork.join(); + + //noOfThread++; + //noOfThread--; an das Ende von compute verschoben + add_res.add(fork_res); + fork.writeLog("final 2"); + }; + } + //noOfThread++; + } 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, finalresult); + }}} + 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()) { + + 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 + //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 + //System.out.println(a_last); + + try {//PL eingefuegt 2019-03-06 da bei map mmer wieder Nullpointer kamen + 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) { + int resOfCompare = oup.compare(compResult, compRes); + if (resOfCompare == -1) { + result = res; + } else { + if (resOfCompare == 0) { + result.addAll(res); + } //else { + if (resOfCompare == 1) { + //result = result; + }}} + else { if (variance == -1) { + int resOfCompare = oup.compare(compResult, compRes); + if (resOfCompare == 1) { + result = res; + } else { + if (resOfCompare == 0) { + result.addAll(res); + } else { + if (resOfCompare == -1) { + //result = result; + }}}} + else { if (variance == 0) { + result.addAll(res); + }}} + } + catch (NullPointerException e) { + } + } + else { + //alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden + result.addAll(res); + } + } + } + if (parallel) { + for (Set> par_res : add_res) { + if (!isUndefinedPairSetSet(par_res) && isUndefinedPairSetSet(result)) { + //wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen + result = par_res; + } + else { + if ((isUndefinedPairSetSet(par_res) && isUndefinedPairSetSet(result)) + || (!isUndefinedPairSetSet(par_res) && !isUndefinedPairSetSet(result)) + || result.isEmpty()) { + //alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden + result.addAll(par_res); + } + } + } + //break; + } + + /* auskommentiert um alle Max und min Betrachtung auszuschalten ANFANG */ + if (!result.isEmpty() && (!isUndefinedPairSetSet(res) || !aParDef.isEmpty())) { + if (nextSetasList.iterator().hasNext() && nextSetasList.iterator().next().stream().filter(x -> x.getLhsType().getName().equals("B")).findFirst().isPresent() && nextSetasList.size()>1) + Iterator> nextSetasListIt = new ArrayList>(nextSetasList).iterator(); + if (variance == 1) { + aParDef.add(a); + Iterator> aParDefIt = aParDef.iterator(); + if (oderConstraint) { + nextSetasList.removeAll(nextSetasListOderConstraints); + nextSetasListOderConstraints = new ArrayList<>(); + while(aParDefIt.hasNext()) { + Set a_new = aParDefIt.next(); + List> smallerSetasList = oup.smallerThan(a_new, nextSetasList); + List> notInherited = smallerSetasList.stream() + .filter(x -> !((Constraint)x).isInherited()) + .collect(Collectors.toCollection(ArrayList::new)); + List> notErased = new ArrayList<>(); + notInherited.stream().forEach(x -> { notErased.addAll(oup.smallerEqThan(x, smallerSetasList)); }); + List> erased = new ArrayList<>(smallerSetasList); + erased.removeAll(notErased); + nextSetasList.removeAll(erased); + + } + } + else { + while(aParDefIt.hasNext()) { + //nextSetasListIt = nextSetasList.iterator(); Sollte eingefuegt werden PL 2020-04-28 + Set a_new = aParDefIt.next(); + List> erased = oup.smallerEqThan(a_new, nextSetasList); + nextSetasList.removeAll(erased); + } + } + } + else { if (variance == -1) { + aParDef.add(a); + Iterator> aParDefIt = aParDef.iterator(); + if (oderConstraint) { + nextSetasList.removeAll(nextSetasListOderConstraints); + nextSetasListOderConstraints = new ArrayList<>(); + while(aParDefIt.hasNext()) { + Set a_new = aParDefIt.next(); + List> greaterSetasList = oup.greaterThan(a_new, nextSetasList); + + //a_new muss hingefuegt werden, wenn es nicht vererbt ist, dann wird es spaeter wieder geloescht + if (!((Constraint)a_new).isInherited()) { + greaterSetasList.add(a_new); + } + List> notInherited = greaterSetasList.stream() + .filter(x -> !((Constraint)x).isInherited()) + .collect(Collectors.toCollection(ArrayList::new)); + List> notErased = new ArrayList<>(); + + //Wenn x nicht vererbt ist, beginnt beim naechstgroesseren Element die naechste Ueberladung + notInherited.stream().forEach(x -> { notErased.addAll(oup.greaterEqThan(x, greaterSetasList)); }); + + //das kleineste Element ist das Element von dem a_new geerbt hat + //muss deshalb geloescht werden + Iterator> notErasedIt = notErased.iterator(); + if (notErasedIt.hasNext()) { + Set min = oup.min(notErasedIt); + notErased.remove(min); + notErased.remove(((Constraint)min).getExtendConstraint()); + } + + List> erased = new ArrayList<>(greaterSetasList); + erased.removeAll(notErased); + nextSetasList.removeAll(erased); + + } + } + else { + while(aParDefIt.hasNext()) { + //nextSetasListIt = nextSetasList.iterator(); Sollte eingefuegt werden PL 2020-04-28 + Set a_new = aParDefIt.next(); + List> erased = oup.greaterEqThan(a_new, nextSetasList); + + nextSetasList.removeAll(erased); + + } + } + } + else { if (variance == 0) { + if (!oderConstraint) { + break; + } + else { + nextSetasList.removeAll(nextSetasListOderConstraints); + nextSetasListOderConstraints = new ArrayList<>(); + List> smallerSetasList = oup.smallerThan(a, nextSetasList); + List> notInherited = smallerSetasList.stream() + .filter(x -> !((Constraint)x).isInherited()) + .collect(Collectors.toCollection(ArrayList::new)); + List> notErased = new ArrayList<>(); + notInherited.stream().forEach(x -> { notErased.addAll(oup.smallerEqThan(x, smallerSetasList)); }); + List> erased = new ArrayList<>(smallerSetasList); + erased.removeAll(notErased); + nextSetasList.removeAll(erased); + + } + + } + else { if (variance == 2) { + }}} + } + } + /* auskommentiert um alle Max und min Betrachtung auszuschalten ENDE */ + + if (isUndefinedPairSetSet(res) && aParDef.isEmpty()) { + 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(); + abhSubst.addAll( + res.stream() + .map(b -> + b.stream() + .map(x -> x.getThisAndAllBases()) //getAllBases durch getThisAndAllBases ersetzt, weil auch im UnifyPair selbst schon ein Fehler liegen kann. + .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)); + })//.filter(y -> couldBecorrect(reducedUndefResSubstGroundedBasePair, y)) //fuer testzwecke auskommentiert um nofstred zu bestimmen PL 2018-10-10 + .collect(Collectors.toCollection(ArrayList::new)); + nofstred = nextSetasList.size(); + noBacktracking++; + System.out.println(""); + } + } + return result; + } + + protected static Boolean checkA (UnifyPair aPair, Set sameEqSet, Set> elems, Set> result) { + for (UnifyPair sameEq : sameEqSet) { + if (sameEq.getLhsType() instanceof PlaceholderType) { + Set localEq = new HashSet<>(); + Set unitedSubst = new HashSet<>(aPair.getAllSubstitutions()); + unitedSubst.addAll(aPair.getAllBases()); + unitedSubst.addAll(sameEq.getAllSubstitutions()); + unitedSubst.addAll(sameEq.getAllBases()); + localEq.add(new UnifyPair(aPair.getRhsType(), sameEq.getRhsType(), sameEq.getPairOp(), unitedSubst, null)); + Set> localRes = unify(localEq, new ArrayList<>(), fc, false, 0, false); + if (isUndefinedPairSetSet(localRes)) { + if (result.isEmpty() || isUndefinedPairSetSet(result)) { + result.addAll(localRes); + } + //writeLog("FALSE: " + aPair + "sameEqSet: " + sameEqSet); + return false; + } + } + else { + Set localEq = new HashSet<>(); + Set unitedSubst = new HashSet<>(aPair.getAllSubstitutions()); + unitedSubst.addAll(aPair.getAllBases()); + unitedSubst.addAll(sameEq.getAllSubstitutions()); + unitedSubst.addAll(sameEq.getAllBases()); + localEq.add(new UnifyPair(sameEq.getLhsType(), aPair.getRhsType(), sameEq.getPairOp(), unitedSubst, null)); + Set> localRes = unify(localEq, new ArrayList<>(), fc, false, 0, false); + if (isUndefinedPairSetSet(localRes)) { + if (result.isEmpty() || isUndefinedPairSetSet(result)) { + result.addAll(localRes); + } + //writeLog("FALSE: " + aPair + "sameEqSet: " + sameEqSet); + return false; + } + } + } + //writeLog("TRUE: " + aPair + "sameEqSet: " + sameEqSet); + return true; + } + + protected boolean couldBecorrect(Set, UnifyPair>> reducedUndefResSubstGroundedBasePair, Set nextElem) { + return reducedUndefResSubstGroundedBasePair.stream() + .map(pair -> { + Set reducedAbhSubst = pair.getKey(); + reducedAbhSubst.addAll(nextElem); + Optional> substRes = rules.subst(reducedAbhSubst); + if (!substRes.isPresent()) { + return true; + } + //PL 2018-10-12 + //Evtl. zurest applyTypeUnification aufrufen + //evtl auch unify aufrufen + else { + UnifyPair checkPair = substRes.get().stream() + .filter(x -> x.getGroundBasePair().equals(pair.getValue().get())).findFirst().get(); + if (((checkPair.getLhsType() instanceof PlaceholderType) || (checkPair.getRhsType() instanceof PlaceholderType)) + && (checkPair.getPairOp() == PairOperator.SMALLERDOT || checkPair.getPairOp() == PairOperator.SMALLERDOTWC)) + { + + PairOperator pairOp = checkPair.getPairOp(); + UnifyType lhsType = checkPair.getLhsType(); + UnifyType rhsType = checkPair.getRhsType(); + ///* Case 1: (a <. Theta') + if ((((pairOp == PairOperator.SMALLERDOT) || (pairOp == PairOperator.SMALLERNEQDOT)) && lhsType instanceof PlaceholderType) + // Case 2: (a <.? ? ext Theta') + || (pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof ExtendsType) + // Case 3: (a <.? ? sup Theta') + || (pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof SuperType) + + // Case 4 was replaced by an inference rule + // Case 4: (a <.? Theta') + || (pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType) + // Case 5: (Theta <. a) + || ((pairOp == PairOperator.SMALLERDOT) && rhsType instanceof PlaceholderType) + // Case 6 was replaced by an inference rule. + // Case 6: (? ext Theta <.? a) + || (pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof ExtendsType && rhsType instanceof PlaceholderType) + // Case 7 was replaced by an inference rule + // Case 7: (? sup Theta <.? a) + || (pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof SuperType && rhsType instanceof PlaceholderType) + // Case 8: (Theta <.? a) + || (pairOp == PairOperator.SMALLERDOTWC && rhsType instanceof PlaceholderType) + //reduceWildcardLow + || (pairOp == PairOperator.SMALLERDOTWC && (lhsType instanceof ExtendsType) && (rhsType instanceof ExtendsType)) + //reduceWildcardLowRight + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof ReferenceType) && (rhsType instanceof ExtendsType)) + //reduceWildcardUp + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof SuperType) && (rhsType instanceof SuperType)) + //reduceWildcardUpRight + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof ReferenceType) && (rhsType instanceof SuperType)) + //reduceFunN + || (((pairOp == PairOperator.SMALLERDOT) || (pairOp == PairOperator.EQUALSDOT)) + //PL 2017-10-03 hinzugefuegt + //da Regel auch fuer EQUALSDOT anwendbar + && (lhsType instanceof FunNType) && (rhsType instanceof FunNType)) + //greaterFunN + || ((pairOp== PairOperator.SMALLERDOT) && (lhsType instanceof FunNType) && (rhsType instanceof PlaceholderType)) + //smallerFunN + || ((pairOp == PairOperator.SMALLERDOT) && (lhsType instanceof PlaceholderType && rhsType instanceof FunNType)) + //reduceTph + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof PlaceholderType && rhsType instanceof ReferenceType)) + //reduceTphExt + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof ExtendsType) && rhsType instanceof PlaceholderType) + //reduceTphSup + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof SuperType) && rhsType instanceof PlaceholderType)) { + return true; + } + // Case unknown: If a pair fits no other case, then the type unification has failed. + // Through application of the rules, every pair should have one of the above forms. + // Pairs that do not have one of the aboves form are contradictory. + else { + return false; + } + //*/ + } else { + //Pair type <. ? extends ? extends type betrachten TODO PL 2018-10-09 + }} + return true;}).reduce((xx, yy) -> xx || yy).get(); + } + + /** + * Checks whether a set of pairs is in solved form. + * @param eqPrimePrime The set of pair + * @return True if in solved form, false otherwise. + */ + protected static boolean isSolvedForm(Set eqPrimePrime) { + for(UnifyPair pair : eqPrimePrime) { + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + + if(!(lhsType instanceof PlaceholderType)) + return false; + + // If operator is not equals, both sides must be placeholders + if(pair.getPairOp() != PairOperator.EQUALSDOT && !(rhsType instanceof PlaceholderType)) + return false; + } + return true; + } + + /** + * Repeatedly applies type unification rules to a set of equations. + * This is step one of the unification algorithm. + * @return The set of pairs that results from repeated application of the inference rules. + */ + public static Set applyTypeUnificationRules(Set eq, IFiniteClosure fc) { + + /* + * Rule Application Strategy: + * + * 1. Swap all pairs and erase all erasable pairs + * 2. Apply all possible rules to a single pair, then move it to the result set. + * Iterating over pairs first, then iterating over rules prevents the application + * of rules to a "finished" pair over and over. + * 2.1 Apply all rules repeatedly except for erase rules. If + * the application of a rule creates new pairs, check immediately + * against the erase rules. + */ + + + LinkedHashSet targetSet = new LinkedHashSet(); + LinkedList eqQueue = new LinkedList<>(); + + /* + * Swap all pairs and erase all erasable pairs + */ + eq.forEach(x -> swapAddOrErase(x, fc, eqQueue)); + + /* + * Apply rules until the queue is empty + */ + while(!eqQueue.isEmpty()) { + UnifyPair pair = eqQueue.pollFirst(); + + // ReduceUp, ReduceLow, ReduceUpLow + Optional opt = rules.reduceUpLow(pair); + opt = opt.isPresent() ? opt : rules.reduceLow(pair); + opt = opt.isPresent() ? opt : rules.reduceUp(pair); + opt = opt.isPresent() ? opt : rules.reduceWildcardLow(pair); + opt = opt.isPresent() ? opt : rules.reduceWildcardLowRight(pair); + opt = opt.isPresent() ? opt : rules.reduceWildcardUp(pair); + opt = opt.isPresent() ? opt : rules.reduceWildcardUpRight(pair); + //PL 2018-03-06 auskommentiert muesste falsch sein vgl. JAVA_BSP/Wildcard6.java + //opt = opt.isPresent() ? opt : rules.reduceWildcardLowUp(pair); + //opt = opt.isPresent() ? opt : rules.reduceWildcardUpLow(pair); + //opt = opt.isPresent() ? opt : rules.reduceWildcardLeft(pair); + + // Reduce TPH + opt = opt.isPresent() ? opt : rules.reduceTph(pair); + + // One of the rules has been applied + if(opt.isPresent()) { + swapAddOrErase(opt.get(), fc, eqQueue); + continue; + } + + // Reduce1, Reduce2, ReduceExt, ReduceSup, ReduceEq + //try { + // logFile.write("PAIR1 " + pair + "\n"); + // logFile.flush(); + //} + //catch (IOException e) { } + + Optional> optSet = rules.reduce1(pair, fc); + optSet = optSet.isPresent() ? optSet : rules.reduce2(pair); + optSet = optSet.isPresent() ? optSet : rules.reduceExt(pair, fc); + optSet = optSet.isPresent() ? optSet : rules.reduceSup(pair, fc); + optSet = optSet.isPresent() ? optSet : rules.reduceEq(pair); + + // ReduceTphExt, ReduceTphSup + optSet = optSet.isPresent() ? optSet : rules.reduceTphExt(pair); + optSet = optSet.isPresent() ? optSet : rules.reduceTphSup(pair); + + + // FunN Rules + optSet = optSet.isPresent() ? optSet : rules.reduceFunN(pair); + optSet = optSet.isPresent() ? optSet : rules.greaterFunN(pair); + optSet = optSet.isPresent() ? optSet : rules.smallerFunN(pair); + + // One of the rules has been applied + if(optSet.isPresent()) { + optSet.get().forEach(x -> swapAddOrErase(x, fc, eqQueue)); + continue; + } + + // Adapt, AdaptExt, AdaptSup + //try { + // logFile.write("PAIR2 " + pair + "\n"); + // logFile.flush(); + //} + //catch (IOException e) { } + opt = rules.adapt(pair, fc); + opt = opt.isPresent() ? opt : rules.adaptExt(pair, fc); + opt = opt.isPresent() ? opt : rules.adaptSup(pair, fc); + + // One of the rules has been applied + if(opt.isPresent()) { + swapAddOrErase(opt.get(), fc, eqQueue); + continue; + } + + // None of the rules has been applied + targetSet.add(pair); + } + + return targetSet; + } + + /** + * Applies the rule swap to a pair if possible. Then adds the pair to the set if no erase rule applies. + * If an erase rule applies, the pair is not added (erased). + * @param pair The pair to swap and add or erase. + * @param collection The collection to which the pairs are added. + */ + protected void swapAddOrErase(UnifyPair pair, IFiniteClosure fc, Collection collection) { + Optional opt = rules.swap(pair); + UnifyPair pair2 = opt.isPresent() ? opt.get() : pair; + + if(rules.erase1(pair2, fc) || rules.erase3(pair2) || rules.erase2(pair2, fc)) + return; + + collection.add(pair2); + } + + /** + * Creates sets of pairs specified in the fourth step. Does not calculate cartesian products. + * TODO: undefined sollte nicht übergeben werden, stattdessen Fehler (empty) zurückgeben + * @param undefined All pairs that did not match one of the 8 cases are added to this set. + * @return The set of the eight cases (without empty sets). Each case is a set, containing sets generated + * 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 static Optional>>>> calculatePairSets(Set eq2s, IFiniteClosure fc) { + //TODO: 4 Sets ineinander verschachtelt. Muss das wirklich sein? + List>>> result = new ArrayList<>(9); + + // 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 eq2sAsListFst = new ArrayList<>(); + ArrayList eq2sAsListSnd = new ArrayList<>(); + ArrayList eq2sAsListThird = new ArrayList<>(); + ArrayList eq2sAsListFourth = new ArrayList<>(); + ArrayList eq2sAsListBack = new ArrayList<>(); + 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() == 1 && + !((PlaceholderType)up.getLhsType()).isInnerType()) || + (up.getRhsType() instanceof PlaceholderType && + ((PlaceholderType)up.getRhsType()).getVariance() == -1) && + !((PlaceholderType)up.getRhsType()).isInnerType()) + { + eq2sAsListFst.add(up); + eq2s.remove(up); + } + else if ((up.getLhsType() instanceof PlaceholderType && ((PlaceholderType)up.getLhsType()).getVariance() == 1 && ((PlaceholderType)up.getLhsType()).isInnerType()) + || (up.getRhsType() instanceof PlaceholderType && ((PlaceholderType)up.getRhsType()).getVariance() == -1) && ((PlaceholderType)up.getRhsType()).isInnerType()) { + eq2sAsListSnd.add(up); + eq2s.remove(up); + } + else if ((up.getLhsType() instanceof PlaceholderType && + ((PlaceholderType)up.getLhsType()).getVariance() == -1 && + !((PlaceholderType)up.getLhsType()).isInnerType()) || + (up.getRhsType() instanceof PlaceholderType && + ((PlaceholderType)up.getRhsType()).getVariance() == -1) && + !((PlaceholderType)up.getRhsType()).isInnerType()) + { + eq2sAsListThird.add(up); + eq2s.remove(up); + } + else if ((up.getLhsType() instanceof PlaceholderType && ((PlaceholderType)up.getLhsType()).getVariance() == -1 && ((PlaceholderType)up.getLhsType()).isInnerType()) + || (up.getRhsType() instanceof PlaceholderType && ((PlaceholderType)up.getRhsType()).getVariance() == 1) && ((PlaceholderType)up.getRhsType()).isInnerType()) { + eq2sAsListFourth.add(up); + eq2s.remove(up); + } + else if ((up.getLhsType() instanceof PlaceholderType && ((PlaceholderType)up.getLhsType()).isInnerType()) + || (up.getRhsType() instanceof PlaceholderType && ((PlaceholderType)up.getRhsType()).isInnerType())) { + eq2sAsListBack.add(up); + eq2s.remove(up); + } + } + //if (eq2sAsListFst.isEmpty()) + eq2sAsList.addAll(eq2sAsListFst); + eq2sAsList.addAll(eq2sAsListSnd); + eq2sAsList.addAll(eq2sAsListThird); + eq2sAsList.addAll(eq2sAsListFourth); + eq2sAsList.addAll(eq2s); + eq2sAsList.addAll(eq2sAsListBack); + + /* + Bei allen die Abhaengigkeit der Elemente aus eq2sAsList als evtl. als Substitution + hinzufuegen + */ + Set consideredElements = new HashSet<>(); + for(UnifyPair pair : eq2sAsList) { + if (consideredElements.contains(pair)) { + continue; + } + PairOperator pairOp = pair.getPairOp(); + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + + // Case 1: (a <. Theta') + 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<>(); + remElem.add(new UnifyPair(pair.getLhsType(), pair.getRhsType(), PairOperator.EQUALSDOT)); + x1.remove(remElem); + remElem = new HashSet<>(); + remElem.add(new UnifyPair(pair.getLhsType(), new ExtendsType(pair.getRhsType()), PairOperator.EQUALSDOT)); + x1.remove(remElem); + remElem = new HashSet<>(); + remElem.add(new UnifyPair(pair.getLhsType(), new SuperType(pair.getRhsType()), PairOperator.EQUALSDOT)); + x1.remove(remElem); + } + result.get(0).add(x1); + if (x1.isEmpty()) { + //undefined.add(pair); //Theta ist nicht im FC => Abbruch + return Optional.empty(); + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(0).add(s2); + } + + } + // Case 2: (a <.? ? ext Theta') + else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof ExtendsType) + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase2(pair, fc); + result.get(1).add(x1); + if (x1.isEmpty()) { + //undefined.add(pair); //Theta ist nicht im FC + return Optional.empty(); + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(1).add(s2); + } + + // Case 3: (a <.? ? sup Theta') + else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof SuperType) + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase3(pair, fc); + result.get(2).add(x1); + if (x1.isEmpty()) { + //undefined.add(pair); //Theta ist nicht im FC + return Optional.empty(); + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(2).add(s2); + } + + // Case 5: (Theta <. a) + else if ((pairOp == PairOperator.SMALLERDOT) && rhsType instanceof PlaceholderType) + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase5(pair, fc); + result.get(4).add(x1); + if (x1.isEmpty()) { + //undefined.add(pair); //Theta ist nicht im FC + return Optional.empty(); + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(4).add(s2); + } + + // Case 8: (Theta <.? a) + else if(pairOp == PairOperator.SMALLERDOTWC && rhsType instanceof PlaceholderType) + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase8(pair, fc); + result.get(7).add(x1); + if (x1.isEmpty()) { + return Optional.empty();//undefined.add(pair); //Theta ist nicht im FC + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(7).add(s2); + } + // Case unknown: If a pair fits no other case, then the type unification has failed. + // Through application of the rules, every pair should have one of the above forms. + // Pairs that do not have one of the aboves form are contradictory. + else { + // If a pair is not defined, the unificiation will fail, so the loop can be stopped here. + return Optional.empty();//undefined.add(pair); + break; + } + first = false; + } + + // Filter empty sets or sets that only contain an empty set. + return Optional.of(result.stream().map(x -> x.stream().filter(y -> y.size() > 0).collect(Collectors.toCollection(HashSet::new))) + .filter(x -> x.size() > 0).collect(Collectors.toCollection(HashSet::new))); + } + + //TODO: Wenn Theta' nicht im FC muss ein Fehler produziert werden PL 18-04-20 + /** + * Cartesian product Case 1: (a <. Theta') + */ + protected static Set> unifyCase1(UnifyPair pair, IFiniteClosure fc) { + PlaceholderType a = (PlaceholderType)pair.getLhsType(); + UnifyType thetaPrime = pair.getRhsType(); + + if (thetaPrime instanceof ExtendsType) { + thetaPrime = ((ExtendsType)thetaPrime).getExtendedType(); + } + + if (thetaPrime instanceof SuperType) { + //HIER MUSS NOCH WAS UEBERLEGT WERDEN + } + + Set> result = new HashSet<>(); + + boolean allGen = thetaPrime.getTypeParams().size() > 0; + for(UnifyType t : thetaPrime.getTypeParams()) + if(!(t instanceof PlaceholderType) || !((PlaceholderType) t).isGenerated()) { + 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 + + //cs muessen fresh Typvars gesetzt werden PL 2018-03-18 + Set csPHRenamed = cs.stream().map(x -> { + BinaryOperator> combiner = (aa, b) -> { aa.putAll(b); return aa;}; + HashMap hm = x.getInvolvedPlaceholderTypes().stream() + .reduce(new HashMap(), + (aa, b)-> { aa.put(b,PlaceholderType.freshPlaceholder()); return aa; }, combiner); + return x.accept(new freshPlaceholder(), hm); + }).collect(Collectors.toCollection(HashSet::new)); + + IMatch match = new Match(); + for(UnifyType c : csPHRenamed) { + //PL 18-02-05 getChildren durch smaller ersetzt in getChildren werden die Varianlen nicht ersetzt. + Set thetaQs = new HashSet<>(); + //TODO smaller wieder reinnehmen? + //thetaQs.add(c);// + thetaQs = fc.smaller(c, new HashSet<>()).stream().collect(Collectors.toCollection(HashSet::new)); + ArrayList ml = new ArrayList<>(); + ml.add(new UnifyPair(c, thetaPrime, PairOperator.EQUALSDOT)); + if (!(match.match(ml)).isPresent()) { + thetaQs.remove(c); + } + + Set thetaQPrimes = new HashSet<>(); + TypeParams cParams = c.getTypeParams(); + if(cParams.size() == 0) + thetaQPrimes.add(c); + else { + ArrayList> candidateParams = new ArrayList<>(); + + for(UnifyType param : cParams) + candidateParams.add(fc.grArg(param, new HashSet<>())); + + for(TypeParams tp : permuteParams(candidateParams)) + thetaQPrimes.add(c.setTypeParams(tp)); + } + for(UnifyType tqp : thetaQPrimes) {//PL 2020-03-08 umbauen in der Schleife wird nur unifizierbarer Typ gesucht break am Ende + Collection tphs = tqp.getInvolvedPlaceholderTypes(); + Optional opt = new MartelliMontanariUnify().unify(tqp, thetaPrime); + if (!opt.isPresent()) { + continue; + } + Unifier unifier = opt.get(); + unifier.swapPlaceholderSubstitutions(thetaPrime.getTypeParams()); + Set substitutionSet = new HashSet<>(); + for (Map.Entry sigma : unifier) { + 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) { + //geaendert PL 20-03-07 + Set smaller = new HashSet<>(); + smaller.add(unifier.apply(tq)); + //Set smaller = fc.smaller(unifier.apply(tq), new HashSet<>()); + //eingefuegt PL 2018-03-29 Anfang ? ext. theta hinzufuegen + if (a.isWildcardable()) { + Set smaller_ext = smaller.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 ExtendsType (x);})//.accept(new freshPlaceholder(), hm));} + .collect(Collectors.toCollection(HashSet::new)); + smaller.addAll(smaller_ext); + } + //eingefuegt PL 2018-03-29 Ende ? ext. theta hinzufuegen + for(UnifyType theta : smaller) { + List freshTphs = new ArrayList<>(); + Set resultPrime = new HashSet<>(); + + 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(); + //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(); + 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); + //writeLog("Substitution: " + substitutionSet.toString()); + result.add(resultPrime); + //writeLog("Result: " + resultPrime.toString()); + //writeLog("MAX: " + oup.max(resultPrime.iterator()).toString()); + } + } + } + } + writeLog("result von " + pair + ": " + result.toString()); + return result; + } + + /** + * Cartesian Product Case 2: (a <.? ? ext Theta') + */ + private Set> unifyCase2(UnifyPair pair, IFiniteClosure fc) { + PlaceholderType a = (PlaceholderType) pair.getLhsType(); + ExtendsType extThetaPrime = (ExtendsType) pair.getRhsType(); + Set> result = new HashSet<>(); + + 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<>(); + resultPrime.add(new UnifyPair(a, thetaPrime, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + result.add(resultPrime); + + resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, extAPrime, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(aPrime, thetaPrime, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + result.add(resultPrime); + //writeLog("Result: " + resultPrime.toString()); + return result; + } + + /** + * Cartesian Product Case 3: (a <.? ? sup Theta') + */ + private Set> unifyCase3(UnifyPair pair, IFiniteClosure fc) { + PlaceholderType a = (PlaceholderType) pair.getLhsType(); + a.reversVariance(); + SuperType subThetaPrime = (SuperType) pair.getRhsType(); + 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<>(); + resultPrime.add(new UnifyPair(thetaPrime, a, PairOperator.SMALLERDOT, pair.getSubstitution(), pair, pair.getfBounded())); + result.add(resultPrime); + //writeLog(resultPrime.toString()); + + resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, supAPrime, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(thetaPrime, aPrime, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + result.add(resultPrime); + //writeLog(resultPrime.toString()); + + return result; + } + + /** + * Cartesian Product Case 5: (Theta <. a) + */ + private Set> unifyCase5(UnifyPair pair, IFiniteClosure fc) { + UnifyType theta = pair.getLhsType(); + PlaceholderType a = (PlaceholderType) pair.getRhsType(); + Set> result = new HashSet<>(); + + boolean allGen = theta.getTypeParams().size() > 0; + for(UnifyType t : theta.getTypeParams()) + if(!(t instanceof PlaceholderType) || !((PlaceholderType) t).isGenerated()) { + allGen = false; + break; + } + + //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(); + + UnifyType[] freshTphs = new UnifyType[thetaS.getTypeParams().size()]; + for(int i = 0; !allGen && i < freshTphs.length; i++) { + freshTphs[i] = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)freshTphs[i]).setVariance(((PlaceholderType)a).getVariance()); + Set fBounded = new HashSet<>(pair.getfBounded()); //PL 2019-01-09 new HashSet eingefuegt + + int i_ef = i; + BiFunction f = (x, y) -> + { + ArrayList termList = new ArrayList(); + termList.add(new UnifyPair(y,thetaS.getTypeParams().get(i_ef), PairOperator.EQUALSDOT)); + return ((match.match(termList).isPresent()) || x); + }; + //if (parai.getName().equals("java.lang.Integer")) { + // System.out.println(""); + //} + BinaryOperator bo = (x,y) -> (x || y); + if (fBounded.stream().reduce(false,f,bo)) { + resultPrime.add(new UnifyPair(freshTphs[i], thetaS.getTypeParams().get(i), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + } + else { + fBounded.add(thetaS.getTypeParams().get(i)); + resultPrime.add(new UnifyPair(thetaS.getTypeParams().get(i), freshTphs[i], PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair, fBounded)); + } + } + + if(allGen) + resultPrime.add(new UnifyPair(a, thetaS, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + else + resultPrime.add(new UnifyPair(a, thetaS.setTypeParams(new TypeParams(freshTphs)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + result.add(resultPrime); + //writeLog("FBOUNDED2: " + pair.getfBounded()); + //writeLog("resultPrime Theta < a: " + greater + pair + "THETA: " + theta + "FBOUNDED: " + pair.getfBounded() + " " + resultPrime.toString()); + } + + return result; + } + + /** + * Cartesian Product Case 8: (Theta <.? a) + */ + private Set> unifyCase8(UnifyPair pair, IFiniteClosure fc) { + UnifyType theta = pair.getLhsType(); + PlaceholderType a = (PlaceholderType) pair.getRhsType(); + Set> result = new HashSet<>(); + //for(UnifyType thetaS : fc.grArg(theta)) { + Set resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + result.add(resultPrime); + //writeLog(resultPrime.toString()); + + 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())); + result.add(resultPrime); + //writeLog("resultPrime: " + resultPrime.toString()); + + resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, new SuperType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(freshTph, theta, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + result.add(resultPrime); + //writeLog(resultPrime.toString()); + //} + + return result; + } + + /** + * Takes a set of candidates for each position and computes all possible permutations. + * @param candidates The length of the list determines the number of type params. Each set + * contains the candidates for the corresponding position. + */ + protected static Set permuteParams(ArrayList> candidates) { + Set result = new HashSet<>(); + permuteParams(candidates, 0, result, new UnifyType[candidates.size()]); + return result; + } + + /** + * Takes a set of candidates for each position and computes all possible permutations. + * @param candidates The length of the list determines the number of type params. Each set + * contains the candidates for the corresponding position. + * @param idx Idx for the current permutatiton. + * @param result Set of all permutations found so far + * @param current The permutation of type params that is currently explored + */ + private static void permuteParams(ArrayList> candidates, int idx, Set result, UnifyType[] current) { + if(candidates.size() == idx) { + result.add(new TypeParams(Arrays.copyOf(current, current.length))); + return; + } + + Set localCandidates = candidates.get(idx); + + for(UnifyType t : localCandidates) { + current[idx] = t; + permuteParams(candidates, idx+1, result, current); + } + } +} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java index ec613cd0..23b3e2aa 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java @@ -60,7 +60,33 @@ import com.google.common.collect.Ordering; * Implementation of the type unification algorithm * @author Florian Steurer */ -public class TypeUnifyTask extends RecursiveTask>> { +public class TypeUnifyTask { + + public static Set> typeUnifyTask(Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, Writer logFile, Boolean log, int rekTiefe, UnifyResultModel urm){ + Set neweq = new HashSet<>(eq); + /* 1-elementige Oder-Constraints werden in und-Constraints umgewandelt */ + oderConstraints.stream() + .filter(x -> x.size()==1) + .map(y -> y.stream().findFirst().get()).forEach(x -> neweq.addAll(x)); + ArrayList>> remainingOderconstraints = oderConstraints.stream() + .filter(x -> x.size()>1) + .collect(Collectors.toCollection(ArrayList::new)); + Set> res = unify(neweq, remainingOderconstraints, fc, parallel, rekTiefe, true); + try { + logFile.close(); + } + catch (IOException ioE) { + System.err.println("no log-File"); + } + if (isUndefinedPairSetSet(res)) { + throw new TypeinferenceException("Unresolved constraints: " + res.toString(), new NullToken()); //return new HashSet<>(); + } + else { + return res; + } + + + } private static final long serialVersionUID = 1L; private static int i = 0; @@ -71,7 +97,7 @@ public class TypeUnifyTask extends RecursiveTask>> { * Element, das aus dem nextSet den Gleichunen dieses Threads hinzugefuegt wurde */ Set nextSetElement; - + Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, Writer logFile, Boolean log, int rekTiefe, UnifyResultModel urm /** * Fuer die Threads */ @@ -210,12 +236,9 @@ public class TypeUnifyTask extends RecursiveTask>> { * @param fc The finite closure * @return The set of all principal type unifiers */ - protected Set> unify(final Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, int rekTiefe, Boolean finalresult) { + protected static Set> unify(final Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, int rekTiefe, Boolean finalresult) { rekTiefe++; - nOfUnify++; - writeLog(nOfUnify.toString() + " Unifikation: " + eq.toString()); - writeLog(nOfUnify.toString() + " Oderconstraints: " + oderConstraints.toString()); /* * Variancen auf alle Gleichungen vererben @@ -352,7 +375,7 @@ public class TypeUnifyTask extends RecursiveTask>> { //Aufruf von computeCartesianRecursive ANFANG //writeLog("topLevelSets: " + topLevelSets.toString()); - return computeCartesianRecursive(new HashSet<>(), new ArrayList<>(topLevelSets), eq, oderConstraintsOutput, fc, parallel, rekTiefe, finalresult); + return computeCartesianRecursive(new HashSet<>(), new ArrayList<>(topLevelSets), eq, oderConstraintsOutput, fc, rekTiefe, finalresult); } @@ -360,17 +383,7 @@ public class TypeUnifyTask extends RecursiveTask>> { Set> unify2(Set> setToFlatten, Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, int rekTiefe, Boolean finalresult) { //Aufruf von computeCartesianRecursive ENDE - //keine Ahnung woher das kommt - //Set> setToFlatten = topLevelSets.stream().map(x -> x.iterator().next()).collect(Collectors.toCollection(HashSet::new)); - - //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG - // Cartesian product over all (up to 10) top level sets - //Set>> eqPrimeSet = setOps.cartesianProduct(topLevelSets) - // .stream().map(x -> new HashSet<>(x)) - // .collect(Collectors.toCollection(HashSet::new)); - //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE - Set> eqPrimePrimeSet = new HashSet<>(); Set forks = new HashSet<>(); @@ -393,47 +406,9 @@ public class TypeUnifyTask extends RecursiveTask>> { Set> unifyres1 = null; Set> unifyres2 = null; if (!ocString.equals(newOderConstraints.toString())) writeLog("nach Subst: " + newOderConstraints); - //writeLog("nach Subst: " + eqPrimePrime); - /* - * Step 6 a) Restart (fork) for pairs where subst was applied - */ - /* - if(parallel) { - 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. - eqPrimePrimeSet.add(eqPrime); - else if(eqPrimePrime.isPresent()) { - //System.out.println("nextStep: " + eqPrimePrime.get()); - TypeUnifyTask fork = new TypeUnifyTask(eqPrimePrime.get(), fc, true, logFile, log); - forks.add(fork); - fork.fork(); - } - else { - //System.out.println("nextStep: " + eqPrime); - TypeUnifyTask fork = new TypeUnifyTask(eqPrime, fc, true, logFile, log); - forks.add(fork); - fork.fork(); - } - } - else */ {// sequentiell (Step 6b is included) - if (printtag) System.out.println("nextStep: " + eqPrimePrime); 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)) { - // writeLog("eqPrime:" + eqPrime.toString()+"\n"); - //} - //} - //catch (IOException e) { - // System.err.println("log-File nicht vorhanden"); - //} + && oderConstraints.isEmpty()) { eqPrimePrimeSet.add(eqPrime); if (finalresult && isSolvedForm(eqPrime)) { writeLog("eqPrime:" + eqPrime.toString()+"\n"); @@ -452,23 +427,6 @@ public class TypeUnifyTask extends RecursiveTask>> { eqPrimePrimeSet.addAll(unifyres); } } - //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG - //} - //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE - - /* - * 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)) { writeLog("Result1 " + eqPrimePrimeSet.toString()); @@ -478,9 +436,7 @@ public class TypeUnifyTask extends RecursiveTask>> { - Set> computeCartesianRecursive(Set> fstElems, ArrayList>> topLevelSets, Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, int rekTiefe, Boolean finalresult) { - //ArrayList>> remainingSets = new ArrayList<>(topLevelSets); - + Set> computeCartesianRecursive(Set> fstElems, ArrayList>> topLevelSets, Set eq, List>> oderConstraints, IFiniteClosure fc, int rekTiefe, Boolean finalresult) { fstElems.addAll(topLevelSets.stream() .filter(x -> x.size()==1) .map(y -> y.stream().findFirst().get()) @@ -493,17 +449,8 @@ public class TypeUnifyTask extends RecursiveTask>> { 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; @@ -560,25 +507,15 @@ public class TypeUnifyTask extends RecursiveTask>> { 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()); + Set nextSetElem = nextSetasList.get(0); - //writeLog("BasePair1: " + nextSetElem + " " + nextSetElem.iterator().next().getBasePair()); - /* sameEqSet-Bestimmung: Wenn a = ty \in nextSet dann enthaelt sameEqSet alle Paare a < ty1 oder ty2 < a aus fstElems */ Set sameEqSet = new HashSet<>(); Optional optOrigPair = null; //if (variance != 2) { if (!oderConstraint) { optOrigPair = nextSetElem.stream().filter(x -> ( - //x.getBasePair() != null && ist gegeben wenn variance != 2 - //x.getBasePair().getPairOp().equals(PairOperator.SMALLERDOT) && - (x.getPairOp().equals(PairOperator.EQUALSDOT) - /* - (x.getBasePair().getLhsType() instanceof PlaceholderType - && x.getLhsType().equals(x.getBasePair().getLhsType())) - || (x.getBasePair().getRhsType() instanceof PlaceholderType - && x.getLhsType().equals(x.getBasePair().getRhsType()) - */ + (x.getPairOp().equals(PairOperator.EQUALSDOT) ))).filter(x -> //Sicherstellen, dass bei a = ty a auch wirklich die gesuchte Typvariable ist x.getLhsType().equals(x.getBasePair().getLhsType()) || x.getLhsType().equals(x.getBasePair().getRhsType()) @@ -735,7 +672,7 @@ public class TypeUnifyTask extends RecursiveTask>> { newElemsOrig.add(a); /* FORK ANFANG */ - TypeUnify2Task forkOrig = new TypeUnify2Task(newElemsOrig, newEqOrig, newOderConstraintsOrig, a, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); + TypeUnify2Task forkOrig = new TypeUnify2Task(newElemsOrig, newEqOrig, newOderConstraintsOrig, a, fc, parallel, logFile, log, rekTiefe, urm); //forks.add(forkOrig); /* FORK ENDE */ @@ -785,41 +722,14 @@ public class TypeUnifyTask extends RecursiveTask>> { Set> newElems = new HashSet<>(elems); List>> newOderConstraints = new ArrayList<>(oderConstraints); newElems.add(nSaL); - TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, nSaL, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); - forks.add(fork); - synchronized(usedTasks) { - if (this.myIsCancelled()) { - return new HashSet<>(); - } - fork.fork(); - } + TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, nSaL, fc, parallel, logFile, log, rekTiefe, urm); } //res = unify2(newElemsOrig, newEqOrig, newOderConstraintsOrig, fc, parallel, rekTiefe); - - /* FORK ANFANG */ - synchronized (this) { - writeLog("wait "+ forkOrig.thNo); - noOfThread--; - res = forkOrig.join(); - synchronized (usedTasks) { - if (this.myIsCancelled()) { - return new HashSet<>(); - } - } - //noOfThread++; - forkOrig.writeLog("final Orig 1"); - forkOrig.closeLogFile(); - //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 */ - - forks.forEach(x -> writeLog("wait: " + x.thNo)); + + res = forkOrig.join(); + for(TypeUnify2Task fork : forks) { synchronized (this) { - noOfThread--; Set> fork_res = fork.join(); synchronized (usedTasks) { if (this.myIsCancelled()) { @@ -836,28 +746,18 @@ public class TypeUnifyTask extends RecursiveTask>> { aParDef.add(fork.getNextSetElement()); } fork.writeLog("final 1"); - fork.closeLogFile(); }; } //noOfThread++; } else { - if(parallel && (variance == -1) && noOfThread <= MaxNoOfThreads) { + if((variance == -1)) { 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, a, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); - //forks.add(forkOrig); - synchronized(usedTasks) { - if (this.myIsCancelled()) { - return new HashSet<>(); - } - forkOrig.fork(); - } - /* FORK ENDE */ + + TypeUnify2Task forkOrig = new TypeUnify2Task(newElemsOrig, newEqOrig, newOderConstraintsOrig, a, fc, parallel, logFile, log, rekTiefe, urm); synchronized (this) { writeLog("a in " + variance + " "+ a); @@ -1512,7 +1412,7 @@ public class TypeUnifyTask extends RecursiveTask>> { return true;}).reduce((xx, yy) -> xx || yy).get(); } - protected boolean isUndefinedPairSet(Set s) { + protected static boolean isUndefinedPairSet(Set s) { if (s.size() >= 1 ) { Boolean ret = s.stream().map(x -> x.isUndefinedPair()).reduce(true, (x,y)-> (x && y)); return ret; @@ -1522,7 +1422,7 @@ public class TypeUnifyTask extends RecursiveTask>> { } } - protected boolean isUndefinedPairSetSet(Set> s) { + protected static boolean isUndefinedPairSetSet(Set> s) { if (s.size() >= 1) { Boolean ret = s.stream(). map(x -> isUndefinedPairSet(x)).reduce(true, (x,y)-> (x && y)); return ret; @@ -1581,7 +1481,7 @@ public class TypeUnifyTask extends RecursiveTask>> { /* * Apply rules until the queue is empty */ - while(!eqQueue.isEmpty()) { + while(!eqQueue.isEmpty()) { UnifyPair pair = eqQueue.pollFirst(); // ReduceUp, ReduceLow, ReduceUpLow diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultEvent.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultEvent.java deleted file mode 100644 index a79e34ec..00000000 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultEvent.java +++ /dev/null @@ -1,18 +0,0 @@ -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/UnifyResultListener.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultListener.java deleted file mode 100644 index f490ccde..00000000 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultListener.java +++ /dev/null @@ -1,7 +0,0 @@ -package de.dhbwstuttgart.typeinference.unify; - -public interface UnifyResultListener { - - void onNewTypeResultFound(UnifyResultEvent evt); - -} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultListenerImpl.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultListenerImpl.java deleted file mode 100644 index ea34728b..00000000 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultListenerImpl.java +++ /dev/null @@ -1,21 +0,0 @@ -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 deleted file mode 100644 index 7a4f0ccf..00000000 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultModel.java +++ /dev/null @@ -1,59 +0,0 @@ -package de.dhbwstuttgart.typeinference.unify; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - -import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; -import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; -import de.dhbwstuttgart.typeinference.result.ResultSet; -import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; -import de.dhbwstuttgart.typeinference.unify.model.PairOperator; -import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; - -public class UnifyResultModel { - - ConstraintSet cons; - - IFiniteClosure fc; - - public UnifyResultModel(ConstraintSet cons, - IFiniteClosure fc) { - this.cons = cons; - this.fc = fc; - } - - private List listeners = new ArrayList<>(); - - public void addUnifyResultListener(UnifyResultListener listenerToAdd) { - listeners.add(listenerToAdd); - } - - public void removeUnifyResultListener(UnifyResultListener listenerToRemove) { - listeners.remove(listenerToRemove); - } - - public void notify(Set> eqPrimePrimeSet) { - 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)); - List newResult = eqPrimePrimeSetRet.stream().map(unifyPairs -> - new ResultSet(UnifyTypeFactory.convert(unifyPairs, de.dhbwstuttgart.typeinference.constraints.Pair.generateTPHMap(cons)))) - .collect(Collectors.toList()); - UnifyResultEvent evt = new UnifyResultEvent(newResult); - - for (UnifyResultListener listener : listeners) { - listener.onNewTypeResultFound(evt); - } - } -} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java index 497fd811..3cf1ccc6 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java @@ -29,8 +29,6 @@ public class UnifyPair { */ private PairOperator pairOp; - private boolean undefinedPair = false; - /** * Unifier/substitute that generated this pair * PL 2018-03-15 @@ -114,10 +112,7 @@ public class UnifyPair { public void addSubstitutions(Set sup) { substitution.addAll(sup); } - - public void setUndefinedPair() { - undefinedPair = true; - } + public Set getSubstitution() { return new HashSet<>(substitution); } @@ -125,10 +120,6 @@ public class UnifyPair { public UnifyPair getBasePair() { return basePair; } - public boolean isUndefinedPair() { - return undefinedPair; - } - public Set getAllSubstitutions () { Set ret = new HashSet<>(); ret.addAll(new ArrayList<>(getSubstitution()));