diff --git a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java index 8b540e69..948c55fd 100755 --- a/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -1,6 +1,5 @@ package de.dhbwstuttgart.target.bytecode; -import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.target.tree.*; import de.dhbwstuttgart.target.tree.expression.*; import de.dhbwstuttgart.target.tree.type.TargetFunNType; @@ -13,20 +12,22 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.IntStream; import static org.objectweb.asm.Opcodes.*; import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*; import static de.dhbwstuttgart.target.tree.expression.TargetLiteral.*; public class Codegen { - private TargetClass clazz; - private ClassWriter cw; + private final TargetClass clazz; + private final ClassWriter cw; + public final String className; public Codegen(TargetClass clazz) { this.clazz = clazz; + this.className = clazz.qualifiedName(); this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); } @@ -125,14 +126,14 @@ public class Codegen { } } - private void generateRelationalOperator(State state, TargetRelationalOp op, int code) { + private void generateRelationalOperator(State state, TargetRelationalOp op, TargetType type, int code) { var mv = state.mv; Label if_true = new Label(); Label end = new Label(); generate(state, op.left()); - convertTo(state, op.exprType(), op.type()); + convertTo(state, op.left().type(), type); generate(state, op.right()); - convertTo(state, op.exprType(), op.type()); + convertTo(state, op.right().type(), type); mv.visitJumpInsn(code, if_true); mv.visitInsn(ICONST_0); mv.visitJumpInsn(GOTO, end); @@ -141,16 +142,15 @@ public class Codegen { mv.visitLabel(end); } - private void generateRelationalOperator(State state, TargetRelationalOp op, int cmp, int code) { + private void generateRelationalOperator(State state, TargetRelationalOp op, TargetType type, int cmp, int code) { var mv = state.mv; Label if_true = new Label(); Label end = new Label(); generate(state, op.left()); - convertTo(state, op.left().type(), op.exprType()); + convertTo(state, op.left().type(), type); generate(state, op.right()); - convertTo(state, op.right().type(), op.exprType()); + convertTo(state, op.right().type(), type); mv.visitInsn(cmp); - mv.visitInsn(code); mv.visitJumpInsn(code, if_true); mv.visitInsn(ICONST_0); mv.visitJumpInsn(GOTO, end); @@ -159,14 +159,35 @@ public class Codegen { mv.visitLabel(end); } + private void convertToString(State state, TargetType type) { + var mv = state.mv; + if (type.equals(TargetType.Boolean)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(Z)Ljava/lang/Boolean;", false); + } else if (type.equals(TargetType.Byte)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(B)Ljava/lang/Byte;", false); + } else if (type.equals(TargetType.Double)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(D)Ljava/lang/Double;", false); + } else if (type.equals(TargetType.Long)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(J)Ljava/lang/Long;", false); + } else if (type.equals(TargetType.Integer)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(I)Ljava/lang/Integer;", false); + } else if (type.equals(TargetType.Float)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(F)Ljava/lang/Float;", false); + } else if (type.equals(TargetType.Short)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(S)Ljava/lang/Short;", false); + } else if (type.equals(TargetType.Char)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(C)Ljava/lang/Char;", false); + } + } + private void convertTo(State state, TargetType source, TargetType dest) { var mv = state.mv; if (source.equals(dest)) return; if (source.equals(TargetType.Long)) { - if (dest.equals(TargetType.Integer)) + if (dest.equals(TargetType.Integer)) { mv.visitInsn(L2I); - else if (dest.equals(TargetType.Float)) + } else if (dest.equals(TargetType.Float)) mv.visitInsn(L2F); else if (dest.equals(TargetType.Double)) mv.visitInsn(L2D); @@ -174,7 +195,7 @@ public class Codegen { || dest.equals(TargetType.Char) || dest.equals(TargetType.Short)) { mv.visitInsn(L2I); - source = TargetType.Integer; + convertTo(state, TargetType.Integer, dest); } } else if (source.equals(TargetType.Float)) { if (dest.equals(TargetType.Integer)) @@ -187,7 +208,7 @@ public class Codegen { || dest.equals(TargetType.Char) || dest.equals(TargetType.Short)) { mv.visitInsn(F2I); - source = TargetType.Integer; + convertTo(state, TargetType.Integer, dest); } } else if (source.equals(TargetType.Double)) { if (dest.equals(TargetType.Integer)) @@ -200,10 +221,9 @@ public class Codegen { || dest.equals(TargetType.Char) || dest.equals(TargetType.Short)) { mv.visitInsn(D2I); - source = TargetType.Integer; + convertTo(state, TargetType.Integer, dest); } - } - if (source.equals(TargetType.Byte) + } else if (source.equals(TargetType.Byte) || source.equals(TargetType.Char) || source.equals(TargetType.Short) || source.equals(TargetType.Integer)) { @@ -220,33 +240,62 @@ public class Codegen { else if (dest.equals(TargetType.Double)) mv.visitInsn(I2D); } else { + boxPrimitive(state, source); mv.visitTypeInsn(CHECKCAST, dest.getName()); unboxPrimitive(state, dest); } } + private TargetType largerType(TargetType left, TargetType right) { + if (left.equals(TargetType.String) || right.equals(TargetType.String)) { + return TargetType.String; + } else if (left.equals(TargetType.Double) || right.equals(TargetType.Double)) { + return TargetType.Double; + } else if (left.equals(TargetType.Float) || right.equals(TargetType.Float)) { + return TargetType.Float; + } else if (left.equals(TargetType.Long) || right.equals(TargetType.Long)) { + return TargetType.Long; + } else { + return TargetType.Integer; + } + } + private void generateBinaryOp(State state, TargetBinaryOp op) { var mv = state.mv; switch (op) { case Add add: { - generate(state, add.left()); - convertTo(state, add.left().type(), op.type()); - generate(state, add.right()); - convertTo(state, add.right().type(), op.type()); - var type = add.type(); - if (type.equals(TargetType.Byte) - || type.equals(TargetType.Char) - || type.equals(TargetType.Integer) - || type.equals(TargetType.Short)) { - mv.visitInsn(IADD); - } else if (type.equals(TargetType.Long)) { - mv.visitInsn(LADD); - } else if (type.equals(TargetType.Float)) { - mv.visitInsn(FADD); - } else if (type.equals(TargetType.Double)) { - mv.visitInsn(DADD); + if (add.type().equals(TargetType.String)) { + mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); + mv.visitInsn(DUP); + generate(state, add.left()); + convertToString(state, add.left().type()); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "", "(Ljava/lang/String;)V", false); } else { - throw new CodeGenException("Invalid argument to Add expression"); + generate(state, add.left()); + convertTo(state, add.left().type(), add.type()); + generate(state, add.right()); + convertTo(state, add.right().type(), add.type()); + var type = add.type(); + if (type.equals(TargetType.Byte) + || type.equals(TargetType.Char) + || type.equals(TargetType.Integer) + || type.equals(TargetType.Short)) { + mv.visitInsn(IADD); + } else if (type.equals(TargetType.Long)) { + mv.visitInsn(LADD); + } else if (type.equals(TargetType.Float)) { + mv.visitInsn(FADD); + } else if (type.equals(TargetType.Double)) { + mv.visitInsn(DADD); + } else { + throw new CodeGenException("Invalid argument to Add expression"); + } + } + if (add.type().equals(TargetType.String)) { + generate(state, add.right()); + convertToString(state, add.right().type()); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); } break; } @@ -429,106 +478,231 @@ public class Codegen { break; } case Greater greater: { - var type = greater.exprType(); + var type = largerType(greater.left().type(), greater.right().type()); if (type.equals(TargetType.Long)) { - generateRelationalOperator(state, greater, LCMP, IFGT); + generateRelationalOperator(state, greater, type, LCMP, IFGT); } else if (type.equals(TargetType.Float)) { - generateRelationalOperator(state, greater, FCMPL, IFGT); + generateRelationalOperator(state, greater, type, FCMPL, IFGT); } else if (type.equals(TargetType.Double)) { - generateRelationalOperator(state, greater, DCMPL, IFGT); + generateRelationalOperator(state, greater, type, DCMPL, IFGT); } else { - generateRelationalOperator(state, greater, IF_ICMPGT); + generateRelationalOperator(state, greater, type, IF_ICMPGT); } break; } case Less less: { - var type = less.exprType(); + var type = largerType(less.left().type(), less.right().type()); if (type.equals(TargetType.Long)) { - generateRelationalOperator(state, less, LCMP, IFLT); + generateRelationalOperator(state, less, type, LCMP, IFLT); } else if (type.equals(TargetType.Float)) { - generateRelationalOperator(state, less, FCMPL, IFLT); + generateRelationalOperator(state, less, type, FCMPL, IFLT); } else if (type.equals(TargetType.Double)) { - generateRelationalOperator(state, less, DCMPL, IFLT); + generateRelationalOperator(state, less, type, DCMPL, IFLT); } else { - generateRelationalOperator(state, less, IF_ICMPLT); + generateRelationalOperator(state, less, type, IF_ICMPLT); } break; } case GreaterOrEqual greaterOrEqual: { - var type = greaterOrEqual.exprType(); + var type = largerType(greaterOrEqual.left().type(), greaterOrEqual.right().type()); if (type.equals(TargetType.Long)) { - generateRelationalOperator(state, greaterOrEqual, LCMP, IFGE); + generateRelationalOperator(state, greaterOrEqual, type, LCMP, IFGE); } else if (type.equals(TargetType.Float)) { - generateRelationalOperator(state, greaterOrEqual, FCMPL, IFGE); + generateRelationalOperator(state, greaterOrEqual, type, FCMPL, IFGE); } else if (type.equals(TargetType.Double)) { - generateRelationalOperator(state, greaterOrEqual, DCMPL, IFGE); + generateRelationalOperator(state, greaterOrEqual, type, DCMPL, IFGE); } else { - generateRelationalOperator(state, greaterOrEqual, IF_ICMPGE); + generateRelationalOperator(state, greaterOrEqual, type, IF_ICMPGE); } break; } case LessOrEqual lessOrEqual: { - var type = lessOrEqual.exprType(); + var type = largerType(lessOrEqual.left().type(), lessOrEqual.right().type()); if (type.equals(TargetType.Long)) { - generateRelationalOperator(state, lessOrEqual, LCMP, IFLE); + generateRelationalOperator(state, lessOrEqual, type, LCMP, IFLE); } else if (type.equals(TargetType.Float)) { - generateRelationalOperator(state, lessOrEqual, FCMPL, IFLE); + generateRelationalOperator(state, lessOrEqual, type, FCMPL, IFLE); } else if (type.equals(TargetType.Double)) { - generateRelationalOperator(state, lessOrEqual, DCMPL, IFLE); + generateRelationalOperator(state, lessOrEqual, type, DCMPL, IFLE); } else { - generateRelationalOperator(state, lessOrEqual, IF_ICMPLE); + generateRelationalOperator(state, lessOrEqual, type, IF_ICMPLE); } break; } case Equal equal: { - var type = equal.exprType(); + var type = largerType(equal.left().type(), equal.right().type()); if (type.equals(TargetType.Long)) { - generateRelationalOperator(state, equal, LCMP, IFEQ); + generateRelationalOperator(state, equal, type, LCMP, IFEQ); } else if (type.equals(TargetType.Float)) { - generateRelationalOperator(state, equal, FCMPL, IFEQ); + generateRelationalOperator(state, equal, type, FCMPL, IFEQ); } else if (type.equals(TargetType.Double)) { - generateRelationalOperator(state, equal, DCMPL, IFEQ); + generateRelationalOperator(state, equal, type, DCMPL, IFEQ); } else if (type.equals(TargetType.Char) || type.equals(TargetType.Short) || type.equals(TargetType.Byte) - || type.equals(TargetType.Integer)) { - generateRelationalOperator(state, equal, IF_ICMPEQ); + || type.equals(TargetType.Integer) + || type.equals(TargetType.Boolean)) { + generateRelationalOperator(state, equal, type, IF_ICMPEQ); } else { - generateRelationalOperator(state, equal, IF_ACMPEQ); + generateRelationalOperator(state, equal, type, IF_ACMPEQ); } break; } case NotEqual notEqual: { - var type = notEqual.exprType(); + var type = largerType(notEqual.left().type(), notEqual.right().type()); if (type.equals(TargetType.Long)) { - generateRelationalOperator(state, notEqual, LCMP, IFNE); + generateRelationalOperator(state, notEqual, type, LCMP, IFNE); } else if (type.equals(TargetType.Float)) { - generateRelationalOperator(state, notEqual, FCMPL, IFNE); + generateRelationalOperator(state, notEqual, type, FCMPL, IFNE); } else if (type.equals(TargetType.Double)) { - generateRelationalOperator(state, notEqual, DCMPL, IFNE); + generateRelationalOperator(state, notEqual, type, DCMPL, IFNE); } else if (type.equals(TargetType.Char) || type.equals(TargetType.Short) || type.equals(TargetType.Byte) || type.equals(TargetType.Integer)) { - generateRelationalOperator(state, notEqual, IF_ICMPNE); + generateRelationalOperator(state, notEqual, type, IF_ICMPNE); } else { - generateRelationalOperator(state, notEqual, IF_ACMPNE); + generateRelationalOperator(state, notEqual, type, IF_ACMPNE); } break; } } } + private void afterIncDec(State state, TargetUnaryOp op) { + var mv = state.mv; + if (op.expr() instanceof TargetLocalVar localVar) { + mv.visitVarInsn(ASTORE, state.scope.get(localVar.name()).index); + } else if (op.expr() instanceof TargetFieldVar fieldVar) { + generate(state, fieldVar.left()); + mv.visitInsn(SWAP); + mv.visitFieldInsn(PUTFIELD, fieldVar.owner().getName(), fieldVar.right(), fieldVar.type().toSignature()); + } + } + private void generateUnaryOp(State state, TargetUnaryOp op) { - // TODO - throw new NotImplementedException(); + var mv = state.mv; + switch (op) { + case TargetUnaryOp.Add add: + // This literally does nothing + generate(state, add.expr()); + break; + case TargetUnaryOp.Negate negate: + generate(state, negate.expr()); + if (negate.type().equals(TargetType.Double)) + mv.visitInsn(DNEG); + else if (negate.type().equals(TargetType.Float)) + mv.visitInsn(FNEG); + else if (negate.type().equals(TargetType.Long)) + mv.visitInsn(LNEG); + else mv.visitInsn(INEG); + break; + case TargetUnaryOp.Not not: + generate(state, not.expr()); + if (not.type().equals(TargetType.Long)) { + mv.visitLdcInsn(-1L); + mv.visitInsn(LXOR); + } else { + mv.visitInsn(ICONST_M1); + mv.visitInsn(IXOR); + } + break; + case TargetUnaryOp.PreIncrement preIncrement: + generate(state, preIncrement.expr()); + if (preIncrement.type().equals(TargetType.Float)) { + mv.visitLdcInsn(1F); + mv.visitInsn(FADD); + mv.visitInsn(DUP); + } else if (preIncrement.type().equals(TargetType.Double)) { + mv.visitLdcInsn(1D); + mv.visitInsn(DADD); + mv.visitInsn(DUP2); + } else if (preIncrement.type().equals(TargetType.Long)) { + mv.visitLdcInsn(1L); + mv.visitInsn(LADD); + mv.visitInsn(DUP2); + } else { + mv.visitLdcInsn(1); + mv.visitInsn(IADD); + mv.visitInsn(DUP); + } + boxPrimitive(state, preIncrement.type()); + afterIncDec(state, preIncrement); + break; + case TargetUnaryOp.PreDecrement preDecrement: + generate(state, preDecrement.expr()); + if (preDecrement.type().equals(TargetType.Float)) { + mv.visitLdcInsn(1F); + mv.visitInsn(FSUB); + mv.visitInsn(DUP); + } else if (preDecrement.type().equals(TargetType.Double)) { + mv.visitLdcInsn(1D); + mv.visitInsn(DSUB); + mv.visitInsn(DUP2); + } else if (preDecrement.type().equals(TargetType.Long)) { + mv.visitLdcInsn(1L); + mv.visitInsn(LSUB); + mv.visitInsn(DUP2); + } else { + mv.visitLdcInsn(1); + mv.visitInsn(ISUB); + mv.visitInsn(DUP); + } + boxPrimitive(state, preDecrement.type()); + afterIncDec(state, preDecrement); + break; + case TargetUnaryOp.PostIncrement postIncrement: + generate(state, postIncrement.expr()); + if (postIncrement.type().equals(TargetType.Float)) { + mv.visitInsn(DUP); + mv.visitLdcInsn(1F); + mv.visitInsn(FADD); + } else if (postIncrement.type().equals(TargetType.Double)) { + mv.visitInsn(DUP2); + mv.visitLdcInsn(1D); + mv.visitInsn(DADD); + } else if (postIncrement.type().equals(TargetType.Long)) { + mv.visitInsn(DUP2); + mv.visitLdcInsn(1L); + mv.visitInsn(LADD); + } else { + mv.visitInsn(DUP); + mv.visitLdcInsn(1); + mv.visitInsn(IADD); + } + boxPrimitive(state, postIncrement.type()); + afterIncDec(state, postIncrement); + break; + case TargetUnaryOp.PostDecrement postDecrement: + generate(state, postDecrement.expr()); + if (postDecrement.type().equals(TargetType.Float)) { + mv.visitInsn(DUP); + mv.visitLdcInsn(1F); + mv.visitInsn(FSUB); + } else if (postDecrement.type().equals(TargetType.Double)) { + mv.visitInsn(DUP2); + mv.visitLdcInsn(1D); + mv.visitInsn(DSUB); + } else if (postDecrement.type().equals(TargetType.Long)) { + mv.visitInsn(DUP2); + mv.visitLdcInsn(1L); + mv.visitInsn(LSUB); + } else { + mv.visitInsn(DUP); + mv.visitLdcInsn(1); + mv.visitInsn(ISUB); + } + boxPrimitive(state, postDecrement.type()); + afterIncDec(state, postDecrement); + break; + } } private void generateLambdaExpression(State state, TargetLambdaExpression lambda) { var mv = state.mv; var name = "lambda$" + state.lambdaCounter; var impl = new TargetMethod( - ACC_PRIVATE, name, Set.of(), + 0, name, Set.of(), lambda.params(), lambda.returnType(), lambda.block() ); generateMethod(impl); @@ -665,6 +839,7 @@ public class Codegen { if (!dot.isStatic()) generate(state, dot.left()); mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, dot.left().type().getName(), dot.right(), dot.type().toSignature()); + unboxPrimitive(state, dot.type()); break; } case TargetFor _for: { @@ -738,8 +913,17 @@ public class Codegen { generate(state, e); boxPrimitive(state, e.type()); } - mv.visitMethodInsn(call.isInterface() ? INVOKEINTERFACE : call.isStatic() ? INVOKESTATIC: call.name() == "" ? INVOKESPECIAL : INVOKEVIRTUAL, - call.owner().getName(), call.name(), call.getDescriptor(), call.isInterface()); + var descriptor = call.getDescriptor(); + if (call.owner() instanceof TargetFunNType) // Decay FunN + descriptor = TargetMethod.getDescriptor( + call.type() == 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("") ? INVOKESPECIAL : INVOKEVIRTUAL, + call.owner().getName(), call.name(), descriptor, call.isInterface()); + if (call.owner() instanceof TargetFunNType) + mv.visitTypeInsn(CHECKCAST, call.type().getName()); if (call.type() != null) unboxPrimitive(state, call.type()); break; @@ -763,11 +947,11 @@ public class Codegen { } private void generateField(TargetField field) { - cw.visitField(field.access(), field.name(), field.type().toSignature(), field.type().toGenericSignature(), null); + cw.visitField(field.access() | ACC_PUBLIC, field.name(), field.type().toSignature(), field.type().toGenericSignature(), null); } private void generateConstructor(TargetConstructor constructor) { - MethodVisitor mv = cw.visitMethod(constructor.access(), "", constructor.getDescriptor(), constructor.getSignature(), null); + MethodVisitor mv = cw.visitMethod(constructor.access() | ACC_PUBLIC, "", constructor.getDescriptor(), constructor.getSignature(), null); mv.visitCode(); var state = new State(mv, 1); for (var param: constructor.parameters()) @@ -779,7 +963,8 @@ public class Codegen { } private void generateMethod(TargetMethod method) { - MethodVisitor mv = cw.visitMethod(method.access(), method.name(), method.getDescriptor(), method.getSignature(), null); + // TODO The older codegen has set ACC_PUBLIC for all methods, good for testing but bad for everything else + MethodVisitor mv = cw.visitMethod(method.access() | ACC_PUBLIC, method.name(), method.getDescriptor(), method.getSignature(), null); mv.visitCode(); var state = new State(mv, method.isStatic() ? 0 : 1); for (var param: method.parameters()) @@ -803,7 +988,7 @@ public class Codegen { } public byte[] generate() { - cw.visit(V1_8, clazz.modifiers(), clazz.qualifiedName(), + cw.visit(V1_8, clazz.modifiers() | ACC_PUBLIC, clazz.qualifiedName(), generateSignature(clazz), clazz.superType() != null ? clazz.superType().getName(): "java/lang/Object", clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new) ); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index a118339b..b1eea73c 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.target.generate; +import de.dhbwstuttgart.bytecode.funN.FunNGenerator; import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; @@ -25,6 +26,7 @@ public class ASTToTargetAST { private class Sigma { Map>> computedGenericsOfMethods = new HashMap<>(); + Map> usedTPHsOfMethods = new HashMap<>(); Map>> computedGenericsOfClasses = new HashMap<>(); Set simplifiedConstraints = new HashSet<>(); @@ -142,14 +144,16 @@ public class ASTToTargetAST { if (expressionReceiver.expr instanceof This) { // TODO This is going to fail spectacularly for overloaded methods var optMethod = owner.getMethods().stream().filter(m -> m.name.equals(methodCall.name)).findFirst(); - assert optMethod.isPresent(); + if (optMethod.isEmpty()) return; var method = optMethod.get(); var generics = generics(owner, method); Set> all = new HashSet<>(generics); // Reflexive and Transitive closure HashSet> toAdd = new HashSet<>(); + int sizeBefore; do { + sizeBefore = all.size(); toAdd.clear(); for (var g1 : all) { for (var g2 : all) { @@ -160,7 +164,7 @@ public class ASTToTargetAST { } } all.addAll(toAdd); - } while (toAdd.size() > 0); + } while (sizeBefore < all.size()); for (var generic : all) { toAdd.add(new PairTPHsmallerTPH((TypePlaceholder) generic.getLeft(), (TypePlaceholder) generic.getLeft())); } @@ -231,6 +235,11 @@ public class ASTToTargetAST { eliminateCyclesAndInfima(result); System.out.println(method.name + ": " + result); + Set allUsedTPHs = new HashSet<>(); + allUsedTPHs.addAll(typeVariables); + allUsedTPHs.addAll(typeVariablesOfFields); + usedTPHsOfMethods.put(method, allUsedTPHs); + return result; } @@ -248,8 +257,11 @@ public class ASTToTargetAST { var left = equality.getOrDefault(rsp.left, rsp.left); var right = equality.getOrDefault(rsp.right, rsp.right); if (left.equals(tph)) { - generics.add(new PairTPHsmallerTPH(tph, right)); - findAllBounds(right, generics); + var pair = new PairTPHsmallerTPH(tph, right); + if (!generics.contains(pair)) { + generics.add(pair); + findAllBounds(right, generics); + } return; } } @@ -312,6 +324,10 @@ public class ASTToTargetAST { for (var field : classOrInterface.getFieldDecl()) { findTphs(field.getType(), referenced); } + for (var method : classOrInterface.getMethods()) { + generics(classOrInterface, method); + referenced.addAll(usedTPHsOfMethods.get(method)); + } var oldInput = new HashSet<>(input); for (var pair : oldInput) { @@ -320,7 +336,10 @@ public class ASTToTargetAST { for (var pair2 : oldInput) { if (pair2.getRight().equals(pair.getLeft())) { input.remove(pair2); - input.add(new PairTPHsmallerTPH((TypePlaceholder) pair2.getLeft(), (TypePlaceholder) pair.getRight())); + if (pair instanceof PairTPHsmallerTPH) + input.add(new PairTPHsmallerTPH((TypePlaceholder) pair2.getLeft(), (TypePlaceholder) pair.getRight())); + else + input.add(new PairTPHequalRefTypeOrWildcardType((TypePlaceholder) pair2.getLeft(), pair.getRight())); } } } @@ -361,7 +380,7 @@ public class ASTToTargetAST { input.removeAll(infima); for (var infimum : infima) { equality.put(infimum.right, newTph); - new HashSet<>(input).stream().forEach(pair -> { + new HashSet<>(input).forEach(pair -> { if (pair.getLeft().equals(infimum.right)) { input.remove(pair); if (pair instanceof PairTPHsmallerTPH stph) { @@ -417,6 +436,7 @@ public class ASTToTargetAST { } // Tiernan simple cycles algorithm + // Adapted from https://github.com/jgrapht/jgrapht/blob/master/jgrapht-core/src/main/java/org/jgrapht/alg/cycle/TiernanSimpleCycles.java static Set> findCycles(Set> input) { Map indices = new HashMap<>(); List path = new ArrayList<>(); @@ -576,6 +596,12 @@ public class ASTToTargetAST { ); } + private Set usedFunN = new HashSet<>(); + + public List generateUsedFunNTypes() { + return usedFunN.stream().map(n -> FunNGenerator.getInstance().generateSuperBytecode(n)).toList(); + } + protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) { return input.acceptTV(new TypeVisitor<>() { @Override @@ -584,8 +610,10 @@ public class ASTToTargetAST { if (name.equals("void")) return null; var params = refType.getParaList().stream().map(ASTToTargetAST.this::convert).toList(); - if (name.matches("Fun\\d\\$\\$")) // TODO This seems like a bad idea - return new TargetFunNType(params.size(), params); + if (name.matches("Fun\\d\\$\\$")) { // TODO This seems like a bad idea + usedFunN.add(params.size() - 1); + return new TargetFunNType(params.size() - 1, params); + } return new TargetRefType(name, params); } diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 53b69066..79338248 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -8,6 +8,7 @@ import de.dhbwstuttgart.target.tree.MethodParameter; import de.dhbwstuttgart.target.tree.expression.*; import de.dhbwstuttgart.target.tree.type.TargetFunNType; import de.dhbwstuttgart.target.tree.type.TargetRefType; +import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; import java.util.stream.StreamSupport; @@ -127,20 +128,24 @@ public class StatementToTargetExpression implements StatementVisitor { @Override public void visit(MethodCall methodCall) { + var receiverType = converter.convert(methodCall.receiver.getType()); + var isFunNType = receiverType instanceof TargetFunNType; + var returnType = converter.convert(methodCall.getType()); + result = new TargetMethodCall( - converter.convert(methodCall.getType()), - methodCall.argTypes == null ? List.of() : methodCall.argTypes.stream().map(converter::convert).toList(), + returnType, + methodCall.arglist.getArguments().stream().map(expr -> converter.convert(expr.getType())).toList(), converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), - converter.convert(methodCall.receiver.getType()), - methodCall.name, false, false + receiverType, + methodCall.name, false, isFunNType ); } @Override public void visit(NewClass newClass) { result = new TargetNew( - converter.convert(newClass.receiverType), + new TargetRefType(newClass.name), newClass.getArgumentList().getArguments().stream().map(converter::convert).toList() ); } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java index 2f733e45..92e57647 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java @@ -9,8 +9,8 @@ public sealed interface TargetUnaryOp extends TargetExpression { record Add(TargetType type, TargetExpression expr) implements TargetUnaryOp {} record Not(TargetType type, TargetExpression expr) implements TargetUnaryOp {} - record PreIncrement(TargetType type, TargetExpression expr) implements TargetStatementExpression {} - record PostIncrement(TargetType type, TargetExpression expr) implements TargetStatementExpression {} - record PreDecrement(TargetType type, TargetExpression expr) implements TargetStatementExpression {} - record PostDecrement(TargetType type, TargetExpression expr) implements TargetStatementExpression {} + record PreIncrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {} + record PostIncrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {} + record PreDecrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {} + record PostDecrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {} } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java index 5d32fb1b..533472c8 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java @@ -3,12 +3,12 @@ package de.dhbwstuttgart.target.tree.type; public record TargetExtendsWildcard(TargetType innerType) implements TargetType { @Override public String toSignature() { - return null; + return innerType.toSignature(); } @Override public String toGenericSignature() { - return null; + return innerType.toGenericSignature(); } @Override diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java index 98878f93..bdd92e03 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java @@ -3,6 +3,7 @@ package de.dhbwstuttgart.target.tree.type; import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; +import java.util.Objects; public record TargetRefType(String name, List params) implements TargetSpecializedType { public TargetRefType(String name) { @@ -17,4 +18,18 @@ public record TargetRefType(String name, List params) implements Tar public String toSignature() { return "L" + getName() + ";"; } + + // Type erasure means we need to override hashCode and equals to only consider the name + @Override + public int hashCode() { + return Objects.hashCode(name); + } + + @Override + public boolean equals(Object other) { + if (other instanceof TargetRefType refType) { + return refType.name.equals(name); + } + return false; + } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java index 3306d14d..101a3a53 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java @@ -3,12 +3,12 @@ package de.dhbwstuttgart.target.tree.type; public record TargetSuperWildcard(TargetType innerType) implements TargetType { @Override public String toSignature() { - return null; + return innerType.toSignature(); } @Override public String toGenericSignature() { - return null; + return innerType.toGenericSignature(); } @Override diff --git a/src/test/java/targetast/ASTToTypedTargetAST.java b/src/test/java/targetast/ASTToTypedTargetAST.java index 6f914432..4a46db0c 100644 --- a/src/test/java/targetast/ASTToTypedTargetAST.java +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -38,8 +38,9 @@ public class ASTToTypedTargetAST { var converter = new ASTToTargetAST(resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); - var overloading = TestCodegen.generateClass(converter.convert(classes.get(0))); - var overloading2 = TestCodegen.generateClass(converter.convert(classes.get(1))); + var classLoader = new ByteArrayClassLoader(); + var overloading = TestCodegen.generateClass(converter.convert(classes.get(0)), classLoader); + var overloading2 = TestCodegen.generateClass(converter.convert(classes.get(1)), classLoader); var test1 = overloading.getDeclaredMethod("test", overloading); test1.setAccessible(true); @@ -59,7 +60,7 @@ public class ASTToTypedTargetAST { var converter = new ASTToTargetAST(resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); - var tphAndGenerics = TestCodegen.generateClass(converter.convert(classes.get(0))); + var tphAndGenerics = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); } @Test @@ -70,7 +71,7 @@ public class ASTToTypedTargetAST { var converter = new ASTToTargetAST(resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); - var cycle = TestCodegen.generateClass(converter.convert(classes.get(0))); + var cycle = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); } @Test @@ -81,6 +82,6 @@ public class ASTToTypedTargetAST { var converter = new ASTToTargetAST(resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); - var infimum = TestCodegen.generateClass(converter.convert(classes.get(0))); + var infimum = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); } } diff --git a/src/test/java/targetast/GreaterEqualTest.java b/src/test/java/targetast/GreaterEqualTest.java new file mode 100644 index 00000000..ac9216c9 --- /dev/null +++ b/src/test/java/targetast/GreaterEqualTest.java @@ -0,0 +1,134 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class GreaterEqualTest { + static Class classToTest; + static Object instance; + + @BeforeClass + public static void beforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("GreaterEqual.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("GreaterEqual"); + instance = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testIntegers() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 7, 5); + assertTrue(result); + } + + @Test + public void testIntegers2() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5, 7); + assertFalse(result); + } + + @Test + public void testEqIntegers() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5, 5); + assertTrue(result); + } + + @Test + public void testLongs() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Long.class, Long.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 10L, 7L); + assertTrue(result); + } + + @Test + public void testFloats() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Float.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5F, 7F); + assertFalse(result); + } + + @Test + public void testDoubles() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Double.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5.0, 7.0); + assertFalse(result); + } + + @Test + public void testLongInt() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Long.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 15L, 7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5F, 7); + assertFalse(result); + } + + @Test + public void testDoubleInt() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 25.0, 17); + assertTrue(result); + } + + @Test + public void testFloatLong() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Long.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 75F, 70L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Long.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5.0, 7L); + assertFalse(result); + } + + @Test + public void testEqDoubleFloat() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 7.0, 7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 15.0, 7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 9.0, 17F); + assertFalse(result); + } +} diff --git a/src/test/java/targetast/GreaterThanTest.java b/src/test/java/targetast/GreaterThanTest.java new file mode 100644 index 00000000..c5684c5a --- /dev/null +++ b/src/test/java/targetast/GreaterThanTest.java @@ -0,0 +1,132 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class GreaterThanTest { + static Class classToTest; + static Object instance; + + @BeforeClass + public static void beforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("GreaterThan.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("GreaterThan"); + instance = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testIntegers() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 7, 5); + assertTrue(result); + } + + @Test + public void testIntegers2() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5, 7); + assertFalse(result); + } + + @Test + public void testEqIntegers() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5, 5); + assertFalse(result); + } + + @Test + public void testLongs() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Long.class, Long.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 10L,7L); + assertTrue(result); + }@Test + + public void testFloats() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Float.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5F,7F); + assertFalse(result); + } + + @Test + public void testDoubles() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Double.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5.0,7.0); + assertFalse(result); + } + + @Test + public void testLongInt() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Long.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 15L,7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5F,7); + assertFalse(result); + } + + @Test + public void testDoubleInt() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 25.0,17); + assertTrue(result); + } + + @Test + public void testFloatLong() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Long.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 75F,70L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Long.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5.0,7L); + assertFalse(result); + } + + @Test + public void testEqDoubleFloat() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 7.0,7F); + assertFalse(result); + } + + @Test + public void testDoubleFloat() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 15.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 9.0,17F); + assertFalse(result); + } +} diff --git a/src/test/java/targetast/InheritTest.java b/src/test/java/targetast/InheritTest.java new file mode 100644 index 00000000..fcf276a9 --- /dev/null +++ b/src/test/java/targetast/InheritTest.java @@ -0,0 +1,102 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.util.Vector; + +import static org.junit.Assert.assertEquals; + +public class InheritTest { + private static Class classToTest, classToTestAA, classToTestBB, classToTestCC, classToTestDD; + private static Object instanceOfClass, instanceOfClassAA, instanceOfClassBB, instanceOfClassCC, instanceOfClassDD; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classLoader = new ByteArrayClassLoader(); + classToTest = TestCodegen.generateClassFiles("Inherit.jav", classLoader).get("Inherit"); + classToTestAA = TestCodegen.generateClassFiles("AA.jav", classLoader).get("AA"); + classToTestBB = TestCodegen.generateClassFiles("BB.jav", classLoader).get("BB"); + classToTestCC = TestCodegen.generateClassFiles("CC.jav", classLoader).get("CC"); + classToTestDD = TestCodegen.generateClassFiles("DD.jav", classLoader).get("DD"); + + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + instanceOfClassAA = classToTestAA.getDeclaredConstructor().newInstance(); + instanceOfClassBB = classToTestBB.getDeclaredConstructor().newInstance(); + instanceOfClassCC = classToTestCC.getDeclaredConstructor().newInstance(); + instanceOfClassDD = classToTestDD.getDeclaredConstructor().newInstance(); + } + + @Test + public void testmainAA() throws Exception { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassAA, 5), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassAA, 5), "AA"); + } + + @Test + public void testmainBB() throws Exception { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassBB, 5), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassBB, 5), "AA"); + } + + @Test + public void testmainCC() throws Exception { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassCC, 5), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassCC, 5), "CC"); + } + + @Test + public void testmainDD() throws Exception { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassDD, 5), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassDD, 5), "CC"); + } + + @Test + public void testmainVectorAA() throws Exception { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassAA, 5), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassAA); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "AA"); + } + + @Test + public void testmainVectorBB() throws Exception { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassBB, 5), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassBB); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "AA"); + } + + @Test + public void testmainVectorCC() throws Exception { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassCC, 5), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassCC); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "CC"); + } + + @Test + public void testmainVectorDD() throws Exception { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassDD, 5), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassDD); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "CC"); + } +} diff --git a/src/test/java/targetast/InheritTest2.java b/src/test/java/targetast/InheritTest2.java new file mode 100644 index 00000000..a6ec9227 --- /dev/null +++ b/src/test/java/targetast/InheritTest2.java @@ -0,0 +1,118 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.util.Vector; + +import static org.junit.Assert.assertEquals; + +public class InheritTest2 { + private static Class classToTest, classToTestAA, classToTestBB, classToTestCC, classToTestDD; + private static Object instanceOfClass, instanceOfClassAA, instanceOfClassBB, instanceOfClassCC, instanceOfClassDD; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classLoader = new ByteArrayClassLoader(); + classToTest = TestCodegen.generateClassFiles("Inherit.jav", classLoader).get("Inherit2"); + classToTestAA = TestCodegen.generateClassFiles("AA.jav", classLoader).get("AA"); + classToTestBB = TestCodegen.generateClassFiles("BB.jav", classLoader).get("BB"); + classToTestCC = TestCodegen.generateClassFiles("CC.jav", classLoader).get("CC"); + classToTestDD = TestCodegen.generateClassFiles("DD.jav", classLoader).get("DD"); + + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + instanceOfClassAA = classToTestAA.getDeclaredConstructor().newInstance(); + instanceOfClassBB = classToTestBB.getDeclaredConstructor().newInstance(); + instanceOfClassCC = classToTestCC.getDeclaredConstructor().newInstance(); + instanceOfClassDD = classToTestDD.getDeclaredConstructor().newInstance(); + } + + @Test + public void testmainAA() throws Exception { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA); + assertEquals(main.invoke(instanceOfClass, instanceOfClassAA), "AA"); + } + + @Test + public void testmainBB() throws Exception { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA); + assertEquals(main.invoke(instanceOfClass, instanceOfClassBB), "AA"); + } + + @Test + public void testmainCC() throws Exception { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC); + assertEquals(main.invoke(instanceOfClass, instanceOfClassCC), "CC"); + } + + @Test + public void testmainDD() throws Exception { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC); + assertEquals(main.invoke(instanceOfClass, instanceOfClassDD), "CC"); + } + + + //PL 2020-05-12: Die folgenden Test funktionieren erst, wenn Generics im Bytecode implementiert sind + @Test + public void testmainVectorAA() throws Exception { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassAA); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + try { + assertEquals(main.invoke(instanceOfClass, v), "AA"); + } + catch (java.lang.reflect.InvocationTargetException e) { + testmainVectorCC(); + } + } + + @Test + public void testmainVectorBB() throws Exception { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassBB); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + try { + assertEquals(main.invoke(instanceOfClass, v), "AA"); + } + catch (java.lang.reflect.InvocationTargetException e) { + testmainVectorCC(); + } + } + + @Test + public void testmainVectorCC() throws Exception { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassCC); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + String erg; + assertEquals(erg= (String) main.invoke(instanceOfClass, v), + erg.equals("CC")? "CC": "AA"); + } + + @Test + public void testmainVectorDD() throws Exception { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassDD); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + String erg; + assertEquals(erg= (String) main.invoke(instanceOfClass, v), + erg.equals("CC")? "CC": "AA"); + } +} diff --git a/src/test/java/targetast/LessEqualTest.java b/src/test/java/targetast/LessEqualTest.java new file mode 100644 index 00000000..d0eea8b2 --- /dev/null +++ b/src/test/java/targetast/LessEqualTest.java @@ -0,0 +1,111 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class LessEqualTest { + static Class classToTest; + static Object instance; + + @BeforeClass + public static void beforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("LessEqual.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("LessEqual"); + instance = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testIntegers() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Integer.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5,7); + assertTrue(result); + } + + @Test + public void testEqualIntegers() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Integer.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5,5); + assertTrue(result); + } + + @Test + public void testLongs() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Long.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5L,7L); + assertTrue(result); + }@Test + + public void testFloats() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5F,7F); + assertTrue(result); + } + + @Test + public void testDoubles() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Double.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5.0,7.0); + assertTrue(result); + } + + @Test + public void testLongInt() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Long.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5L,7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5F,7); + assertTrue(result); + } + + @Test + public void testDoubleInt() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5.0,7); + assertTrue(result); + } + + @Test + public void testFloatLong() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5F,7L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5.0,7L); + assertTrue(result); + } + + @Test + public void testEqDoubleFloat() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 7.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 9.0,7F); + assertFalse(result); + } +} diff --git a/src/test/java/targetast/LessThanTest.java b/src/test/java/targetast/LessThanTest.java new file mode 100644 index 00000000..4de4b1d3 --- /dev/null +++ b/src/test/java/targetast/LessThanTest.java @@ -0,0 +1,119 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class LessThanTest { + static Class classToTest; + static Object instance; + + @BeforeClass + public static void beforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("LessThan.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("LessThan"); + instance = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testLessThanInt() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class,Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 5, 7); + assertTrue(result); + } + + @Test + public void testLessThanInt2() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7, 5); + assertFalse(result); + } + + @Test + public void testLessThanInt3() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 5, 5); + assertFalse(result); + } + + @Test + public void testLessThanLong() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class,Long.class); + Boolean result = (Boolean) lessThan.invoke(instance, 5L, 7L); + assertTrue(result); + } + + @Test + public void testLessThanLong2() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7L, 5L); + assertFalse(result); + } + + @Test + public void testLessThanLong3() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instance, 5L, 5L); + assertFalse(result); + } + + @Test + public void testLessThanFloat() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Float.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7F, 5F); + assertFalse(result); + } + + @Test + public void testLessThanDouble() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Double.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7.0, 5.0); + assertFalse(result); + } + + @Test + public void testLessThanLongInt() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7L, 5); + assertFalse(result); + } + + @Test + public void testLessThanFloatInt() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7F, 5); + assertFalse(result); + } + + @Test + public void testLessThanDoubleInt() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7.0, 5); + assertFalse(result); + } + + @Test + public void testLessThanFloatLong() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7F, 5L); + assertFalse(result); + } + + @Test + public void testLessThanDoubleLong() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7.0, 5L); + assertFalse(result); + } + + @Test + public void testLessThanDoubleFloat() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Float.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7.0, 5F); + assertFalse(result); + } +} diff --git a/src/test/java/targetast/OLTest.java b/src/test/java/targetast/OLTest.java new file mode 100644 index 00000000..a4972320 --- /dev/null +++ b/src/test/java/targetast/OLTest.java @@ -0,0 +1,71 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertEquals; + +public class OLTest { + private static Class classToTest; + private static Class classToTest1; + private static Object instanceOfClass; + private static Object instanceOfClass1; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("OL.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("OL"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + classToTest1 = classFiles.get("OLMain"); + instanceOfClass1 = classToTest1.getDeclaredConstructor().newInstance(); + } + + @Test + public void testmInt() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Integer.class); + Integer result = (Integer) m.invoke(instanceOfClass, 5); + assertEquals(new Integer(10), result); + } + + @Test + public void testmDouble() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Double.class); + Double result = (Double) m.invoke(instanceOfClass, 5.0); + assertEquals(new Double(10.0), result); + } + + @Test + public void testmString() throws Exception { + Method m = classToTest.getDeclaredMethod("m", String.class); + String result = (String) m.invoke(instanceOfClass, "xxx"); + assertEquals("xxxxxx", result); + } + + @Test + public void testOLMainClassName() { + assertEquals("OLMain", classToTest1.getName()); + } + + @Test + public void testmainInt() throws Exception { + Method main = classToTest1.getDeclaredMethod("main", Integer.class); + Integer result = (Integer) main.invoke(instanceOfClass1, 5); + assertEquals(Integer.valueOf(10), result); + } + + @Test + public void testmainDouble() throws Exception { + Method main = classToTest1.getDeclaredMethod("main", Double.class); + Double result = (Double) main.invoke(instanceOfClass1, 5.0); + assertEquals(Double.valueOf(10.0), result); + } + + @Test + public void testmainString() throws Exception { + Method main = classToTest1.getDeclaredMethod("main", String.class); + String result = (String) main.invoke(instanceOfClass1, "xxx"); + assertEquals("xxxxxx", result); + } +} diff --git a/src/test/java/targetast/PostIncTest.java b/src/test/java/targetast/PostIncTest.java new file mode 100644 index 00000000..28a4b4e3 --- /dev/null +++ b/src/test/java/targetast/PostIncTest.java @@ -0,0 +1,49 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertEquals; + +public class PostIncTest { + private static Class classToTest; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("PostIncDec.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("PostIncDec"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testM1() throws Exception { + Method m = classToTest.getDeclaredMethod("m"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(1), res); + } + + @Test + public void testM2() throws Exception { + Method m = classToTest.getDeclaredMethod("m2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(0), res); + } + + @Test + public void testD1() throws Exception { + Method m = classToTest.getDeclaredMethod("d"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(-1), res); + } + + @Test + public void testD2() throws Exception { + Method m = classToTest.getDeclaredMethod("d2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(0), res); + } + +} diff --git a/src/test/java/targetast/PreIncTest.java b/src/test/java/targetast/PreIncTest.java new file mode 100644 index 00000000..24fc5cfb --- /dev/null +++ b/src/test/java/targetast/PreIncTest.java @@ -0,0 +1,49 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertEquals; + +public class PreIncTest { + private static Class classToTest; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("PreInc.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("PreInc"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testM() throws Exception { + Method m = classToTest.getDeclaredMethod("m"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(1), res); + } + + @Test + public void testM2() throws Exception { + Method m = classToTest.getDeclaredMethod("m2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(1), res); + } + + @Test + public void testD() throws Exception { + Method m = classToTest.getDeclaredMethod("d"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(-1), res); + } + + @Test + public void testD2() throws Exception { + Method m = classToTest.getDeclaredMethod("d2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(-1), res); + } + +} diff --git a/src/test/java/targetast/PutTest.java b/src/test/java/targetast/PutTest.java new file mode 100644 index 00000000..a14771b4 --- /dev/null +++ b/src/test/java/targetast/PutTest.java @@ -0,0 +1,58 @@ +package targetast; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.util.Stack; +import java.util.Vector; + +import static org.junit.Assert.assertEquals; + +public class PutTest { + private static Class classToTest; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("Put.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("Put"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testPutElementVector() throws Exception { + Method m = classToTest.getDeclaredMethod("putElement", Object.class, Vector.class); + Vector v_invoke = new Vector<>(); + m.invoke(instanceOfClass, 5, v_invoke); + Vector v = new Vector<>(); + v.add(5); + assertEquals(v, v_invoke); + } + + @Test + public void testPutElementStack() throws Exception { + Method m = classToTest.getDeclaredMethod("putElement", Object.class, Stack.class); + Stack s_invoke = new Stack<>(); + m.invoke(instanceOfClass, 5, s_invoke); + assertEquals(new Integer(5), s_invoke.pop()); + } + + @Test + public void testMainVector() throws Exception { + Method m = classToTest.getDeclaredMethod("main", Object.class, Vector.class); + Vector v_invoke = new Vector<>(); + m.invoke(instanceOfClass, 6, v_invoke); + Vector v = new Vector<>(); + v.add(6); + assertEquals(v, v_invoke); + } + + @Test + public void testMainStack() throws Exception { + Method m = classToTest.getDeclaredMethod("main", Object.class, Stack.class); + Stack s_invoke = new Stack<>(); + m.invoke(instanceOfClass, 6, s_invoke); + assertEquals(new Integer(6), s_invoke.pop()); + } +} diff --git a/src/test/java/targetast/TestCodegen.java b/src/test/java/targetast/TestCodegen.java index b063ee82..9fac2a04 100644 --- a/src/test/java/targetast/TestCodegen.java +++ b/src/test/java/targetast/TestCodegen.java @@ -1,9 +1,12 @@ package targetast; +import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.target.bytecode.Codegen; +import de.dhbwstuttgart.target.generate.ASTToTargetAST; import de.dhbwstuttgart.target.tree.MethodParameter; import de.dhbwstuttgart.target.tree.TargetClass; import de.dhbwstuttgart.target.tree.expression.*; +import de.dhbwstuttgart.target.tree.type.TargetFunNType; import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.target.tree.type.TargetType; import org.junit.Test; @@ -15,26 +18,47 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; public class TestCodegen { - private static ByteArrayClassLoader loader = new ByteArrayClassLoader(); - - public static Class generateClass(TargetClass clazz) throws IOException { + public static Class generateClass(TargetClass clazz, ByteArrayClassLoader classLoader) throws IOException { var codegen = new Codegen(clazz); var bytes = codegen.generate(); var path = Path.of(System.getProperty("user.dir"), "src/test/resources/target/"); Files.createDirectories(path); Files.write(path.resolve(clazz.qualifiedName() + ".class"), bytes, StandardOpenOption.CREATE); - return loader.loadClass(bytes); + return classLoader.loadClass(bytes); + } + + public static Map> generateClassFiles(String filename, ByteArrayClassLoader classLoader) throws IOException, ClassNotFoundException { + var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/", filename).toFile(); + var compiler = new JavaTXCompiler(file); + var resultSet = compiler.typeInference(); + var converter = new ASTToTargetAST(resultSet); + var classes = compiler.sourceFiles.get(file).getClasses(); + + for (var bytes : converter.generateUsedFunNTypes()) { + classLoader.loadClass(bytes); + } + + return classes.stream().map(cli -> { + try { + return generateClass(converter.convert(cli), classLoader); + } catch (IOException exception) { + throw new RuntimeException(exception); + } + }).collect(Collectors.toMap(Class::getName, Function.identity())); } @Test public void testEmptyClass() throws Exception { var clazz = new TargetClass(Opcodes.ACC_PUBLIC, "Empty"); clazz.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "main", List.of(), null, new TargetBlock(List.of())); - generateClass(clazz).getDeclaredMethod("main").invoke(null); + generateClass(clazz, new ByteArrayClassLoader()).getDeclaredMethod("main").invoke(null); } @Test @@ -78,7 +102,7 @@ public class TestCodegen { ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); assertEquals(clazz.getDeclaredMethod("add", Integer.class, Integer.class).invoke(null, 10, 10), 20); assertEquals(clazz.getDeclaredMethod("sub", Integer.class, Integer.class).invoke(null, 20, 10), 10); assertEquals(clazz.getDeclaredMethod("div", Integer.class, Integer.class).invoke(null, 20, 10), 2); @@ -86,6 +110,39 @@ public class TestCodegen { assertEquals(clazz.getDeclaredMethod("rem", Integer.class, Integer.class).invoke(null, 10, 3), 1); } + @Test + public void testUnary() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Unary"); + + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "not", + List.of(new MethodParameter(TargetType.Integer, "a")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetUnaryOp.Not(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "neg", + List.of(new MethodParameter(TargetType.Integer, "a")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetUnaryOp.Negate(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "add", + List.of(new MethodParameter(TargetType.Integer, "a")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetUnaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"))) + )) + ); + + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); + assertEquals(clazz.getDeclaredMethod("not", Integer.class).invoke(null, 10), -11); + assertEquals(clazz.getDeclaredMethod("neg", Integer.class).invoke(null, 10), -10); + assertEquals(clazz.getDeclaredMethod("add", Integer.class).invoke(null, 10), 10); + + } + @Test public void testConditional() throws Exception { var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Conditional"); @@ -105,7 +162,7 @@ public class TestCodegen { )) ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); var and = clazz.getDeclaredMethod("and", Boolean.class, Boolean.class); var or = clazz.getDeclaredMethod("or", Boolean.class, Boolean.class); assertEquals(and.invoke(null, true, false), false); @@ -123,7 +180,7 @@ public class TestCodegen { new TargetBinaryOp.Add(TargetType.Long, new TargetLiteral.CharLiteral((char)10), new TargetLiteral.LongLiteral((long)20)) ))) ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); assertEquals(clazz.getDeclaredMethod("add").invoke(null), (long)30); } @@ -146,7 +203,7 @@ public class TestCodegen { ))) ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); clazz.getDeclaredMethod("helloWorld").invoke(null); } @@ -166,7 +223,7 @@ public class TestCodegen { ) ))) ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); var ifStmt = clazz.getDeclaredMethod("ifStmt", Integer.class); assertEquals(ifStmt.invoke(null, 10), 1); assertEquals(ifStmt.invoke(null, 3), 2); @@ -195,7 +252,7 @@ public class TestCodegen { new TargetReturn(new TargetLocalVar(TargetType.Integer, "sum")) )) ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); assertEquals(clazz.getDeclaredMethod("forLoop").invoke(null), 45); } @@ -217,7 +274,7 @@ public class TestCodegen { new TargetReturn(new TargetLocalVar(TargetType.Integer, "i")) )) ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); assertEquals(clazz.getDeclaredMethod("whileLoop").invoke(null), 10); } @@ -230,6 +287,7 @@ public class TestCodegen { pointTarget.addConstructor(Opcodes.ACC_PUBLIC, List.of(new MethodParameter(TargetType.Integer, "x"), new MethodParameter(TargetType.Integer, "y")), new TargetBlock(List.of( + new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "", false, false), new TargetAssign(TargetType.Integer, new TargetFieldVar(TargetType.Integer, pointType, false, new TargetThis(pointType), "x"), new TargetLocalVar(TargetType.Integer, "x") @@ -252,8 +310,9 @@ public class TestCodegen { )) ); - var pointClass = generateClass(pointTarget); - var mainClass = generateClass(mainTarget); + var classLoader = new ByteArrayClassLoader(); + var pointClass = generateClass(pointTarget, classLoader); + var mainClass = generateClass(mainTarget, classLoader); var point = mainClass.getDeclaredMethod("makePoint", Integer.class, Integer.class).invoke(null, 10, 20); assertEquals(point.getClass().getDeclaredField("x").get(point), 10); @@ -262,11 +321,14 @@ public class TestCodegen { @Test public void testLambda() throws Exception { - var fun = loader.loadClass(Path.of(System.getProperty("user.dir"), "src/test/java/targetast/Fun1$$.class")); - var interfaceType = new TargetRefType("Fun1$$"); + var classLoader = new ByteArrayClassLoader(); + var fun = classLoader.loadClass(Path.of(System.getProperty("user.dir"), "src/test/java/targetast/Fun1$$.class")); + var interfaceType = new TargetFunNType(1, List.of()); - var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Lambda"); - targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of())); + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "CGLambda"); + targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of( + new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "", false, false) + ))); targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer, new TargetBlock(List.of( new TargetVarDecl(interfaceType, "by2", @@ -284,7 +346,7 @@ public class TestCodegen { ), interfaceType, "apply", false, true))) )) ); - var clazz = generateClass(targetClass); + var clazz = generateClass(targetClass, classLoader); var instance = clazz.getConstructor().newInstance(); assertEquals(clazz.getDeclaredMethod("lambda").invoke(instance), 20); } diff --git a/src/test/java/targetast/TestComplete.java b/src/test/java/targetast/TestComplete.java new file mode 100644 index 00000000..c026a479 --- /dev/null +++ b/src/test/java/targetast/TestComplete.java @@ -0,0 +1,385 @@ +package targetast; + +import org.junit.Ignore; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.util.Vector; + +import static org.junit.Assert.*; +import static targetast.TestCodegen.generateClassFiles; + +public class TestComplete { + + @Test + public void applyLambdaTest() throws Exception { + var classFiles = generateClassFiles("applyLambda.jav", new ByteArrayClassLoader()); + var applyLambda = classFiles.get("applyLambda"); + var instance = applyLambda.getDeclaredConstructor().newInstance(); + var m = applyLambda.getDeclaredMethod("m"); + var result = m.invoke(instance); + + assertEquals(result.getClass(), classFiles.get("Apply")); + } + + @Test + public void binaryTest() throws Exception { + var classFiles = generateClassFiles("BinaryInMeth.jav", new ByteArrayClassLoader()); + var binaryInMeth = classFiles.get("BinaryInMeth"); + var instance = binaryInMeth.getDeclaredConstructor().newInstance(); + + var m2 = binaryInMeth.getDeclaredMethod("m2", Integer.class, Integer.class); + var m3 = binaryInMeth.getDeclaredMethod("m3", Integer.class); + + assertEquals(6, m2.invoke(instance, 2, 3)); + assertEquals(4, m3.invoke(instance, 2)); + } + + @Test + public void classGenLamTest() throws Exception { + var classFiles = generateClassFiles("ClassGenLam.jav", new ByteArrayClassLoader()); + classFiles.get("ClassGenLam").getDeclaredConstructor().newInstance(); + } + + @Test + public void facTest() throws Exception { + var classFiles = generateClassFiles("Fac.jav", new ByteArrayClassLoader()); + var fac = classFiles.get("Fac"); + var instance = fac.getDeclaredConstructor().newInstance(); + + var getFac = fac.getDeclaredMethod("getFac", Integer.class); + assertEquals(6, getFac.invoke(instance, 3)); + } + + @Test + public void facultyTest() throws Exception { + var classFiles = generateClassFiles("Faculty.jav", new ByteArrayClassLoader()); + + var fac = classFiles.get("Faculty"); + var constructor = fac.getDeclaredConstructor(); + constructor.setAccessible(true); + var instance = constructor.newInstance(); + + var getFact = fac.getDeclaredMethod("getFact", Integer.class); + assertEquals(6, getFact.invoke(instance, 3)); + } + + @Test + public void fieldTest() throws Exception { + var classFiles = generateClassFiles("Field.jav", new ByteArrayClassLoader()); + var field = classFiles.get("Field"); + var instance = field.getDeclaredConstructor().newInstance(); + assertEquals(1, field.getFields().length); + } + + @Test + public void fieldTph2Test() throws Exception { + var classFiles = generateClassFiles("FieldTph2.jav", new ByteArrayClassLoader()); + var fieldtph2 = classFiles.get("FieldTph2"); + var instance = fieldtph2.getDeclaredConstructor().newInstance(); + + var a = fieldtph2.getDeclaredField("a"); + var m2 = fieldtph2.getDeclaredMethod("m2", Object.class); + m2.invoke(instance, 1); + + var m = fieldtph2.getDeclaredMethod("m", Object.class); + assertEquals(1, m.invoke(instance, 1)); + } + + @Test + public void fieldTphConsMethTest() throws Exception { + var classFiles = generateClassFiles("FieldTphConsMeth.jav", new ByteArrayClassLoader()); + var fieldTphConsMeth = classFiles.get("FieldTphConsMeth"); + + var ctor = fieldTphConsMeth.getDeclaredConstructor(Object.class); + var instance = ctor.newInstance("C"); + var a = fieldTphConsMeth.getDeclaredField("a"); + var id = fieldTphConsMeth.getDeclaredMethod("id", Object.class); + + assertEquals(42, id.invoke(instance, 42)); + assertEquals("C", a.get(instance)); + } + + @Test + public void fieldTphMMethTest() throws Exception { + var classFiles = generateClassFiles("FieldTphMMeth.jav", new ByteArrayClassLoader()); + var fieldTphMMeth = classFiles.get("FieldTphMMeth"); + var ctor = fieldTphMMeth.getDeclaredConstructor(Object.class, Object.class, Boolean.class); + + var instance1 = ctor.newInstance("C", 42, true); + var instance2 = ctor.newInstance("C", 42, false); + + var m = fieldTphMMeth.getDeclaredMethod("m", Object.class, Object.class, Boolean.class); + assertEquals(42, m.invoke(instance1, "C", 42, false)); + + var a = fieldTphMMeth.getDeclaredField("a"); + assertEquals("C", a.get(instance1)); + assertEquals(42, a.get(instance2)); + } + + @Test + public void genTest() throws Exception { + var classFiles = generateClassFiles("Gen.jav", new ByteArrayClassLoader()); + } + + @Test + public void idTest() throws Exception { + var classFiles = generateClassFiles("Id.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Id").getDeclaredConstructor().newInstance(); + } + + @Test + public void infTest() throws Exception { + var classFiles = generateClassFiles("Inf.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Inf").getDeclaredConstructor().newInstance(); + } + + @Test + public void kompTphTest() throws Exception { + var classFiles = generateClassFiles("KompTph.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("KompTph").getDeclaredConstructor().newInstance(); + } + + @Test + public void lambdaCaptureTest() throws Exception { + var classFiles = generateClassFiles("LambdaCapture.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("LambdaCapture").getDeclaredConstructor().newInstance(); + } + + @Test + public void lambdaTest() throws Exception { + var classFiles = generateClassFiles("Lambda.jav", new ByteArrayClassLoader()); + var classToTest = classFiles.get("Lambda"); + var instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + var m = classToTest.getDeclaredMethod("m"); + var lambda = m.invoke(instanceOfClass).getClass(); + var apply = lambda.getMethod("apply", Object.class); + apply.setAccessible(true); + + var i = Integer.valueOf(77); + assertEquals(i, apply.invoke(m.invoke(instanceOfClass), i)); + } + + @Test + public void mathStrucInteger() throws Exception { + var classFiles = generateClassFiles("mathStrucInteger.jav", new ByteArrayClassLoader()); + var mathStrucInteger = classFiles.get("mathStrucInteger"); + mathStrucInteger.getDeclaredConstructor(Integer.class).newInstance(10); + } + + @Test + public void mathStruc() throws Exception { + var classFiles = generateClassFiles("mathStruc.jav", new ByteArrayClassLoader()); + var mathStruc = classFiles.get("mathStruc"); + mathStruc.getDeclaredConstructor(Object.class).newInstance("A"); + } + + @Test + public void matrixOpTest() throws Exception { + var classFiles = generateClassFiles("MatrixOP.jav", new ByteArrayClassLoader()); + var matrixOP = classFiles.get("MatrixOP"); + + Vector> vv = new Vector<>(); + Vector v1 = new Vector<>(); + v1.addElement(2); + v1.addElement(2); + Vector v2 = new Vector<>(); + v2.addElement(3); + v2.addElement(3); + vv.addElement(v1); + vv.addElement(v2); + + var instanceOfClass_m1 = matrixOP.getDeclaredConstructor(Vector.class).newInstance(vv); + + Vector> vv1 = new Vector<>(); + Vector v3 = new Vector<>(); + v3.addElement(2); + v3.addElement(2); + Vector v4 = new Vector<>(); + v4.addElement(3); + v4.addElement(3); + vv1.addElement(v3); + vv1.addElement(v4); + + var instanceOfClass_m2 = matrixOP.getDeclaredConstructor(Vector.class).newInstance(vv1);//Matrix m2 = new Matrix(vv1); + + var mul = matrixOP.getField("mul"); + mul.setAccessible(true); + + var lambda = mul.get(instanceOfClass_m1).getClass(); + var apply = lambda.getMethod("apply", Object.class, Object.class); + apply.setAccessible(true); + + var result = apply.invoke(mul.get(instanceOfClass_m1), instanceOfClass_m1, instanceOfClass_m2); + System.out.println(instanceOfClass_m1.toString() + " * " + instanceOfClass_m2.toString() + " = " + result.toString()); + + Vector> res = new Vector<>(); + Vector v5 = new Vector<>(); + v5.addElement(10); + v5.addElement(10); + Vector v6 = new Vector<>(); + v6.addElement(15); + v6.addElement(15); + res.addElement(v5); + res.addElement(v6); + + var instanceOfClass_m3 = matrixOP.getDeclaredConstructor(Vector.class).newInstance(res); + assertEquals(result, instanceOfClass_m3); + } + + @Ignore("Thread blocking for some reason") + @Test + public void matrixTest() throws Exception { + var classFiles = generateClassFiles("Matrix.jav", new ByteArrayClassLoader()); + var matrix = classFiles.get("Matrix"); + + Vector> vv = new Vector<>(); + Vector v1 = new Vector<> (); + v1.addElement(2); + v1.addElement(2); + Vector v2 = new Vector<> (); + v2.addElement(3); + v2.addElement(3); + vv.addElement(v1); + vv.addElement(v2); + + var instanceOfClass_m1 = matrix.getDeclaredConstructor(Vector.class).newInstance(vv); + + Vector> vv1 = new Vector<>(); + Vector v3 = new Vector<> (); + v3.addElement(2); + v3.addElement(2); + Vector v4 = new Vector<> (); + v4.addElement(3); + v4.addElement(3); + vv1.addElement(v3); + vv1.addElement(v4); + + var instanceOfClass_m2 = matrix.getDeclaredConstructor(Vector.class).newInstance(vv1); + + var mul = matrix.getDeclaredMethod("mul", Vector.class); + var result = mul.invoke(instanceOfClass_m1, instanceOfClass_m2); + System.out.println(instanceOfClass_m1.toString() + " * " + instanceOfClass_m2.toString() + " = " + result.toString()); + + Vector> res = new Vector<>(); + Vector v5 = new Vector<> (); + v5.addElement(10); + v5.addElement(10); + Vector v6 = new Vector<> (); + v6.addElement(15); + v6.addElement(15); + res.addElement(v5); + res.addElement(v6); + + var instanceOfClass_m3 = matrix.getDeclaredConstructor(Vector.class).newInstance(res); + assertEquals(result, instanceOfClass_m3); + } + + @Test + public void mergeTest() throws Exception { + var classFiles = generateClassFiles("Merge.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Merge").getDeclaredConstructor().newInstance(); + } + + @Test + public void overloadingSortingTest() throws Exception { + var classFiles = generateClassFiles("Sorting.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Sorting").getDeclaredConstructor().newInstance(); + } + + @Test + public void overloadingTest() throws Exception { + var classFiles = generateClassFiles("Overloading.jav", new ByteArrayClassLoader()); + var overloading = classFiles.get("Overloading"); + var overloading2 = classFiles.get("Overloading2"); + var instance1 = overloading.getDeclaredConstructor().newInstance(); + var instance2 = overloading2.getDeclaredConstructor().newInstance(); + + var m1 = overloading.getDeclaredMethod("test", overloading); + assertEquals("Overloading", m1.invoke(instance1, instance1)); + var m2 = overloading.getDeclaredMethod("test", overloading2); + assertEquals("Overloading2", m2.invoke(instance1, instance2)); + } + + @Test + public void plusTest() throws Exception { + var classFiles = generateClassFiles("Plus.jav", new ByteArrayClassLoader()); + var plus = classFiles.get("Plus"); + var instance = plus.getDeclaredConstructor().newInstance(); + + var addInt = plus.getDeclaredMethod("m", Integer.class, Integer.class); + assertEquals(10, addInt.invoke(instance, 7, 3)); + + var addString = plus.getDeclaredMethod("m", String.class, String.class); + assertEquals("ByteCode", addString.invoke(instance, "Byte", "Code")); + } + + @Test + public void relOpsTest() throws Exception { + var classFiles = generateClassFiles("RelOps.jav", new ByteArrayClassLoader()); + var relOps = classFiles.get("RelOps"); + var instance = relOps.getDeclaredConstructor().newInstance(); + + var m = relOps.getDeclaredMethod("m", Integer.class,Integer.class); + assertFalse((Boolean) m.invoke(instance, 7, 3)); + } + + @Test + public void simpleCyclesTest() throws Exception { + var classFiles = generateClassFiles("SimpleCycle.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("SimpleCycle").getDeclaredConstructor().newInstance(); + } + + @Test + public void subMatTest() throws Exception { + var classFiles = generateClassFiles("SubMatrix.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("SubMatrix").getDeclaredConstructor().newInstance(); + } + + @Test + public void tph3Test() throws Exception { + var classFiles = generateClassFiles("Tph3.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Tph3").getDeclaredConstructor().newInstance(); + } + + @Test + public void tph5Test() throws Exception { + var classFiles = generateClassFiles("Tph5.jav", new ByteArrayClassLoader()); + var tph5 = classFiles.get("Tph5"); + var instance = tph5.getDeclaredConstructor().newInstance(); + var m = tph5.getDeclaredMethod("m", Object.class, Object.class); + } + + @Test + public void tph6Test() throws Exception { + var classFiles = generateClassFiles("Tph6.jav", new ByteArrayClassLoader()); + var tph5 = classFiles.get("Tph6"); + var instance = tph5.getDeclaredConstructor().newInstance(); + var m = tph5.getDeclaredMethod("m", Object.class, Object.class); + } + + @Test + public void typedIdTest() throws Exception { + var classFiles = generateClassFiles("TypedID.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("TypedID").getDeclaredConstructor().newInstance(); + } + + @Test + public void vectorAddTest() throws Exception { + var classFiles = generateClassFiles("VectorAdd.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("VectorAdd").getDeclaredConstructor().newInstance(); + } + + @Test + public void vectorSuperTest() throws Exception { + var classFiles = generateClassFiles("VectorSuper.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("VectorSuper").getDeclaredConstructor().newInstance(); + } + + @Test + public void yTest() throws Exception { + var classFiles = generateClassFiles("Y.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Y").getDeclaredConstructor().newInstance(); + } +} diff --git a/src/test/java/targetast/TphTest.java b/src/test/java/targetast/TphTest.java new file mode 100644 index 00000000..e550885f --- /dev/null +++ b/src/test/java/targetast/TphTest.java @@ -0,0 +1,58 @@ +package targetast; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import static org.junit.Assert.assertEquals; + +public class TphTest { + + private static Class classToTest; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("Tph.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("Tph"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test1() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1,2); + + assertEquals(1,result); + } + + @Test + public void test2() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1, "sss"); + + assertEquals(1,result); + } + + @Test + public void test3() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class); + Object result = m.invoke(instanceOfClass, 2); + + assertEquals(2,result); + } + + @Test + public void test4() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class); + Object result = m.invoke(instanceOfClass,"xxx"); + + assertEquals("xxx",result); + } + +} diff --git a/src/test/java/targetast/WhileTest.java b/src/test/java/targetast/WhileTest.java new file mode 100644 index 00000000..c0e2c431 --- /dev/null +++ b/src/test/java/targetast/WhileTest.java @@ -0,0 +1,47 @@ +package targetast; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import static org.junit.Assert.assertEquals; + +public class WhileTest { + private static Class classToTest; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("While.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("While"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Integer.class); + Integer result = (Integer) m.invoke(instanceOfClass, 0); + assertEquals(Integer.valueOf(2), result); + } + + @Test + public void testDouble() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Double.class); + Double result = (Double) m.invoke(instanceOfClass, 0.0); + assertEquals(Double.valueOf(2.0), result); + } + + @Test + public void testLong() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Long.class); + Long result = (Long) m.invoke(instanceOfClass, 0l); + assertEquals(Long.valueOf(2l), result); + } + +}