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.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<SourceFile> sourceFiles = new ArrayList<>();
public List<TypeInsertPoint> getTypeInserts(File forFile){
public List<TypeInsert> getTypeInserts(File forFile){
ResultSet result = typeInference();
for(SourceFile sf : sourceFiles){
if(sf.getFile().equals(forFile)){

View File

@ -150,7 +150,7 @@ public class UnifyTypeFactory {
public static RefTypeOrTPHOrWildcardOrGeneric convert(ReferenceType t, Map<String,TypePlaceholder> 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;
}

View File

@ -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<? extends RefTypeOrTPHOrWildcardOrGeneric> T;
/**
* @author Andreas Stadelmeier, a10023
* BenÃtigt ¼r den Typinferenzalgorithmus ¼r Java 8
* Generiert einen RefType auf eine FunN<R,T1,...,TN> - Klasse.
* @param R
* @param T
* @param params
* @return
*/
public FunN(RefTypeOrTPHOrWildcardOrGeneric R, List<? extends RefTypeOrTPHOrWildcardOrGeneric> T) {
super(null,null);
public FunN(List<RefTypeOrTPHOrWildcardOrGeneric> params) {
super(new JavaClassName("Fun"+params.size()), params, new NullToken());
}
/**
* 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.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<TypeInsertPoint> createTypeInsertPoints(SourceFile forSourcefile, ResultSet withResults){
List<TypeInsertPoint> ret = new ArrayList<>();
public static List<TypeInsert> createTypeInsertPoints(SourceFile forSourcefile, ResultSet withResults){
List<TypeInsert> 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<Pair> 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<Pair> 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<Pair> 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<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){
//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();
}
}
}
}

View File

@ -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<TypeInsertPoint> 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();
}
}

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.UnifyPair;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class ResultSet {
Set<Set<Pair>> results;
public final Set<Set<Pair>> results;
public ResultSet(Set<Set<Pair>> results){
this.results = results;
}
public RefTypeOrTPHOrWildcardOrGeneric resolveType(RefTypeOrTPHOrWildcardOrGeneric type) {
public List<Pair> 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<Pair> ret = new ArrayList<>();
for(Set<Pair> 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;
}
}

View File

@ -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<MethodAssumption> 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<Constraint> 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<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:
TYPE lambdaScope = new TYPE(new TypeInferenceBlockInformation(info, lambdaExpression));
lambdaExpression.methodBody.accept(lambdaScope);

View File

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

View File

@ -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<TypeInsertPoint> result = compiler.getTypeInserts(f);
List<TypeInsert> 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));
}
}