diff --git a/src/de/dhbwstuttgart/strucTypes/Construct.java b/src/de/dhbwstuttgart/strucTypes/Construct.java index 18a42e27..15f6c952 100644 --- a/src/de/dhbwstuttgart/strucTypes/Construct.java +++ b/src/de/dhbwstuttgart/strucTypes/Construct.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import org.antlr.v4.runtime.Token; @@ -27,6 +28,7 @@ import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; public class Construct extends DefaultASTVisitor { @@ -57,6 +59,10 @@ public class Construct extends DefaultASTVisitor { public List getSubTypeConstraints() { return subTypeConstraints; } + + public Set getSubTypeConstraintsAsUnifyPairs(){ + return subTypeConstraints.stream().map(SubTypeConstraint::getAsUnifyPair).collect(Collectors.toSet()); + } private void gatherSubTypeConstraints(ConstraintsSet constraintsSet) { this.subTypeConstraints.addAll(constraintsSet.getSubTypeConstraints()); diff --git a/src/de/dhbwstuttgart/strucTypes/RuleSetStrucType.java b/src/de/dhbwstuttgart/strucTypes/RuleSetStrucType.java new file mode 100644 index 00000000..dd56ae82 --- /dev/null +++ b/src/de/dhbwstuttgart/strucTypes/RuleSetStrucType.java @@ -0,0 +1,94 @@ +package de.dhbwstuttgart.strucTypes; + +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.unify.RuleSet; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +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 javafx.util.Pair; + +public class RuleSetStrucType extends RuleSet { + + public Optional> reduce(UnifyPair pair) { + return super.reduce2(pair); + } + + public Optional adapt1(UnifyPair pair, IFiniteClosure fc) { + return super.adapt(pair, fc); + } + + public Optional> adapt2(Set pairs, IFiniteClosure fc) { + // TODO + return null; + } + + public boolean erase1(UnifyPair pair, IFiniteClosure fc) { + return super.erase1(pair, fc); + } + + public boolean erase2(UnifyPair pair) { + return super.erase3(pair); + } + + public Optional swap(UnifyPair pair) { + return super.swap(pair); + } + + public Optional> subst(Set pairs) { + return super.subst(pairs); + } + + public Optional> refl(Set pairs) { + // Filter SMALLERDOT Pairs + final Set pairsSmallerDot = pairs.stream().filter(p -> PairOperator.SMALLERDOT.equals(p.getPairOp())) + .collect(Collectors.toSet()); + // Filter Tuples of Pairs for a potential Linking (t> tupleOfPotentialLinkings = new ArrayList<>(); + for (UnifyPair pair : pairsSmallerDot) { + if (!(pair.getRhsType() instanceof PlaceholderType)) { + continue; + } + tupleOfPotentialLinkings = pairsSmallerDot.stream() + .filter(p -> p.getLhsType() instanceof PlaceholderType && p.getRhsType().equals(pair.getLhsType())) + .map(p -> new Pair<>(pair, p)).collect(Collectors.toList()); + } + // Build Linking between the Pairs. Empty if no Linking is possible. + for (Pair tuple : tupleOfPotentialLinkings) { + UnifyPair outerLeftPair = tuple.getKey(); + UnifyPair outerRightPair = tuple.getValue(); + Optional> opt = StrucTypeUnifyUtils.linkPairs(outerLeftPair, outerRightPair, + pairsSmallerDot); + // Remove Pairs of the Linking incl. outerLeft and outerRight, add + // EQUALSDOT Pairs instead. + if (opt.isPresent()) { + pairs.remove(outerLeftPair); + pairs.remove(outerRightPair); + pairs.removeAll(opt.get()); + // Get all Placeholder in Linking. + Set placeholderInLinking = new HashSet<>(); + opt.get().forEach(p -> { + placeholderInLinking.add(p.getLhsType()); + placeholderInLinking.add(p.getRhsType()); + }); + // Generate and add new EQUALSDOT Pairs of Placeholder and + // outermost UnifyType to the result. + final UnifyType outermostUnifyType = outerLeftPair.getLhsType(); + placeholderInLinking.forEach(placeholder -> pairs + .add(UnifyTypeFactory.generateEqualDotPair(placeholder, outermostUnifyType))); + return Optional.of(pairs); + } + } + // No Linking was found. + return Optional.empty(); + } + +} diff --git a/src/de/dhbwstuttgart/strucTypes/StrucTypeUnify.java b/src/de/dhbwstuttgart/strucTypes/StrucTypeUnify.java new file mode 100644 index 00000000..cfd87692 --- /dev/null +++ b/src/de/dhbwstuttgart/strucTypes/StrucTypeUnify.java @@ -0,0 +1,89 @@ +package de.dhbwstuttgart.strucTypes; + +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Optional; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +public class StrucTypeUnify { + + private Set pairs; + private IFiniteClosure fc; + private RuleSetStrucType rules = new RuleSetStrucType(); + + public StrucTypeUnify(Set unifyPairs, IFiniteClosure finiteClosure) { + this.pairs = unifyPairs; + this.fc = finiteClosure; + } + + public Set unify() { + Set pairs = this.applyTypeUnificationRules(this.pairs, fc); + return pairs; + } + + + private Set applyTypeUnificationRules(Set pairs, IFiniteClosure fc) { + Set resultSet = new HashSet<>(); + + LinkedList pairQueue = new LinkedList<>(); + + pairs.forEach(p -> this.swapAddOrErase(p, fc, pairQueue)); + + while (!pairQueue.isEmpty()) { + UnifyPair pair = pairQueue.pollFirst(); + + // reduce + Optional> optSet = rules.reduce(pair); + if (optSet.isPresent()) { + optSet.get().forEach(p -> swapAddOrErase(p, fc, pairQueue)); + continue; + } + + // adapt1 + Optional opt = rules.adapt1(pair, fc); + + if (opt.isPresent()) { + this.swapAddOrErase(opt.get(), fc, pairQueue); + continue; + } + + // no rule applied + resultSet.add(pair); + } + + // adapt2 + Optional> adapt2 = rules.adapt2(resultSet, fc); + if(adapt2.isPresent()){ + resultSet = this.applyTypeUnificationRules(adapt2.get(), fc); + } + + // subst + Optional> subst = rules.subst(resultSet); + if(subst.isPresent()){ + resultSet = this.applyTypeUnificationRules(subst.get(), fc); + } + + // refl + Optional> refl = rules.refl(resultSet); + if(refl.isPresent()){ + resultSet = this.applyTypeUnificationRules(refl.get(), fc); + } + + return resultSet; + } + + private void swapAddOrErase(UnifyPair pair, IFiniteClosure fc, Collection collection) { + // swap + Optional opt = rules.swap(pair); + UnifyPair unifyPair = opt.isPresent() ? opt.get() : pair; + + // erase + if (rules.erase1(unifyPair, fc) || rules.erase2(unifyPair)) + return; + collection.add(unifyPair); + } +} diff --git a/src/de/dhbwstuttgart/strucTypes/StrucTypeUnifyUtils.java b/src/de/dhbwstuttgart/strucTypes/StrucTypeUnifyUtils.java new file mode 100644 index 00000000..2ed5b3ed --- /dev/null +++ b/src/de/dhbwstuttgart/strucTypes/StrucTypeUnifyUtils.java @@ -0,0 +1,36 @@ +package de.dhbwstuttgart.strucTypes; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +public class StrucTypeUnifyUtils { + + public static Optional> linkPairs(UnifyPair outerLeft, UnifyPair outerRight, + Collection pairs) { + + Set resultLinking = new HashSet<>(); + + if (outerLeft.getRhsType().equals(outerRight.getLhsType())) { + resultLinking.add(outerLeft); + return Optional.of(resultLinking); + } + + List nextLinks = pairs.stream().filter(p -> outerLeft.getRhsType().equals(p.getLhsType())) + .collect(Collectors.toList()); + for (UnifyPair nextLink : nextLinks) { + Optional> opt = linkPairs(nextLink, outerRight, pairs); + if (opt.isPresent()) { + resultLinking = opt.get(); + resultLinking.add(nextLink); + return Optional.of(resultLinking); + } + } + return Optional.empty(); + } +} diff --git a/src/de/dhbwstuttgart/strucTypes/TYPEExpr.java b/src/de/dhbwstuttgart/strucTypes/TYPEExpr.java index d87a2486..fad3c8e9 100644 --- a/src/de/dhbwstuttgart/strucTypes/TYPEExpr.java +++ b/src/de/dhbwstuttgart/strucTypes/TYPEExpr.java @@ -9,6 +9,7 @@ import de.dhbwstuttgart.strucTypes.constraint.MethodConstraint; import de.dhbwstuttgart.strucTypes.constraint.SubTypeConstraint; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.Field; +import de.dhbwstuttgart.syntaxtree.FormalParameter; import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; import de.dhbwstuttgart.syntaxtree.statement.Block; @@ -21,7 +22,9 @@ import de.dhbwstuttgart.syntaxtree.statement.MethodCall; import de.dhbwstuttgart.syntaxtree.statement.NewClass; import de.dhbwstuttgart.syntaxtree.statement.Return; import de.dhbwstuttgart.syntaxtree.statement.This; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; public class TYPEExpr extends DefaultASTVisitor { @@ -167,9 +170,19 @@ public class TYPEExpr extends DefaultASTVisitor { "The number of fields (%d) in %s doesn't match the number of arguments (%d) passed to its constructor.", fieldsSize, newClass.name, argumentsSize)); } + + // List of Generics of newClass + List paraList = ((RefType)newClass.getType()).getParaList(); + List formalparalist = typeExtract.getConstructors().get(0).getParameterList().getFormalparalist(); for (int i = 0; i < argumentsSize; i++) { - SubTypeConstraint subTypeConstraint = new SubTypeConstraint(arguments.get(i).getType(), - fields.get(i).getType()); + // Bei Fields wird kein GenericRefType sondern Object als Typ geparst. + // SubTypeConstraint subTypeConstraint = new SubTypeConstraint(arguments.get(i).getType(), + // fields.get(i).getType()); + + // Es darf nur einen Konstruktor mit allen Feldern geben. + RefTypeOrTPHOrWildcardOrGeneric supertype = formalparalist.get(i).getType(); + supertype = supertype instanceof GenericRefType ? paraList.remove(0) : supertype; + SubTypeConstraint subTypeConstraint = new SubTypeConstraint(arguments.get(i).getType(), supertype); this.constraints.addConstraint(subTypeConstraint); } } @@ -204,5 +217,10 @@ public class TYPEExpr extends DefaultASTVisitor { public void visit(Return aReturn) { aReturn.retexpr.accept(this); } + + @Override + public void visit(GenericRefType genericRefType){ + + } } diff --git a/src/de/dhbwstuttgart/strucTypes/constraint/SubTypeConstraint.java b/src/de/dhbwstuttgart/strucTypes/constraint/SubTypeConstraint.java index 3eb2f483..095003ec 100644 --- a/src/de/dhbwstuttgart/strucTypes/constraint/SubTypeConstraint.java +++ b/src/de/dhbwstuttgart/strucTypes/constraint/SubTypeConstraint.java @@ -2,8 +2,11 @@ package de.dhbwstuttgart.strucTypes.constraint; import de.dhbwstuttgart.strucTypes.InferredTypes; import de.dhbwstuttgart.strucTypes.exception.ImpossibleSubTypeException; +import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; /** * c <. c' : c ist subtyp von c' @@ -52,6 +55,12 @@ public class SubTypeConstraint { } return true; } + + public UnifyPair getAsUnifyPair(){ + UnifyType tl = UnifyTypeFactory.convert(this.subtype); + UnifyType tr = UnifyTypeFactory.convert(this.supertype); + return UnifyTypeFactory.generateSmallerDotPair(tl, tr); + } private Class createClass(String name) { try { diff --git a/src/de/dhbwstuttgart/strucTypes/printutils/PrintConstraints.java b/src/de/dhbwstuttgart/strucTypes/printutils/PrintConstraints.java index cbd086d6..26ace5fa 100644 --- a/src/de/dhbwstuttgart/strucTypes/printutils/PrintConstraints.java +++ b/src/de/dhbwstuttgart/strucTypes/printutils/PrintConstraints.java @@ -1,11 +1,13 @@ package de.dhbwstuttgart.strucTypes.printutils; import java.util.List; +import java.util.Set; import de.dhbwstuttgart.strucTypes.constraint.ConstraintsSet; import de.dhbwstuttgart.strucTypes.constraint.FieldConstraint; import de.dhbwstuttgart.strucTypes.constraint.MethodConstraint; import de.dhbwstuttgart.strucTypes.constraint.SubTypeConstraint; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; public class PrintConstraints { @@ -22,6 +24,11 @@ public class PrintConstraints { // .println(String.format("%s <* %s", c.getSubtype().toString(), // c.getSupertype().toString()))); } + + public void printSubTypeConstraints(Set constraints){ + System.out.println("\n SubTypeConstraints:"); + constraints.forEach(System.out::println); + } public void printFieldConstraints(List constraints) { System.out.println("\n FieldConstraints:"); diff --git a/src/de/dhbwstuttgart/strucTypes/printutils/SyntaxTreePrinter.java b/src/de/dhbwstuttgart/strucTypes/printutils/SyntaxTreePrinter.java index dd4750c2..02034465 100644 --- a/src/de/dhbwstuttgart/strucTypes/printutils/SyntaxTreePrinter.java +++ b/src/de/dhbwstuttgart/strucTypes/printutils/SyntaxTreePrinter.java @@ -390,7 +390,7 @@ public class SyntaxTreePrinter implements ASTVisitor { @Override public void visit(GenericRefType genericRefType) { - System.out.println("GenRT " + genericRefType.getParsedName()); + System.out.println("GRT " + genericRefType.getParsedName()); } @Override diff --git a/src/de/dhbwstuttgart/syntaxtree/type/GenericRefType.java b/src/de/dhbwstuttgart/syntaxtree/type/GenericRefType.java index a14813e7..9c1a7ece 100644 --- a/src/de/dhbwstuttgart/syntaxtree/type/GenericRefType.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/GenericRefType.java @@ -17,8 +17,15 @@ public class GenericRefType extends RefTypeOrTPHOrWildcardOrGeneric public String getParsedName(){ return name.toString(); } + + @Override + public String toString() { + return "GRT " + this.name ; + } + + @Override public void accept(ASTVisitor visitor) { visitor.visit(this); } diff --git a/test/strucType/TestConstruct.java b/test/strucType/TestConstruct.java index bdd6c5aa..cbdb0316 100644 --- a/test/strucType/TestConstruct.java +++ b/test/strucType/TestConstruct.java @@ -4,19 +4,20 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Set; import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.strucTypes.Construct; import de.dhbwstuttgart.strucTypes.InferredTypes; import de.dhbwstuttgart.strucTypes.StrucTYPE; import de.dhbwstuttgart.strucTypes.constraint.ConstraintsSet; -import de.dhbwstuttgart.strucTypes.constraint.SubTypeConstraint; import de.dhbwstuttgart.strucTypes.exception.ImpossibleSubTypeException; import de.dhbwstuttgart.strucTypes.printutils.PrintConstraints; import de.dhbwstuttgart.strucTypes.printutils.PrintInferredTypes; import de.dhbwstuttgart.strucTypes.printutils.SyntaxTreePrinter; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; public class TestConstruct { public static final String rootDirectory = System.getProperty("user.dir") + "/test/strucType/javFiles/"; @@ -52,7 +53,8 @@ public class TestConstruct { Construct construct = new Construct(constraints, inferredTypesType); final List constructedInterfaces = construct.getConstructedInterfaces(); - final List subTypeConstraints = construct.getSubTypeConstraints(); +// final List subTypeConstraints = construct.getSubTypeConstraints(); + Set subTypeConstraints = construct.getSubTypeConstraintsAsUnifyPairs(); final InferredTypes inferredTypesConstruct = construct.getInferredTypes(); final SyntaxTreePrinter syntaxTreePrinterInferred = new SyntaxTreePrinter(inferredTypesConstruct); diff --git a/test/strucType/TestRuleSetStrucType.java b/test/strucType/TestRuleSetStrucType.java new file mode 100644 index 00000000..d41f555a --- /dev/null +++ b/test/strucType/TestRuleSetStrucType.java @@ -0,0 +1,43 @@ +package strucType; + +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; + +import org.junit.Test; + +import de.dhbwstuttgart.strucTypes.RuleSetStrucType; +import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import junit.framework.Assert; + +public class TestRuleSetStrucType { + + @Test + public void testRefl() { + + Set pairs = new HashSet<>(); + + ReferenceType t = new ReferenceType("t"); + PlaceholderType T1 = new PlaceholderType("T1"); + PlaceholderType T2 = new PlaceholderType("T2"); + PlaceholderType T3 = new PlaceholderType("T3"); + + UnifyPair p1 = UnifyTypeFactory.generateSmallerDotPair(t, T1); + UnifyPair p2 = UnifyTypeFactory.generateSmallerDotPair(T1, T3); + UnifyPair p3 = UnifyTypeFactory.generateSmallerDotPair(T1, T2); + UnifyPair p4 = UnifyTypeFactory.generateSmallerDotPair(T2, t); + + pairs.add(p1); + pairs.add(p2); + pairs.add(p3); + pairs.add(p4); + + RuleSetStrucType rules = new RuleSetStrucType(); + Optional> opt = rules.refl(pairs); +// System.out.println(opt.get()); + Assert.assertTrue("Refl: " + opt.get(),opt.isPresent()); + } +} diff --git a/test/strucType/TestStrucTypeUnifyUtils.java b/test/strucType/TestStrucTypeUnifyUtils.java new file mode 100644 index 00000000..aedfb545 --- /dev/null +++ b/test/strucType/TestStrucTypeUnifyUtils.java @@ -0,0 +1,46 @@ +package strucType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import org.junit.Test; + +import de.dhbwstuttgart.strucTypes.StrucTypeUnifyUtils; +import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import junit.framework.Assert; + +public class TestStrucTypeUnifyUtils { + + @Test + public void testLinkPairs() { + List pairs = new ArrayList<>(); + + ReferenceType t = new ReferenceType("t"); + PlaceholderType T1 = new PlaceholderType("T1"); + PlaceholderType T2 = new PlaceholderType("T2"); + PlaceholderType T3 = new PlaceholderType("T3"); + + UnifyPair p1 = UnifyTypeFactory.generateSmallerDotPair(t, T1); + UnifyPair p2 = UnifyTypeFactory.generateSmallerDotPair(T1, T3); + UnifyPair p3 = UnifyTypeFactory.generateSmallerDotPair(T1, T2); + UnifyPair p4 = UnifyTypeFactory.generateSmallerDotPair(T2, t); + + pairs.add(p1); + pairs.add(p2); + pairs.add(p3); + pairs.add(p4); + + Optional> opt = StrucTypeUnifyUtils.linkPairs(p1, p4, pairs); + + Assert.assertTrue(opt.isPresent()); + Assert.assertTrue(p3 + "is not in LinkedPairs: " + opt.get(), opt.get().contains(p3)); + Assert.assertEquals("Expected size = 1; Actual size = " + opt.get().size(), 1, opt.get().size()); + } + + +} diff --git a/test/strucType/javFiles/testNew.jav b/test/strucType/javFiles/testNew.jav index 15218b98..8ebe72c2 100644 --- a/test/strucType/javFiles/testNew.jav +++ b/test/strucType/javFiles/testNew.jav @@ -5,6 +5,8 @@ class N { a; + N(a){ a = a; } + mA(){ return new A(a); } mB(x){ return new B(x,a); } mN(a) {return new N(a); }