Logik für Generics implementieren. Unvollständig

This commit is contained in:
JanUlrich 2017-09-25 01:14:02 +02:00
parent 6a1f5dc248
commit b31da88902
13 changed files with 195 additions and 73 deletions

View File

@ -1,6 +1,7 @@
package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.core.IItemWithOffset;
import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
@ -17,7 +18,7 @@ import java.util.List;
/**
* Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces
*/
public class ClassOrInterface extends SyntaxTreeNode {
public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
protected int modifiers;
protected JavaClassName name;
private List<Field> fields = new ArrayList<>();
@ -81,6 +82,11 @@ public class ClassOrInterface extends SyntaxTreeNode {
return this.genericClassParameters;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
return null;
}
public List<Constructor> getConstructors() {
return constructors;
}

View File

@ -3,13 +3,12 @@ package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
public class Field extends SyntaxTreeNode{
import java.util.ArrayList;
public class Field extends SyntaxTreeNode implements TypeScope{
private String name;
private RefTypeOrTPHOrWildcardOrGeneric type;
private GenericDeclarationList genericParameters;
public Field(String name, RefTypeOrTPHOrWildcardOrGeneric type, int modifier, Token offset){
super(offset);
@ -29,5 +28,15 @@ public class Field extends SyntaxTreeNode{
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
@Override
public Iterable<? extends GenericTypeVar> getGenerics() {
return new ArrayList<>();
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
return type;
}
}

View File

@ -22,7 +22,7 @@ import de.dhbwstuttgart.syntaxtree.statement.Block;
* @author janulrich
*
*/
public class Method extends Field implements IItemWithOffset, TypeScope
public class Method extends Field implements IItemWithOffset
{
public final Block block;
private ParameterList parameterlist = new ParameterList(new ArrayList<>(), new NullToken());

View File

@ -0,0 +1,15 @@
package de.dhbwstuttgart.typeinference.assumptions;
import de.dhbwstuttgart.syntaxtree.TypeScope;
public class Assumption {
private final TypeScope typeScope;
public Assumption(TypeScope typeScope) {
this.typeScope = typeScope;
}
public TypeScope getTypeScope() {
return typeScope;
}
}

View File

@ -1,13 +1,15 @@
package de.dhbwstuttgart.typeinference.assumptions;
import de.dhbwstuttgart.syntaxtree.TypeScope;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
public class FieldAssumption {
public class FieldAssumption extends Assumption{
private RefTypeOrTPHOrWildcardOrGeneric receiverType;
private RefTypeOrTPHOrWildcardOrGeneric type;
public FieldAssumption(RefTypeOrTPHOrWildcardOrGeneric receiverType,
RefTypeOrTPHOrWildcardOrGeneric type){
RefTypeOrTPHOrWildcardOrGeneric type, TypeScope scope){
super(scope);
this.type = type;
this.receiverType = receiverType;
}

View File

@ -1,18 +1,22 @@
package de.dhbwstuttgart.typeinference.assumptions;
import de.dhbwstuttgart.syntaxtree.ParameterList;
import de.dhbwstuttgart.syntaxtree.TypeScope;
import de.dhbwstuttgart.syntaxtree.statement.Assign;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import java.util.List;
import java.util.stream.Collectors;
public class MethodAssumption {
public class MethodAssumption extends Assumption{
private RefType receiver;
private RefTypeOrTPHOrWildcardOrGeneric retType;
List<RefTypeOrTPHOrWildcardOrGeneric> params;
public MethodAssumption(RefType receiver, RefTypeOrTPHOrWildcardOrGeneric retType, List<RefTypeOrTPHOrWildcardOrGeneric> params){
public MethodAssumption(RefType receiver, RefTypeOrTPHOrWildcardOrGeneric retType,
List<RefTypeOrTPHOrWildcardOrGeneric> params, TypeScope scope){
super(scope);
this.receiver = receiver;
this.retType = retType;
this.params = params;

View File

@ -33,28 +33,4 @@ public class TypeInferenceBlockInformation extends TypeInferenceInformation {
public TypeScope getCurrentTypeScope() {
return methodContext;
}
private class TypeScopeContainer implements TypeScope{
ArrayList<TypeScope> scopes = new ArrayList<>();
Stack<RefTypeOrTPHOrWildcardOrGeneric> types = new Stack<>();
public TypeScopeContainer(TypeScope scope1, TypeScope scope2){
scopes.add(scope1);
scopes.add(scope2);
types.push(scope1.getReturnType());
types.push(scope2.getReturnType());
}
public void add(TypeScope scope){
}
@Override
public Iterable<? extends GenericTypeVar> getGenerics() {
return Iterables.concat(scopes.stream().
map(TypeScope::getGenerics).collect(Collectors.toList()).toArray(new Iterable[0]));
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
return types.peek();
}
}
}

View File

@ -45,7 +45,7 @@ public class TypeInferenceInformation {
for(ClassOrInterface cl : classes){
for(Field m : cl.getFieldDecl()){
if(m.getName().equals(name)){
ret.add(new FieldAssumption(cl.getType(), checkGTV(m.getType())));
ret.add(new FieldAssumption(cl.getType(), checkGTV(m.getType()), new TypeScopeContainer(cl, m)));
}
}
}

View File

@ -0,0 +1,32 @@
package de.dhbwstuttgart.typeinference.assumptions;
import com.google.common.collect.Iterables;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.TypeScope;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import java.util.ArrayList;
import java.util.Stack;
import java.util.stream.Collectors;
public class TypeScopeContainer implements TypeScope {
ArrayList<TypeScope> scopes = new ArrayList<>();
Stack<RefTypeOrTPHOrWildcardOrGeneric> types = new Stack<>();
public TypeScopeContainer(TypeScope scope1, TypeScope scope2){
scopes.add(scope1);
scopes.add(scope2);
types.push(scope1.getReturnType());
types.push(scope2.getReturnType());
}
@Override
public Iterable<? extends GenericTypeVar> getGenerics() {
return Iterables.concat(scopes.stream().
map(TypeScope::getGenerics).collect(Collectors.toList()).toArray(new Iterable[0]));
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
return types.peek();
}
}

View File

@ -1,6 +1,8 @@
package de.dhbwstuttgart.typeinference.constraints;
import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.TypeScope;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
@ -9,27 +11,44 @@ import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ConstraintsFactory {
public static Pair createPair(RefTypeOrTPHOrWildcardOrGeneric t1, RefTypeOrTPHOrWildcardOrGeneric t2, PairOperator equalsdot, TypeInferenceBlockInformation info){
//Check whether Generics are in the same class:
return new Pair(checkGeneric(t1, info), checkGeneric(t2, info), equalsdot);
public static Pair createPair(RefTypeOrTPHOrWildcardOrGeneric t1, RefTypeOrTPHOrWildcardOrGeneric t2,
PairOperator equalsdot, TypeScope currentScope, TypeScope additionalScope,
GenericsResolver resolver){
//Check whether Generics are in the same class and resolve all other generics:
return new Pair(checkGeneric(t1, currentScope, additionalScope,resolver),
checkGeneric(t2, currentScope,additionalScope, resolver), equalsdot);
}
public static Pair createPair(RefTypeOrTPHOrWildcardOrGeneric t1,
RefTypeOrTPHOrWildcardOrGeneric t2, TypeInferenceBlockInformation info){
return createPair(t1,t2,PairOperator.SMALLERDOT, info);
RefTypeOrTPHOrWildcardOrGeneric t2, TypeScope currentScope, TypeScope additionalScope,
GenericsResolver resolver){
return createPair(t1,t2,PairOperator.SMALLERDOT, currentScope, additionalScope, resolver);
}
private static RefTypeOrTPHOrWildcardOrGeneric checkGeneric(RefTypeOrTPHOrWildcardOrGeneric type, TypeInferenceBlockInformation info){
private static RefTypeOrTPHOrWildcardOrGeneric checkGeneric(RefTypeOrTPHOrWildcardOrGeneric type,
TypeScope currentScope, TypeScope additionalScope,
GenericsResolver resolver){
if(type instanceof GenericRefType){
for(GenericTypeVar genericTypeVar : info.getCurrentTypeScope().getGenerics()){
//TODO: Für Generics müssen auch noch Constraints generiert werden
for(GenericTypeVar genericTypeVar : currentScope.getGenerics()){
if(genericTypeVar.getName().equals(((GenericRefType)type).getName())){
return new RefType(((GenericRefType)type).getName(),type.getOffset());
}
}
//Nicht in den Generics in diesem Kontext enthalten:
TypePlaceholder ret = TypePlaceholder.fresh(type.getOffset());
TypePlaceholder ret = null;
for(GenericTypeVar genericTypeVar : additionalScope.getGenerics()){
if(genericTypeVar.getName().equals(((GenericRefType)type).getName())){
ret = resolver.resolve(genericTypeVar);
}
}
if(ret == null)
throw new DebugException("Der Generic " + ((GenericRefType) type).getName() + " kommt in keine TypeScope vor!");
return ret;
}else{
return type;

View File

@ -0,0 +1,12 @@
package de.dhbwstuttgart.typeinference.constraints;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
/**
* Wird für Generics benötigt
* TODO: Erklörung!
*/
public interface GenericsResolver {
public TypePlaceholder resolve(GenericTypeVar generic);
}

View File

@ -6,6 +6,7 @@ import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.exceptions.TypeinferenceException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.GenericsRegistry;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.syntaxtree.statement.literal.Literal;
@ -17,16 +18,10 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption;
import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.ConstraintsFactory;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.constraints.*;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
public class TYPEStmt implements StatementVisitor{
@ -42,6 +37,20 @@ public class TYPEStmt implements StatementVisitor{
return constraintsSet;
}
private static GenericsResolver getResolverInstance(){
Map<GenericTypeVar, TypePlaceholder> map = new HashMap<>();
return generic -> {
if(map.containsKey(generic))return map.get(generic);
TypePlaceholder ret = TypePlaceholder.fresh(generic.getOffset());
map.put(generic, ret);
return ret;
};
}
private static TypeScope createTypeScope(ClassOrInterface cl, Method method) {
return null;
}
@Override
public void visit(ArgumentList arglist) {
for(int i = 0;i<arglist.getArguments().size();i++){
@ -57,10 +66,10 @@ public class TYPEStmt implements StatementVisitor{
lambdaParams.add(0,tphRetType);
constraintsSet.addUndConstraint(
ConstraintsFactory.createPair(lambdaExpression.getType(),
new FunN(lambdaParams),PairOperator.EQUALSDOT,info));
new FunN(lambdaParams),PairOperator.EQUALSDOT,info.getCurrentTypeScope(), createNullTypeScope(), getResolverInstance()));
constraintsSet.addUndConstraint(
ConstraintsFactory.createPair(lambdaExpression.getReturnType(),
tphRetType,info));
tphRetType,info.getCurrentTypeScope(), createNullTypeScope(), getResolverInstance()));
//Constraints des Bodys generieren:
TYPEStmt lambdaScope = new TYPEStmt(new TypeInferenceBlockInformation(info, lambdaExpression));
@ -73,7 +82,7 @@ public class TYPEStmt implements StatementVisitor{
assign.lefSide.accept(this);
assign.rightSide.accept(this);
constraintsSet.addUndConstraint(ConstraintsFactory.createPair(
assign.rightSide.getType(), assign.lefSide.getType(), PairOperator.SMALLERDOT, info));
assign.rightSide.getType(), assign.lefSide.getType(), PairOperator.SMALLERDOT, info.getCurrentTypeScope(), createNullTypeScope(), getResolverInstance()));
}
@Override
@ -104,10 +113,11 @@ public class TYPEStmt implements StatementVisitor{
Set<Constraint> oderConstraints = new HashSet<>();
for(FieldAssumption fieldAssumption : info.getFields(fieldVar.fieldVarName)){
Constraint constraint = new Constraint();
GenericsResolver resolver = getResolverInstance();
constraint.add(ConstraintsFactory.createPair(
fieldVar.receiver.getType(),fieldAssumption.getReceiverType(), info));
fieldVar.receiver.getType(),fieldAssumption.getReceiverType(), info.getCurrentTypeScope(), fieldAssumption.getTypeScope(), resolver));
constraint.add(ConstraintsFactory.createPair(
fieldVar.getType(),fieldAssumption.getType(), info));
fieldVar.getType(),fieldAssumption.getType(), info.getCurrentTypeScope(), fieldAssumption.getTypeScope(), resolver));
oderConstraints.add(constraint);
}
if(oderConstraints.size() == 0)
@ -146,7 +156,9 @@ public class TYPEStmt implements StatementVisitor{
//Overloading:
Set<Constraint> methodConstraints = new HashSet<>();
for(MethodAssumption m : this.getMethods(methodCall.name, methodCall.arglist, info)){
methodConstraints.add(generateConstraint(methodCall, m, info));
GenericsResolver resolver = getResolverInstance();
TypeScope additionalScope = m.getTypeScope();
methodConstraints.add(generateConstraint(methodCall, m, info, getResolverInstance()));
}
if(methodConstraints.size()<1){
throw new TypeinferenceException("Methode "+methodCall.name+" ist nicht vorhanden!",methodCall.getOffset());
@ -159,7 +171,7 @@ public class TYPEStmt implements StatementVisitor{
//Overloading:
Set<Constraint> methodConstraints = new HashSet<>();
for(MethodAssumption m : this.getConstructors(info, (RefType) methodCall.getType(), methodCall.getArgumentList())){
methodConstraints.add(generateConstructorConstraint(methodCall, m, info));
methodConstraints.add(generateConstructorConstraint(methodCall, m, info, getResolverInstance()));
}
if(methodConstraints.size()<1){
throw new TypeinferenceException("Konstruktor in Klasse "+methodCall.getType().toString()+" ist nicht vorhanden!",methodCall.getOffset());
@ -181,7 +193,8 @@ public class TYPEStmt implements StatementVisitor{
public void visit(Return returnExpr) {
returnExpr.retexpr.accept(this);
constraintsSet.addUndConstraint(ConstraintsFactory.createPair(
returnExpr.getType(),info.getCurrentTypeScope().getReturnType(), PairOperator.EQUALSDOT, info));
returnExpr.getType(),info.getCurrentTypeScope().getReturnType(), PairOperator.EQUALSDOT,
info.getCurrentTypeScope(), createNullTypeScope(), getResolverInstance()));
}
@Override
@ -201,7 +214,23 @@ public class TYPEStmt implements StatementVisitor{
@Override
public void visit(This aThis) {
constraintsSet.addUndConstraint(ConstraintsFactory.createPair( aThis.getType(), info.getCurrentClass().getType(), PairOperator.EQUALSDOT, info));
constraintsSet.addUndConstraint(ConstraintsFactory.createPair(
aThis.getType(), info.getCurrentClass().getType(), PairOperator.EQUALSDOT, info.getCurrentTypeScope(),
createNullTypeScope(), getResolverInstance()));
}
private static TypeScope createNullTypeScope() {
return new TypeScope() {
@Override
public Iterable<? extends GenericTypeVar> getGenerics() {
return null;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
return null;
}
};
}
@Override
@ -249,20 +278,24 @@ public class TYPEStmt implements StatementVisitor{
METHOD CALL Section:
*/
protected Constraint<Pair> generateConstraint(MethodCall forMethod, MethodAssumption assumption, TypeInferenceBlockInformation info){
protected Constraint<Pair> generateConstraint(MethodCall forMethod, MethodAssumption assumption,
TypeInferenceBlockInformation info, GenericsResolver resolver){
Constraint methodConstraint = new Constraint();
methodConstraint.add(ConstraintsFactory.createPair(forMethod.receiver.getType(), assumption.getReceiverType(), PairOperator.SMALLERDOT, info));
methodConstraint.add(ConstraintsFactory.createPair(assumption.getReturnType(), forMethod.getType(), PairOperator.EQUALSDOT, info));
methodConstraint.addAll(generateParameterConstraints(forMethod, assumption, info));
methodConstraint.add(ConstraintsFactory.createPair(forMethod.receiver.getType(), assumption.getReceiverType(),
PairOperator.SMALLERDOT, info.getCurrentTypeScope(), assumption.getTypeScope(), resolver));
methodConstraint.add(ConstraintsFactory.createPair(assumption.getReturnType(), forMethod.getType(),
PairOperator.EQUALSDOT, info.getCurrentTypeScope(), assumption.getTypeScope(), resolver));
methodConstraint.addAll(generateParameterConstraints(forMethod, assumption, info, resolver));
return methodConstraint;
}
protected Set<Pair> generateParameterConstraints(MethodCall foMethod, MethodAssumption assumption, TypeInferenceBlockInformation info) {
protected Set<Pair> generateParameterConstraints(MethodCall foMethod, MethodAssumption assumption,
TypeInferenceBlockInformation info, GenericsResolver resolver) {
Set<Pair> ret = new HashSet<>();
for(int i = 0;i<foMethod.arglist.getArguments().size();i++){
foMethod.arglist.getArguments().get(i).accept(this);
ret.add(ConstraintsFactory.createPair(foMethod.arglist.getArguments().get(i).getType(),
assumption.getArgTypes().get(i), PairOperator.SMALLERDOT, info));
assumption.getArgTypes().get(i), PairOperator.SMALLERDOT, info.getCurrentTypeScope(), assumption.getTypeScope(), resolver));
}
return ret;
}
@ -275,7 +308,18 @@ public class TYPEStmt implements StatementVisitor{
for(int i = 0; i< numArgs + 1 ; i++){
funNParams.add(TypePlaceholder.fresh(new NullToken()));
}
ret.add(new MethodAssumption(new FunN(funNParams), funNParams.get(0), funNParams.subList(1, funNParams.size())));
ret.add(new MethodAssumption(new FunN(funNParams), funNParams.get(0), funNParams.subList(1, funNParams.size()),
new TypeScope() {
@Override
public Iterable<? extends GenericTypeVar> getGenerics() {
throw new NotImplementedException();
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
throw new NotImplementedException();
}
}));
}
for(ClassOrInterface cl : info.getAvailableClasses()){
for(Method m : cl.getMethods()){
@ -283,7 +327,8 @@ public class TYPEStmt implements StatementVisitor{
m.getParameterList().getFormalparalist().size() == numArgs){
RefTypeOrTPHOrWildcardOrGeneric retType = info.checkGTV(m.getType());
ret.add(new MethodAssumption(cl.getType(), retType, convertParams(m.getParameterList(),info)));
ret.add(new MethodAssumption(cl.getType(), retType, convertParams(m.getParameterList(),info),
createTypeScope(cl, m)));
}
}
}
@ -317,7 +362,8 @@ public class TYPEStmt implements StatementVisitor{
if(cl.getClassName().equals(ofType.getName())){
for(Method m : cl.getConstructors()){
if(m.getParameterList().getFormalparalist().size() == argList.getArguments().size()){
ret.add(new MethodAssumption(cl.getType(), ofType, convertParams(m.getParameterList(), info)));
ret.add(new MethodAssumption(cl.getType(), ofType, convertParams(m.getParameterList(),
info), createTypeScope(cl, m)));
}
}
}
@ -325,10 +371,12 @@ public class TYPEStmt implements StatementVisitor{
return ret;
}
protected Constraint<Pair> generateConstructorConstraint(NewClass forConstructor, MethodAssumption assumption, TypeInferenceBlockInformation info){
protected Constraint<Pair> generateConstructorConstraint(NewClass forConstructor, MethodAssumption assumption,
TypeInferenceBlockInformation info, GenericsResolver resolver){
Constraint methodConstraint = new Constraint();
methodConstraint.add(ConstraintsFactory.createPair(assumption.getReturnType(), forConstructor.getType(), PairOperator.SMALLERDOT, info));
methodConstraint.addAll(generateParameterConstraints(forConstructor, assumption, info));
methodConstraint.add(ConstraintsFactory.createPair(assumption.getReturnType(), forConstructor.getType(),
PairOperator.SMALLERDOT, info.getCurrentTypeScope(), assumption.getTypeScope(), resolver));
methodConstraint.addAll(generateParameterConstraints(forConstructor, assumption, info, resolver));
return methodConstraint;
}

View File

@ -17,5 +17,4 @@ auto test = new List<String>();
auto test2 = new List<Integer>();
... //code, welcher möglicherweise test und test2 vertauscht
test.add("hallo");
*/