diff --git a/resources/bytecode/javFiles/LambdaRunnable.jav b/resources/bytecode/javFiles/LambdaRunnable.jav index 37924ea2..dcedb1f5 100644 --- a/resources/bytecode/javFiles/LambdaRunnable.jav +++ b/resources/bytecode/javFiles/LambdaRunnable.jav @@ -7,7 +7,7 @@ public class LamRunnable{ public LamRunnable(){ - Runnable lam = () -> {System.out.println("lambda");}; + Runnable lam = () -> {var a;}; lam.run(); } } diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java index 71dcef52..2bf82cd7 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java @@ -2,8 +2,11 @@ package de.dhbwstuttgart.parser.SyntaxTreeGenerator; import de.dhbwstuttgart.exceptions.DebugException; import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.Pattern; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; import de.dhbwstuttgart.syntaxtree.type.*; @@ -32,12 +35,29 @@ public class FCGenerator { HashMap gtvs = new HashMap<>(); for(ClassOrInterface cly : availableClasses){ pairs.addAll(getSuperTypes(cly, availableClasses, gtvs, classLoader)); + + //For all Functional Interfaces FI: FunN$$<... args auf dem Functional Interface ...> <. FI is added to FC + if (isFunctionalInterface(cly)) { + pairs.add(genImplFunType(cly)); + } } return pairs; } - + private static Boolean isFunctionalInterface(ClassOrInterface cly) { + return (cly.isInterface() && cly.getMethods().size() == 1); + } + + private static Pair genImplFunType(ClassOrInterface cly) { + Method m = cly.getMethods().get(0); + List tl = + (m.getParameterList().getFormalparalist().stream().map(p -> p.getType()).collect(Collectors.toList())); + tl.add(m.getReturnType()); + return new Pair(new RefType(new JavaClassName("Fun" + (tl.size()-1) + "$$"), tl, new NullToken()), + new RefType(cly.getClassName(), new NullToken())); + // new FunN(lambdaParams), + } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java index 5d60428b..006502ac 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java @@ -880,15 +880,44 @@ public class RuleSet implements IRuleSet{ @Override - public Optional> greaterFunN(UnifyPair pair) { + public Optional> greaterFunN(UnifyPair pair, IFiniteClosure fc) { if(pair.getPairOp() != PairOperator.SMALLERDOT) return Optional.empty(); UnifyType lhsType = pair.getLhsType(); UnifyType rhsType = pair.getRhsType(); - if(!(lhsType instanceof FunNType) || !(rhsType instanceof PlaceholderType)) + if(!(lhsType instanceof FunNType)) return Optional.empty(); + + //FunN$$<...> <. FunctinalInterface wird umgewandelt in FunN$$<...> <. FunN$$<... args aus FuntionalInterface ...> + if (rhsType instanceof ReferenceType) { + + UnifyType typeD = pair.getRhsType(); + + Optional opt = fc.getRightHandedNoParameterType(typeD.getName()); + if(!opt.isPresent()) + return Optional.empty(); + + // Should be eual as typeD + UnifyType typeFunFc = opt.get(); + + + if(!(typeFunFc instanceof FunNType)) + return Optional.empty(); + + UnifyType newRhsType = opt.get(); + + Set result = new HashSet<>(); + result.add(new UnifyPair(lhsType, newRhsType, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + + return Optional.of(result); + } + + else { + if(!(rhsType instanceof PlaceholderType)) + return Optional.empty(); + } FunNType funNLhsType = (FunNType) lhsType; diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java index 6e24e9da..17fbcedd 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java @@ -1808,7 +1808,7 @@ public class TypeUnifyTask extends RecursiveTask>> { // FunN Rules optSet = optSet.isPresent() ? optSet : rules.reduceFunN(pair); - optSet = optSet.isPresent() ? optSet : rules.greaterFunN(pair); + optSet = optSet.isPresent() ? optSet : rules.greaterFunN(pair, fc); optSet = optSet.isPresent() ? optSet : rules.smallerFunN(pair); // One of the rules has been applied 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 50371d34..b3704c10 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java @@ -60,6 +60,7 @@ public interface IFiniteClosure { public Set smArg(FunNType type, Set fBounded); public Optional getLeftHandedType(String typeName); + public Optional getRightHandedNoParameterType(String typeName); public Set getAncestors(UnifyType t); public Set getChildren(UnifyType t); public Set getAllTypesByName(String typeName); diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java index bac6bcb0..9b86600a 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java @@ -60,7 +60,7 @@ public interface IRuleSet { * FunN Rules */ public Optional> reduceFunN(UnifyPair pair); - public Optional> greaterFunN(UnifyPair pair); + public Optional> greaterFunN(UnifyPair pair, IFiniteClosure fc); public Optional> smallerFunN(UnifyPair pair); /** @@ -100,4 +100,5 @@ public interface IRuleSet { * @return An optional of the modified set, if there were any substitutions. An empty optional if there were no substitutions. */ public Optional> subst(Set pairs); + } 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 5f047d0c..bc84ead4 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java @@ -608,6 +608,18 @@ implements IFiniteClosure { return Optional.empty(); } + @Override + public Optional getRightHandedNoParameterType(String typeName) { + if(!strInheritanceGraph.containsKey(typeName)) + return Optional.empty(); + + for(UnifyPair pair : pairs) + if(pair.getRhsType().getName().equals(typeName) && pair.getRhsType().typeParams.size() == 0) + return Optional.of(pair.getLhsType()); + + return Optional.empty(); + } + @Override public Set getAncestors(UnifyType t) { if(!inheritanceGraph.containsKey(t)) diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index dbdfff2d..422ac00a 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -736,4 +736,13 @@ public class TestComplete { var m = clazz.getDeclaredMethod("m", Integer.class); assertEquals(m.invoke(instance, 10), 60); } + + @Test + public void testLambdaRunnable() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "LambdaRunnable.jav"); + var clazz = classFiles.get("LambdaRunnable"); + var instance = clazz.getDeclaredConstructor().newInstance(); + //var m = clazz.getDeclaredMethod("m", Integer.class); + //assertEquals(m.invoke(instance, 10), 60); + } }