Fix #300 and also call private methods correctly
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m35s

This commit is contained in:
Daniel Holle 2024-03-21 11:49:16 +01:00
parent 1c63321b30
commit 786e0a7a23
12 changed files with 75 additions and 31 deletions

View File

@ -0,0 +1,17 @@
import java.lang.String;
class Base {
toString() {
return "Base";
}
}
public class Bug300 extends Base {
public m() {
return super.toString();
}
toString() {
return "Derived";
}
}

View File

@ -1045,7 +1045,12 @@ public class Codegen {
if (call.owner() instanceof TargetFunNType) // Decay FunN if (call.owner() instanceof TargetFunNType) // Decay FunN
descriptor = TargetMethod.getDescriptor(call.returnType() == null ? null : TargetType.Object, call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new)); descriptor = TargetMethod.getDescriptor(call.returnType() == null ? null : TargetType.Object, call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new));
mv.visitMethodInsn(call.isInterface() ? INVOKEINTERFACE : call.isStatic() ? INVOKESTATIC : call.name().equals("<init>") ? INVOKESPECIAL : INVOKEVIRTUAL, call.owner().getInternalName(), call.name(), descriptor, call.isInterface()); int insn = INVOKEVIRTUAL;
if (call.isInterface()) insn = INVOKEINTERFACE;
else if (call.isStatic()) insn = INVOKESTATIC;
else if (call.name().equals("<init>") || call.expr() instanceof TargetSuper || call.isPrivate()) insn = INVOKESPECIAL;
mv.visitMethodInsn(insn, call.owner().getInternalName(), call.name(), descriptor, call.isInterface());
if (call.type() != null && call.returnType() != null && !(call.returnType() instanceof TargetPrimitiveType)) { if (call.type() != null && call.returnType() != null && !(call.returnType() instanceof TargetPrimitiveType)) {
if (!call.returnType().equals(call.type()) && !(call.type() instanceof TargetGenericType)) if (!call.returnType().equals(call.type()) && !(call.type() instanceof TargetGenericType))

View File

@ -131,6 +131,7 @@ public class JavaTXCompiler {
public ConstraintSet<Pair> getConstraints() throws ClassNotFoundException, IOException { public ConstraintSet<Pair> getConstraints() throws ClassNotFoundException, IOException {
Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses(); Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
ClassOrInterface objectClass = ASTFactory.createClass(classLoader.loadClass(new JavaClassName("java.lang.Object").toString())); ClassOrInterface objectClass = ASTFactory.createClass(classLoader.loadClass(new JavaClassName("java.lang.Object").toString()));
allClasses.add(objectClass);
// Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC // Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC
for (Entry<File, SourceFile> source : sourceFiles.entrySet()) { for (Entry<File, SourceFile> source : sourceFiles.entrySet()) {
var importedClasses = new ArrayList<ClassOrInterface>(); var importedClasses = new ArrayList<ClassOrInterface>();

View File

@ -1028,7 +1028,7 @@ public class StatementGenerator {
case PrimaryThisContext primthis: case PrimaryThisContext primthis:
return new This(primthis.getStart()); return new This(primthis.getStart());
case PrimarySuperContext primsuper: case PrimarySuperContext primsuper:
throw new NotImplementedException(); return new Super(primsuper.getStart());
case PrimaryLiteralContext primliteral: case PrimaryLiteralContext primliteral:
return convert(primliteral.literal()); return convert(primliteral.literal());
case PrimaryIdentifierContext primidentifier: case PrimaryIdentifierContext primidentifier:

View File

@ -3,6 +3,7 @@ package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
@ -10,8 +11,12 @@ import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.exceptions.NotImplementedException;
public class Super extends Expression public class Super extends Expression {
{
public Super(Token offset) {
super(TypePlaceholder.fresh(offset), offset);
}
public Super(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) public Super(RefTypeOrTPHOrWildcardOrGeneric type, Token offset)
{ {
super(type, offset); super(type, offset);

View File

@ -8,9 +8,8 @@ import de.dhbwstuttgart.exceptions.NotImplementedException;
public class This extends Expression public class This extends Expression
{ {
public This(Token offset) public This(Token offset) {
{ super(TypePlaceholder.fresh(offset), offset);
super(TypePlaceholder.fresh(offset),offset);
} }
public ArgumentList arglist; public ArgumentList arglist;

View File

@ -199,6 +199,7 @@ public class StatementToTargetExpression implements ASTVisitor {
Method foundMethod = null; Method foundMethod = null;
var isStatic = false; var isStatic = false;
var isInterface = true; var isInterface = true;
var isPrivate = false;
var signature = methodCall.signatureArguments().stream().map(converter::convert).toList(); var signature = methodCall.signatureArguments().stream().map(converter::convert).toList();
var receiverClass = converter.currentClass; var receiverClass = converter.currentClass;
@ -214,10 +215,11 @@ public class StatementToTargetExpression implements ASTVisitor {
returnType = converter.convert(foundMethod.getReturnType()); returnType = converter.convert(foundMethod.getReturnType());
argList = foundMethod.getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList(); argList = foundMethod.getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
isStatic = Modifier.isStatic(foundMethod.modifier); isStatic = Modifier.isStatic(foundMethod.modifier);
isPrivate = Modifier.isPrivate(foundMethod.modifier);
isInterface = receiverClass.isInterface(); isInterface = receiverClass.isInterface();
} }
result = new TargetMethodCall(converter.convert(methodCall.getType()), returnType, argList, converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), receiverType, methodCall.name, isStatic, isInterface); result = new TargetMethodCall(converter.convert(methodCall.getType()), returnType, argList, converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), receiverType, methodCall.name, isStatic, isInterface, isPrivate);
} }
@Override @Override
@ -288,7 +290,7 @@ public class StatementToTargetExpression implements ASTVisitor {
var type = converter.convert(superCall.getType()); var type = converter.convert(superCall.getType());
var parameters = superCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList(); var parameters = superCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList();
result = new TargetMethodCall(type, type, parameters, new TargetSuper(aSuper), superCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aSuper, superCall.name, false, false); result = new TargetMethodCall(type, type, parameters, new TargetSuper(aSuper), superCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aSuper, superCall.name, false, false, false);
} }
@Override @Override
@ -297,7 +299,7 @@ public class StatementToTargetExpression implements ASTVisitor {
var type = converter.convert(thisCall.getType()); var type = converter.convert(thisCall.getType());
var parameters = thisCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList(); var parameters = thisCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList();
result = new TargetMethodCall(type, type, parameters, new TargetThis(aThis), thisCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aThis, thisCall.name, false, false); result = new TargetMethodCall(type, type, parameters, new TargetThis(aThis), thisCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aThis, thisCall.name, false, false, false);
} }
@Override @Override

View File

@ -1,15 +1,13 @@
package de.dhbwstuttgart.target.tree.expression; package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.MethodParameter;
import de.dhbwstuttgart.target.tree.TargetMethod; import de.dhbwstuttgart.target.tree.TargetMethod;
import de.dhbwstuttgart.target.tree.type.TargetRefType;
import de.dhbwstuttgart.target.tree.type.TargetType; import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List; import java.util.List;
public record TargetMethodCall(TargetType type, TargetType returnType, List<TargetType> parameterTypes, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface) implements TargetStatementExpression { public record TargetMethodCall(TargetType type, TargetType returnType, List<TargetType> parameterTypes, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface, boolean isPrivate) implements TargetStatementExpression {
public TargetMethodCall(TargetType type, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface) { public TargetMethodCall(TargetType type, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface, boolean isPrivate) {
this(type, type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface); this(type, type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface, isPrivate);
} }

View File

@ -30,6 +30,14 @@ public class TypeInferenceBlockInformation extends TypeInferenceInformation {
public ClassOrInterface getCurrentClass() { public ClassOrInterface getCurrentClass() {
return currentClass; return currentClass;
} }
public ClassOrInterface getSuperClass() {
for (var clazz : getAvailableClasses()) {
if (clazz.getClassName().equals(currentClass.getSuperClass().getName()))
return clazz;
}
return null;
}
public TypeScope getCurrentTypeScope() { public TypeScope getCurrentTypeScope() {
return methodContext; return methodContext;
} }

View File

@ -499,7 +499,13 @@ public class TYPEStmt implements StatementVisitor {
@Override @Override
public void visit(Super aSuper) { public void visit(Super aSuper) {
throw new NotImplementedException(); var superClass = info.getSuperClass();
var params = new ArrayList<RefTypeOrTPHOrWildcardOrGeneric>();
for (var gtv : superClass.getGenerics()) {
params.add(new GenericRefType(gtv.getName(), aSuper.getOffset()));
}
var superType = new RefType(superClass.getClassName(), params, aSuper.getOffset());
constraintsSet.addUndConstraint(new Pair(aSuper.getType(), superType, PairOperator.EQUALSDOT, loc(aSuper.getOffset())));
} }
@Override @Override
@ -559,19 +565,15 @@ public class TYPEStmt implements StatementVisitor {
@Override @Override
public void visit(SuperCall superCall) { public void visit(SuperCall superCall) {
Set<Constraint<Pair>> methodConstraints = new HashSet<>(); Set<Constraint<Pair>> methodConstraints = new HashSet<>();
for (var clazz : info.getAvailableClasses()) { var clazz = info.getSuperClass();
if (clazz.getClassName().equals(info.getCurrentClass().getSuperClass().getName())) { for (var ctor : clazz.getConstructors()) {
for (var ctor : clazz.getConstructors()) { var params = convertParams(ctor.getParameterList(), info);
var params = convertParams(ctor.getParameterList(), info); if (params.size() != superCall.arglist.getArguments().size()) continue;
if (params.size() != superCall.arglist.getArguments().size()) continue; var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(clazz, ctor), ctor.isInherited);
var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(clazz, ctor), ctor.isInherited);
GenericsResolver resolver = getResolverInstance(); GenericsResolver resolver = getResolverInstance();
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver); Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver);
methodConstraints.addAll(oneMethodConstraints); methodConstraints.addAll(oneMethodConstraints);
}
break;
}
} }
constraintsSet.addOderConstraint(methodConstraints); constraintsSet.addOderConstraint(methodConstraints);
} }

View File

@ -980,4 +980,11 @@ public class TestComplete {
var clazz = classFiles.get("Bug298"); var clazz = classFiles.get("Bug298");
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
} }
@Test
public void testBug300() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug300.jav");
var clazz = classFiles.get("Bug300");
var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("m").invoke(instance), "Base");
}
} }

View File

@ -174,7 +174,7 @@ public class TestCodegen {
@Test @Test
public void testMethodCall() throws Exception { public void testMethodCall() throws Exception {
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("HelloWorld")); var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("HelloWorld"));
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "helloWorld", List.of(), null, new TargetBlock(List.of(new TargetMethodCall(null, new TargetFieldVar(new TargetRefType("java.io.PrintStream"), new TargetRefType("java.lang.System"), true, new TargetClassName(new TargetRefType("java.lang.System")), "out"), List.of(new TargetLiteral.StringLiteral("Hello World!")), new TargetRefType("java.io.PrintStream"), "println", false, false)))); targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "helloWorld", List.of(), null, new TargetBlock(List.of(new TargetMethodCall(null, new TargetFieldVar(new TargetRefType("java.io.PrintStream"), new TargetRefType("java.lang.System"), true, new TargetClassName(new TargetRefType("java.lang.System")), "out"), List.of(new TargetLiteral.StringLiteral("Hello World!")), new TargetRefType("java.io.PrintStream"), "println", false, false, false))));
var clazz = generateClass(targetClass, new ByteArrayClassLoader()); var clazz = generateClass(targetClass, new ByteArrayClassLoader());
clazz.getDeclaredMethod("helloWorld").invoke(null); clazz.getDeclaredMethod("helloWorld").invoke(null);
@ -271,8 +271,8 @@ public class TestCodegen {
var interfaceType = TargetFunNType.fromParams(List.of(TargetType.Integer)); var interfaceType = TargetFunNType.fromParams(List.of(TargetType.Integer));
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("CGLambda")); var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("CGLambda"));
targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of(new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "<init>", false, false)))); targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of(new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "<init>", false, false, false))));
targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(interfaceType, "by2", new TargetLambdaExpression(interfaceType, List.of(), List.of(new MethodParameter(TargetType.Integer, "num")), TargetType.Integer, new TargetBlock(List.of(new TargetReturn(new TargetBinaryOp.Mul(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "num"), new TargetLiteral.IntLiteral(2))))))), new TargetReturn(new TargetCast(TargetType.Integer, new TargetMethodCall(TargetType.Object, TargetType.Object, List.of(TargetType.Object), new TargetLocalVar(interfaceType, "by2"), List.of(new TargetLiteral.IntLiteral(10)), interfaceType, "apply", false, true)))))); targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(interfaceType, "by2", new TargetLambdaExpression(interfaceType, List.of(), List.of(new MethodParameter(TargetType.Integer, "num")), TargetType.Integer, new TargetBlock(List.of(new TargetReturn(new TargetBinaryOp.Mul(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "num"), new TargetLiteral.IntLiteral(2))))))), new TargetReturn(new TargetCast(TargetType.Integer, new TargetMethodCall(TargetType.Object, TargetType.Object, List.of(TargetType.Object), new TargetLocalVar(interfaceType, "by2"), List.of(new TargetLiteral.IntLiteral(10)), interfaceType, "apply", false, true, false))))));
var clazz = generateClass(targetClass, classLoader); var clazz = generateClass(targetClass, classLoader);
var instance = clazz.getConstructor().newInstance(); var instance = clazz.getConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("lambda").invoke(instance), 20); assertEquals(clazz.getDeclaredMethod("lambda").invoke(instance), 20);