Fix super calls

This commit is contained in:
Daniel Holle 2024-01-23 14:00:42 +01:00
parent b80cc726c8
commit f18903834e
11 changed files with 91 additions and 52 deletions

View File

@ -0,0 +1,11 @@
import java.lang.Integer;
class Parent {
public Parent(Integer x) {}
}
public class SuperCall extends Parent {
public SuperCall() {
super(20);
}
}

View File

@ -1382,8 +1382,8 @@ public class Codegen {
generate(state, stmts.get(0));
if (constructor.fieldInitializer() != null) {
var stmts2 = constructor.fieldInitializer().statements();
for (var i = 1; i < stmts2.size(); i++) {
generate(state, stmts2.get(i));
for (TargetExpression expression : stmts2) {
generate(state, expression);
}
}
for (var i = 1; i < stmts.size(); i++)

View File

@ -707,13 +707,19 @@ public class StatementGenerator {
} else if (!Objects.isNull(expr.SUPER())) {
// if(methodInvocationContext.Identifier() != null){
name = expr.SUPER().getText();
receiver = new Super(offset);
}
ArgumentList argumentList = convertArguments(expr.expressionList());
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> signature = argumentList.getArguments().stream().map(x -> (RefTypeOrTPHOrWildcardOrGeneric) TypePlaceholder.fresh(offset)).collect(Collectors.toCollection(ArrayList::new));
signature.add(TypePlaceholder.fresh(offset)); // return type
MethodCall ret = new MethodCall(TypePlaceholder.fresh(offset), getReceiver(receiver), name, argumentList, TypePlaceholder.fresh(offset), signature, offset);
MethodCall ret;
if (expr.SUPER() != null) {
ret = new SuperCall(argumentList, TypePlaceholder.fresh(offset), signature, offset);
} else {
ret = new MethodCall(TypePlaceholder.fresh(offset), getReceiver(receiver), name, argumentList, TypePlaceholder.fresh(offset), signature, offset);
}
ret.setStatement();
return ret;
}
@ -796,7 +802,7 @@ public class StatementGenerator {
receiver = new This(offset);
isStatic = Modifier.isStatic(fields.get(fieldName).modifiers());
} else if (parts[0].contentEquals("super")) {
receiver = new Super(offset);
receiver = new Super(TypePlaceholder.fresh(offset), offset);
isStatic = Modifier.isStatic(compiler.getClass(new JavaClassName(superClass.getName().toString())).getField(fieldName).orElseThrow().modifier);
} else if (receiver == null) { // Handelt es sich um keinen Statischen Klassennamen:
String part = expression.substring(0, expression.length() - (1 + parts[parts.length - 1].length()));

View File

@ -16,6 +16,7 @@ import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.Record;
import de.dhbwstuttgart.syntaxtree.statement.*;
import org.antlr.v4.runtime.CommonToken;
import org.antlr.v4.runtime.Token;
@ -66,15 +67,6 @@ import de.dhbwstuttgart.parser.scope.GenericsRegistry;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.statement.Assign;
import de.dhbwstuttgart.syntaxtree.statement.AssignLeftSide;
import de.dhbwstuttgart.syntaxtree.statement.AssignToField;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.FieldVar;
import de.dhbwstuttgart.syntaxtree.statement.LocalVar;
import de.dhbwstuttgart.syntaxtree.statement.Return;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
import de.dhbwstuttgart.syntaxtree.statement.This;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
@ -280,8 +272,8 @@ public class SyntaxTreeGenerator {
methods.add(new Method(allmodifiers.get("public"), fieldname, fieldtype, new ParameterList(new ArrayList<>(), offset), new Block(Arrays.asList(returnStatement), offset), new GenericDeclarationList(new ArrayList<>(), offset), offset));
}
RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), genericClassParameters, offset);
Constructor implicitConstructor = new Constructor(allmodifiers.get("public"), identifier, classType, new ParameterList(constructorParameters, offset), new Block(constructorStatements, offset), genericClassParameters, offset);
Optional<Constructor> initializations = Optional.of(implicitConstructor);
Constructor implicitConstructor = new Constructor(allmodifiers.get("public"), identifier, classType, new ParameterList(constructorParameters, offset), prepareBlock(new Block(constructorStatements, offset), superClass), genericClassParameters, offset);
//Optional<Constructor> initializations = Optional.of(implicitConstructor);
constructors.add(implicitConstructor);
for (ClassBodyDeclarationContext bodyDeclaration : recordDeclaration.recordBody().classBodyDeclaration()) {
convert(bodyDeclaration, fielddecl, constructors, methods, name, superClass, generics);
@ -290,7 +282,7 @@ public class SyntaxTreeGenerator {
implementedInterfaces.addAll(convert(recordDeclaration.typeList(), generics));
}
var staticCtor = Optional.of(this.generateStaticConstructor(recordDeclaration.identifier().getText(), staticFieldInitializations, genericClassParameters, offset));
return new Record(modifiers, name, fielddecl, initializations, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset);
return new Record(modifiers, name, fielddecl, Optional.empty(), staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset);
}
private void convert(ClassBodyDeclarationContext classBody, List<Field> fields, List<Constructor> constructors, List<Method> methods, JavaClassName name, RefType superClass, GenericsRegistry generics) {
@ -451,18 +443,24 @@ public class SyntaxTreeGenerator {
return new Method(modifiers, name, retType, paramlist, block, gtvDeclarations, bodydeclaration.getStart());
}
protected static Block prepareBlock(Block constructorBlock, RefType superClass) {
List<Statement> statements = constructorBlock.getStatements();
if (statements.isEmpty() || !(statements.get(0) instanceof SuperCall)) {
var signature = new ArrayList<RefTypeOrTPHOrWildcardOrGeneric>();
signature.add(new Void(new NullToken()));
statements.add(0, new SuperCall(superClass, signature, constructorBlock.getOffset()));
}
/* statements.addAll(fieldInitializations); geloescht PL 2018-11-24 */
return new Block(statements, constructorBlock.getOffset());
}
/**
* http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.9
*/
private Constructor generateStandardConstructor(String className, JavaClassName parentClass, RefType superClass, GenericDeclarationList classGenerics, Token offset) {
RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset);
ParameterList params = new ParameterList(new ArrayList<>(), offset);
Block block = new Block(new ArrayList<>(), offset);
//
//
return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset); // fieldInitializations
// geloescht PL
// 2018-11-24
return new Constructor(Modifier.PUBLIC, className, classType, params, prepareBlock(new Block(new ArrayList<>(), offset), superClass), classGenerics, offset); // fieldInitializations // 2018-11-24
}
/*
@ -471,10 +469,7 @@ public class SyntaxTreeGenerator {
private Constructor generatePseudoConstructor(String className, List<Statement> initializations, GenericDeclarationList classGenerics, Token offset) {
RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset);
ParameterList params = new ParameterList(new ArrayList<>(), offset);
Block block = new Block(new ArrayList<>(initializations), offset);
return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset /*
* fieldInitializations geloescht PL 2018-11-24
*/);
return new Constructor(Modifier.PUBLIC, className, classType, params, new Block(new ArrayList<>(initializations), offset), classGenerics, offset);
}
private Method generateStaticConstructor(String className, List<Statement> initializations, GenericDeclarationList classGenerics, Token offset) {
@ -553,7 +548,7 @@ public class SyntaxTreeGenerator {
block = stmtgen.convert(methodblock.block(), true);
}
if (name.equals(parentClass.getClassName())) {
return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, methoddeclaration.getStart());
return new Constructor(modifiers, name, retType, paramlist, prepareBlock(block, superClass), gtvDeclarations, methoddeclaration.getStart());
} else {
return new Method(modifiers, name, retType, paramlist, block, gtvDeclarations, methoddeclaration.getStart());
}
@ -582,7 +577,7 @@ public class SyntaxTreeGenerator {
RefTypeOrTPHOrWildcardOrGeneric retType = TypeGenerator.convertTypeName(name, constructordeclaration.getStart(), reg, localgenerics);
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fields, new HashMap<>());
ParameterList paramlist = stmtgen.convert(constructordeclaration.formalParameters().formalParameterList());
Block block = stmtgen.convert(constructordeclaration.constructorBody, true);
Block block = prepareBlock(stmtgen.convert(constructordeclaration.constructorBody, true), superClass);
return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, constructordeclaration.getStart());
}

