From 7a337843e65199727eb1ea8bc68d92523f27a00b Mon Sep 17 00:00:00 2001 From: JanUlrich Date: Wed, 14 Jun 2017 04:07:27 +0200 Subject: [PATCH] Lambda-TYPE anpassen. Beginnen mit TypeInsert --- src/de/dhbwstuttgart/core/JavaTXCompiler.java | 3 +- .../syntaxtree/factory/UnifyTypeFactory.java | 2 +- .../dhbwstuttgart/syntaxtree/type/FunN.java | 16 ++-- .../typedeployment/TypeInsert.java | 31 +++++++ .../typedeployment/TypeInsertFactory.java | 84 +++++++++++++++---- .../typedeployment/TypeInsertPoint.java | 13 ++- .../typeinference/ResultSet.java | 20 ++--- .../typeinference/typeAlgo/TYPE.java | 20 +++++ test/javFiles/Lambda.jav | 4 +- test/typeinference/JavaTXCompilerTest.java | 5 +- 10 files changed, 155 insertions(+), 43 deletions(-) create mode 100644 src/de/dhbwstuttgart/typedeployment/TypeInsert.java diff --git a/src/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/de/dhbwstuttgart/core/JavaTXCompiler.java index 15430da87..f777727f2 100644 --- a/src/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -8,6 +8,7 @@ import de.dhbwstuttgart.syntaxtree.SourceFile; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typedeployment.TypeInsert; import de.dhbwstuttgart.typedeployment.TypeInsertFactory; import de.dhbwstuttgart.typedeployment.TypeInsertPoint; import de.dhbwstuttgart.typeinference.ResultSet; @@ -28,7 +29,7 @@ public class JavaTXCompiler { private List sourceFiles = new ArrayList<>(); - public List getTypeInserts(File forFile){ + public List getTypeInserts(File forFile){ ResultSet result = typeInference(); for(SourceFile sf : sourceFiles){ if(sf.getFile().equals(forFile)){ diff --git a/src/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java b/src/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java index be99fb7ca..3a5a3142b 100644 --- a/src/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java +++ b/src/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java @@ -150,7 +150,7 @@ public class UnifyTypeFactory { public static RefTypeOrTPHOrWildcardOrGeneric convert(ReferenceType t, Map tphs) { if(JavaClassName.Void.equals(t.getName()))return new Void(new NullToken()); - RefType ret = new RefType(JavaClassName.Void,convert(t.getTypeParams(), tphs),new NullToken()); + RefType ret = new RefType(new JavaClassName(t.getName()),convert(t.getTypeParams(), tphs),new NullToken()); return ret; } diff --git a/src/de/dhbwstuttgart/syntaxtree/type/FunN.java b/src/de/dhbwstuttgart/syntaxtree/type/FunN.java index 77083c004..d09100533 100755 --- a/src/de/dhbwstuttgart/syntaxtree/type/FunN.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/FunN.java @@ -1,6 +1,9 @@ package de.dhbwstuttgart.syntaxtree.type; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.typecheck.JavaClassName; + import java.util.List; /** @@ -13,22 +16,17 @@ import java.util.List; * */ public class FunN extends RefType { - - private RefTypeOrTPHOrWildcardOrGeneric R; - private List T; - /** * @author Andreas Stadelmeier, a10023 * Benötigt für den Typinferenzalgorithmus für Java 8 * Generiert einen RefType auf eine FunN - Klasse. - * @param R - * @param T + * @param params * @return */ - public FunN(RefTypeOrTPHOrWildcardOrGeneric R, List T) { - super(null,null); + public FunN(List params) { + super(new JavaClassName("Fun"+params.size()), params, new NullToken()); } - + /** * Spezieller Konstruktor um eine FunN ohne Returntype zu generieren diff --git a/src/de/dhbwstuttgart/typedeployment/TypeInsert.java b/src/de/dhbwstuttgart/typedeployment/TypeInsert.java new file mode 100644 index 000000000..f88e19049 --- /dev/null +++ b/src/de/dhbwstuttgart/typedeployment/TypeInsert.java @@ -0,0 +1,31 @@ +package de.dhbwstuttgart.typedeployment; + +import org.antlr.v4.runtime.Token; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TypeInsert { + Set inserts; + + public TypeInsert(Token point, String toInsert){ + inserts = new HashSet<>(); + inserts.add(new TypeInsertPoint(point, toInsert)); + } + + public TypeInsert(Set points){ + inserts = points; + } + + public String insert(String intoSource){ + String ret = intoSource; + List offsets = new ArrayList<>(); + for(TypeInsertPoint insertPoint : inserts){ + ret = insertPoint.insert(ret, offsets); + offsets.add(insertPoint); + } + return ret; + } +} diff --git a/src/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java b/src/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java index e07d299a9..8c2e1a829 100644 --- a/src/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java +++ b/src/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java @@ -7,46 +7,98 @@ import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import org.antlr.v4.runtime.Token; -import java.util.ArrayList; -import java.util.List; +import java.util.*; /** * TODO: * Falls in Feldern Generics entstehen, dann werden diese als Klassenparameter eingesetzt * Für die Instanzierung von Klassen kann man dann beispielsweise nur noch den Diamond-Operator verwenden + * + * Es müssen zu einem TPH alle in Beziehung stehenden Constraints gefunden werden */ public class TypeInsertFactory { - public static List createTypeInsertPoints(SourceFile forSourcefile, ResultSet withResults){ - List ret = new ArrayList<>(); + public static List createTypeInsertPoints(SourceFile forSourcefile, ResultSet withResults){ + List ret = new ArrayList<>(); for(ClassOrInterface cl : forSourcefile.getClasses()){ //Felder: for(Field field : cl.getFieldDecl()){ if(field.getType() instanceof TypePlaceholder){ - RefTypeOrTPHOrWildcardOrGeneric resolved = withResults.resolveType(field.getType()); - String toInsert = getString(resolved) + " "; - ret.add(new TypeInsertPoint(field.getType().getOffset(), toInsert)); + for(Set pairs : withResults.results) + ret.add(new TypeInsert(createInsertPoints( + field.getType(), field.getType().getOffset(), cl, null, pairs))); } } for(Method m : cl.getMethods()){ - RefTypeOrTPHOrWildcardOrGeneric resolved = withResults.resolveType(m.getReturnType()); - String toInsert = getString(resolved) + " "; - ret.add(new TypeInsertPoint(m.getReturnType().getOffset(), toInsert)); + for(Set pairs : withResults.results) + ret.add(new TypeInsert(createInsertPoints( + m.getReturnType(), m.getReturnType().getOffset(), cl, m, pairs))); for(FormalParameter param : m.getParameterList().getFormalparalist()){ - resolved = withResults.resolveType(param.getType()); - toInsert = getString(resolved) + " "; - ret.add(new TypeInsertPoint(param.getType().getOffset(), toInsert)); - + for(Set pairs : withResults.results) + ret.add(new TypeInsert(createInsertPoints( + param.getType(), param.getType().getOffset(), cl, m, pairs))); } } } return ret; } - private static String getString(RefTypeOrTPHOrWildcardOrGeneric resolved) { + private static Set createInsertPoints(RefTypeOrTPHOrWildcardOrGeneric type, Token offset, ClassOrInterface cl, Method m, Set pairs) { + Set ret = new HashSet<>(); + for(Pair pair : pairs){ + RefTypeOrTPHOrWildcardOrGeneric relatedType = null; + if(pair.TA1.equals(type) ){ + relatedType = pair.TA2; + } else if(pair.TA2.equals(type)){ + relatedType = pair.TA1; + } + if(relatedType != null){ + //Es wurde ein direkter Treffer gefunden: + if(pair.OperatorEqual()){ //type ist vom Typ TypePlaceholder + type = relatedType; + }else{ + ret.addAll(createInsertPoints(relatedType, offset, cl, m, pairs)); + } + } + } + ret.addAll(new TypeInsertPointCreator(type, offset).createPoints()); + return ret; + } +} + +class TypeInsertPointCreator{ + + private final RefTypeOrTPHOrWildcardOrGeneric type; + private final Token offset; + List ret = new ArrayList<>(); + + TypeInsertPointCreator(RefTypeOrTPHOrWildcardOrGeneric type, Token offset){ + this.type = type; + this.offset = offset; + } + + public List createPoints(){ + if(type instanceof RefType){ + RefType refType = ((RefType) type); + String insert = refType.getName().toString()+"<"; + for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){ + + } + insert += ">"; + ret.add(new TypeInsertPoint(offset, insert)); + }else { + ret.add(new TypeInsertPoint(offset, getInsertString(type))); + } + return ret; + } + + private String getInsertString(RefTypeOrTPHOrWildcardOrGeneric resolved) { if(resolved instanceof RefType){ + //TODO: Kontrollieren, ob der Reftype und seine Parameter bekannt sind, ansonsten auch einsetzen return ((RefType) resolved).getName().toString(); }else if(resolved instanceof TypePlaceholder){ return ((TypePlaceholder) resolved).getName(); @@ -56,4 +108,4 @@ public class TypeInsertFactory { throw new NotImplementedException(); } } -} +} \ No newline at end of file diff --git a/src/de/dhbwstuttgart/typedeployment/TypeInsertPoint.java b/src/de/dhbwstuttgart/typedeployment/TypeInsertPoint.java index e57422cfb..3a444c7d8 100644 --- a/src/de/dhbwstuttgart/typedeployment/TypeInsertPoint.java +++ b/src/de/dhbwstuttgart/typedeployment/TypeInsertPoint.java @@ -2,16 +2,23 @@ package de.dhbwstuttgart.typedeployment; import org.antlr.v4.runtime.Token; +import java.util.List; +import java.util.stream.Collectors; + public class TypeInsertPoint { Token point; private String insertString; public TypeInsertPoint(Token point, String toInsert){ this.point = point; - this.insertString = toInsert; + this.insertString = toInsert + " "; } - public String insert(String intoSource){ - return new StringBuilder(intoSource).insert(point.getStartIndex(), insertString).toString(); + public String insert(String intoSource, List additionalOffset){ + int offset = additionalOffset.stream().filter((token -> + //token.point.getLine() != point.getLine() && token.point.getCharPositionInLine() <= point.getCharPositionInLine())) + token.point.getStartIndex() <= point.getStartIndex())) + .mapToInt((typeInsertPoint -> typeInsertPoint.insertString.length())).sum(); + return new StringBuilder(intoSource).insert(point.getStartIndex()+offset, insertString).toString(); } } diff --git a/src/de/dhbwstuttgart/typeinference/ResultSet.java b/src/de/dhbwstuttgart/typeinference/ResultSet.java index 448905765..915fb81fc 100644 --- a/src/de/dhbwstuttgart/typeinference/ResultSet.java +++ b/src/de/dhbwstuttgart/typeinference/ResultSet.java @@ -7,30 +7,30 @@ import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.unify.model.PairOperator; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import java.util.ArrayList; +import java.util.List; import java.util.Set; public class ResultSet { - Set> results; + public final Set> results; public ResultSet(Set> results){ this.results = results; } - public RefTypeOrTPHOrWildcardOrGeneric resolveType(RefTypeOrTPHOrWildcardOrGeneric type) { + public List resolveType(RefTypeOrTPHOrWildcardOrGeneric type) { /*//Probleme: * Es müssen teilweise mehrere TPH eingesetzt werden * Es werden alle eingesetzt, welch in der Kette stehen! * TPHs müssen zu eindeutigen Namen aufgelöst werden */ - final RefTypeOrTPHOrWildcardOrGeneric ret; + final List ret = new ArrayList<>(); for(Set pairs : results)for(Pair pair : pairs){ - if(pair.OperatorEqual()){ //type ist vom Typ TypePlaceholder - if(pair.TA1.equals(type)){ - return pair.TA2; - }else if(pair.TA2.equals(type)){ - return pair.TA1; - } + //if(pair.OperatorEqual()){ //type ist vom Typ TypePlaceholder + if(pair.TA1.equals(type) || pair.TA2.equals(type)){ + ret.add(pair); } + //} } - return type; + return ret; } } diff --git a/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPE.java b/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPE.java index ae1c69529..cb5128134 100644 --- a/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPE.java +++ b/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPE.java @@ -3,12 +3,15 @@ package de.dhbwstuttgart.typeinference.typeAlgo; import com.sun.org.apache.xpath.internal.Arg; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.exceptions.TypeinferenceException; +import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.statement.literal.Literal; import de.dhbwstuttgart.syntaxtree.statement.literal.Null; +import de.dhbwstuttgart.syntaxtree.type.FunN; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption; import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; @@ -19,6 +22,7 @@ import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.unify.model.PairOperator; import java.util.*; +import java.util.stream.Collectors; public class TYPE implements StatementVisitor{ @@ -35,18 +39,34 @@ public class TYPE implements StatementVisitor{ @Override public void visit(LambdaExpression lambdaExpression) { + /* List methodAssumptionss = getMethods("apply", lambdaExpression.params.getFormalparalist().size(), info); //TODO: Nur FunN-Interface als mögliche Typen verwenden //methodAssumptionss.stream().filter((methodAssumption -> methodAssumption.getReceiverType().getName().toString())) Set possibleLambdaTypes = new HashSet<>(); + for(MethodAssumption mAss : methodAssumptionss){ Constraint cons = new Constraint(); cons.add( ConstraintsFactory.createPair(lambdaExpression.methodBody.getType(),mAss.getReturnType(),info)); cons.add( ConstraintsFactory.createPair(lambdaExpression.getType(),mAss.getReceiverType(),PairOperator.EQUALSDOT, info)); + possibleLambdaTypes.add(cons); } + if(methodAssumptionss.size() == 0)throw new TypeinferenceException("Kein passendes Funktionales Interface für Lambda Ausdruck gefunden", lambdaExpression.getOffset()); + constraintsSet.addOderConstraint(possibleLambdaTypes); + */ + TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken()); + List lambdaParams = lambdaExpression.params.getFormalparalist().stream().map((formalParameter -> formalParameter.getType())).collect(Collectors.toList()); + lambdaParams.add(tphRetType); + constraintsSet.addUndConstraint( + ConstraintsFactory.createPair(lambdaExpression.getType(), + new FunN(lambdaParams),PairOperator.EQUALSDOT,info)); + constraintsSet.addUndConstraint( + ConstraintsFactory.createPair(lambdaExpression.getReturnType(), + tphRetType,info)); + //Constraints des Bodys generieren: TYPE lambdaScope = new TYPE(new TypeInferenceBlockInformation(info, lambdaExpression)); lambdaExpression.methodBody.accept(lambdaScope); diff --git a/test/javFiles/Lambda.jav b/test/javFiles/Lambda.jav index 998dbe3bb..6ec358b3c 100644 --- a/test/javFiles/Lambda.jav +++ b/test/javFiles/Lambda.jav @@ -1,5 +1,4 @@ class Lambda{ - String var; methode(){ @@ -8,7 +7,10 @@ methode(){ return var; }; } +} +interface Fun0{ + A apply(); } interface Fun1{ diff --git a/test/typeinference/JavaTXCompilerTest.java b/test/typeinference/JavaTXCompilerTest.java index 4bd02ba62..975e5928e 100644 --- a/test/typeinference/JavaTXCompilerTest.java +++ b/test/typeinference/JavaTXCompilerTest.java @@ -3,6 +3,7 @@ package typeinference; import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.parser.ClassNotFoundException; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import de.dhbwstuttgart.typedeployment.TypeInsert; import de.dhbwstuttgart.typedeployment.TypeInsertPoint; import de.dhbwstuttgart.typeinference.ResultSet; import org.junit.Test; @@ -35,9 +36,9 @@ public class JavaTXCompilerTest { JavaTXCompiler compiler = new JavaTXCompiler(); for(File f : filesToTest){ compiler.parse(f); - List result = compiler.getTypeInserts(f); + List result = compiler.getTypeInserts(f); String content = readFile(f.getPath(), StandardCharsets.UTF_8); - for(TypeInsertPoint tip : result){ + for(TypeInsert tip : result){ System.out.println(tip.insert(content)); } }