Anpassung zur Integration von Functional Interfaces und FunN$$-Typen

modified:   src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java
	modified:   src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java
	modified:   src/main/java/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java
	modified:   src/main/java/de/dhbwstuttgart/syntaxtree/Record.java
	modified:   src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/assumptions/FunNClass.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java
	modified:   src/test/java/targetast/ASTToTypedTargetAST.java
This commit is contained in:
pl@gohorb.ba-horb.de 2023-10-27 21:17:52 +02:00
parent df852ef36e
commit c4ce97f20c
10 changed files with 64 additions and 30 deletions

View File

@ -34,11 +34,12 @@ public class FCGenerator {
//PL 2018-09-18: gtvs vor die for-Schleife gezogen, damit immer die gleichen Typeplaceholder eingesetzt werden. //PL 2018-09-18: gtvs vor die for-Schleife gezogen, damit immer die gleichen Typeplaceholder eingesetzt werden.
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs = new HashMap<>(); HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs = new HashMap<>();
for(ClassOrInterface cly : availableClasses){ for(ClassOrInterface cly : availableClasses){
pairs.addAll(getSuperTypes(cly, availableClasses, gtvs, classLoader)); List<Pair> newPairs = getSuperTypes(cly, availableClasses, gtvs, classLoader);
pairs.addAll(newPairs);
//For all Functional Interfaces FI: FunN$$<... args auf dem Functional Interface ...> <. FI is added to FC //For all Functional Interfaces FI: FunN$$<... args auf dem Functional Interface ...> <. FI is added to FC
if (isFunctionalInterface(cly)) { if (isFunctionalInterface(cly)) {
pairs.add(genImplFunType(cly)); pairs.add(genImplFunType(cly, newPairs.get(0).TA1, gtvs));
} }
} }
return pairs; return pairs;
@ -46,17 +47,22 @@ public class FCGenerator {
private static Boolean isFunctionalInterface(ClassOrInterface cly) { private static Boolean isFunctionalInterface(ClassOrInterface cly) {
return (cly.isInterface() && cly.getMethods().size() == 1); return (cly.isInterface() && (cly.isFunctionalInterface() || cly.getMethods().size() == 1));
} }
private static Pair genImplFunType(ClassOrInterface cly) { private static Pair genImplFunType(ClassOrInterface cly, RefTypeOrTPHOrWildcardOrGeneric fIType, HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs) {
Method m = cly.getMethods().get(0); for(Method m : cly.getMethods()) {
List<RefTypeOrTPHOrWildcardOrGeneric> tl = if (!java.lang.reflect.Modifier.isAbstract(m.modifier))
(m.getParameterList().getFormalparalist().stream().map(p -> p.getType()).collect(Collectors.toList())); continue;
tl.add(m.getReturnType()); List<RefTypeOrTPHOrWildcardOrGeneric> tl =
return new Pair(new RefType(new JavaClassName("Fun" + (tl.size()-1) + "$$"), tl, new NullToken()), (m.getParameterList().getFormalparalist()
new RefType(cly.getClassName(), new NullToken())); .stream().map(p -> p.getType().acceptTV(new TypeExchanger(gtvs)))
// new FunN(lambdaParams), .collect(Collectors.toList()));
tl.add(m.getReturnType().acceptTV(new TypeExchanger(gtvs)));
return new Pair(new RefType(new JavaClassName("Fun" + (tl.size()-1) + "$$"), tl, new NullToken()),
fIType);
}
return null; //kann nicht passieren, da die Methode nur aufgerufen wird wenn cl Functional Interface ist
} }

View File

@ -210,6 +210,7 @@ public class SyntaxTreeGenerator {
List<Method> methods = new ArrayList<>(); List<Method> methods = new ArrayList<>();
List<Constructor> constructors = new ArrayList<>(); List<Constructor> constructors = new ArrayList<>();
Boolean isInterface = false; Boolean isInterface = false;
Boolean isFunctionalInterface = false;
List<RefType> implementedInterfaces = new ArrayList<>(); List<RefType> implementedInterfaces = new ArrayList<>();
List<RefType> permittedSubtypes = new ArrayList<>(); List<RefType> permittedSubtypes = new ArrayList<>();
for (ClassBodyDeclarationContext clsbodydecl : ctx.classBody().classBodyDeclaration()) { for (ClassBodyDeclarationContext clsbodydecl : ctx.classBody().classBodyDeclaration()) {
@ -233,7 +234,7 @@ public class SyntaxTreeGenerator {
} }
var ctor = Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), fieldInitializations, genericClassParameters, offset)); var ctor = Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), fieldInitializations, genericClassParameters, offset));
var staticCtor = Optional.of(this.generateStaticConstructor(ctx.identifier().getText(), staticFieldInitializations, genericClassParameters, offset)); var staticCtor = Optional.of(this.generateStaticConstructor(ctx.identifier().getText(), staticFieldInitializations, genericClassParameters, offset));
return new ClassOrInterface(modifiers, name, fielddecl, ctor, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, permittedSubtypes, offset); return new ClassOrInterface(modifiers, name, fielddecl, ctor, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, isFunctionalInterface, implementedInterfaces, permittedSubtypes, offset);
} }
@ -408,7 +409,7 @@ public class SyntaxTreeGenerator {
} }
var staticCtor = Optional.of(this.generateStaticConstructor(ctx.identifier().getText(), staticFieldInitializations, genericParams, ctx.getStart())); var staticCtor = Optional.of(this.generateStaticConstructor(ctx.identifier().getText(), staticFieldInitializations, genericParams, ctx.getStart()));
return new ClassOrInterface(modifiers, name, fields, Optional.empty(), staticCtor, methods, new ArrayList<>(), genericParams, superClass, true, extendedInterfaces, permittedSubtypes, ctx.getStart()); return new ClassOrInterface(modifiers, name, fields, Optional.empty(), staticCtor, methods, new ArrayList<>(), genericParams, superClass, true, methods.size() == 1 ? true : false, extendedInterfaces, permittedSubtypes, ctx.getStart());
} }
private GenericDeclarationList createEmptyGenericDeclarationList(Token classNameIdentifier) { private GenericDeclarationList createEmptyGenericDeclarationList(Token classNameIdentifier) {

View File

@ -28,11 +28,12 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
private GenericDeclarationList genericClassParameters; private GenericDeclarationList genericClassParameters;
private RefType superClass; private RefType superClass;
protected boolean isInterface; protected boolean isInterface;
protected boolean isFunctionalInterface;
private List<RefType> implementedInterfaces; private List<RefType> implementedInterfaces;
private List<RefType> permittedSubtypes; private List<RefType> permittedSubtypes;
private List<Constructor> constructors; private List<Constructor> constructors;
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, List<RefType> permittedSubtypes, Token offset) { public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, Boolean isFunctionalInterface, List<RefType> implementedInterfaces, List<RefType> permittedSubtypes, Token offset) {
super(offset); super(offset);
if (isInterface) { if (isInterface) {
modifiers |= Modifier.INTERFACE | Modifier.ABSTRACT; modifiers |= Modifier.INTERFACE | Modifier.ABSTRACT;
@ -45,6 +46,7 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
this.genericClassParameters = genericClassParameters; this.genericClassParameters = genericClassParameters;
this.superClass = superClass; this.superClass = superClass;
this.isInterface = isInterface; this.isInterface = isInterface;
this.isFunctionalInterface= isFunctionalInterface;
this.implementedInterfaces = implementedInterfaces; this.implementedInterfaces = implementedInterfaces;
this.permittedSubtypes = permittedSubtypes; this.permittedSubtypes = permittedSubtypes;
this.methods = methods; this.methods = methods;
@ -64,6 +66,7 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
this.genericClassParameters = cl.genericClassParameters; this.genericClassParameters = cl.genericClassParameters;
this.superClass = cl.superClass; this.superClass = cl.superClass;
this.isInterface = cl.isInterface; this.isInterface = cl.isInterface;
this.isFunctionalInterface= cl.isFunctionalInterface;
this.implementedInterfaces = cl.implementedInterfaces; this.implementedInterfaces = cl.implementedInterfaces;
this.methods = new ArrayList<>(cl.methods); this.methods = new ArrayList<>(cl.methods);
this.constructors = new ArrayList<>(cl.constructors); this.constructors = new ArrayList<>(cl.constructors);
@ -82,6 +85,10 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
return (Modifier.INTERFACE & this.getModifiers()) != 0; return (Modifier.INTERFACE & this.getModifiers()) != 0;
} }
public boolean isFunctionalInterface() {
return this.isFunctionalInterface;
}
// Gets if it is added // Gets if it is added
public Boolean areMethodsAdded() { public Boolean areMethodsAdded() {
return methodAdded; return methodAdded;
@ -173,4 +180,5 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
public String toString() { public String toString() {
return this.name.toString() + this.genericClassParameters.toString(); return this.name.toString() + this.genericClassParameters.toString();
} }
} }

View File

@ -14,6 +14,6 @@ import javax.swing.text.html.Option;
public class Record extends ClassOrInterface { public class Record extends ClassOrInterface {
public Record(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, Token offset) { public Record(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, Token offset) {
super(modifiers, name, fielddecl, fieldInitializations, staticInitializer, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, new ArrayList<>(), offset); super(modifiers, name, fielddecl, fieldInitializations, staticInitializer, methods, constructors, genericClassParameters, superClass, isInterface, methods.size() == 1 ? true : false, implementedInterfaces, new ArrayList<>(), offset);
} }
} }

View File

@ -1,6 +1,7 @@
package de.dhbwstuttgart.syntaxtree.factory; package de.dhbwstuttgart.syntaxtree.factory;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@ -86,7 +87,6 @@ public class ASTFactory {
} catch (IOException e) { } catch (IOException e) {
// Skip // Skip
} }
JavaClassName name = new JavaClassName(jreClass.getName()); JavaClassName name = new JavaClassName(jreClass.getName());
List<Method> methoden = new ArrayList<>(); List<Method> methoden = new ArrayList<>();
List<de.dhbwstuttgart.syntaxtree.Constructor> konstruktoren = new ArrayList<>(); List<de.dhbwstuttgart.syntaxtree.Constructor> konstruktoren = new ArrayList<>();
@ -112,6 +112,12 @@ public class ASTFactory {
} }
int modifier = jreClass.getModifiers(); int modifier = jreClass.getModifiers();
boolean isInterface = jreClass.isInterface(); boolean isInterface = jreClass.isInterface();
List<Annotation> aLA;
boolean isFunctionalInterface =
(aLA = Arrays.asList(jreClass.getAnnotations())).size() > 0 &&
aLA.get(0) instanceof FunctionalInterface ?
true :
false;
// see: https://stackoverflow.com/questions/9934774/getting-generic-parameter-from-supertype-class // see: https://stackoverflow.com/questions/9934774/getting-generic-parameter-from-supertype-class
ParameterizedType parameterSuperClass = null; ParameterizedType parameterSuperClass = null;
Type tempSuperClass = jreClass.getGenericSuperclass(); Type tempSuperClass = jreClass.getGenericSuperclass();
@ -141,7 +147,7 @@ public class ASTFactory {
Token offset = new NullToken(); // Braucht keinen Offset, da diese Klasse nicht aus einem Quellcode geparst wurde Token offset = new NullToken(); // Braucht keinen Offset, da diese Klasse nicht aus einem Quellcode geparst wurde
var cinf = new ClassOrInterface(modifier, name, felder, Optional.empty() /* eingefuegt PL 2018-11-24 */, Optional.empty(), methoden, konstruktoren, genericDeclarationList, superClass, isInterface, implementedInterfaces, permittedSubtypes, offset); var cinf = new ClassOrInterface(modifier, name, felder, Optional.empty() /* eingefuegt PL 2018-11-24 */, Optional.empty(), methoden, konstruktoren, genericDeclarationList, superClass, isInterface, isFunctionalInterface, implementedInterfaces, permittedSubtypes, offset);
cache.put(jreClass, cinf); cache.put(jreClass, cinf);
return cinf; return cinf;
} }