View File

@ -1,31 +1,25 @@
package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
import de.dhbwstuttgart.syntaxtree.statement.Super;
import de.dhbwstuttgart.syntaxtree.statement.SuperCall;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.Void;
import org.antlr.v4.runtime.Token;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import java.sql.Ref;
import java.util.ArrayList;
import java.util.List;
public class Constructor extends Method {
// TODO: Constructor braucht ein super-Statement
public Constructor(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block codeInsideConstructor, GenericDeclarationList gtvDeclarations, Token offset /* , List<Statement> fieldInitializations geloescht PL 2018-11-24 */) {
super(modifier, name, returnType, parameterList, /* codeInsideConstructor, */ prepareBlock(codeInsideConstructor) /* ,fieldInitializations )geloescht PL 2018-11-24 ) */, gtvDeclarations, offset);
}
/**
* @param fieldInitializations - Das sind die Statements, welche die Felder der zugehörigen Klasse dieses Konstruktor initialisieren
*/
protected static Block prepareBlock(Block constructorBlock /* , List<Statement> fieldInitializations new ArrayList<>() geloescht PL 2018-11-24 */) {
List<Statement> statements = constructorBlock.getStatements();
statements.add(0, new SuperCall(null, null, constructorBlock.getOffset()));
/* statements.addAll(fieldInitializations); geloescht PL 2018-11-24 */
return new Block(statements, constructorBlock.getOffset());
public Constructor(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block codeInsideConstructor, GenericDeclarationList gtvDeclarations, Token offset) {
super(modifier, name, returnType, parameterList, codeInsideConstructor, gtvDeclarations, offset);
}
@Override

View File

@ -37,6 +37,7 @@ public class MethodCall extends Statement
this.receiver = receiver;
this.receiverType = receiverType;
this.signature = signature;
if (signature == null) throw new NullPointerException();
}
public List<RefTypeOrTPHOrWildcardOrGeneric> signatureArguments() {

View File

@ -1,6 +1,9 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
@ -9,9 +12,9 @@ import de.dhbwstuttgart.exceptions.NotImplementedException;
public class Super extends Expression
{
public Super(Token offset)
public Super(RefTypeOrTPHOrWildcardOrGeneric type, Token offset)
{
super(null,null);
super(type, offset);
}
@Override

View File

@ -1,5 +1,6 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
@ -9,6 +10,7 @@ import org.antlr.v4.runtime.Token;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import java.util.ArrayList;
import java.util.List;
public class SuperCall extends MethodCall
@ -20,7 +22,7 @@ public class SuperCall extends MethodCall
public SuperCall(ArgumentList argumentList, RefTypeOrTPHOrWildcardOrGeneric receiverType,
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> argTypes, Token offset){
super(new Void(offset), new ExpressionReceiver(new This(offset)), "<init>", argumentList, receiverType, argTypes, offset);
super(new Void(offset), new ExpressionReceiver(new Super(receiverType, offset)), "<init>", argumentList, receiverType, argTypes, offset);
}

View File

@ -8,6 +8,7 @@ import de.dhbwstuttgart.syntaxtree.TypeScope;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.typeinference.constraints.GenericsResolver;
import java.util.ArrayList;
@ -66,6 +67,7 @@ public class MethodAssumption extends Assumption{
* @return
*/
public RefTypeOrTPHOrWildcardOrGeneric getReceiverType(GenericsResolver resolver) {
if (receiver == null) return null;
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for(GenericTypeVar gtv : receiver.getGenerics()){
//Die Generics werden alle zu TPHs umgewandelt.

View File

@ -538,7 +538,23 @@ public class TYPEStmt implements StatementVisitor {
@Override
public void visit(SuperCall superCall) {
// TODO: Für einen super-Call werden keine Constraints erzeugt bisher
Set<Constraint<Pair>> methodConstraints = new HashSet<>();
for (var clazz : info.getAvailableClasses()) {
if (clazz.getClassName().equals(info.getCurrentClass().getSuperClass().getName())) {
for (var ctor : clazz.getConstructors()) {
var assumption = new MethodAssumption(null, new Void(new NullToken()), convertParams(ctor.getParameterList(), info), createTypeScope(clazz, ctor), ctor.isInherited);
GenericsResolver resolver = getResolverInstance();
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver);
System.out.println(">>>");
System.out.println(oneMethodConstraints);
System.out.println("<<<");
methodConstraints.addAll(oneMethodConstraints);
}
break;
}
}
constraintsSet.addOderConstraint(methodConstraints);
}
/*
@ -558,10 +574,12 @@ public class TYPEStmt implements StatementVisitor {
*/
RefTypeOrTPHOrWildcardOrGeneric receiverType = assumption.getReceiverType(resolver);
methodConstraint.add(new Pair(forMethod.receiver.getType(), receiverType, PairOperator.EQUALSDOT));// PL 2020-03-17 SMALLERDOT in EQUALSDOT umgewandelt, weil alle geerbten Methoden in den jeweilen Klassen enthalten sind.
if (receiverType != null) {
methodConstraint.add(new Pair(forMethod.receiver.getType(), receiverType, PairOperator.EQUALSDOT));// PL 2020-03-17 SMALLERDOT in EQUALSDOT umgewandelt, weil alle geerbten Methoden in den jeweilen Klassen enthalten sind.
// PL 2023-01-24: dafuer ? extends receiverType noch ergaenzt
extendsMethodConstraint.add(new Pair(forMethod.receiver.getType(), new ExtendsWildcardType(receiverType, receiverType.getOffset()), PairOperator.EQUALSDOT));
// PL 2023-01-24: dafuer ? extends receiverType noch ergaenzt
extendsMethodConstraint.add(new Pair(forMethod.receiver.getType(), new ExtendsWildcardType(receiverType, receiverType.getOffset()), PairOperator.EQUALSDOT));
}
// gegenseite Verschraenkung der beiden Mengen von Typannahmen
methodConstraint.setExtendConstraint(extendsMethodConstraint);
@ -578,7 +596,8 @@ public class TYPEStmt implements StatementVisitor {
// methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT));
// extendsMethodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT));
((TypePlaceholder) forMethod.getType()).setOrCons((byte) -1);// fuer Maximums-Bestimmung
if (forMethod.getType() instanceof TypePlaceholder tph)
tph.setOrCons((byte) -1);// fuer Maximums-Bestimmung
Set<Pair> parameterContraints = generateParameterConstraints(forMethod, assumption, info, resolver);
@ -625,7 +644,6 @@ public class TYPEStmt implements StatementVisitor {
}
// Zuordnung von MethodCall.signature(ReturnType) zu dem ReturnType der ausgewaehlten Methode (assumption.returnType)
System.out.println(foMethod.name);
ret.add(new Pair(foMethod.signature.get(foMethod.signature.size() - 1), assumption.getReturnType(), PairOperator.EQUALSDOT));
return ret;
}

View File

@ -234,7 +234,7 @@ public class TestComplete {
}
@Test
//@Ignore("This is to complex")
//@Ignore("This is too complex")
public void matrixTest() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Matrix.jav");
var matrix = classFiles.get("Matrix");
@ -781,4 +781,11 @@ public class TestComplete {
var hello = clazz.getDeclaredMethod("hello");
hello.invoke(null);
}
@Test
public void testSuperCall() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "SuperCall.jav");
var clazz = classFiles.get("SuperCall");
var instance = clazz.getDeclaredConstructor().newInstance();
}
}