Unvollständiger Stand bei der Implementierung von Generics

This commit is contained in:
JanUlrich 2017-09-22 18:31:47 +02:00
parent 0e2390a80a
commit 6a1f5dc248
9 changed files with 48 additions and 17 deletions

View File

@ -137,7 +137,7 @@ public class SyntaxTreeGenerator{
Java8Parser.MethodHeaderContext header = methodDeclarationContext.methodHeader(); Java8Parser.MethodHeaderContext header = methodDeclarationContext.methodHeader();
int modifiers = SyntaxTreeGenerator.convert(methodDeclarationContext.methodModifier()); int modifiers = SyntaxTreeGenerator.convert(methodDeclarationContext.methodModifier());
GenericsRegistry localGenerics = createGenerics(methodDeclarationContext.methodHeader().typeParameters(), GenericsRegistry localGenerics = createGenerics(methodDeclarationContext.methodHeader().typeParameters(),
parentClass, header.methodDeclarator().Identifier().getText()); parentClass, header.methodDeclarator().Identifier().getText(), reg, generics);
localGenerics.putAll(generics); localGenerics.putAll(generics);
return convert(modifiers, header, methodDeclarationContext.methodBody(),parentClass, superClass, localGenerics); return convert(modifiers, header, methodDeclarationContext.methodBody(),parentClass, superClass, localGenerics);
} }
@ -146,7 +146,7 @@ public class SyntaxTreeGenerator{
Java8Parser.MethodHeaderContext header = ctx.methodHeader(); Java8Parser.MethodHeaderContext header = ctx.methodHeader();
int modifiers = SyntaxTreeGenerator.convertInterfaceModifier(ctx.interfaceMethodModifier()); int modifiers = SyntaxTreeGenerator.convertInterfaceModifier(ctx.interfaceMethodModifier());
GenericsRegistry localGenerics = createGenerics(header.typeParameters(), parentClass, header.methodDeclarator().Identifier().getText()); GenericsRegistry localGenerics = createGenerics(header.typeParameters(), parentClass, header.methodDeclarator().Identifier().getText(), reg, generics);
localGenerics.putAll(generics); localGenerics.putAll(generics);
return convert(modifiers, header, ctx.methodBody(),parentClass, superClass, localGenerics); return convert(modifiers, header, ctx.methodBody(),parentClass, superClass, localGenerics);
@ -209,7 +209,7 @@ public class SyntaxTreeGenerator{
} }
} }
JavaClassName name = reg.getName(ctx.Identifier().getText()); JavaClassName name = reg.getName(ctx.Identifier().getText());
GenericsRegistry generics = createGenerics(ctx.typeParameters(), name, ""); GenericsRegistry generics = createGenerics(ctx.typeParameters(), name, "", reg, new GenericsRegistry(globalGenerics));
Token offset = ctx.getStart(); Token offset = ctx.getStart();
GenericDeclarationList genericClassParameters; GenericDeclarationList genericClassParameters;
if(ctx.typeParameters() == null){ if(ctx.typeParameters() == null){
@ -412,7 +412,7 @@ public class SyntaxTreeGenerator{
} }
JavaClassName name = reg.getName(ctx.Identifier().getText()); JavaClassName name = reg.getName(ctx.Identifier().getText());
GenericsRegistry generics = createGenerics(ctx.typeParameters(), name, ""); GenericsRegistry generics = createGenerics(ctx.typeParameters(), name, "", reg, new GenericsRegistry(globalGenerics));
GenericDeclarationList genericParams; GenericDeclarationList genericParams;
if(ctx.typeParameters() != null){ if(ctx.typeParameters() != null){
@ -438,8 +438,9 @@ public class SyntaxTreeGenerator{
return new GenericDeclarationList(new ArrayList<>(), gtvOffset); return new GenericDeclarationList(new ArrayList<>(), gtvOffset);
} }
private GenericsRegistry createGenerics(Java8Parser.TypeParametersContext ctx, JavaClassName parentClass, String parentMethod) { private GenericsRegistry createGenerics(Java8Parser.TypeParametersContext ctx, JavaClassName parentClass, String parentMethod, JavaClassRegistry reg, GenericsRegistry generics) {
GenericsRegistry ret = new GenericsRegistry(this.globalGenerics); GenericsRegistry ret = new GenericsRegistry(this.globalGenerics);
ret.putAll(generics);
if(ctx == null || ctx.typeParameterList() == null)return ret; if(ctx == null || ctx.typeParameterList() == null)return ret;
for(Java8Parser.TypeParameterContext tp : ctx.typeParameterList().typeParameter()){ for(Java8Parser.TypeParameterContext tp : ctx.typeParameterList().typeParameter()){
TypeGenerator.convert(tp, parentClass, parentMethod, reg, ret); TypeGenerator.convert(tp, parentClass, parentMethod, reg, ret);

View File

@ -69,6 +69,8 @@ public class TypeGenerator {
public static GenericTypeVar convert(Java8Parser.TypeParameterContext typeParameter, JavaClassName parentClass, String parentMethod, JavaClassRegistry reg, GenericsRegistry generics) { public static GenericTypeVar convert(Java8Parser.TypeParameterContext typeParameter, JavaClassName parentClass, String parentMethod, JavaClassRegistry reg, GenericsRegistry generics) {
String name = typeParameter.Identifier().getText(); String name = typeParameter.Identifier().getText();
//TODO: Es müssen erst alle GenericTypeVars generiert werden, dann können die bounds dieser Generics ermittelt werden
//Problem <A extends B, B> ist erlaubt, würde aber bei den Bounds von A den Generic B nicht als solchen erkennen
List<RefTypeOrTPHOrWildcardOrGeneric> bounds = TypeGenerator.convert(typeParameter.typeBound(),reg, generics); List<RefTypeOrTPHOrWildcardOrGeneric> bounds = TypeGenerator.convert(typeParameter.typeBound(),reg, generics);
GenericTypeVar ret = new GenericTypeVar(new GenericTypeName(new GenericContext(parentClass, parentMethod), name), bounds, typeParameter.getStart(), typeParameter.getStop()); GenericTypeVar ret = new GenericTypeVar(new GenericTypeName(new GenericContext(parentClass, parentMethod), name), bounds, typeParameter.getStart(), typeParameter.getStop());
@ -83,7 +85,7 @@ public class TypeGenerator {
return ret; return ret;
} }
if(typeBoundContext.typeVariable() != null){ if(typeBoundContext.typeVariable() != null){
ret.add(convert(typeBoundContext.typeVariable())); ret.add(convertTypeName(typeBoundContext.typeVariable().Identifier().getText(), null, typeBoundContext.typeVariable().getStart(), reg, generics));
return ret; return ret;
} }
if(typeBoundContext.classOrInterfaceType() != null){ if(typeBoundContext.classOrInterfaceType() != null){
@ -106,10 +108,6 @@ public class TypeGenerator {
throw new NotImplementedException(); throw new NotImplementedException();
} }
private static RefTypeOrTPHOrWildcardOrGeneric convert(Java8Parser.TypeVariableContext typeVariableContext) {
throw new NotImplementedException();
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(Java8Parser.ReferenceTypeContext referenceTypeContext, JavaClassRegistry reg, GenericsRegistry generics) { public static RefTypeOrTPHOrWildcardOrGeneric convert(Java8Parser.ReferenceTypeContext referenceTypeContext, JavaClassRegistry reg, GenericsRegistry generics) {
return convertTypeName(referenceTypeContext.getText(), referenceTypeContext.getStart(), reg, generics); return convertTypeName(referenceTypeContext.getText(), referenceTypeContext.getStart(), reg, generics);
} }

View File

@ -3,6 +3,7 @@ package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.core.IItemWithOffset; import de.dhbwstuttgart.core.IItemWithOffset;
import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.typeinference.constraints.Constraint; import de.dhbwstuttgart.typeinference.constraints.Constraint;
@ -63,7 +64,13 @@ public class ClassOrInterface extends SyntaxTreeNode {
} }
public static RefType generateTypeOfClass(JavaClassName name, GenericDeclarationList genericsOfClass ,Token offset){ public static RefType generateTypeOfClass(JavaClassName name, GenericDeclarationList genericsOfClass ,Token offset){
return new RefType(name, offset); //Hier wird immer ein generischer Typ generiert, also mit Type placeholdern
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for(GenericTypeVar genericTypeVar : genericsOfClass){
//params.add(genericTypeVar.getTypePlaceholder());
params.add(TypePlaceholder.fresh(offset));
}
return new RefType(name, params, offset);
} }
public RefTypeOrTPHOrWildcardOrGeneric getSuperClass() { public RefTypeOrTPHOrWildcardOrGeneric getSuperClass() {

View File

@ -9,6 +9,7 @@ import org.antlr.v4.runtime.Token;
public class GenericRefType extends RefTypeOrTPHOrWildcardOrGeneric public class GenericRefType extends RefTypeOrTPHOrWildcardOrGeneric
{ {
private GenericTypeName name; private GenericTypeName name;
public GenericRefType(GenericTypeName name, Token offset) public GenericRefType(GenericTypeName name, Token offset)
{ {
super(offset); super(offset);

View File

@ -30,7 +30,7 @@ public class RefType extends RefTypeOrTPHOrWildcardOrGeneric
public RefType(JavaClassName fullyQualifiedName, Token offset) public RefType(JavaClassName fullyQualifiedName, Token offset)
{ {
this(fullyQualifiedName, null, offset); this(fullyQualifiedName, new ArrayList<>(), offset);
} }
@Override @Override

View File

@ -29,7 +29,8 @@ public class ConstraintsFactory {
} }
} }
//Nicht in den Generics in diesem Kontext enthalten: //Nicht in den Generics in diesem Kontext enthalten:
return TypePlaceholder.fresh(type.getOffset()); TypePlaceholder ret = TypePlaceholder.fresh(type.getOffset());
return ret;
}else{ }else{
return type; return type;
} }

View File

@ -167,27 +167,31 @@ class RelatedTypeWalker implements ResultSetVisitor {
/** /**
* Läuft über das resultSet und speichert alle TPHs, welche mit start in Verbindung stehen * Läuft über das resultSet und speichert alle TPHs, welche mit start in Verbindung stehen
* @param start * @param start - kann null sein, wenn der Walker für einen RefType benutzt wird
* @param resultSet * @param resultSet
*/ */
RelatedTypeWalker(TypePlaceholder start, ResultSet resultSet){ RelatedTypeWalker(TypePlaceholder start, ResultSet resultSet){
this.toResolve = start; this.toResolve = start;
this.resultSet = resultSet; this.resultSet = resultSet;
int resolved = 0;
do{
resolved = relatedTPHs.size();
for(ResultPair p : resultSet.results){ for(ResultPair p : resultSet.results){
p.accept(this); p.accept(this);
p.accept(this); p.accept(this);
} }
}while(resolved - relatedTPHs.size() > 0);
} }
@Override @Override
public void visit(PairTPHsmallerTPH p) { public void visit(PairTPHsmallerTPH p) {
if(p.getRight().equals(toResolve)){ if(p.getRight().equals(toResolve)){
relatedTPHs.addAll(new TPHResolver(p.right, resultSet).resolved); relatedTPHs.addAll(new TPHResolver(p.right, resultSet).resolved);
relatedTPHs.addAll(new RelatedTypeWalker(p.right, resultSet).relatedTPHs); //relatedTPHs.addAll(new RelatedTypeWalker(p.right, resultSet).relatedTPHs);
} }
if(p.getLeft().equals(toResolve)){ if(p.getLeft().equals(toResolve)){
relatedTPHs.addAll(new TPHResolver(p.left, resultSet).resolved); relatedTPHs.addAll(new TPHResolver(p.left, resultSet).resolved);
relatedTPHs.addAll(new RelatedTypeWalker(p.left, resultSet).relatedTPHs); //relatedTPHs.addAll(new RelatedTypeWalker(p.left, resultSet).relatedTPHs);
} }
} }
@ -200,6 +204,7 @@ class RelatedTypeWalker implements ResultSetVisitor {
/* /*
Die folgenden Funktionen fügen alle TPHs an die relatedTPHs an, denen sie begegnen: Die folgenden Funktionen fügen alle TPHs an die relatedTPHs an, denen sie begegnen:
Das wird verwendet, wenn alle relatedTPHs aus den Parametern eines RefTypes angefügt werden sollen
*/ */
@Override @Override

View File

@ -295,6 +295,15 @@ public class TYPEStmt implements StatementVisitor{
} }
protected static List<RefTypeOrTPHOrWildcardOrGeneric> convertParams(ParameterList parameterList, TypeInferenceBlockInformation info){ protected static List<RefTypeOrTPHOrWildcardOrGeneric> convertParams(ParameterList parameterList, TypeInferenceBlockInformation info){
//TODO: Hier müssen die Parameter mit den TPHs in den GEnerics des Receivers verknüpft werden
/*
BEispiel:
auto test = new List<String>();
test.add("hallo");
Hier kriegt der Receiver ja den COnstraint TPH REceiver <. List<TPH A>
Dann mus bei dem Parameter der COnstraint entstehen: TPH A <. String
*/
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>(); List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for(FormalParameter fp : parameterList.getFormalparalist()){ for(FormalParameter fp : parameterList.getFormalparalist()){
params.add(info.checkGTV(fp.getType())); params.add(info.checkGTV(fp.getType()));
@ -308,7 +317,7 @@ public class TYPEStmt implements StatementVisitor{
if(cl.getClassName().equals(ofType.getName())){ if(cl.getClassName().equals(ofType.getName())){
for(Method m : cl.getConstructors()){ for(Method m : cl.getConstructors()){
if(m.getParameterList().getFormalparalist().size() == argList.getArguments().size()){ if(m.getParameterList().getFormalparalist().size() == argList.getArguments().size()){
ret.add(new MethodAssumption(ofType, ofType, convertParams(m.getParameterList(), info))); ret.add(new MethodAssumption(cl.getType(), ofType, convertParams(m.getParameterList(), info)));
} }
} }
} }

View File

@ -10,3 +10,12 @@ class Test {
return new Generics<String>().mt1(s,s); return new Generics<String>().mt1(s,s);
} }
} }
/*
Problem:
auto test = new List<String>();
auto test2 = new List<Integer>();
... //code, welcher möglicherweise test und test2 vertauscht
test.add("hallo");
*/