View File

@ -22,7 +22,7 @@ import java.util.Optional;
public class FunNClass extends ClassOrInterface { public class FunNClass extends ClassOrInterface {
public FunNClass(List<GenericRefType> funNParams) { public FunNClass(List<GenericRefType> funNParams) {
super(0, new JavaClassName("Fun" + (funNParams.size() - 1)), new ArrayList<>(), Optional.empty(), Optional.empty() /* eingefuegt PL 2018-11-24 */, createMethods(funNParams), new ArrayList<>(), createGenerics(funNParams), ASTFactory.createObjectType(), true, new ArrayList<>(), new ArrayList<>(), new NullToken()); super(0, new JavaClassName("Fun" + (funNParams.size() - 1)), new ArrayList<>(), Optional.empty(), Optional.empty() /* eingefuegt PL 2018-11-24 */, createMethods(funNParams), new ArrayList<>(), createGenerics(funNParams), ASTFactory.createObjectType(), true, false, new ArrayList<>(), new ArrayList<>(), new NullToken());
} }

View File

@ -890,26 +890,39 @@ public class RuleSet implements IRuleSet{
if(!(lhsType instanceof FunNType)) if(!(lhsType instanceof FunNType))
return Optional.empty(); return Optional.empty();
//FunN$$<...> <. FunctinalInterface wird umgewandelt in FunN$$<...> <. FunN$$<... args aus FuntionalInterface ...> //FunN$$<...> <. FunctinalInterface<...> wird umgewandelt in FunN$$<...> <. FunN$$<... args aus FuntionalInterface ...>
if (rhsType instanceof ReferenceType) { if (rhsType instanceof ReferenceType) {
UnifyType typeD = pair.getRhsType(); UnifyType typeFI = pair.getRhsType();
Optional<UnifyType> opt = fc.getRightHandedNoParameterType(typeD.getName()); Optional<UnifyType> opt = fc.getRightHandedFunctionalInterfaceType(typeFI.getName());
if(!opt.isPresent()) if(!opt.isPresent())
return Optional.empty(); return Optional.empty();
// Should be eual as typeD // The generic Version of typeFI (FI<a1, a2, a3, ... >)
UnifyType typeFunFc = opt.get(); UnifyType typeDgen = opt.get();
// Actually greater+ because the types are ensured to have different names
Set<UnifyType> smaller = fc.getChildren(typeDgen);
opt = smaller.stream().filter(x -> x.getName().equals(pair.getLhsType().getName())).findAny();
if(!(typeFunFc instanceof FunNType)) if(!opt.isPresent())
return Optional.empty(); return Optional.empty();
TypeParams typeDParams = typeFI.getTypeParams();
TypeParams typeDgenParams = typeDgen.getTypeParams();
Unifier unif = Unifier.identity();
for(int i = 0; i < typeDParams.size(); i++) {
if (typeDgenParams.get(i) instanceof PlaceholderType)
unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i));
else System.out.println("ERROR");
}
UnifyType newRhsType = opt.get(); UnifyType newRhsType = opt.get();
Set<UnifyPair> result = new HashSet<>(); Set<UnifyPair> result = new HashSet<>();
result.add(new UnifyPair(lhsType, newRhsType, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); result.add(new UnifyPair(lhsType, unif.apply(newRhsType), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
return Optional.of(result); return Optional.of(result);
} }

View File

@ -60,7 +60,7 @@ public interface IFiniteClosure {
public Set<UnifyType> smArg(FunNType type, Set<UnifyType> fBounded); public Set<UnifyType> smArg(FunNType type, Set<UnifyType> fBounded);
public Optional<UnifyType> getLeftHandedType(String typeName); public Optional<UnifyType> getLeftHandedType(String typeName);
public Optional<UnifyType> getRightHandedNoParameterType(String typeName); public Optional<UnifyType> getRightHandedFunctionalInterfaceType(String typeName);
public Set<UnifyType> getAncestors(UnifyType t); public Set<UnifyType> getAncestors(UnifyType t);
public Set<UnifyType> getChildren(UnifyType t); public Set<UnifyType> getChildren(UnifyType t);
public Set<UnifyType> getAllTypesByName(String typeName); public Set<UnifyType> getAllTypesByName(String typeName);

View File

@ -609,13 +609,13 @@ implements IFiniteClosure {
} }
@Override @Override
public Optional<UnifyType> getRightHandedNoParameterType(String typeName) { public Optional<UnifyType> getRightHandedFunctionalInterfaceType(String typeName) {
if(!strInheritanceGraph.containsKey(typeName)) if(!strInheritanceGraph.containsKey(typeName))
return Optional.empty(); return Optional.empty();
for(UnifyPair pair : pairs) for(UnifyPair pair : pairs)
if(pair.getRhsType().getName().equals(typeName) && pair.getRhsType().typeParams.size() == 0) if(pair.getRhsType().getName().equals(typeName))
return Optional.of(pair.getLhsType()); return Optional.of(pair.getRhsType());
return Optional.empty(); return Optional.empty();
} }

View File

@ -22,7 +22,7 @@ public class ASTToTypedTargetAST {
@Test @Test
public void emptyClass() { public void emptyClass() {
ClassOrInterface emptyClass = new ClassOrInterface(0, new JavaClassName("EmptyClass"), new ArrayList<>(), Optional.empty(), Optional.empty(), new ArrayList<>(), new ArrayList<>(), new GenericDeclarationList(new ArrayList<>(), new NullToken()), new RefType(new JavaClassName("Object"), new NullToken()), false, new ArrayList<>(), new ArrayList<>(), new NullToken()); ClassOrInterface emptyClass = new ClassOrInterface(0, new JavaClassName("EmptyClass"), new ArrayList<>(), Optional.empty(), Optional.empty(), new ArrayList<>(), new ArrayList<>(), new GenericDeclarationList(new ArrayList<>(), new NullToken()), new RefType(new JavaClassName("Object"), new NullToken()), false, false, new ArrayList<>(), new ArrayList<>(), new NullToken());
ResultSet emptyResultSet = new ResultSet(new HashSet<>()); ResultSet emptyResultSet = new ResultSet(new HashSet<>());
TargetStructure emptyTargetClass = new ASTToTargetAST(List.of(emptyResultSet)).convert(emptyClass); TargetStructure emptyTargetClass = new ASTToTargetAST(List.of(emptyResultSet)).convert(emptyClass);
assert emptyTargetClass.getName().equals("EmptyClass"); assert emptyTargetClass.getName().equals("EmptyClass");