Lambda-TYPE anpassen. Beginnen mit TypeInsert

This commit is contained in:
JanUlrich 2017-06-14 04:07:27 +02:00
parent 5f31150dc8
commit 7a337843e6
10 changed files with 155 additions and 43 deletions

View File

@ -8,6 +8,7 @@ import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typedeployment.TypeInsert;
import de.dhbwstuttgart.typedeployment.TypeInsertFactory; import de.dhbwstuttgart.typedeployment.TypeInsertFactory;
import de.dhbwstuttgart.typedeployment.TypeInsertPoint; import de.dhbwstuttgart.typedeployment.TypeInsertPoint;
import de.dhbwstuttgart.typeinference.ResultSet; import de.dhbwstuttgart.typeinference.ResultSet;
@ -28,7 +29,7 @@ public class JavaTXCompiler {
private List<SourceFile> sourceFiles = new ArrayList<>(); private List<SourceFile> sourceFiles = new ArrayList<>();
public List<TypeInsertPoint> getTypeInserts(File forFile){ public List<TypeInsert> getTypeInserts(File forFile){
ResultSet result = typeInference(); ResultSet result = typeInference();
for(SourceFile sf : sourceFiles){ for(SourceFile sf : sourceFiles){
if(sf.getFile().equals(forFile)){ if(sf.getFile().equals(forFile)){

View File

@ -150,7 +150,7 @@ public class UnifyTypeFactory {
public static RefTypeOrTPHOrWildcardOrGeneric convert(ReferenceType t, Map<String,TypePlaceholder> tphs) { public static RefTypeOrTPHOrWildcardOrGeneric convert(ReferenceType t, Map<String,TypePlaceholder> tphs) {
if(JavaClassName.Void.equals(t.getName()))return new Void(new NullToken()); 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; return ret;
} }

View File

@ -1,6 +1,9 @@
package de.dhbwstuttgart.syntaxtree.type; package de.dhbwstuttgart.syntaxtree.type;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.typecheck.JavaClassName;
import java.util.List; import java.util.List;
/** /**
@ -13,22 +16,17 @@ import java.util.List;
* *
*/ */
public class FunN extends RefType { public class FunN extends RefType {
private RefTypeOrTPHOrWildcardOrGeneric R;
private List<? extends RefTypeOrTPHOrWildcardOrGeneric> T;
/** /**
* @author Andreas Stadelmeier, a10023 * @author Andreas Stadelmeier, a10023
* BenÃtigt ¼r den Typinferenzalgorithmus ¼r Java 8 * BenÃtigt ¼r den Typinferenzalgorithmus ¼r Java 8
* Generiert einen RefType auf eine FunN<R,T1,...,TN> - Klasse. * Generiert einen RefType auf eine FunN<R,T1,...,TN> - Klasse.
* @param R * @param params
* @param T
* @return * @return
*/ */
public FunN(RefTypeOrTPHOrWildcardOrGeneric R, List<? extends RefTypeOrTPHOrWildcardOrGeneric> T) { public FunN(List<RefTypeOrTPHOrWildcardOrGeneric> params) {
super(null,null); super(new JavaClassName("Fun"+params.size()), params, new NullToken());
} }
/** /**
* Spezieller Konstruktor um eine FunN ohne Returntype zu generieren * Spezieller Konstruktor um eine FunN ohne Returntype zu generieren

View File

@ -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<TypeInsertPoint> inserts;
public TypeInsert(Token point, String toInsert){
inserts = new HashSet<>();
inserts.add(new TypeInsertPoint(point, toInsert));
}
public TypeInsert(Set<TypeInsertPoint> points){
inserts = points;
}
public String insert(String intoSource){
String ret = intoSource;
List<TypeInsertPoint> offsets = new ArrayList<>();
for(TypeInsertPoint insertPoint : inserts){
ret = insertPoint.insert(ret, offsets);
offsets.add(insertPoint);
}
return ret;
}
}

View File

@ -7,46 +7,98 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.ResultSet; import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import org.antlr.v4.runtime.Token;
import java.util.ArrayList; import java.util.*;
import java.util.List;
/** /**
* TODO: * TODO:
* Falls in Feldern Generics entstehen, dann werden diese als Klassenparameter eingesetzt * 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 * 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 class TypeInsertFactory {
public static List<TypeInsertPoint> createTypeInsertPoints(SourceFile forSourcefile, ResultSet withResults){ public static List<TypeInsert> createTypeInsertPoints(SourceFile forSourcefile, ResultSet withResults){
List<TypeInsertPoint> ret = new ArrayList<>(); List<TypeInsert> ret = new ArrayList<>();
for(ClassOrInterface cl : forSourcefile.getClasses()){ for(ClassOrInterface cl : forSourcefile.getClasses()){
//Felder: //Felder:
for(Field field : cl.getFieldDecl()){ for(Field field : cl.getFieldDecl()){
if(field.getType() instanceof TypePlaceholder){ if(field.getType() instanceof TypePlaceholder){
RefTypeOrTPHOrWildcardOrGeneric resolved = withResults.resolveType(field.getType()); for(Set<Pair> pairs : withResults.results)
String toInsert = getString(resolved) + " "; ret.add(new TypeInsert(createInsertPoints(
ret.add(new TypeInsertPoint(field.getType().getOffset(), toInsert)); field.getType(), field.getType().getOffset(), cl, null, pairs)));
} }
} }
for(Method m : cl.getMethods()){ for(Method m : cl.getMethods()){
RefTypeOrTPHOrWildcardOrGeneric resolved = withResults.resolveType(m.getReturnType()); for(Set<Pair> pairs : withResults.results)
String toInsert = getString(resolved) + " "; ret.add(new TypeInsert(createInsertPoints(
ret.add(new TypeInsertPoint(m.getReturnType().getOffset(), toInsert)); m.getReturnType(), m.getReturnType().getOffset(), cl, m, pairs)));
for(FormalParameter param : m.getParameterList().getFormalparalist()){ for(FormalParameter param : m.getParameterList().getFormalparalist()){
resolved = withResults.resolveType(param.getType()); for(Set<Pair> pairs : withResults.results)
toInsert = getString(resolved) + " "; ret.add(new TypeInsert(createInsertPoints(
ret.add(new TypeInsertPoint(param.getType().getOffset(), toInsert)); param.getType(), param.getType().getOffset(), cl, m, pairs)));
} }
} }
} }
return ret; return ret;
} }
private static String getString(RefTypeOrTPHOrWildcardOrGeneric resolved) { private static Set<TypeInsertPoint> createInsertPoints(RefTypeOrTPHOrWildcardOrGeneric type, Token offset, ClassOrInterface cl, Method m, Set<Pair> pairs) {
Set<TypeInsertPoint> 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<TypeInsertPoint> ret = new ArrayList<>();
TypeInsertPointCreator(RefTypeOrTPHOrWildcardOrGeneric type, Token offset){
this.type = type;
this.offset = offset;
}
public List<TypeInsertPoint> 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){ if(resolved instanceof RefType){
//TODO: Kontrollieren, ob der Reftype und seine Parameter bekannt sind, ansonsten auch einsetzen
return ((RefType) resolved).getName().toString(); return ((RefType) resolved).getName().toString();
}else if(resolved instanceof TypePlaceholder){ }else if(resolved instanceof TypePlaceholder){
return ((TypePlaceholder) resolved).getName(); return ((TypePlaceholder) resolved).getName();
@ -56,4 +108,4 @@ public class TypeInsertFactory {
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }
} }

View File

@ -2,16 +2,23 @@ package de.dhbwstuttgart.typedeployment;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
import java.util.List;
import java.util.stream.Collectors;
public class TypeInsertPoint { public class TypeInsertPoint {
Token point; Token point;
private String insertString; private String insertString;
public TypeInsertPoint(Token point, String toInsert){ public TypeInsertPoint(Token point, String toInsert){
this.point = point; this.point = point;
this.insertString = toInsert; this.insertString = toInsert + " ";
} }
public String insert(String intoSource){ public String insert(String intoSource, List<TypeInsertPoint> additionalOffset){
return new StringBuilder(intoSource).insert(point.getStartIndex(), insertString).toString(); 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();
} }
} }

View File

@ -7,30 +7,30 @@ import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator; import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import java.util.ArrayList;
import java.util.List;
import java.util.Set; import java.util.Set;
public class ResultSet { public class ResultSet {
Set<Set<Pair>> results; public final Set<Set<Pair>> results;
public ResultSet(Set<Set<Pair>> results){ public ResultSet(Set<Set<Pair>> results){
this.results = results; this.results = results;
} }
public RefTypeOrTPHOrWildcardOrGeneric resolveType(RefTypeOrTPHOrWildcardOrGeneric type) { public List<Pair> resolveType(RefTypeOrTPHOrWildcardOrGeneric type) {
/*//Probleme: /*//Probleme:
* Es müssen teilweise mehrere TPH eingesetzt werden * Es müssen teilweise mehrere TPH eingesetzt werden
* Es werden alle eingesetzt, welch in der Kette stehen! * Es werden alle eingesetzt, welch in der Kette stehen!
* TPHs müssen zu eindeutigen Namen aufgelöst werden * TPHs müssen zu eindeutigen Namen aufgelöst werden
*/ */
final RefTypeOrTPHOrWildcardOrGeneric ret; final List<Pair> ret = new ArrayList<>();
for(Set<Pair> pairs : results)for(Pair pair : pairs){ for(Set<Pair> pairs : results)for(Pair pair : pairs){
if(pair.OperatorEqual()){ //type ist vom Typ TypePlaceholder //if(pair.OperatorEqual()){ //type ist vom Typ TypePlaceholder
if(pair.TA1.equals(type)){ if(pair.TA1.equals(type) || pair.TA2.equals(type)){
return pair.TA2; ret.add(pair);
}else if(pair.TA2.equals(type)){
return pair.TA1;
}
} }
//}
} }
return type; return ret;
} }
} }

View File

@ -3,12 +3,15 @@ package de.dhbwstuttgart.typeinference.typeAlgo;
import com.sun.org.apache.xpath.internal.Arg; import com.sun.org.apache.xpath.internal.Arg;
import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.exceptions.TypeinferenceException; import de.dhbwstuttgart.exceptions.TypeinferenceException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.syntaxtree.statement.literal.Literal; import de.dhbwstuttgart.syntaxtree.statement.literal.Literal;
import de.dhbwstuttgart.syntaxtree.statement.literal.Null; import de.dhbwstuttgart.syntaxtree.statement.literal.Null;
import de.dhbwstuttgart.syntaxtree.type.FunN;
import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption; import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption;
import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
@ -19,6 +22,7 @@ import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator; import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
public class TYPE implements StatementVisitor{ public class TYPE implements StatementVisitor{
@ -35,18 +39,34 @@ public class TYPE implements StatementVisitor{
@Override @Override
public void visit(LambdaExpression lambdaExpression) { public void visit(LambdaExpression lambdaExpression) {
/*
List<MethodAssumption> methodAssumptionss = getMethods("apply", lambdaExpression.params.getFormalparalist().size(), info); List<MethodAssumption> methodAssumptionss = getMethods("apply", lambdaExpression.params.getFormalparalist().size(), info);
//TODO: Nur FunN-Interface als mögliche Typen verwenden //TODO: Nur FunN-Interface als mögliche Typen verwenden
//methodAssumptionss.stream().filter((methodAssumption -> methodAssumption.getReceiverType().getName().toString())) //methodAssumptionss.stream().filter((methodAssumption -> methodAssumption.getReceiverType().getName().toString()))
Set<Constraint> possibleLambdaTypes = new HashSet<>(); Set<Constraint> possibleLambdaTypes = new HashSet<>();
for(MethodAssumption mAss : methodAssumptionss){ for(MethodAssumption mAss : methodAssumptionss){
Constraint cons = new Constraint(); Constraint cons = new Constraint();
cons.add( cons.add(
ConstraintsFactory.createPair(lambdaExpression.methodBody.getType(),mAss.getReturnType(),info)); ConstraintsFactory.createPair(lambdaExpression.methodBody.getType(),mAss.getReturnType(),info));
cons.add( cons.add(
ConstraintsFactory.createPair(lambdaExpression.getType(),mAss.getReceiverType(),PairOperator.EQUALSDOT, info)); 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); constraintsSet.addOderConstraint(possibleLambdaTypes);
*/
TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken());
List<RefTypeOrTPHOrWildcardOrGeneric> 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: //Constraints des Bodys generieren:
TYPE lambdaScope = new TYPE(new TypeInferenceBlockInformation(info, lambdaExpression)); TYPE lambdaScope = new TYPE(new TypeInferenceBlockInformation(info, lambdaExpression));
lambdaExpression.methodBody.accept(lambdaScope); lambdaExpression.methodBody.accept(lambdaScope);

View File

@ -1,5 +1,4 @@
class Lambda{ class Lambda{
String var; String var;
methode(){ methode(){
@ -8,7 +7,10 @@ methode(){
return var; return var;
}; };
} }
}
interface Fun0<A>{
A apply();
} }
interface Fun1<A,B>{ interface Fun1<A,B>{

View File

@ -3,6 +3,7 @@ package typeinference;
import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.parser.ClassNotFoundException; import de.dhbwstuttgart.parser.ClassNotFoundException;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.typedeployment.TypeInsert;
import de.dhbwstuttgart.typedeployment.TypeInsertPoint; import de.dhbwstuttgart.typedeployment.TypeInsertPoint;
import de.dhbwstuttgart.typeinference.ResultSet; import de.dhbwstuttgart.typeinference.ResultSet;
import org.junit.Test; import org.junit.Test;
@ -35,9 +36,9 @@ public class JavaTXCompilerTest {
JavaTXCompiler compiler = new JavaTXCompiler(); JavaTXCompiler compiler = new JavaTXCompiler();
for(File f : filesToTest){ for(File f : filesToTest){
compiler.parse(f); compiler.parse(f);
List<TypeInsertPoint> result = compiler.getTypeInserts(f); List<TypeInsert> result = compiler.getTypeInserts(f);
String content = readFile(f.getPath(), StandardCharsets.UTF_8); String content = readFile(f.getPath(), StandardCharsets.UTF_8);
for(TypeInsertPoint tip : result){ for(TypeInsert tip : result){
System.out.println(tip.insert(content)); System.out.println(tip.insert(content));
} }
} }