diff --git a/src/de/dhbwstuttgart/core/MyCompiler.java b/src/de/dhbwstuttgart/core/MyCompiler.java index 5c066cee..8b9758f9 100755 --- a/src/de/dhbwstuttgart/core/MyCompiler.java +++ b/src/de/dhbwstuttgart/core/MyCompiler.java @@ -38,6 +38,7 @@ import de.dhbwstuttgart.syntaxtree.type.Type; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.ByteCodeResult; import de.dhbwstuttgart.typeinference.FunNInterface; +import de.dhbwstuttgart.typeinference.FunVoidNInterface; import de.dhbwstuttgart.typeinference.Pair; import de.dhbwstuttgart.typeinference.ResultSet; import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; @@ -550,6 +551,10 @@ public class MyCompiler implements MyCompilerAPI FunNInterface funN = new FunNInterface(i); ret.add(funN.getPublicFieldAssumptions()); } + for(int i = 0; i<6; i++){ + FunVoidNInterface funN = new FunVoidNInterface(i); + ret.add(funN.getPublicFieldAssumptions()); + } return ret; diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/LambdaExpression.java b/src/de/dhbwstuttgart/syntaxtree/statement/LambdaExpression.java index c4aacb12..6d8cdf96 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/LambdaExpression.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/LambdaExpression.java @@ -31,6 +31,7 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.WildcardType; import de.dhbwstuttgart.typeinference.ConstraintsSet; import de.dhbwstuttgart.typeinference.FunN; +import de.dhbwstuttgart.typeinference.FunVoidN; import de.dhbwstuttgart.typeinference.JavaCodeResult; import de.dhbwstuttgart.typeinference.OderConstraint; import de.dhbwstuttgart.typeinference.ResultSet; @@ -175,17 +176,21 @@ public class LambdaExpression extends Expr{ //retType bleibt unverändert } }else{ - retType = new ExtendsWildcardType((ObjectType) retType); + //Die LambdaExpression kann zu diesem Zeit schon feststellen, ob der Return-Type Void ist (Kein Return-Statement): + if(!typeIsVoid(retType)){ //Nur, wenn es nicht void ist, kann der ExtendsWildcardType gebildet werden. + retType = new ExtendsWildcardType((ObjectType) retType); + } } - - //Die LambdaExpression kann zu diesem Zeit schon feststellen, ob der Return-Type Void ist (Kein Return-Statement): - if(retType.getName().equals(new JavaClassName("Void"))){ - System.out.println("Void rettype"); + if(typeIsVoid(retType)){//In diesem Fall, muss der Typ des LambdaAusdrucks FunVoid sein + ret.add(new SingleConstraint(new FunVoidN(modifiedParamTypes).TYPE(assumptions, this),this.getType().TYPE(assumptions, this))); + }else{ + ret.add(new SingleConstraint(new FunN(retType, modifiedParamTypes).TYPE(assumptions, this),this.getType().TYPE(assumptions, this))); } - ret.add(new SingleConstraint(new FunN(retType, modifiedParamTypes).TYPE(assumptions, this),this.getType().TYPE(assumptions, this))); return ret; } - + private boolean typeIsVoid(Type type){ + return type.getName().equals(new JavaClassName("void")); + } @Override public ConstraintsSet TYPEStmt(TypeAssumptions ass){ throw new TypeinferenceException("Eine LambdaExpression darf nicht als Statement verwendet werden.", this); diff --git a/src/de/dhbwstuttgart/typeinference/FunN.java b/src/de/dhbwstuttgart/typeinference/FunN.java index 55101d67..ec84c8e9 100755 --- a/src/de/dhbwstuttgart/typeinference/FunN.java +++ b/src/de/dhbwstuttgart/typeinference/FunN.java @@ -44,6 +44,16 @@ public class FunN extends RefType { this.name = new JavaClassName("Fun"+T.size());//getName(); } + /** + * Spezieller Konstruktor um eine FunN ohne Returntype zu generieren + */ + protected FunN(Menge T){ + super("",null,0); + if(T==null)throw new NullPointerException(); + setT(T); + this.name = new JavaClassName("Fun"+T.size());//getName(); + } + /** * Erstellt eine FunN: * FunN diff --git a/src/de/dhbwstuttgart/typeinference/FunNInterface.java b/src/de/dhbwstuttgart/typeinference/FunNInterface.java index b4c23318..920b4899 100644 --- a/src/de/dhbwstuttgart/typeinference/FunNInterface.java +++ b/src/de/dhbwstuttgart/typeinference/FunNInterface.java @@ -22,7 +22,6 @@ public class FunNInterface extends Class{ //TODO: Diese Klasse sollte eigentlich von Interface erben //TODO: getType muss einen Typ mit der ParameterListe zurückliefern. - //private Menge gtvparalist; /** diff --git a/src/de/dhbwstuttgart/typeinference/FunVoidN.java b/src/de/dhbwstuttgart/typeinference/FunVoidN.java new file mode 100644 index 00000000..a48d36e2 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/FunVoidN.java @@ -0,0 +1,64 @@ +package de.dhbwstuttgart.typeinference; + + +import java.util.Iterator; +import de.dhbwstuttgart.typeinference.Menge; + +import de.dhbwstuttgart.parser.JavaClassName; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; + +/** + * @see Spezifikation "Complete Typeinference in Java 8" von Martin Plümicke + * "interface FunN { R apply(T1 arg1, T2 arg2, ... , TN argN); }" + * @author A10023 - Andreas Stadelmeier + * + * Bemerkung: + * FunN ist ein RefType. Der RefType ist nicht mit einem FunNInterface verbunden. + * + */ +public class FunVoidN extends FunN { + + private Type R; + private Menge T; + + /** + * @author Andreas Stadelmeier, a10023 + * Benötigt für den Typinferenzalgorithmus für Java 8 + * Generiert einen RefType auf eine FunVoidN - Klasse. + * @param T + * @return + */ + public FunVoidN(Menge T) { + super(T); + this.name = new JavaClassName("FunVoid"+T.size()); + } + + /** + * Erstellt eine FunVoidN: + * FunN + * T1 - TparameterCount werden mit TypePlaceholdern besetzt. + * @param parameterCount + */ + public FunVoidN(int parameterCount) { + super(parameterCount); + this.name = new JavaClassName("FunVoid"+T.size()); + } + + /** + * Muss nach jeder Änderung von T oder R aufgerufen werden. + * Dabei werden bestimmte, von RefType geerbte, Parameter angepasst. Dies ist wichtig für den Typinferenzalgorithmus. + */ + private void calculateNewParalist(){ + Menge t = new Menge(); + if(T!=null)t.addAll(T); + this.set_ParaList(t); + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/FunVoidNInterface.java b/src/de/dhbwstuttgart/typeinference/FunVoidNInterface.java new file mode 100644 index 00000000..ad7d6108 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/FunVoidNInterface.java @@ -0,0 +1,64 @@ +package de.dhbwstuttgart.typeinference; + +import de.dhbwstuttgart.typeinference.Menge; + +import de.dhbwstuttgart.parser.JavaClassName; +import de.dhbwstuttgart.syntaxtree.Class; +import de.dhbwstuttgart.syntaxtree.modifier.Modifiers; +import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.assumptions.ClassAssumption; +import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; + +/** + * Stellt das Interface FunVoidN dar. + * @author janulrich + * + */ +public class FunVoidNInterface extends Class{ +//TODO: Diese Klasse sollte eigentlich von Interface erben + //TODO: getType muss einen Typ mit der ParameterListe zurückliefern. + + //private Menge gtvparalist; + + /** + * Ein FunN-Interface enthält nur eine Methode (namens apply). Ist also ein Funktionales Interface. + * @param N - Die Anzahl der Parameter der apply-Methode. Beispiel N = 1 ergibt R apply(T1 par1); + */ + public FunVoidNInterface(int N) { + super("FunVoid"+N, null, new Modifiers(), FunVoidNInterface.makeParaList(N)); + } + + private static Menge makeParaList(int n) { + Menge ret = new Menge<>(); + for(int i = 1; i<=n;i++){ + ret.add("T"+i); + } + return ret; + } + + /** + * @return Im Falle von einem FunN-Interface ist dies die apply-Methode + */ + @Override + public TypeAssumptions getPublicFieldAssumptions() { + //return super.getPublicFieldAssumptions(); + TypeAssumptions ret = new TypeAssumptions(); + ret.addAssumption(new MethodAssumption(this.getApplyFunction(), this)); + ret.addClassAssumption(new ClassAssumption(this)); + for(GenericTypeVar gtv : this.getGenericParameter())ret.addGenericVarAssumption(gtv); + return ret; + } + + /** + * Erstellt die nach Definition des Typinferenzalgorithmus von Martin Plümicke, in jedem FunN-Interface enthaltene apply-Methode + * @return + */ + private FunVoidNMethod getApplyFunction(){ + return new FunVoidNMethod(this.get_ParaList(),this); + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/FunVoidNMethod.java b/src/de/dhbwstuttgart/typeinference/FunVoidNMethod.java new file mode 100644 index 00000000..bf1d9f41 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/FunVoidNMethod.java @@ -0,0 +1,63 @@ +package de.dhbwstuttgart.typeinference; + +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.syntaxtree.type.Void; + +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.Class; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.misc.DeclId; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; + +public class FunVoidNMethod extends Method{ + /** + * + * @param N - Anzahl der Parameter (Beispiel: Fun2) + */ + public FunVoidNMethod(Menge paralist, Class parent){ + super(0); //Hat keinen Offset, da nur theoretisch gedachte Methode + int N = paralist.size(); + this.setType(new Void(this, -1)); + this.set_DeclId(new DeclId("apply")); + ParameterList pl = new ParameterList(); + Menge fpList = new Menge(); + for(int i = 0;i fpList = new Menge(); + for(int i = 1;i<=N;i++){ //Alle verbleibenden Elemente in der übergebenen paralist durchgehen. + DeclId paramName = new DeclId("T"+i); + FormalParameter parameter = new FormalParameter(paramName); + parameter.setType(TypePlaceholder.fresh(parameter)); + //parameter.set_DeclId(paramName); + fpList.add(parameter); + } + pl.formalparameter = fpList; + this.parameterlist = pl; + this.parserPostProcessing(new Class("Fun"+N, 0)); + } + */ + @Override + public TypeInsertPoint createTypeInsertPoint(TypePlaceholder tph, + ResultSet resultSet) { + return null; + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/Unify.java b/src/de/dhbwstuttgart/typeinference/unify/Unify.java index bd10be77..84a72188 100755 --- a/src/de/dhbwstuttgart/typeinference/unify/Unify.java +++ b/src/de/dhbwstuttgart/typeinference/unify/Unify.java @@ -696,7 +696,7 @@ public class Unify } SetView>> difference = Sets.difference(cartProduktSets, temp); log.debug("Ausgelöschte Constraints: "+difference.toString()); - //cartProduktSets = temp; + cartProduktSets = temp; /* Unifier filterUnify = (pairs)->{ String pairsString = pairs.toString(); diff --git a/test/plugindevelopment/TypeInsertTests/FunVoid.jav b/test/plugindevelopment/TypeInsertTests/FunVoid.jav new file mode 100644 index 00000000..2503977f --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/FunVoid.jav @@ -0,0 +1,5 @@ + +class FunTest{ + + funVoid = ()->{}; +} diff --git a/test/plugindevelopment/TypeInsertTests/FunVoid.java b/test/plugindevelopment/TypeInsertTests/FunVoid.java new file mode 100644 index 00000000..017b6b9f --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/FunVoid.java @@ -0,0 +1,19 @@ +package plugindevelopment.TypeInsertTests; + +import java.util.ArrayList; +import java.util.List; +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class FunVoid { + private static final String TEST_FILE = "FunVoid.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("TestIfStmt var"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + ArrayList l = new ArrayList(); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/MultipleTypesInsertTester.java b/test/plugindevelopment/TypeInsertTests/MultipleTypesInsertTester.java index 1dca7ed6..e0421943 100755 --- a/test/plugindevelopment/TypeInsertTests/MultipleTypesInsertTester.java +++ b/test/plugindevelopment/TypeInsertTests/MultipleTypesInsertTester.java @@ -106,5 +106,11 @@ public class MultipleTypesInsertTester extends TypeInsertTester{ for(String containString : mustContain){ TestCase.assertTrue("\""+containString+"\" muss in den inferierten Lösungen vorkommen",gesamterSrc.contains(containString)); } + try { + Files.write(Logger.getWholeLog().getBytes(),new File(rootDirectory+sourceFileToInfere+".log")); + } catch (IOException e) { + e.printStackTrace(); + TestCase.fail(); + } } }