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
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m35s
This commit is contained in:
parent
1c63321b30
commit
786e0a7a23
17
resources/bytecode/javFiles/Bug300.jav
Normal file
17
resources/bytecode/javFiles/Bug300.jav
Normal 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";
|
||||
}
|
||||
}
|
@ -1045,7 +1045,12 @@ public class Codegen {
|
||||
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));
|
||||
|
||||
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.returnType().equals(call.type()) && !(call.type() instanceof TargetGenericType))
|
||||
|
@ -131,6 +131,7 @@ public class JavaTXCompiler {
|
||||
public ConstraintSet<Pair> getConstraints() throws ClassNotFoundException, IOException {
|
||||
Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
|
||||
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
|
||||
for (Entry<File, SourceFile> source : sourceFiles.entrySet()) {
|
||||
var importedClasses = new ArrayList<ClassOrInterface>();
|
||||
|
@ -1028,7 +1028,7 @@ public class StatementGenerator {
|
||||
case PrimaryThisContext primthis:
|
||||
return new This(primthis.getStart());
|
||||
case PrimarySuperContext primsuper:
|
||||
throw new NotImplementedException();
|
||||
return new Super(primsuper.getStart());
|
||||
case PrimaryLiteralContext primliteral:
|
||||
return convert(primliteral.literal());
|
||||
case PrimaryIdentifierContext primidentifier:
|
||||
|
@ -3,6 +3,7 @@ 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.TypePlaceholder;
|
||||
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||
@ -10,8 +11,12 @@ import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
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)
|
||||
{
|
||||
super(type, offset);
|
||||
|
@ -8,8 +8,7 @@ import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
|
||||
public class This extends Expression
|
||||
{
|
||||
public This(Token offset)
|
||||
{
|
||||
public This(Token offset) {
|
||||
super(TypePlaceholder.fresh(offset), offset);
|
||||
}
|
||||
|
||||
|
@ -199,6 +199,7 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
Method foundMethod = null;
|
||||
var isStatic = false;
|
||||
var isInterface = true;
|
||||
var isPrivate = false;
|
||||
var signature = methodCall.signatureArguments().stream().map(converter::convert).toList();
|
||||
|
||||
var receiverClass = converter.currentClass;
|
||||
@ -214,10 +215,11 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
returnType = converter.convert(foundMethod.getReturnType());
|
||||
argList = foundMethod.getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
|
||||
isStatic = Modifier.isStatic(foundMethod.modifier);
|
||||
isPrivate = Modifier.isPrivate(foundMethod.modifier);
|
||||
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
|
||||
@ -288,7 +290,7 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
var type = converter.convert(superCall.getType());
|
||||
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
|
||||
@ -297,7 +299,7 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
var type = converter.convert(thisCall.getType());
|
||||
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
|
||||
|
@ -1,15 +1,13 @@
|
||||
package de.dhbwstuttgart.target.tree.expression;
|
||||
|
||||
import de.dhbwstuttgart.target.tree.MethodParameter;
|
||||
import de.dhbwstuttgart.target.tree.TargetMethod;
|
||||
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
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 TargetMethodCall(TargetType type, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface) {
|
||||
this(type, type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface);
|
||||
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, boolean isPrivate) {
|
||||
this(type, type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface, isPrivate);
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,6 +30,14 @@ public class TypeInferenceBlockInformation extends TypeInferenceInformation {
|
||||
public ClassOrInterface getCurrentClass() {
|
||||
return currentClass;
|
||||
}
|
||||
|
||||
public ClassOrInterface getSuperClass() {
|
||||
for (var clazz : getAvailableClasses()) {
|
||||
if (clazz.getClassName().equals(currentClass.getSuperClass().getName()))
|
||||
return clazz;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public TypeScope getCurrentTypeScope() {
|
||||
return methodContext;
|
||||
}
|
||||
|
@ -499,7 +499,13 @@ public class TYPEStmt implements StatementVisitor {
|
||||
|
||||
@Override
|
||||
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
|
||||
@ -559,8 +565,7 @@ public class TYPEStmt implements StatementVisitor {
|
||||
@Override
|
||||
public void visit(SuperCall superCall) {
|
||||
Set<Constraint<Pair>> methodConstraints = new HashSet<>();
|
||||
for (var clazz : info.getAvailableClasses()) {
|
||||
if (clazz.getClassName().equals(info.getCurrentClass().getSuperClass().getName())) {
|
||||
var clazz = info.getSuperClass();
|
||||
for (var ctor : clazz.getConstructors()) {
|
||||
var params = convertParams(ctor.getParameterList(), info);
|
||||
if (params.size() != superCall.arglist.getArguments().size()) continue;
|
||||
@ -570,9 +575,6 @@ public class TYPEStmt implements StatementVisitor {
|
||||
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver);
|
||||
methodConstraints.addAll(oneMethodConstraints);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
constraintsSet.addOderConstraint(methodConstraints);
|
||||
}
|
||||
|
||||
|
@ -980,4 +980,11 @@ public class TestComplete {
|
||||
var clazz = classFiles.get("Bug298");
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ public class TestCodegen {
|
||||
@Test
|
||||
public void testMethodCall() throws Exception {
|
||||
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());
|
||||
clazz.getDeclaredMethod("helloWorld").invoke(null);
|
||||
@ -271,8 +271,8 @@ public class TestCodegen {
|
||||
var interfaceType = TargetFunNType.fromParams(List.of(TargetType.Integer));
|
||||
|
||||
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.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.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, false))))));
|
||||
var clazz = generateClass(targetClass, classLoader);
|
||||
var instance = clazz.getConstructor().newInstance();
|
||||
assertEquals(clazz.getDeclaredMethod("lambda").invoke(instance), 20);
|
||||
|
Loading…
Reference in New Issue
Block a user