From 6850a8fa2165d124d0805072a34bddbd24774062 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Thu, 28 Mar 2024 10:35:34 +0100 Subject: [PATCH] Decouple unify from the rest of the code --- .../de/dhbwstuttgart/core/JavaTXCompiler.java | 4 +- .../SyntaxTreeGenerator/FCGenerator.java | 5 +- .../syntaxtree/factory/UnifyTypeFactory.java | 79 +++++++++++-------- .../typeinference/unify/RuleSet.java | 18 +---- .../unify/interfaces/IFiniteClosure.java | 3 - .../unify/model/FiniteClosure.java | 36 --------- .../unify/model/FunInterfaceType.java | 49 ++++++++++++ .../unify/model/ReferenceType.java | 6 -- src/test/java/TestComplete.java | 2 +- 9 files changed, 103 insertions(+), 99 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/typeinference/unify/model/FunInterfaceType.java diff --git a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java index 15ae40f4..b230c097 100644 --- a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -292,7 +292,7 @@ public class JavaTXCompiler { System.out.println(finiteClosure); urm = new UnifyResultModel(cons, finiteClosure); urm.addUnifyResultListener(resultListener); - ConstraintSet unifyCons = UnifyTypeFactory.convert(cons); + ConstraintSet unifyCons = UnifyTypeFactory.convert(this, cons); Function distributeInnerVars = x -> { UnifyType lhs, rhs; @@ -428,7 +428,7 @@ public class JavaTXCompiler { Writer logFile = log ? new FileWriter(new File(logFolder, "log_" + sourceFiles.keySet().iterator().next().getName())) : new OutputStreamWriter(new NullOutputStream()); IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logFile, classLoader, this); System.out.println(finiteClosure); - ConstraintSet unifyCons = UnifyTypeFactory.convert(cons); + ConstraintSet unifyCons = UnifyTypeFactory.convert(this, cons); System.out.println("xxx1"); Function distributeInnerVars = x -> { UnifyType lhs, rhs; diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java index e864200f..4f4474a5 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.parser.SyntaxTreeGenerator; +import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.exceptions.DebugException; import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.scope.JavaClassName; @@ -25,8 +26,8 @@ public class FCGenerator { * * @param availableClasses - Alle geparsten Klassen */ - public static Set toUnifyFC(Collection availableClasses, ClassLoader classLoader) throws ClassNotFoundException { - return toFC(availableClasses, classLoader).stream().map(t -> UnifyTypeFactory.convert(t)).collect(Collectors.toSet()); + public static Set toUnifyFC(JavaTXCompiler compiler, Collection availableClasses, ClassLoader classLoader) throws ClassNotFoundException { + return toFC(availableClasses, classLoader).stream().map(t -> UnifyTypeFactory.convert(compiler, t)).collect(Collectors.toSet()); } public static Set toFC(Collection availableClasses, ClassLoader classLoader) throws ClassNotFoundException { diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java index 1b802a3f..e73e9ba7 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java @@ -1,10 +1,12 @@ package de.dhbwstuttgart.syntaxtree.factory; import java.io.Writer; +import java.lang.reflect.Modifier; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.exceptions.NotImplementedException; @@ -13,6 +15,7 @@ import de.dhbwstuttgart.parser.SourceLoc; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.FCGenerator; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.syntaxtree.type.WildcardType; @@ -41,7 +44,7 @@ public class UnifyTypeFactory { Generell dürfen sie immer die gleichen Namen haben. TODO: die transitive Hülle bilden */ - return new FiniteClosure(FCGenerator.toUnifyFC(fromClasses, classLoader), logFile, compiler); + return new FiniteClosure(FCGenerator.toUnifyFC(compiler, fromClasses, classLoader), logFile, compiler); } public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr, SourceLoc location){ @@ -64,23 +67,23 @@ public class UnifyTypeFactory { * Convert from * ASTType -> UnifyType */ - public static UnifyType convert(RefTypeOrTPHOrWildcardOrGeneric t, Boolean innerType){ + public static UnifyType convert(JavaTXCompiler compiler, RefTypeOrTPHOrWildcardOrGeneric t, Boolean innerType){ if (t instanceof GenericRefType){ - return UnifyTypeFactory.convert((GenericRefType)t, innerType); + return UnifyTypeFactory.convert(compiler, (GenericRefType)t, innerType); } else if (t instanceof TypePlaceholder){ - return UnifyTypeFactory.convert((TypePlaceholder)t, innerType); + return UnifyTypeFactory.convert(compiler, (TypePlaceholder)t, innerType); } else if (t instanceof ExtendsWildcardType){ - return UnifyTypeFactory.convert((ExtendsWildcardType)t, innerType); + return UnifyTypeFactory.convert(compiler, (ExtendsWildcardType)t, innerType); } else if (t instanceof SuperWildcardType) { - return UnifyTypeFactory.convert((SuperWildcardType) t, innerType); + return UnifyTypeFactory.convert(compiler, (SuperWildcardType) t, innerType); } else if (t instanceof RefType){ - return UnifyTypeFactory.convert((RefType)t, innerType); + return UnifyTypeFactory.convert(compiler, (RefType)t, innerType); } //Es wurde versucht ein Typ umzuwandeln, welcher noch nicht von der Factory abgedeckt ist throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden"); } - public static UnifyType convert(RefType t, Boolean innerType){ + public static UnifyType convert(JavaTXCompiler compiler, RefType t, Boolean innerType){ //Check if it is a FunN Type: Pattern p = Pattern.compile("Fun(\\d+)[$][$]"); Matcher m = p.matcher(t.getName().toString()); @@ -88,35 +91,41 @@ public class UnifyTypeFactory { if(b){ Integer N = Integer.valueOf(m.group(1)); if((N + 1) == t.getParaList().size()){ - return convertFunN(t.getParaList(), false); + return convertFunN(compiler, t.getParaList(), false); } } UnifyType ret; - if(t.getParaList() != null && t.getParaList().size() > 0){ - List params = new ArrayList<>(); - for(RefTypeOrTPHOrWildcardOrGeneric pT : t.getParaList()){ - params.add(UnifyTypeFactory.convert(pT, true)); + List params = new ArrayList<>(); + if (t.getParaList() != null) { + for (RefTypeOrTPHOrWildcardOrGeneric pT : t.getParaList()) { + params.add(UnifyTypeFactory.convert(compiler, pT, true)); } - ret = new ReferenceType(t.getName().toString(),new TypeParams(params)); - }else{ - ret = new ReferenceType(t.getName().toString(), false); } - return ret; + + var clazz = compiler.getClass(t.getName()); + if (clazz != null && clazz.isInterface() && clazz.isFunctionalInterface()) { + var method = clazz.getMethods().stream().filter(x -> Modifier.isAbstract(x.modifier)).findFirst().orElseThrow(); + var methodParams = method.getParameterList().getFormalparalist().stream().map(x -> convert(compiler, x.getType(), true)).toList(); + var generics = StreamSupport.stream(clazz.getGenerics().spliterator(), false).map(GenericTypeVar::getName).toList(); + return new FunInterfaceType(t.getName().toString(), new TypeParams(params), methodParams, convert(compiler, method.getReturnType(), true), generics); + } + + return new ReferenceType(t.getName().toString(),new TypeParams(params)); } - public static UnifyType convertFunN(List paraList, Boolean innerType){ + public static UnifyType convertFunN(JavaTXCompiler compiler, List paraList, Boolean innerType){ UnifyType ret; List params = new ArrayList<>(); if(paraList != null && paraList.size() > 0){ for(RefTypeOrTPHOrWildcardOrGeneric pT : paraList){ - params.add(UnifyTypeFactory.convert(pT, false)); + params.add(UnifyTypeFactory.convert(compiler, pT, false)); } } ret = FunNType.getFunNType(new TypeParams(params)); return ret; } - public static UnifyType convert(TypePlaceholder tph, Boolean innerType){ + public static UnifyType convert(JavaTXCompiler compiler, TypePlaceholder tph, Boolean innerType){ if (tph.getName().equals("AFR")) { System.out.println("XXX"+innerType); } @@ -136,21 +145,21 @@ public class UnifyTypeFactory { } } - public static UnifyType convert(GenericRefType t, Boolean innerType){ + public static UnifyType convert(JavaTXCompiler compiler, GenericRefType t, Boolean innerType){ return new ReferenceType(t.getParsedName(), true); } - public static UnifyType convert(WildcardType t, Boolean innerType){ + public static UnifyType convert(JavaTXCompiler compiler, WildcardType t, Boolean innerType){ if(t.isExtends()) - return new ExtendsType(UnifyTypeFactory.convert(t.getInnerType(), false)); + return new ExtendsType(UnifyTypeFactory.convert(compiler, t.getInnerType(), false)); else if(t.isSuper()) - return new SuperType(UnifyTypeFactory.convert(t.getInnerType(), false)); + return new SuperType(UnifyTypeFactory.convert(compiler, t.getInnerType(), false)); else throw new NotImplementedException(); } - public static ConstraintSet convert(ConstraintSet constraints) { - return constraints.map(UnifyTypeFactory::convert); + public static ConstraintSet convert(JavaTXCompiler compiler, ConstraintSet constraints) { + return constraints.map(c -> UnifyTypeFactory.convert(compiler, c)); } //NEVER USED @@ -161,23 +170,23 @@ public class UnifyTypeFactory { // return unifyPairConstraint; //} - public static UnifyPair convert(Pair p) { + public static UnifyPair convert(JavaTXCompiler compiler, Pair p) { UnifyPair ret = null; if(p.GetOperator().equals(PairOperator.SMALLERDOT)) { - ret = generateSmallerDotPair(UnifyTypeFactory.convert(p.TA1, false) - , UnifyTypeFactory.convert(p.TA2, false), p.getLocation()); + ret = generateSmallerDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false) + , UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation()); //return ret; }else if(p.GetOperator().equals(PairOperator.SMALLERNEQDOT)) { - ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(p.TA1, false) - , UnifyTypeFactory.convert(p.TA2, false), p.getLocation()); + ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false) + , UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation()); //return ret; }else if(p.GetOperator().equals(PairOperator.EQUALSDOT)) { - ret = generateEqualDotPair(UnifyTypeFactory.convert(p.TA1, false) - , UnifyTypeFactory.convert(p.TA2, false), p.getLocation()); + ret = generateEqualDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false) + , UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation()); //return ret; }else if(p.GetOperator().equals(PairOperator.SMALLER)){ - ret = generateSmallerPair(UnifyTypeFactory.convert(p.TA1, false), - UnifyTypeFactory.convert(p.TA2, false), p.getLocation()); + ret = generateSmallerPair(UnifyTypeFactory.convert(compiler, p.TA1, false), + UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation()); }else throw new NotImplementedException(); UnifyType lhs, rhs; if (((lhs = ret.getLhsType()) instanceof PlaceholderType) diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java index e318f737..a3d2474c 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java @@ -19,17 +19,7 @@ import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet; -import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; -import de.dhbwstuttgart.typeinference.unify.model.FunNType; -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.*; import de.dhbwstuttgart.typeinference.constraints.Constraint; import de.dhbwstuttgart.typeinference.unify.distributeVariance; @@ -901,12 +891,12 @@ public class RuleSet implements IRuleSet{ if(!opt.isPresent()) return Optional.empty(); - if (!(typeFI instanceof ReferenceType refType) || !fc.isFunctionalInterface(refType)) + if (!(typeFI instanceof ReferenceType refType) || !(refType instanceof FunInterfaceType intf)) return Optional.empty(); - var fiArgs = fc.getFunctionalInterfaceTypeArguments(refType); + var fiArgs = intf.getFunctionalInterfaceTypeArguments(refType); var retType = fiArgs.getFirst(); - var lhsArgs = fc.getFunctionalInterfaceTypeArguments(lhsType); + var lhsArgs = intf.getFunctionalInterfaceTypeArguments(lhsType); var lhsRet = lhsArgs.getFirst(); Set result = new HashSet<>(); diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java index 707d320f..f7b3f7ad 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java @@ -74,8 +74,5 @@ public interface IFiniteClosure { public Set getChildren(UnifyType t); public Set getAllTypesByName(String typeName); - public boolean isFunctionalInterface(ReferenceType t); - public List getFunctionalInterfaceTypeArguments(UnifyType t); - public int compare(UnifyType rhsType, UnifyType rhsType2, PairOperator pairop); } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java index 9c8301e0..4ef94fba 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java @@ -607,42 +607,6 @@ implements IFiniteClosure { return strInheritanceGraph.get(typeName).stream().map(x -> x.getContent()).collect(Collectors.toCollection(HashSet::new)); } - @Override - public boolean isFunctionalInterface(ReferenceType t) { - return compiler.getClass(new JavaClassName(t.getName())).isFunctionalInterface(); - } - - @Override - public List getFunctionalInterfaceTypeArguments(UnifyType t) { - if (t instanceof FunNType) { - var ret = new ArrayList(); - if (t.getTypeParams().size() > 0) { - ret.add(t.getTypeParams().get(t.getTypeParams().size() - 1)); - ret.addAll(Arrays.asList(t.getTypeParams().get()).subList(0, t.getTypeParams().size() - 1)); - } - return ret; - } - - var clazz = compiler.getClass(new JavaClassName(t.getName())); - var intfMethod = clazz.getMethods().stream().filter(m -> Modifier.isAbstract(m.modifier)).findFirst().orElseThrow(); - - var args = new ArrayList(); - args.add(UnifyTypeFactory.convert(intfMethod.getReturnType(), false)); - intfMethod.getParameterList().getFormalparalist().forEach(param -> args.add(UnifyTypeFactory.convert(param.getType(), false))); - - // TODO There might be a better way of dealing with this - var i = 0; - for (var generic : clazz.getGenerics()) { - for (var j = 0; j < args.size(); j++) { - if (args.get(j).getName().equals(generic.getName())) - args.set(j, t.getTypeParams().get(i)); - } - i += 1; - } - - return args; - } - @Override public Optional getLeftHandedType(String typeName) { if(!strInheritanceGraph.containsKey(typeName)) diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FunInterfaceType.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FunInterfaceType.java new file mode 100644 index 00000000..f47f9f0b --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FunInterfaceType.java @@ -0,0 +1,49 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FunInterfaceType extends ReferenceType { + final List intfArgTypes; + final UnifyType intfReturnType; + final List generics; + + public FunInterfaceType(String name, TypeParams params, List intfArgTypes, UnifyType intfReturnType, List generics) { + super(name, params); + this.intfArgTypes = intfArgTypes; + this.intfReturnType = intfReturnType; + this.generics = generics; + } + + public List getFunctionalInterfaceTypeArguments(UnifyType t) { + if (t instanceof FunNType) { + var ret = new ArrayList(); + if (t.getTypeParams().size() > 0) { + ret.add(t.getTypeParams().get(t.getTypeParams().size() - 1)); + ret.addAll(Arrays.asList(t.getTypeParams().get()).subList(0, t.getTypeParams().size() - 1)); + } + return ret; + } + + var args = new ArrayList(); + args.add(intfReturnType); + args.addAll(intfArgTypes); + + // TODO There might be a better way of dealing with this + var i = 0; + for (var generic : generics) { + for (var j = 0; j < args.size(); j++) { + if (args.get(j).getName().equals(generic)) + args.set(j, t.getTypeParams().get(i)); + } + i += 1; + } + + return args; + } +} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java index 62465b1a..0b1f50c8 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java @@ -34,12 +34,6 @@ public class ReferenceType extends UnifyType { this.genericTypeVar = genericTypeVar; } - public ReferenceType(String name, UnifyType... params) { - super(name, new TypeParams(params)); - hashCode = 31 + 17 * typeName.hashCode() + 17 * typeParams.hashCode(); - genericTypeVar = false; - } - public ReferenceType(String name, TypeParams params) { super(name, params); hashCode = 31 + 17 * typeName.hashCode() + 17 * typeParams.hashCode(); diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index e15930b0..f1c2b77f 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -233,7 +233,7 @@ public class TestComplete { } @Test - @Ignore("This is too complex") + //@Ignore("This is too complex") public void matrixTest() throws Exception { var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Matrix.jav"); var matrix = classFiles.get("Matrix");