Merge branch 'bigRefactoring' of ssh://gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into bigRefactoring
This commit is contained in:
commit
7d50ddab51
12
pom.xml
12
pom.xml
@ -47,6 +47,14 @@ http://maven.apache.org/maven-v4_0_0.xsd">
|
|||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.0</version>
|
||||||
|
<configuration>
|
||||||
|
<compilerArgs>--enable-preview</compilerArgs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.antlr</groupId>
|
<groupId>org.antlr</groupId>
|
||||||
<artifactId>antlr4-maven-plugin</artifactId>
|
<artifactId>antlr4-maven-plugin</artifactId>
|
||||||
@ -69,8 +77,8 @@ http://maven.apache.org/maven-v4_0_0.xsd">
|
|||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>17</maven.compiler.source>
|
<maven.compiler.source>19</maven.compiler.source>
|
||||||
<maven.compiler.target>17</maven.compiler.target>
|
<maven.compiler.target>19</maven.compiler.target>
|
||||||
<mainClass>de.dhbwstuttgart.core.ConsoleInterface</mainClass>
|
<mainClass>de.dhbwstuttgart.core.ConsoleInterface</mainClass>
|
||||||
</properties>
|
</properties>
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
|
6
resources/bytecode/javFiles/Cycle.jav
Normal file
6
resources/bytecode/javFiles/Cycle.jav
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
class Cycle {
|
||||||
|
m(x, y) {
|
||||||
|
y = x;
|
||||||
|
x = y;
|
||||||
|
}
|
||||||
|
}
|
@ -12,8 +12,44 @@ public class Inf {
|
|||||||
b=a;
|
b=a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// v w
|
|
||||||
// \ /
|
/*
|
||||||
// z y b
|
TPH M m(TPH N x, TPH O y, TPH P a)({
|
||||||
// \ / \ /
|
TPH Q z;
|
||||||
// x a
|
TPH R v;
|
||||||
|
TPH S w;
|
||||||
|
TPH T b;
|
||||||
|
(y)::TPH O = (x)::TPH N;
|
||||||
|
(z)::TPH Q = (x)::TPH N;
|
||||||
|
(v)::TPH R = (y)::TPH O;
|
||||||
|
(w)::TPH S = (y)::TPH O;
|
||||||
|
(y)::TPH O = (a)::TPH P;
|
||||||
|
(b)::TPH T = (a)::TPH P;
|
||||||
|
return;
|
||||||
|
})::TPH U
|
||||||
|
|
||||||
|
Inf()({
|
||||||
|
super(());
|
||||||
|
})::TPH X
|
||||||
|
|
||||||
|
}
|
||||||
|
// v::R w::S
|
||||||
|
// \ /
|
||||||
|
// z::Q y::O b::T
|
||||||
|
// \ / \ /
|
||||||
|
// x::N a::P
|
||||||
|
|
||||||
|
RESULT Final: [[(TPH O < TPH S), (TPH P < TPH O), (TPH O < TPH R), (TPH P < TPH T), (TPH M = void), (TPH N < TPH O), (TPH N < TPH Q)]]
|
||||||
|
Simplified constraints: [(TPH O < TPH S), (TPH P < TPH O), (TPH O < TPH R), (TPH P < TPH T), (TPH N < TPH O), (TPH N < TPH Q)]
|
||||||
|
m: [(TPH DDV = java.lang.Object), (TPH DDX = java.lang.Object), (TPH DDX < TPH DDV), (TPH N < TPH DDX), (TPH P < TPH DDX)]
|
||||||
|
Class Inf: []
|
||||||
|
Inf: []
|
||||||
|
|
||||||
|
Unify nach Oder-Constraints-Anpassung:
|
||||||
|
UND:[(void =. M, , -1 WC: false, IT: false), (N <. O, 1 WC: false, IT: false, 1 WC: false, IT: false), (P <. O, 1 WC: false, IT: false, 1 WC: false, IT: false), (N <. Q, 1 WC: false, IT: false, 0 WC: true, IT: false), (O <. S, 1 WC: false, IT: false, 0 WC: true, IT: false), (O <. R, 1 WC: false, IT: false, 0 WC: true, IT: false), (P <. T, 1 WC: false, IT: false, 0 WC: true, IT: false)]
|
||||||
|
isInherited = false
|
||||||
|
isStatement = false
|
||||||
|
|
||||||
|
ODER:
|
||||||
|
*/
|
||||||
|
|
||||||
|
6
resources/bytecode/javFiles/Infimum.jav
Normal file
6
resources/bytecode/javFiles/Infimum.jav
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
class Infimum {
|
||||||
|
m(x, y, z) {
|
||||||
|
y = x;
|
||||||
|
z = x;
|
||||||
|
}
|
||||||
|
}
|
@ -4,14 +4,10 @@ import java.lang.Double;
|
|||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
import java.lang.Boolean;
|
import java.lang.Boolean;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class OLFun {
|
public class OLFun {
|
||||||
|
|
||||||
//f = x -> {return x + x;};
|
//f = x -> {return x + x;};
|
||||||
|
|
||||||
m(f, x) {
|
m(f, x) {
|
||||||
x = f.apply(x+x);
|
x = f.apply(x+x);
|
||||||
}
|
}
|
||||||
}
|
}
|
13
resources/bytecode/javFiles/OLFun2.jav
Normal file
13
resources/bytecode/javFiles/OLFun2.jav
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import java.lang.String;
|
||||||
|
import java.lang.Integer;
|
||||||
|
import java.lang.Double;
|
||||||
|
import java.util.Vector;
|
||||||
|
import java.lang.Boolean;
|
||||||
|
|
||||||
|
public class OLFun2 {
|
||||||
|
|
||||||
|
x;
|
||||||
|
m(f){
|
||||||
|
x = f.apply(x + x)
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
public class SimpleCycle {
|
public class SimpleCycle {
|
||||||
|
|
||||||
m(a,b,d){
|
m(a,b,d){
|
||||||
/* var g;
|
var g;
|
||||||
var h;
|
var h;
|
||||||
g = h;
|
g = h;
|
||||||
h = g;
|
h = g;
|
||||||
|
/*
|
||||||
var y;
|
var y;
|
||||||
var z;
|
var z;
|
||||||
y=z;
|
y=z;
|
||||||
@ -18,8 +18,8 @@ public class SimpleCycle {
|
|||||||
var f = d;
|
var f = d;
|
||||||
b = x;
|
b = x;
|
||||||
var l = c;
|
var l = c;
|
||||||
a = l; */
|
a = l;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -3,7 +3,6 @@ public class Tph {
|
|||||||
m(a,b){
|
m(a,b){
|
||||||
var c = m2(b);
|
var c = m2(b);
|
||||||
return a;
|
return a;
|
||||||
// return m2(b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m2(b){
|
m2(b){
|
||||||
|
@ -4,7 +4,7 @@ public class Tph2 {
|
|||||||
return id.apply(x);
|
return id.apply(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
m(a,b){
|
m(a,b){
|
||||||
var c = m2(a,b);
|
var c = m2(a,b);
|
||||||
//m2(a,b);
|
//m2(a,b);
|
||||||
@ -14,4 +14,5 @@ public class Tph2 {
|
|||||||
m2(a,b){
|
m2(a,b){
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
11
resources/bytecode/javFiles/Tph7.jav
Normal file
11
resources/bytecode/javFiles/Tph7.jav
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
public class Tph7 {
|
||||||
|
|
||||||
|
m(a,b){
|
||||||
|
var c = m2(b);
|
||||||
|
return m2(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
m2(b){
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,10 @@ import java.util.HashMap;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.bytecode.funN.FunNGenerator;
|
||||||
|
import de.dhbwstuttgart.bytecode.funN.FunNUtilities;
|
||||||
import de.dhbwstuttgart.bytecode.utilities.*;
|
import de.dhbwstuttgart.bytecode.utilities.*;
|
||||||
import de.dhbwstuttgart.environment.DirectoryClassLoader;
|
import de.dhbwstuttgart.environment.DirectoryClassLoader;
|
||||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
@ -589,10 +592,21 @@ public class BytecodeGenMethod implements StatementVisitor {
|
|||||||
this.lamCounter++;
|
this.lamCounter++;
|
||||||
|
|
||||||
String typeErasure = createDescriptorWithTypeErasure(lambdaExpression);
|
String typeErasure = createDescriptorWithTypeErasure(lambdaExpression);
|
||||||
|
//ToDo Etienne: Double Check
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric returnType = resolver.resolve(lambdaExpression.getReturnType());
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes = lambdaExpression
|
||||||
|
.params
|
||||||
|
.getFormalparalist()
|
||||||
|
.stream()
|
||||||
|
.map(FormalParameter::getType)
|
||||||
|
.map(resolver::resolve)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
FunNUtilities funNUtilities = FunNGenerator.getInstance();
|
||||||
|
FunNUtilities.writeClassFile(funNUtilities.getSuperClassName(argumentTypes.size()),
|
||||||
|
funNUtilities.generateSuperBytecode(argumentTypes.size()), path);
|
||||||
|
FunNUtilities.writeClassFile(funNUtilities.getSpecializedClassName(argumentTypes, returnType),
|
||||||
|
funNUtilities.generateSpecializedBytecode(argumentTypes, returnType), path);
|
||||||
|
|
||||||
ByteCodeForFunNGenerator.generateBCForFunN(lambdaExpression, typeErasure,path);
|
|
||||||
|
|
||||||
|
|
||||||
Lambda lam = new Lambda(lambdaExpression);
|
Lambda lam = new Lambda(lambdaExpression);
|
||||||
String lamDesc = lam.accept(new DescriptorToString(resultSet));
|
String lamDesc = lam.accept(new DescriptorToString(resultSet));
|
||||||
// Call site, which, when invoked, returns an instance of the functional
|
// Call site, which, when invoked, returns an instance of the functional
|
||||||
@ -814,8 +828,20 @@ public class BytecodeGenMethod implements StatementVisitor {
|
|||||||
} else if(!helper.isInCurrPkg(clazz)){
|
} else if(!helper.isInCurrPkg(clazz)){
|
||||||
if(clazz.contains(CONSTANTS.$$)) {
|
if(clazz.contains(CONSTANTS.$$)) {
|
||||||
mDesc = helper.getDescriptorOfApplyMethod(methCallType);
|
mDesc = helper.getDescriptorOfApplyMethod(methCallType);
|
||||||
helper.generateBCForFunN(mDesc);
|
//ToDo Etienne: Double Check
|
||||||
// mDesc = helper.generateBCForFunN(methCallType,typesOfParams);
|
RefTypeOrTPHOrWildcardOrGeneric returnType = resolver.resolve(methodCall.getType());
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes = methodCall
|
||||||
|
.arglist
|
||||||
|
.getArguments()
|
||||||
|
.stream()
|
||||||
|
.map(TypableStatement::getType)
|
||||||
|
.map(resolver::resolve)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
FunNUtilities funNUtilities = FunNGenerator.getInstance();
|
||||||
|
FunNUtilities.writeClassFile(funNUtilities.getSuperClassName(argumentTypes.size()),
|
||||||
|
funNUtilities.generateSuperBytecode(argumentTypes.size()), path);
|
||||||
|
FunNUtilities.writeClassFile(funNUtilities.getSpecializedClassName(argumentTypes, returnType),
|
||||||
|
funNUtilities.generateSpecializedBytecode(argumentTypes, returnType), path);
|
||||||
}else {
|
}else {
|
||||||
try {
|
try {
|
||||||
cLoader2 = new DirectoryClassLoader(path, classLoader);
|
cLoader2 = new DirectoryClassLoader(path, classLoader);
|
||||||
|
@ -153,6 +153,7 @@ public class DescriptorToString implements DescriptorVisitor, CONSTANTS {
|
|||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ToDo Etienne: ändern
|
||||||
@Override
|
@Override
|
||||||
public String visit(Lambda lambdaExpression) {
|
public String visit(Lambda lambdaExpression) {
|
||||||
String desc = "(";
|
String desc = "(";
|
||||||
|
@ -1,17 +1,24 @@
|
|||||||
package de.dhbwstuttgart.bytecode.descriptor;
|
package de.dhbwstuttgart.bytecode.descriptor;
|
||||||
|
|
||||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
import de.dhbwstuttgart.bytecode.funN.FunNGenerator;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
|
import de.dhbwstuttgart.bytecode.funN.FunNUtilities;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
import de.dhbwstuttgart.syntaxtree.type.*;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
|
||||||
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
|
|
||||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
|
||||||
import de.dhbwstuttgart.syntaxtree.type.TypeVisitor;
|
|
||||||
|
|
||||||
public class TypeToDescriptor implements TypeVisitor<String>{
|
public class TypeToDescriptor implements TypeVisitor<String>{
|
||||||
|
|
||||||
|
private final boolean specializedFunN;
|
||||||
|
|
||||||
|
public TypeToDescriptor(){ this(true); }
|
||||||
|
|
||||||
|
public TypeToDescriptor(boolean specializedFunN) { this.specializedFunN = specializedFunN; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String visit(RefType refType) {
|
public String visit(RefType refType) {
|
||||||
|
if (refType.getName().toString().matches("Fun\\d+\\$\\$") && specializedFunN) {
|
||||||
|
FunNUtilities funNUtilities = FunNGenerator.getInstance();
|
||||||
|
return funNUtilities.getSpecializedDescriptor(funNUtilities.getArguments(refType.getParaList()), funNUtilities.getReturnType(refType.getParaList()));
|
||||||
|
}
|
||||||
|
|
||||||
return refType.getName().toString().replace(".", "/");
|
return refType.getName().toString().replace(".", "/");
|
||||||
// String t = refType.getName().toString().replace(".", "/");
|
// String t = refType.getName().toString().replace(".", "/");
|
||||||
// return t.equals("Fun1")?(t+"$$"):t;
|
// return t.equals("Fun1")?(t+"$$"):t;
|
||||||
|
149
src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java
Normal file
149
src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
package de.dhbwstuttgart.bytecode.funN;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
|
||||||
|
import de.dhbwstuttgart.bytecode.signature.TypeToSignature;
|
||||||
|
import de.dhbwstuttgart.bytecode.utilities.CONSTANTS;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* //ToDo beschreiben
|
||||||
|
*
|
||||||
|
* @since Studienarbeit Type Erasure
|
||||||
|
* @author etiennezink
|
||||||
|
*/
|
||||||
|
public class FunNGenerator implements FunNUtilities{
|
||||||
|
|
||||||
|
private static FunNGenerator funNGenerator = new FunNGenerator();
|
||||||
|
|
||||||
|
public static FunNGenerator getInstance(){
|
||||||
|
return funNGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String argumentGenericBase = "T";
|
||||||
|
private final String returnGeneric = "R";
|
||||||
|
private final String methodName = "apply";
|
||||||
|
private final int bytecodeVersion = V1_8;
|
||||||
|
|
||||||
|
private final String objectSuperType = Type.getInternalName(Object.class).replace('.','/');
|
||||||
|
private final RefType objectRefType = new RefType(new JavaClassName(objectSuperType), null);
|
||||||
|
private final String objectSignature = applySignature(objectRefType);
|
||||||
|
|
||||||
|
private String applyDescriptor(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToDescriptor(true)); }
|
||||||
|
private String applySignature(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToSignature(true)); }
|
||||||
|
private String applyNameDescriptor(RefTypeOrTPHOrWildcardOrGeneric a){ return a instanceof TypePlaceholder ? "LTPH;" : String.format("L%s;", applyDescriptor(a)); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] generateSuperBytecode(int numberArguments) {
|
||||||
|
StringBuilder superFunNClassSignature = new StringBuilder("<");
|
||||||
|
StringBuilder superFunNMethodSignature = new StringBuilder("(");
|
||||||
|
StringBuilder superFunNMethodDescriptor = new StringBuilder("(");
|
||||||
|
|
||||||
|
for (int currentParameter = 1; currentParameter <= numberArguments; currentParameter++){
|
||||||
|
superFunNClassSignature.append(String.format("%s%d:%s",argumentGenericBase, currentParameter, objectSignature));
|
||||||
|
superFunNMethodSignature.append(String.format("T%s;", applySignature( new GenericRefType(argumentGenericBase + currentParameter, null))));
|
||||||
|
superFunNMethodDescriptor.append(objectSignature);
|
||||||
|
}
|
||||||
|
superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature));
|
||||||
|
superFunNMethodSignature.append(String.format(")T%s;", applySignature(new GenericRefType(returnGeneric, null))));
|
||||||
|
superFunNMethodDescriptor.append(String.format(")%s", objectSignature));
|
||||||
|
|
||||||
|
ClassWriter classWriter = new ClassWriter(0);
|
||||||
|
MethodVisitor methodVisitor;
|
||||||
|
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSuperClassName(numberArguments), superFunNClassSignature.toString(), objectSuperType, null);
|
||||||
|
methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor.toString(), superFunNMethodSignature.toString(), null);
|
||||||
|
methodVisitor.visitEnd();
|
||||||
|
classWriter.visitEnd();
|
||||||
|
return classWriter.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSuperClassName(int numberArguments) {
|
||||||
|
return String.format("Fun%d$$", numberArguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] generateSpecializedBytecode(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) {
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> parameters = Stream
|
||||||
|
.concat(argumentTypes.stream(), Stream.of(returnType))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
RefType superFunN = new RefType(new JavaClassName(getSuperClassName(argumentTypes.size())), parameters , null);
|
||||||
|
StringBuilder funNClassSignature = new StringBuilder(objectSignature + (superFunN.acceptTV(new TypeToSignature(false))));
|
||||||
|
boolean containsGeneric = false;
|
||||||
|
|
||||||
|
String genericSignature = "<";
|
||||||
|
for (RefTypeOrTPHOrWildcardOrGeneric typeArgument : parameters) {
|
||||||
|
//ToDo Etienne: Refactor
|
||||||
|
if (typeArgument instanceof GenericRefType){
|
||||||
|
GenericRefType generic = (GenericRefType) typeArgument;
|
||||||
|
if(genericSignature.contains(generic.getParsedName())) continue;
|
||||||
|
genericSignature += String.format("%s:%s", generic.getParsedName(), applyDescriptor(generic));
|
||||||
|
containsGeneric = true;
|
||||||
|
} else if(typeArgument instanceof TypePlaceholder){
|
||||||
|
TypePlaceholder placeholder = (TypePlaceholder) typeArgument;
|
||||||
|
if(genericSignature.contains(applySignature(placeholder).substring(1))) continue;
|
||||||
|
genericSignature += String.format("%s:%s", applySignature(placeholder).substring(1), objectSignature);
|
||||||
|
containsGeneric = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
genericSignature += ">";
|
||||||
|
if (containsGeneric) funNClassSignature.insert(0, genericSignature);
|
||||||
|
|
||||||
|
ClassWriter classWriter = new ClassWriter(0);
|
||||||
|
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSpecializedClassName(argumentTypes, returnType), funNClassSignature.toString(), objectSuperType, new String[]{getSuperClassName(argumentTypes.size())});
|
||||||
|
classWriter.visitEnd();
|
||||||
|
return classWriter.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSpecializedClassName(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) {
|
||||||
|
return String.format("Fun%d$$%s%s",
|
||||||
|
argumentTypes.size(),
|
||||||
|
argumentTypes
|
||||||
|
.stream()
|
||||||
|
.map(this::applyNameDescriptor)
|
||||||
|
.collect(Collectors.joining()),
|
||||||
|
applyNameDescriptor(returnType))
|
||||||
|
.replace('/', '$')
|
||||||
|
.replace(";", "$_$");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSpecializedDescriptor(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) {
|
||||||
|
return applyDescriptor(new RefType(new JavaClassName(getSpecializedClassName(argumentTypes, returnType)), null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSpecializedSignature(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) {
|
||||||
|
return applySignature(new RefType(new JavaClassName(getSpecializedClassName(argumentTypes, returnType)), null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RefTypeOrTPHOrWildcardOrGeneric> getArguments(List<RefTypeOrTPHOrWildcardOrGeneric> list) {
|
||||||
|
return list
|
||||||
|
.stream()
|
||||||
|
.limit(Math.max(0, list.size() - 1))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefTypeOrTPHOrWildcardOrGeneric getReturnType(List<RefTypeOrTPHOrWildcardOrGeneric> list) {
|
||||||
|
if(list.size() == 0)
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
return list.get(list.size() - 1);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package de.dhbwstuttgart.bytecode.funN;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.bytecode.utilities.CONSTANTS;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface FunNUtilities {
|
||||||
|
|
||||||
|
byte[] generateSuperBytecode(int numberArguments);
|
||||||
|
String getSuperClassName(int numberArguments);
|
||||||
|
|
||||||
|
byte[] generateSpecializedBytecode(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType);
|
||||||
|
String getSpecializedClassName(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType);
|
||||||
|
String getSpecializedDescriptor(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType);
|
||||||
|
String getSpecializedSignature(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType);
|
||||||
|
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> getArguments(List<RefTypeOrTPHOrWildcardOrGeneric> list);
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric getReturnType(List<RefTypeOrTPHOrWildcardOrGeneric> list);
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public static boolean writeClassFile(String className, byte[] bytecode, File directory) {
|
||||||
|
try (FileOutputStream output = new FileOutputStream(new File(directory , className + CONSTANTS.EXTENSIONCLASS))){
|
||||||
|
output.write(bytecode);
|
||||||
|
output.flush();
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -5,6 +5,8 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.bytecode.funN.FunNGenerator;
|
||||||
|
import de.dhbwstuttgart.bytecode.funN.FunNUtilities;
|
||||||
import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericsGeneratorResult;
|
import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericsGeneratorResult;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
|
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
||||||
@ -17,18 +19,29 @@ import de.dhbwstuttgart.syntaxtree.type.TypeVisitor;
|
|||||||
public class TypeToSignature implements TypeVisitor<String> {
|
public class TypeToSignature implements TypeVisitor<String> {
|
||||||
private List<GenericsGeneratorResult> constraints;
|
private List<GenericsGeneratorResult> constraints;
|
||||||
|
|
||||||
public TypeToSignature() {
|
private final boolean specializedFunN;
|
||||||
this.constraints = new ArrayList<>();
|
|
||||||
}
|
public TypeToSignature() { this(new ArrayList<>(), true); }
|
||||||
|
|
||||||
|
public TypeToSignature(boolean specializedFunN) { this(new ArrayList<>(), specializedFunN); }
|
||||||
|
|
||||||
public TypeToSignature(List<GenericsGeneratorResult> constraints) {
|
public TypeToSignature(List<GenericsGeneratorResult> constraints) {
|
||||||
|
this(constraints, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeToSignature(List<GenericsGeneratorResult> constraints, boolean specializedFunN){
|
||||||
this.constraints = constraints;
|
this.constraints = constraints;
|
||||||
|
this.specializedFunN = specializedFunN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String visit(RefType refType) {
|
public String visit(RefType refType) {
|
||||||
if(refType.getName().toString().equals("void"))
|
if(refType.getName().toString().equals("void"))
|
||||||
return "V";
|
return "V";
|
||||||
|
if (refType.getName().toString().matches("Fun\\d+\\$\\$") && specializedFunN){
|
||||||
|
FunNUtilities funNUtilities = FunNGenerator.getInstance();
|
||||||
|
return funNUtilities.getSpecializedSignature(funNUtilities.getArguments(refType.getParaList()), funNUtilities.getReturnType(refType.getParaList()));
|
||||||
|
}
|
||||||
// return refType.toString().replace(".", "/");
|
// return refType.toString().replace(".", "/");
|
||||||
String params = "";
|
String params = "";
|
||||||
if(refType.getParaList().size()>0){
|
if(refType.getParaList().size()>0){
|
||||||
|
@ -25,4 +25,9 @@ public class Resolver {
|
|||||||
public String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) {
|
public String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) {
|
||||||
return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor());
|
return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ToDo Etienne: Check ob benötigt
|
||||||
|
public RefTypeOrTPHOrWildcardOrGeneric resolve(RefTypeOrTPHOrWildcardOrGeneric type) {
|
||||||
|
return resultSet.resolveType(type).resolvedType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
package de.dhbwstuttgart.target;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class ByteArrayClassLoader extends ClassLoader {
|
||||||
|
public Class loadClass(byte[] code) {
|
||||||
|
return this.defineClass(null, code, 0, code.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class loadClass(Path path) throws IOException {
|
||||||
|
var code = Files.readAllBytes(path);
|
||||||
|
return this.defineClass(null, code, 0, code.length);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package de.dhbwstuttgart.target.bytecode;
|
||||||
|
|
||||||
|
public class CodeGenException extends RuntimeException {
|
||||||
|
public CodeGenException(String cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
1033
src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java
Executable file
1033
src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java
Executable file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,727 @@
|
|||||||
|
package de.dhbwstuttgart.target.generate;
|
||||||
|
|
||||||
|
import com.google.j2objc.annotations.LoopTranslation;
|
||||||
|
import de.dhbwstuttgart.bytecode.funN.FunNGenerator;
|
||||||
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.*;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.*;
|
||||||
|
import de.dhbwstuttgart.target.tree.*;
|
||||||
|
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
||||||
|
import de.dhbwstuttgart.target.tree.expression.TargetExpression;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.*;
|
||||||
|
import de.dhbwstuttgart.typeinference.result.*;
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class ASTToTargetAST {
|
||||||
|
|
||||||
|
static RefType OBJECT = ASTFactory.createObjectType(); // TODO It would be better if I could call this directly but the hashcode seems to change
|
||||||
|
|
||||||
|
protected List<Sigma> all;
|
||||||
|
protected Sigma sigma;
|
||||||
|
protected ClassOrInterface currentClass; // TODO This is only needed because of SuperCall, maybe there's a better way?
|
||||||
|
|
||||||
|
private class Sigma {
|
||||||
|
Map<Method, Set<ResultPair<?, ?>>> computedGenericsOfMethods = new HashMap<>();
|
||||||
|
Map<Method, Set<TypePlaceholder>> usedTPHsOfMethods = new HashMap<>();
|
||||||
|
Map<ClassOrInterface, Set<ResultPair<?, ?>>> computedGenericsOfClasses = new HashMap<>();
|
||||||
|
|
||||||
|
Set<PairTPHsmallerTPH> simplifiedConstraints = new HashSet<>();
|
||||||
|
Map<TypePlaceholder, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes = new HashMap<>();
|
||||||
|
Map<TypePlaceholder, TypePlaceholder> equality = new HashMap<>();
|
||||||
|
|
||||||
|
Sigma(ResultSet constraints) {
|
||||||
|
ASTToTargetAST.this.sigma = this;
|
||||||
|
|
||||||
|
Set<List<TypePlaceholder>> equalitySet = new HashSet<>();
|
||||||
|
Map<TypePlaceholder, List<TypePlaceholder>> unified = new HashMap<>();
|
||||||
|
|
||||||
|
for (var constraint : constraints.results) {
|
||||||
|
if (constraint instanceof PairTPHEqualTPH p) {
|
||||||
|
if (unified.containsKey(p.getLeft())) {
|
||||||
|
var equals = unified.get(p.getLeft());
|
||||||
|
equals.add(p.getRight());
|
||||||
|
unified.put(p.getLeft(), equals);
|
||||||
|
} else if (unified.containsKey(p.getRight())) {
|
||||||
|
var equals = unified.get(p.getRight());
|
||||||
|
equals.add(p.getLeft());
|
||||||
|
unified.put(p.getRight(), equals);
|
||||||
|
} else {
|
||||||
|
List<TypePlaceholder> equals = new ArrayList<>();
|
||||||
|
equals.add(p.getLeft());
|
||||||
|
equals.add(p.getRight());
|
||||||
|
unified.put(p.getLeft(), equals);
|
||||||
|
unified.put(p.getRight(), equals);
|
||||||
|
equalitySet.add(equals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var constraint : constraints.results) {
|
||||||
|
if (constraint instanceof PairTPHsmallerTPH p) {
|
||||||
|
var left = p.left;
|
||||||
|
var right = p.right;
|
||||||
|
if (unified.containsKey(left))
|
||||||
|
left = unified.get(left).get(0);
|
||||||
|
if (unified.containsKey(right))
|
||||||
|
right = unified.get(right).get(0);
|
||||||
|
|
||||||
|
simplifiedConstraints.add(new PairTPHsmallerTPH(left, right));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("Simplified constraints: " + simplifiedConstraints);
|
||||||
|
|
||||||
|
for (var equality : equalitySet) {
|
||||||
|
var first = equality.get(0);
|
||||||
|
for (var i = 1; i < equality.size(); i++)
|
||||||
|
this.equality.put(equality.get(i), first);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var constraint : constraints.results) {
|
||||||
|
if (constraint instanceof PairTPHequalRefTypeOrWildcardType p) {
|
||||||
|
concreteTypes.put(this.equality.getOrDefault(p.left, p.left), p.right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void findTypeVariables(RefTypeOrTPHOrWildcardOrGeneric type, Set<TypePlaceholder> typeVariables) {
|
||||||
|
if (type instanceof TypePlaceholder tph) {
|
||||||
|
tph = equality.getOrDefault(tph, tph);
|
||||||
|
if (concreteTypes.containsKey(tph)) {
|
||||||
|
findTypeVariables(concreteTypes.get(tph), typeVariables);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
typeVariables.add(tph);
|
||||||
|
} else if (type instanceof RefType refType) {
|
||||||
|
for (var t : refType.getParaList())
|
||||||
|
findTypeVariables(t, typeVariables);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasBound(TypePlaceholder name, Set<ResultPair<?, ?>> generics) {
|
||||||
|
return generics.stream().anyMatch(generic -> generic.getLeft().equals(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean containsRelation(Set<ResultPair<?, ?>> result, PairTPHsmallerTPH pair) {
|
||||||
|
// Check if both the right and the left are already part of a relation
|
||||||
|
var containsLeft = false;
|
||||||
|
for (var pair2 : result) {
|
||||||
|
if (pair2.getLeft().equals(pair.left)) {
|
||||||
|
containsLeft = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var containsRight = false;
|
||||||
|
for (var pair2 : result) {
|
||||||
|
if (pair2.getRight().equals(pair.right)) {
|
||||||
|
containsRight = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return containsLeft && containsRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Family of generated Generics
|
||||||
|
Set<ResultPair<?, ?>> generics(ClassOrInterface owner, Method method) {
|
||||||
|
if (computedGenericsOfMethods.containsKey(method))
|
||||||
|
return computedGenericsOfMethods.get(method);
|
||||||
|
|
||||||
|
Set<ResultPair<?, ?>> result = new HashSet<>();
|
||||||
|
computedGenericsOfMethods.put(method, result);
|
||||||
|
|
||||||
|
var genericsOfClass = generics(owner);
|
||||||
|
var simplifiedConstraints = new HashSet<>(this.simplifiedConstraints);
|
||||||
|
|
||||||
|
HashSet<TypePlaceholder> typeVariables = new HashSet<>();
|
||||||
|
HashSet<TypePlaceholder> typeVariablesOfFields = new HashSet<>();
|
||||||
|
HashSet<TypePlaceholder> allTypeVariables = new HashSet<>();
|
||||||
|
|
||||||
|
for (var field : owner.getFieldDecl()) {
|
||||||
|
findTypeVariables(field.getType(), typeVariablesOfFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
//findTypeVariables(method.getReturnType(), typeVariables);
|
||||||
|
for (var arg : method.getParameterList().getFormalparalist()) {
|
||||||
|
findTypeVariables(arg.getType(), typeVariables);
|
||||||
|
}
|
||||||
|
|
||||||
|
method.block.accept(new TracingStatementVisitor() {
|
||||||
|
@Override
|
||||||
|
public void visit(LocalVarDecl localVarDecl) {
|
||||||
|
findTypeVariables(localVarDecl.getType(), typeVariables);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(MethodCall methodCall) {
|
||||||
|
super.visit(methodCall);
|
||||||
|
findTypeVariables(methodCall.getType(), typeVariables);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Assign assign) {}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Type variables with bounds that are also type variables of the method
|
||||||
|
for (var typeVariable : new HashSet<>(typeVariables)) {
|
||||||
|
for (var pair : simplifiedConstraints) {
|
||||||
|
if (pair.left.equals(typeVariable) && typeVariables.contains(pair.right)) {
|
||||||
|
result.add(new PairTPHsmallerTPH(pair.left, equality.getOrDefault(pair.right, pair.right)));
|
||||||
|
typeVariables.add(pair.right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var visitedMethods = new HashSet<Method>();
|
||||||
|
method.block.accept(new TracingStatementVisitor() {
|
||||||
|
@Override
|
||||||
|
public void visit(MethodCall methodCall) {
|
||||||
|
super.visit(methodCall);
|
||||||
|
|
||||||
|
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) {
|
||||||
|
if (expressionReceiver.expr instanceof This) {
|
||||||
|
var optMethod = findMethod(owner, methodCall.name, methodCall.getArgumentList());
|
||||||
|
if (optMethod.isEmpty()) return;
|
||||||
|
var method = optMethod.get();
|
||||||
|
if (visitedMethods.contains(method)) return;
|
||||||
|
visitedMethods.add(method);
|
||||||
|
|
||||||
|
var generics = generics(owner, method);
|
||||||
|
Set<ResultPair<?, ?>> all = new HashSet<>(generics);
|
||||||
|
|
||||||
|
// Reflexive and Transitive closure
|
||||||
|
HashSet<ResultPair<?, ?>> toAdd = new HashSet<>();
|
||||||
|
int sizeBefore;
|
||||||
|
do {
|
||||||
|
sizeBefore = all.size();
|
||||||
|
toAdd.clear();
|
||||||
|
for (var g1 : all) {
|
||||||
|
for (var g2 : all) {
|
||||||
|
if (g1 instanceof PairTPHsmallerTPH pair) {
|
||||||
|
if (g2.getLeft().equals(pair.getLeft()) && generics.stream().anyMatch(generic -> generic.getLeft().equals(pair.getRight())))
|
||||||
|
toAdd.add(new PairTPHsmallerTPH((TypePlaceholder) g1.getLeft(), (TypePlaceholder) g2.getRight()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
all.addAll(toAdd);
|
||||||
|
} while (sizeBefore < all.size());
|
||||||
|
for (var generic : all) {
|
||||||
|
toAdd.add(new PairTPHsmallerTPH((TypePlaceholder) generic.getLeft(), (TypePlaceholder) generic.getLeft()));
|
||||||
|
}
|
||||||
|
all.addAll(toAdd);
|
||||||
|
|
||||||
|
HashSet<PairTPHsmallerTPH> newPairs = new HashSet<>();
|
||||||
|
// Loop from hell
|
||||||
|
outer:
|
||||||
|
for (var tph : typeVariables) {
|
||||||
|
for (var generic : all) {
|
||||||
|
if (!(generic.getRight() instanceof TypePlaceholder type))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (var pair : simplifiedConstraints) {
|
||||||
|
if (!(pair.left.equals(tph) && pair.right.equals(generic.getLeft())))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (var tph2 : typeVariables) {
|
||||||
|
for (var pair2 : simplifiedConstraints) {
|
||||||
|
if (!(pair2.right.equals(tph2) && pair2.left.equals(type)))
|
||||||
|
continue;
|
||||||
|
if (tph.equals(tph2)) continue;
|
||||||
|
|
||||||
|
var newPair = new PairTPHsmallerTPH(tph, tph2);
|
||||||
|
newPairs.add(newPair);
|
||||||
|
|
||||||
|
if (!containsRelation(result, newPair))
|
||||||
|
result.add(newPair);
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
simplifiedConstraints.addAll(newPairs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Type variables with bounds that are also type variables of fields
|
||||||
|
for (var typeVariable : new HashSet<>(typeVariables)) {
|
||||||
|
for (var pair : simplifiedConstraints) {
|
||||||
|
if (pair.left.equals(typeVariable) && typeVariablesOfFields.contains(pair.right)) {
|
||||||
|
result.add(new PairTPHsmallerTPH(pair.left, equality.getOrDefault(pair.right, pair.right)));
|
||||||
|
typeVariables.add(pair.right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All unbounded type variables
|
||||||
|
outer:
|
||||||
|
for (var typeVariable : typeVariables) {
|
||||||
|
for (var pair : simplifiedConstraints) {
|
||||||
|
if (pair.left.equals(typeVariable) && typeVariables.contains(pair.right))
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
|
if (!hasBound(typeVariable, genericsOfClass))
|
||||||
|
result.add(new PairTPHequalRefTypeOrWildcardType(typeVariable, OBJECT));
|
||||||
|
}
|
||||||
|
|
||||||
|
// All unbounded bounds
|
||||||
|
outer:
|
||||||
|
for (var pair : simplifiedConstraints) {
|
||||||
|
for (var pair2 : simplifiedConstraints) {
|
||||||
|
if (pair.right.equals(pair2.left))
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
|
if (!hasBound(pair.right, genericsOfClass) && typeVariables.contains(pair.right))
|
||||||
|
result.add(new PairTPHequalRefTypeOrWildcardType(pair.right, OBJECT));
|
||||||
|
}
|
||||||
|
|
||||||
|
eliminateCyclesAndInfima(result);
|
||||||
|
System.out.println(method.name + ": " + result);
|
||||||
|
|
||||||
|
Set<TypePlaceholder> allUsedTPHs = new HashSet<>();
|
||||||
|
allUsedTPHs.addAll(typeVariables);
|
||||||
|
allUsedTPHs.addAll(typeVariablesOfFields);
|
||||||
|
usedTPHsOfMethods.put(method, allUsedTPHs);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void findAllBounds(RefTypeOrTPHOrWildcardOrGeneric type, Set<ResultPair<?, ?>> generics) {
|
||||||
|
if (type instanceof TypePlaceholder tph) {
|
||||||
|
tph = equality.getOrDefault(tph, tph);
|
||||||
|
|
||||||
|
var concreteType = concreteTypes.get(tph);
|
||||||
|
if (concreteType != null) {
|
||||||
|
findAllBounds(concreteType, generics);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var rsp : simplifiedConstraints) {
|
||||||
|
var left = equality.getOrDefault(rsp.left, rsp.left);
|
||||||
|
var right = equality.getOrDefault(rsp.right, rsp.right);
|
||||||
|
if (left.equals(tph)) {
|
||||||
|
var pair = new PairTPHsmallerTPH(tph, right);
|
||||||
|
if (!generics.contains(pair)) {
|
||||||
|
generics.add(pair);
|
||||||
|
findAllBounds(right, generics);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
generics.add(new PairTPHequalRefTypeOrWildcardType(tph, OBJECT));
|
||||||
|
} else if (type instanceof RefType refType) {
|
||||||
|
refType.getParaList().forEach(t -> findAllBounds(t, generics));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<ResultPair<?, ?>> generics(ClassOrInterface classOrInterface) {
|
||||||
|
if (computedGenericsOfClasses.containsKey(classOrInterface))
|
||||||
|
return computedGenericsOfClasses.get(classOrInterface);
|
||||||
|
|
||||||
|
Set<ResultPair<?, ?>> result = new HashSet<>();
|
||||||
|
for (var field : classOrInterface.getFieldDecl()) {
|
||||||
|
findAllBounds(field.getType(), result);
|
||||||
|
}
|
||||||
|
computedGenericsOfClasses.put(classOrInterface, result);
|
||||||
|
eliminateCyclesAndInfima(result);
|
||||||
|
eliminateInnerTypeVariables(classOrInterface, result);
|
||||||
|
equalizeTypeVariables(result);
|
||||||
|
|
||||||
|
System.out.println("Class " + classOrInterface.getClassName().getClassName() + ": " + result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void equalizeTypeVariables(Set<ResultPair<?, ?>> input) {
|
||||||
|
for (var pair : new HashSet<>(input)) {
|
||||||
|
if (pair instanceof PairTPHsmallerTPH ptph) {
|
||||||
|
if (ptph.left.getVariance() == 1 && ptph.right.getVariance() == -1) {
|
||||||
|
equality.put(ptph.left, ptph.right);
|
||||||
|
input.remove(ptph);
|
||||||
|
for (var pair2 : new HashSet<>(input)) {
|
||||||
|
if (pair2 instanceof PairTPHsmallerTPH ptph2 && ptph2.right.equals(ptph.left)) {
|
||||||
|
input.remove(pair2);
|
||||||
|
input.add(new PairTPHsmallerTPH(ptph2.left, ptph.right));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void findTphs(RefTypeOrTPHOrWildcardOrGeneric type, Set<TypePlaceholder> tphs) {
|
||||||
|
if (type instanceof RefType refType) {
|
||||||
|
refType.getParaList().forEach(t -> findTphs(t, tphs));
|
||||||
|
} else if (type instanceof TypePlaceholder tph) {
|
||||||
|
tph = equality.getOrDefault(tph, tph);
|
||||||
|
var concreteType = concreteTypes.get(tph);
|
||||||
|
if (concreteType != null) {
|
||||||
|
findTphs(concreteType, tphs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tphs.add(tph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void eliminateInnerTypeVariables(ClassOrInterface classOrInterface, Set<ResultPair<?, ?>> input) {
|
||||||
|
Set<TypePlaceholder> referenced = new HashSet<>();
|
||||||
|
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) {
|
||||||
|
if (!referenced.contains(pair.getLeft())) {
|
||||||
|
input.remove(pair);
|
||||||
|
for (var pair2 : oldInput) {
|
||||||
|
if (pair2.getRight().equals(pair.getLeft())) {
|
||||||
|
input.remove(pair2);
|
||||||
|
if (pair instanceof PairTPHsmallerTPH)
|
||||||
|
input.add(new PairTPHsmallerTPH((TypePlaceholder) pair2.getLeft(), (TypePlaceholder) pair.getRight()));
|
||||||
|
else
|
||||||
|
input.add(new PairTPHequalRefTypeOrWildcardType((TypePlaceholder) pair2.getLeft(), pair.getRight()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void eliminateCyclesAndInfima(Set<ResultPair<?, ?>> input) {
|
||||||
|
// Eliminate cycles
|
||||||
|
var cycles = findCycles(input);
|
||||||
|
for (var cycle : cycles) {
|
||||||
|
var newTph = TypePlaceholder.fresh(new NullToken());
|
||||||
|
input.add(new PairTPHequalRefTypeOrWildcardType(newTph, OBJECT));
|
||||||
|
cycle.add(cycle.get(0)); // Make it a complete cycle
|
||||||
|
for (var i = 0; i < cycle.size() - 1; i++) {
|
||||||
|
var left = cycle.get(i);
|
||||||
|
var right = cycle.get(i + 1);
|
||||||
|
var pair = new PairTPHsmallerTPH(left, right);
|
||||||
|
input.remove(pair);
|
||||||
|
equality.put(left, newTph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Eliminate infima
|
||||||
|
var foundInfima = false;
|
||||||
|
do {
|
||||||
|
foundInfima = false;
|
||||||
|
for (var constraint : new HashSet<>(input)) {
|
||||||
|
var left = (TypePlaceholder) constraint.getLeft();
|
||||||
|
Set<PairTPHsmallerTPH> infima = new HashSet<>();
|
||||||
|
for (var pair : input) {
|
||||||
|
if (pair instanceof PairTPHsmallerTPH stph)
|
||||||
|
if (pair.getLeft().equals(constraint.getLeft()))
|
||||||
|
infima.add(stph);
|
||||||
|
}
|
||||||
|
if (infima.size() > 1) {
|
||||||
|
foundInfima = true;
|
||||||
|
var newTph = TypePlaceholder.fresh(new NullToken());
|
||||||
|
input.add(new PairTPHsmallerTPH(left, newTph));
|
||||||
|
input.removeAll(infima);
|
||||||
|
for (var infimum : infima) {
|
||||||
|
equality.put(infimum.right, newTph);
|
||||||
|
new HashSet<>(input).forEach(pair -> {
|
||||||
|
if (pair.getLeft().equals(infimum.right)) {
|
||||||
|
input.remove(pair);
|
||||||
|
if (pair instanceof PairTPHsmallerTPH stph) {
|
||||||
|
input.add(new PairTPHsmallerTPH(newTph, stph.right));
|
||||||
|
} else if (pair instanceof PairTPHequalRefTypeOrWildcardType rtph) {
|
||||||
|
input.add(new PairTPHequalRefTypeOrWildcardType(newTph, rtph.getRight()));
|
||||||
|
}
|
||||||
|
} else if (pair.getRight().equals(infimum.right)) {
|
||||||
|
input.remove(pair);
|
||||||
|
if (pair instanceof PairTPHsmallerTPH stph) {
|
||||||
|
input.add(new PairTPHsmallerTPH(stph.left, newTph));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (foundInfima);
|
||||||
|
}
|
||||||
|
|
||||||
|
TargetType get(TypePlaceholder tph) {
|
||||||
|
if (equality.containsKey(tph)) {
|
||||||
|
return get(equality.get(tph));
|
||||||
|
}
|
||||||
|
var type = concreteTypes.get(tph);
|
||||||
|
if (type == null) return new TargetGenericType(tph.getName());
|
||||||
|
return convert(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ByteArrayClassLoader classLoader;
|
||||||
|
protected SourceFile sourceFile;
|
||||||
|
|
||||||
|
public ASTToTargetAST(List<ResultSet> resultSets) {
|
||||||
|
this(resultSets, null, new ByteArrayClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ASTToTargetAST(List<ResultSet> resultSets, SourceFile sourceFile, ByteArrayClassLoader classLoader) {
|
||||||
|
this.classLoader = classLoader;
|
||||||
|
this.sourceFile = sourceFile;
|
||||||
|
|
||||||
|
all = new ArrayList<>();
|
||||||
|
for (var set : resultSets) {
|
||||||
|
all.add(new Sigma(set));
|
||||||
|
}
|
||||||
|
this.sigma = all.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Set<TypePlaceholder> allNodes(Set<ResultPair<?, ?>> input) {
|
||||||
|
return input.stream()
|
||||||
|
.filter(pair -> pair instanceof PairTPHsmallerTPH)
|
||||||
|
.flatMap(pair -> Stream.of((TypePlaceholder) pair.getLeft(), (TypePlaceholder) pair.getRight())).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
static Set<TypePlaceholder> outgoingEdgesOf(TypePlaceholder tph, Set<ResultPair<?, ?>> input) {
|
||||||
|
return input.stream()
|
||||||
|
.filter(pair -> pair instanceof PairTPHsmallerTPH && pair.getLeft().equals(tph))
|
||||||
|
.map(pair -> (TypePlaceholder) pair.getRight()).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean containsEdge(TypePlaceholder a, TypePlaceholder b, Set<ResultPair<?, ?>> input) {
|
||||||
|
return input.stream().anyMatch(pair -> pair.getLeft().equals(a) && pair.getRight().equals(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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<List<TypePlaceholder>> findCycles(Set<ResultPair<?, ?>> input) {
|
||||||
|
Map<TypePlaceholder, Integer> indices = new HashMap<>();
|
||||||
|
List<TypePlaceholder> path = new ArrayList<>();
|
||||||
|
Set<TypePlaceholder> pathSet = new HashSet<>();
|
||||||
|
Map<TypePlaceholder, Set<TypePlaceholder>> blocked = new HashMap<>();
|
||||||
|
Set<List<TypePlaceholder>> cycles = new HashSet<>();
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
for (var tph : allNodes(input)) {
|
||||||
|
blocked.put(tph, new HashSet<>());
|
||||||
|
indices.put(tph, index++);
|
||||||
|
}
|
||||||
|
|
||||||
|
var vertexIterator = allNodes(input).iterator();
|
||||||
|
if (!vertexIterator.hasNext()) return cycles;
|
||||||
|
|
||||||
|
TypePlaceholder startOfPath = null;
|
||||||
|
TypePlaceholder endOfPath = vertexIterator.next();
|
||||||
|
TypePlaceholder temp = null;
|
||||||
|
int endIndex = 0;
|
||||||
|
boolean extensionFound = false;
|
||||||
|
path.add(endOfPath);
|
||||||
|
pathSet.add(endOfPath);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
do {
|
||||||
|
extensionFound = false;
|
||||||
|
for (TypePlaceholder n : outgoingEdgesOf(endOfPath, input)) {
|
||||||
|
int cmp = indices.get(n).compareTo(indices.get(path.get(0)));
|
||||||
|
if ((cmp > 0) && !pathSet.contains(n) && !blocked.get(endOfPath).contains(n)) {
|
||||||
|
path.add(n);
|
||||||
|
pathSet.add(n);
|
||||||
|
endOfPath = n;
|
||||||
|
extensionFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (extensionFound);
|
||||||
|
|
||||||
|
startOfPath = path.get(0);
|
||||||
|
if (containsEdge(endOfPath, startOfPath, input)) {
|
||||||
|
List<TypePlaceholder> cycle = new ArrayList<>(path);
|
||||||
|
cycles.add(cycle);
|
||||||
|
}
|
||||||
|
if (path.size() > 1) {
|
||||||
|
blocked.get(endOfPath).clear();
|
||||||
|
endIndex = path.size() - 1;
|
||||||
|
path.remove(endIndex);
|
||||||
|
pathSet.remove(endOfPath);
|
||||||
|
--endIndex;
|
||||||
|
temp = endOfPath;
|
||||||
|
endOfPath = path.get(endIndex);
|
||||||
|
blocked.get(endOfPath).add(temp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (vertexIterator.hasNext()) {
|
||||||
|
path.clear();
|
||||||
|
pathSet.clear();
|
||||||
|
endOfPath = vertexIterator.next();
|
||||||
|
path.add(endOfPath);
|
||||||
|
pathSet.add(endOfPath);
|
||||||
|
for (TypePlaceholder tph : blocked.keySet()) {
|
||||||
|
blocked.get(tph).clear();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return cycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<Method> findMethod(ClassOrInterface owner, String name, ArgumentList argumentList) {
|
||||||
|
return owner.getMethods().stream().filter(
|
||||||
|
m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList)
|
||||||
|
).findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean parameterEquals(ParameterList parameterList, ArgumentList argumentList) {
|
||||||
|
var pars = parameterList.getFormalparalist();
|
||||||
|
var arguments = argumentList.getArguments();
|
||||||
|
if (pars.size() != arguments.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (var i = 0; i < pars.size(); i++) {
|
||||||
|
var type1 = convert(pars.get(i).getType());
|
||||||
|
var type2 = convert(arguments.get(i).getType());
|
||||||
|
if (type2 instanceof TargetGenericType && type1 instanceof TargetGenericType)
|
||||||
|
return true;
|
||||||
|
if (!type1.equals(type2)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<TargetGeneric> convert(Set<ResultPair<?, ?>> result) {
|
||||||
|
return result.stream().map(p -> {
|
||||||
|
if (p instanceof PairTPHsmallerTPH pair) {
|
||||||
|
return new TargetGeneric(pair.left.getName(), new TargetGenericType(pair.right.getName()));
|
||||||
|
} else if (p instanceof PairTPHequalRefTypeOrWildcardType pair) {
|
||||||
|
return new TargetGeneric(pair.left.getName(), convert(pair.right));
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public TargetClass convert(ClassOrInterface input) {
|
||||||
|
currentClass = input;
|
||||||
|
TargetBlock fieldInitializer = null;
|
||||||
|
if (input.getfieldInitializations().isPresent())
|
||||||
|
fieldInitializer = convert(input.getfieldInitializations().get().block);
|
||||||
|
TargetBlock finalFieldInitializer = fieldInitializer;
|
||||||
|
|
||||||
|
return new TargetClass(input.getModifiers(), input.getClassName().toString(), convert(input.getSuperClass()),
|
||||||
|
convert(sigma.generics(input)),
|
||||||
|
input.getSuperInterfaces().stream().map(this::convert).toList(),
|
||||||
|
input.getConstructors().stream().map(constructor -> this.convert(constructor, finalFieldInitializer)).flatMap(List::stream).toList(),
|
||||||
|
input.getFieldDecl().stream().map(this::convert).toList(),
|
||||||
|
input.getMethods().stream().map(this::convert).flatMap(List::stream).toList()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<MethodParameter> convert(ParameterList input) {
|
||||||
|
return input.getFormalparalist().stream()
|
||||||
|
.map(param -> new MethodParameter(convert(param.getType()), param.getName())).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TargetConstructor> convert(Constructor input, TargetBlock fieldInitializer) {
|
||||||
|
sigma = all.get(0);
|
||||||
|
List<TargetConstructor> result = new ArrayList<>();
|
||||||
|
Set<List<MethodParameter>> parameterSet = new HashSet<>();
|
||||||
|
|
||||||
|
for (var s : all) {
|
||||||
|
sigma = s;
|
||||||
|
var generics = sigma.generics(currentClass, input);
|
||||||
|
List<MethodParameter> params = convert(input.getParameterList());
|
||||||
|
if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
|
||||||
|
result.add(new TargetConstructor(input.modifier, convert(generics), params, convert(input.block), fieldInitializer));
|
||||||
|
parameterSet.add(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TargetMethod> convert(Method input) {
|
||||||
|
sigma = all.get(0);
|
||||||
|
List<TargetMethod> result = new ArrayList<>();
|
||||||
|
Set<List<MethodParameter>> parameterSet = new HashSet<>();
|
||||||
|
|
||||||
|
for (var s : all) {
|
||||||
|
sigma = s;
|
||||||
|
var generics = sigma.generics(currentClass, input);
|
||||||
|
List<MethodParameter> params = convert(input.getParameterList());
|
||||||
|
if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
|
||||||
|
result.add(new TargetMethod(
|
||||||
|
input.modifier,
|
||||||
|
input.name, convert(generics), params,
|
||||||
|
convert(input.getReturnType()),
|
||||||
|
convert(input.block)
|
||||||
|
));
|
||||||
|
parameterSet.add(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TargetBlock convert(Block block) {
|
||||||
|
return new TargetBlock(block.statements.stream().map(this::convert).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TargetExpression convert(Expression expr) {
|
||||||
|
var converter = new StatementToTargetExpression(this);
|
||||||
|
expr.accept(converter);
|
||||||
|
return converter.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TargetField convert(Field input) {
|
||||||
|
return new TargetField(
|
||||||
|
input.modifier,
|
||||||
|
convert(input.getType()),
|
||||||
|
input.getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Set<Integer> usedFunN = new HashSet<>();
|
||||||
|
|
||||||
|
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
|
||||||
|
return input.acceptTV(new TypeVisitor<>() {
|
||||||
|
@Override
|
||||||
|
public TargetType visit(RefType refType) {
|
||||||
|
var name = refType.getName().toString();
|
||||||
|
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
|
||||||
|
if (!usedFunN.contains(params.size() - 1)) {
|
||||||
|
usedFunN.add(params.size() - 1);
|
||||||
|
classLoader.loadClass(FunNGenerator.getInstance().generateSuperBytecode(params.size() - 1));
|
||||||
|
}
|
||||||
|
return new TargetFunNType(params.size() - 1, params);
|
||||||
|
}
|
||||||
|
return new TargetRefType(name, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TargetType visit(SuperWildcardType superWildcardType) {
|
||||||
|
return new TargetSuperWildcard(convert(superWildcardType.getInnerType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TargetType visit(TypePlaceholder typePlaceholder) {
|
||||||
|
return sigma.get(typePlaceholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TargetType visit(ExtendsWildcardType extendsWildcardType) {
|
||||||
|
return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TargetType visit(GenericRefType genericRefType) {
|
||||||
|
return new TargetGenericType(genericRefType.getParsedName());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,358 @@
|
|||||||
|
package de.dhbwstuttgart.target.generate;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
|
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||||
|
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.TargetSpecializedType;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
public class StatementToTargetExpression implements StatementVisitor {
|
||||||
|
|
||||||
|
public StatementToTargetExpression(ASTToTargetAST converter) {
|
||||||
|
this.converter = converter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TargetExpression result;
|
||||||
|
private final ASTToTargetAST converter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ArgumentList argumentList) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LambdaExpression lambdaExpression) {
|
||||||
|
var parameters = StreamSupport
|
||||||
|
.stream(lambdaExpression.params.spliterator(), false)
|
||||||
|
.map(p -> new MethodParameter(converter.convert(p.getType()), p.getName()))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
List<MethodParameter> captures = new ArrayList<>();
|
||||||
|
lambdaExpression.methodBody.accept(new TracingStatementVisitor() {
|
||||||
|
// TODO The same mechanism is implemented in Codegen, maybe use it from there?
|
||||||
|
final Stack<Set<String>> localVariables = new Stack<>();
|
||||||
|
{ localVariables.push(new HashSet<>()); }
|
||||||
|
|
||||||
|
boolean hasLocalVar(String name) {
|
||||||
|
for (var localVariables : this.localVariables) {
|
||||||
|
if (localVariables.contains(name)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Block block) {
|
||||||
|
localVariables.push(new HashSet<>());
|
||||||
|
super.visit(block);
|
||||||
|
localVariables.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LocalVar localVar) {
|
||||||
|
super.visit(localVar);
|
||||||
|
var capture = new MethodParameter(converter.convert(localVar.getType()), localVar.name);
|
||||||
|
if (!hasLocalVar(localVar.name) && !parameters.contains(capture) && !captures.contains(capture))
|
||||||
|
captures.add(capture);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LocalVarDecl varDecl) {
|
||||||
|
var localVariables = this.localVariables.peek();
|
||||||
|
localVariables.add(varDecl.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LambdaExpression lambda) {} // Don't look at lambda expressions
|
||||||
|
});
|
||||||
|
|
||||||
|
result = new TargetLambdaExpression(
|
||||||
|
new TargetFunNType(parameters.size(), parameters.stream().map(MethodParameter::type).toList()),
|
||||||
|
captures, parameters, converter.convert(lambdaExpression.getReturnType()), converter.convert(lambdaExpression.methodBody)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Assign assign) {
|
||||||
|
TargetExpression left;
|
||||||
|
if (assign.lefSide instanceof AssignToLocal) {
|
||||||
|
left = converter.convert(((AssignToLocal) assign.lefSide).localVar);
|
||||||
|
} else {
|
||||||
|
left = converter.convert(((AssignToField) assign.lefSide).field);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = new TargetAssign(converter.convert(assign.getType()), left, converter.convert(assign.rightSide));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BinaryExpr binary) {
|
||||||
|
result = switch (binary.operation) {
|
||||||
|
case ADD -> new TargetBinaryOp.Add(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||||
|
case SUB -> new TargetBinaryOp.Sub(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||||
|
case MUL -> new TargetBinaryOp.Mul(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||||
|
case MOD -> new TargetBinaryOp.Rem(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||||
|
case AND -> new TargetBinaryOp.And(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||||
|
case OR -> new TargetBinaryOp.Or(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||||
|
case DIV -> new TargetBinaryOp.Div(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||||
|
case LESSTHAN -> new TargetBinaryOp.Less(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||||
|
case BIGGERTHAN -> new TargetBinaryOp.Greater(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||||
|
case LESSEQUAL -> new TargetBinaryOp.LessOrEqual(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||||
|
case BIGGEREQUAL -> new TargetBinaryOp.GreaterOrEqual(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||||
|
case EQUAL -> new TargetBinaryOp.Equal(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||||
|
case NOTEQUAL -> new TargetBinaryOp.NotEqual(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Block block) {
|
||||||
|
result = converter.convert(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(CastExpr castExpr) {
|
||||||
|
result = new TargetCast(converter.convert(castExpr.getType()), converter.convert(castExpr.expr));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(EmptyStmt emptyStmt) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(FieldVar fieldVar) {
|
||||||
|
result = new TargetFieldVar(
|
||||||
|
converter.convert(fieldVar.getType()),
|
||||||
|
converter.convert(fieldVar.receiver.getType()),
|
||||||
|
false,
|
||||||
|
converter.convert(fieldVar.receiver),
|
||||||
|
fieldVar.fieldVarName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ForStmt forStmt) {
|
||||||
|
// TODO Doesn't seem to be fully implemented yet
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IfStmt ifStmt) {
|
||||||
|
result = new TargetIf(
|
||||||
|
converter.convert(ifStmt.expr),
|
||||||
|
converter.convert(ifStmt.then_block),
|
||||||
|
converter.convert(ifStmt.else_block)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InstanceOf instanceOf) {
|
||||||
|
result = new TargetInstanceOf(converter.convert(instanceOf.lexpr), converter.convert(instanceOf.rexpr.getType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LocalVar localVar) {
|
||||||
|
result = new TargetLocalVar(converter.convert(localVar.getType()), localVar.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LocalVarDecl localVarDecl) {
|
||||||
|
// TODO No value, is this correct?
|
||||||
|
result = new TargetVarDecl(converter.convert(localVarDecl.getType()), localVarDecl.getName(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean convertsTo(TargetType from, TargetType to) {
|
||||||
|
if (to.equals(TargetType.Object)) return true; // TODO Consider type coercion and suptyping
|
||||||
|
return to.equals(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
Method findMethod(JavaClassName className, String name, List<TargetType> args) {
|
||||||
|
if (converter.sourceFile != null && converter.sourceFile.imports.contains(className)) {
|
||||||
|
try {
|
||||||
|
var clazz = converter.classLoader.loadClass(className.toString());
|
||||||
|
|
||||||
|
outer: for (var method : clazz.getMethods()) {
|
||||||
|
if (method.getParameterTypes().length != args.size()) continue;
|
||||||
|
if (!method.getName().equals(name)) continue;
|
||||||
|
|
||||||
|
for (var i = 0; i < method.getParameterTypes().length; i++) {
|
||||||
|
var param = method.getParameterTypes()[i];
|
||||||
|
var arg = args.get(i);
|
||||||
|
if (param.isPrimitive()) {
|
||||||
|
arg = TargetType.toPrimitive(arg);
|
||||||
|
}
|
||||||
|
if (!convertsTo(arg, Objects.requireNonNull(TargetType.toTargetType(param)))) continue outer;
|
||||||
|
}
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException ignored) {}
|
||||||
|
}
|
||||||
|
if (converter.sourceFile != null) { // TODO Multiple source files
|
||||||
|
var thisClass = converter.sourceFile.KlassenVektor.stream()
|
||||||
|
.filter(classOrInterface -> classOrInterface.getClassName().equals(className)).findFirst();
|
||||||
|
|
||||||
|
if (thisClass.isPresent()) {
|
||||||
|
var superClass = thisClass.get().getSuperClass().getName();
|
||||||
|
return findMethod(superClass, name, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(MethodCall methodCall) {
|
||||||
|
var receiverType = converter.convert(methodCall.receiver.getType());
|
||||||
|
var isFunNType = receiverType instanceof TargetFunNType;
|
||||||
|
var returnType = isFunNType ? TargetType.Object : converter.convert(methodCall.getType());
|
||||||
|
var receiverName = new JavaClassName(converter.convert(methodCall.receiver.getType()).name());
|
||||||
|
var argList = methodCall.arglist.getArguments().stream().map(expr -> converter.convert(expr.getType())).toList();
|
||||||
|
|
||||||
|
Method foundMethod = null;
|
||||||
|
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver && expressionReceiver.expr instanceof This) {
|
||||||
|
var thisMethod = converter.findMethod(converter.currentClass, methodCall.name, methodCall.arglist);
|
||||||
|
if (thisMethod.isEmpty()) {
|
||||||
|
foundMethod = findMethod(converter.currentClass.getSuperClass().getName(), methodCall.name, argList);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
foundMethod = findMethod(receiverName, methodCall.name, argList);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundMethod != null) {
|
||||||
|
returnType = TargetType.toTargetType(foundMethod.getReturnType());
|
||||||
|
argList = Stream.of(foundMethod.getParameterTypes()).map(TargetType::toTargetType).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
result = new TargetMethodCall(
|
||||||
|
converter.convert(methodCall.getType()),
|
||||||
|
returnType, argList,
|
||||||
|
converter.convert(methodCall.receiver),
|
||||||
|
methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(),
|
||||||
|
receiverType,
|
||||||
|
methodCall.name, false, isFunNType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewClass newClass) {
|
||||||
|
result = new TargetNew(
|
||||||
|
new TargetRefType(newClass.name),
|
||||||
|
newClass.getArgumentList().getArguments().stream().map(converter::convert).toList()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewArray newArray) {
|
||||||
|
// TODO
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Return aReturn) {
|
||||||
|
result = new TargetReturn(converter.convert(aReturn.retexpr));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ReturnVoid aReturn) {
|
||||||
|
result = new TargetReturn(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(StaticClassName staticClassName) {
|
||||||
|
result = new TargetClassName(converter.convert(staticClassName.getType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Super aSuper) {
|
||||||
|
result = new TargetSuper(converter.convert(aSuper.getType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(This aThis) {
|
||||||
|
result = new TargetThis(converter.convert(aThis.getType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WhileStmt whileStmt) {
|
||||||
|
result = new TargetWhile(converter.convert(whileStmt.expr), converter.convert(whileStmt.loopBlock));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(DoStmt whileStmt) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO These two might not be necessary
|
||||||
|
@Override
|
||||||
|
public void visit(AssignToField assignLeftSide) {
|
||||||
|
result = converter.convert(assignLeftSide.field);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignToLocal assignLeftSide) {
|
||||||
|
result = converter.convert(assignLeftSide.localVar);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SuperCall superCall) {
|
||||||
|
var aSuper = converter.convert(converter.currentClass.getSuperClass());
|
||||||
|
var type = converter.convert(superCall.getType());
|
||||||
|
result = new TargetMethodCall(
|
||||||
|
type, type,
|
||||||
|
superCall.argTypes == null ? List.of() : superCall.argTypes.stream().map(converter::convert).toList(),
|
||||||
|
new TargetSuper(aSuper),
|
||||||
|
superCall.getArgumentList().getArguments().stream().map(converter::convert).toList(),
|
||||||
|
aSuper,
|
||||||
|
superCall.name, false, false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ExpressionReceiver expressionReceiver) {
|
||||||
|
result = converter.convert(expressionReceiver.expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(UnaryExpr unaryExpr) {
|
||||||
|
result = switch (unaryExpr.operation) {
|
||||||
|
case NOT -> new TargetUnaryOp.Not(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
|
||||||
|
case MINUS -> new TargetUnaryOp.Negate(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
|
||||||
|
case PREINCREMENT -> new TargetUnaryOp.PreIncrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
|
||||||
|
case PREDECREMENT -> new TargetUnaryOp.PreDecrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
|
||||||
|
case POSTINCREMENT -> new TargetUnaryOp.PostIncrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
|
||||||
|
case PLUS -> new TargetUnaryOp.Add(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
|
||||||
|
case POSTDECREMENT -> new TargetUnaryOp.PostDecrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Literal literal) {
|
||||||
|
if (literal.value instanceof Integer
|
||||||
|
|| literal.value instanceof Short
|
||||||
|
|| literal.value instanceof Byte) {
|
||||||
|
|
||||||
|
result = new TargetLiteral.IntLiteral((int) literal.value);
|
||||||
|
} else if (literal.value instanceof Float) {
|
||||||
|
result = new TargetLiteral.FloatLiteral((float) literal.value);
|
||||||
|
} else if (literal.value instanceof Double) {
|
||||||
|
result = new TargetLiteral.DoubleLiteral((double) literal.value);
|
||||||
|
} else if (literal.value instanceof Long) {
|
||||||
|
result = new TargetLiteral.LongLiteral((long) literal.value);
|
||||||
|
} else if (literal.value instanceof Character) {
|
||||||
|
result = new TargetLiteral.CharLiteral((char) literal.value);
|
||||||
|
} else if (literal.value instanceof String) {
|
||||||
|
result = new TargetLiteral.StringLiteral((String) literal.value);
|
||||||
|
} else if (literal.value instanceof Boolean) {
|
||||||
|
result = new TargetLiteral.BooleanLiteral((boolean) literal.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,159 @@
|
|||||||
|
package de.dhbwstuttgart.target.generate;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||||
|
|
||||||
|
|
||||||
|
// This visitor walks the entire tree, individual methods may be overridden
|
||||||
|
public abstract class TracingStatementVisitor implements StatementVisitor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(MethodCall methodCall) {
|
||||||
|
methodCall.receiver.accept(this);
|
||||||
|
methodCall.getArgumentList().accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ArgumentList argumentList) {
|
||||||
|
argumentList.getArguments().forEach(expr -> expr.accept(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LambdaExpression lambdaExpression) {
|
||||||
|
lambdaExpression.methodBody.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Assign assign) {
|
||||||
|
assign.rightSide.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BinaryExpr binary) {
|
||||||
|
binary.lexpr.accept(this);
|
||||||
|
binary.rexpr.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Block block) {
|
||||||
|
for (var expr : block.statements)
|
||||||
|
expr.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(CastExpr castExpr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(EmptyStmt emptyStmt) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(FieldVar fieldVar) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ForStmt forStmt) {
|
||||||
|
forStmt.body_Loop_block.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IfStmt ifStmt) {
|
||||||
|
ifStmt.then_block.accept(this);
|
||||||
|
ifStmt.else_block.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InstanceOf instanceOf) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LocalVar localVar) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LocalVarDecl localVarDecl) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewClass newClass) {
|
||||||
|
this.visit((MethodCall) newClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewArray newArray) {
|
||||||
|
newArray.expr.forEach(expr -> expr.accept(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Return aReturn) {
|
||||||
|
aReturn.retexpr.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ReturnVoid aReturn) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(StaticClassName staticClassName) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Super aSuper) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(This aThis) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WhileStmt whileStmt) {
|
||||||
|
whileStmt.loopBlock.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(DoStmt whileStmt) {
|
||||||
|
whileStmt.loopBlock.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignToField assignLeftSide) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignToLocal assignLeftSide) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SuperCall superCall) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ExpressionReceiver expressionReceiver) {
|
||||||
|
expressionReceiver.expr.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(UnaryExpr unaryExpr) {
|
||||||
|
unaryExpr.expr.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Literal literal) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record MethodParameter(TargetType type, String name) {
|
||||||
|
}
|
47
src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java
Normal file
47
src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public record TargetClass(int modifiers, String qualifiedName, TargetType superType, Set<TargetGeneric> generics, List<TargetType> implementingInterfaces,
|
||||||
|
List<TargetConstructor> constructors, List<TargetField> fields, List<TargetMethod> methods) {
|
||||||
|
|
||||||
|
public TargetClass(int modifiers, String qualifiedName) {
|
||||||
|
this(modifiers, qualifiedName, TargetType.Object, new HashSet<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
|
||||||
|
}
|
||||||
|
public TargetClass(int modifiers, String qualifiedName, List<TargetType> implementingInterfaces) {
|
||||||
|
this(modifiers, qualifiedName, TargetType.Object, new HashSet<>(), implementingInterfaces, new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return qualifiedName.replaceAll("\\.", "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addMethod(int access, String name, Set<TargetGeneric> generics, List<MethodParameter> parameterTypes, TargetType returnType, TargetBlock block) {
|
||||||
|
this.methods.add(new TargetMethod(access, name, generics, parameterTypes, returnType, block));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addMethod(int access, String name, List<MethodParameter> parameterTypes, TargetType returnType, TargetBlock block) {
|
||||||
|
addMethod(access, name, Set.of(), parameterTypes, returnType, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addConstructor(int access, Set<TargetGeneric> generics, List<MethodParameter> paramterTypes, TargetBlock block) {
|
||||||
|
this.constructors.add(new TargetConstructor(access, generics, paramterTypes, block, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addConstructor(int access, List<MethodParameter> paramterTypes, TargetBlock block) {
|
||||||
|
addConstructor(access, Set.of(), paramterTypes, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addField(int access, TargetRefType type, String name) {
|
||||||
|
this.fields.add(new TargetField(access, type, name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public record TargetConstructor(int access, Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetBlock block, TargetBlock fieldInitializer) {
|
||||||
|
|
||||||
|
public String getDescriptor() {
|
||||||
|
return TargetMethod.getDescriptor(null, parameters.stream().map(MethodParameter::type).toArray(TargetType[]::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSignature() {
|
||||||
|
return TargetMethod.getSignature(generics, parameters, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
11
src/main/java/de/dhbwstuttgart/target/tree/TargetField.java
Normal file
11
src/main/java/de/dhbwstuttgart/target/tree/TargetField.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
public record TargetField(int access, TargetType type, String name) {
|
||||||
|
public boolean isStatic() {
|
||||||
|
return (access & Opcodes.ACC_STATIC) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetGeneric(String name, TargetType bound) {
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record TargetInterface(String name, List<TargetMethod> methods, List<TargetInterface> extendedInterfaces) {
|
||||||
|
}
|
49
src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java
Normal file
49
src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public record TargetMethod(int access, String name, Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType, TargetBlock block) {
|
||||||
|
public static String getDescriptor(TargetType returnType, TargetType... parameters) {
|
||||||
|
String ret = "(";
|
||||||
|
for (var parameterType : parameters) {
|
||||||
|
ret += parameterType.toSignature();
|
||||||
|
}
|
||||||
|
ret += ")";
|
||||||
|
if (returnType == null) ret += "V";
|
||||||
|
else ret += returnType.toSignature();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSignature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) {
|
||||||
|
String ret = "<";
|
||||||
|
for (var generic : generics) {
|
||||||
|
ret += generic.name() + ":" + generic.bound().toGenericSignature();
|
||||||
|
}
|
||||||
|
ret += ">(";
|
||||||
|
for (var param : parameters) {
|
||||||
|
ret += param.type().toGenericSignature();
|
||||||
|
}
|
||||||
|
ret += ")";
|
||||||
|
if (returnType == null) ret += "V";
|
||||||
|
else ret += returnType.toGenericSignature();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescriptor() {
|
||||||
|
return getDescriptor(returnType, parameters.stream().map(MethodParameter::type).toArray(TargetType[]::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSignature() {
|
||||||
|
return getSignature(generics, parameters, returnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStatic() {
|
||||||
|
return (access & Opcodes.ACC_STATIC) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetAssign(TargetType type, TargetExpression left, TargetExpression right) implements TargetStatementExpression {
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.expression.TargetExpression;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public sealed interface TargetBinaryOp extends TargetExpression {
|
||||||
|
TargetExpression left();
|
||||||
|
TargetExpression right();
|
||||||
|
|
||||||
|
// Arithmetic
|
||||||
|
record Add(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
|
||||||
|
record Sub(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
|
||||||
|
record Div(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
|
||||||
|
record Mul(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
|
||||||
|
record Rem(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
|
||||||
|
|
||||||
|
// Bitwise
|
||||||
|
record BAnd(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
|
||||||
|
record BOr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
|
||||||
|
record XOr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
|
||||||
|
record Shl(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
|
||||||
|
record Shr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
|
||||||
|
record UShr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
|
||||||
|
|
||||||
|
// Conditional
|
||||||
|
record And(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
|
||||||
|
record Or(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
|
||||||
|
|
||||||
|
sealed interface TargetRelationalOp extends TargetBinaryOp {
|
||||||
|
@Override
|
||||||
|
default TargetType type() {
|
||||||
|
return TargetType.Boolean;
|
||||||
|
}
|
||||||
|
TargetType exprType();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comparison
|
||||||
|
// exprType is the type that both arguments get converted to before comparison
|
||||||
|
record Equal(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {}
|
||||||
|
record Greater(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {}
|
||||||
|
record GreaterOrEqual(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {}
|
||||||
|
record Less(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {}
|
||||||
|
record LessOrEqual(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {}
|
||||||
|
record NotEqual(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record TargetBlock(List<TargetExpression> statements) implements TargetExpression {
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetBreak() implements TargetExpression {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetCast(TargetType type, TargetExpression expr) implements TargetExpression {
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetClassName(TargetType type) implements TargetExpression {
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetContinue() implements TargetExpression {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.*;
|
||||||
|
|
||||||
|
public sealed interface TargetExpression
|
||||||
|
permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetUnaryOp, TargetVarDecl, TargetWhile {
|
||||||
|
|
||||||
|
TargetType type();
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetFieldVar(TargetType type, TargetType owner, boolean isStatic, TargetExpression left, String right) implements TargetExpression {
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetFor(TargetExpression init, TargetExpression termination, TargetExpression increment, TargetExpression body) implements TargetExpression {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetForEach(TargetExpression vardecl, TargetExpression list) implements TargetExpression {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetIf(TargetExpression cond, TargetExpression if_body, TargetExpression else_body) implements TargetExpression {
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Expression;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetInstanceOf(TargetExpression left, TargetType right) implements TargetExpression {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return TargetType.Boolean;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.MethodParameter;
|
||||||
|
import de.dhbwstuttgart.target.tree.TargetField;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record TargetLambdaExpression(TargetType type, List<MethodParameter> captures, List<MethodParameter> params, TargetType returnType, TargetBlock block) implements TargetExpression {
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public sealed interface TargetLiteral extends TargetExpression {
|
||||||
|
Object value();
|
||||||
|
|
||||||
|
record BooleanLiteral(Boolean value) implements TargetLiteral {
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return TargetType.Boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record CharLiteral(Character value) implements TargetLiteral {
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return TargetType.Char;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record IntLiteral(Integer value) implements TargetLiteral {
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return TargetType.Integer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record LongLiteral(Long value) implements TargetLiteral {
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return TargetType.Long;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record FloatLiteral(Float value) implements TargetLiteral {
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return TargetType.Float;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record DoubleLiteral(Double value) implements TargetLiteral {
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return TargetType.Double;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record StringLiteral(String value) implements TargetLiteral {
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return TargetType.String;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetLocalVar(TargetType type, String name) implements TargetExpression {
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.MethodParameter;
|
||||||
|
import de.dhbwstuttgart.target.tree.TargetMethod;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record TargetMethodCall(TargetType type, TargetType returnType, List<TargetType> parameterTypes, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface) implements TargetStatementExpression {
|
||||||
|
public TargetMethodCall(TargetType type, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface) {
|
||||||
|
this(type, type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getDescriptor() {
|
||||||
|
return TargetMethod.getDescriptor(returnType, parameterTypes.toArray(TargetType[]::new));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.TargetMethod;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record TargetNew(TargetType type, List<TargetExpression> params) implements TargetStatementExpression {
|
||||||
|
public String getDescriptor() {
|
||||||
|
return TargetMethod.getDescriptor(null, params.stream().map(TargetExpression::type).toArray(TargetType[]::new));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetReturn(TargetExpression expression) implements TargetExpression {
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
public sealed interface TargetStatementExpression extends TargetExpression permits TargetAssign, TargetMethodCall, TargetNew, TargetUnaryOp.PostDecrement, TargetUnaryOp.PostIncrement, TargetUnaryOp.PreDecrement, TargetUnaryOp.PreIncrement {
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetSuper(TargetType type) implements TargetExpression {
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Expression;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record TargetSwitch(Expression expr, List<Case> cases, Expression default_) implements TargetExpression {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
record Case(Expression value, Expression body) {}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetTernary(TargetType type, TargetExpression cond, TargetExpression ifTrue, TargetExpression ifFalse) implements TargetExpression {
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetThis(TargetType type) implements TargetExpression {
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public sealed interface TargetUnaryOp extends TargetExpression {
|
||||||
|
TargetExpression expr();
|
||||||
|
|
||||||
|
record Negate(TargetType type, TargetExpression expr) implements TargetUnaryOp {}
|
||||||
|
record Add(TargetType type, TargetExpression expr) implements TargetUnaryOp {}
|
||||||
|
record Not(TargetType type, TargetExpression expr) implements TargetUnaryOp {}
|
||||||
|
|
||||||
|
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 {}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetVarDecl(TargetType varType, String name, TargetExpression value) implements TargetExpression {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetWhile(TargetExpression cond, TargetExpression body) implements TargetExpression {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TargetType type() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.type;
|
||||||
|
|
||||||
|
public record TargetExtendsWildcard(TargetType innerType) implements TargetType {
|
||||||
|
@Override
|
||||||
|
public String toSignature() {
|
||||||
|
return innerType.toSignature();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toGenericSignature() {
|
||||||
|
return innerType.toGenericSignature();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getInternalName() {
|
||||||
|
return innerType.getInternalName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return innerType.name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.type;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record TargetFunNType(int N, List<TargetType> params) implements TargetSpecializedType {
|
||||||
|
@Override
|
||||||
|
public String getInternalName() {
|
||||||
|
return "Fun" + N + "$$";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return getInternalName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toSignature() {
|
||||||
|
return "L" + getInternalName() + ";";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.type;
|
||||||
|
|
||||||
|
public record TargetGenericType(String name) implements TargetType {
|
||||||
|
@Override
|
||||||
|
public String toSignature() {
|
||||||
|
return "Ljava/lang/Object;"; // TODO Use bounds for this?
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toGenericSignature() {
|
||||||
|
return "T" + getInternalName() + ";";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getInternalName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.type;
|
||||||
|
|
||||||
|
public record TargetPrimitiveType(String name) implements TargetType {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toSignature() {
|
||||||
|
return getInternalName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toGenericSignature() {
|
||||||
|
return toSignature();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getInternalName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.type;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public record TargetRefType(String name, List<TargetType> params) implements TargetSpecializedType {
|
||||||
|
public TargetRefType(String name) {
|
||||||
|
this(name, List.of());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInternalName() {
|
||||||
|
return this.name.replaceAll("\\.", "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toSignature() {
|
||||||
|
return "L" + getInternalName() + ";";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.type;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public sealed interface TargetSpecializedType extends TargetType permits TargetFunNType, TargetRefType {
|
||||||
|
List<TargetType> params();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default String toGenericSignature() {
|
||||||
|
String ret = "L" + getInternalName();
|
||||||
|
if (params().size() > 0) {
|
||||||
|
ret += "<";
|
||||||
|
for (var param : params()) {
|
||||||
|
ret += param.toGenericSignature();
|
||||||
|
}
|
||||||
|
ret += ">";
|
||||||
|
}
|
||||||
|
ret += ";";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.type;
|
||||||
|
|
||||||
|
public record TargetSuperWildcard(TargetType innerType) implements TargetType {
|
||||||
|
@Override
|
||||||
|
public String toSignature() {
|
||||||
|
return innerType.toSignature();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toGenericSignature() {
|
||||||
|
return innerType.toGenericSignature();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getInternalName() {
|
||||||
|
return innerType.getInternalName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return innerType.name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.type;
|
||||||
|
|
||||||
|
public sealed interface TargetType
|
||||||
|
permits TargetExtendsWildcard, TargetGenericType, TargetSpecializedType, TargetSuperWildcard, TargetPrimitiveType {
|
||||||
|
|
||||||
|
// Builtin types
|
||||||
|
TargetRefType Boolean = new TargetRefType("java.lang.Boolean");
|
||||||
|
TargetRefType Char = new TargetRefType("java.lang.Character");
|
||||||
|
TargetRefType Byte = new TargetRefType("java.lang.Byte");
|
||||||
|
TargetRefType Short = new TargetRefType("java.lang.Short");
|
||||||
|
TargetRefType Integer = new TargetRefType("java.lang.Integer");
|
||||||
|
TargetRefType Long = new TargetRefType("java.lang.Long");
|
||||||
|
TargetRefType Float = new TargetRefType("java.lang.Float");
|
||||||
|
TargetRefType Double = new TargetRefType("java.lang.Double");
|
||||||
|
TargetRefType String = new TargetRefType("java.lang.String");
|
||||||
|
TargetRefType Object = new TargetRefType("java.lang.Object");
|
||||||
|
|
||||||
|
// Builtin types
|
||||||
|
TargetPrimitiveType boolean_ = new TargetPrimitiveType("Z");
|
||||||
|
TargetPrimitiveType char_ = new TargetPrimitiveType("C");
|
||||||
|
TargetPrimitiveType byte_ = new TargetPrimitiveType("B");
|
||||||
|
TargetPrimitiveType short_ = new TargetPrimitiveType("S");
|
||||||
|
TargetPrimitiveType int_ = new TargetPrimitiveType("I");
|
||||||
|
TargetPrimitiveType long_ = new TargetPrimitiveType("J");
|
||||||
|
TargetPrimitiveType float_ = new TargetPrimitiveType("F");
|
||||||
|
TargetPrimitiveType double_ = new TargetPrimitiveType("D");
|
||||||
|
|
||||||
|
static TargetType toPrimitive(TargetType type) {
|
||||||
|
if (type.equals(Boolean)) return boolean_;
|
||||||
|
if (type.equals(Char)) return char_;
|
||||||
|
if (type.equals(Byte)) return byte_;
|
||||||
|
if (type.equals(Short)) return short_;
|
||||||
|
if (type.equals(Integer)) return int_;
|
||||||
|
if (type.equals(Long)) return long_;
|
||||||
|
if (type.equals(Float)) return float_;
|
||||||
|
if (type.equals(Double)) return double_;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TargetType toTargetType(Class<?> clazz) {
|
||||||
|
if (clazz.isPrimitive()) {
|
||||||
|
if (clazz.equals(boolean.class)) return boolean_;
|
||||||
|
if (clazz.equals(char.class)) return char_;
|
||||||
|
if (clazz.equals(byte.class)) return byte_;
|
||||||
|
if (clazz.equals(short.class)) return short_;
|
||||||
|
if (clazz.equals(int.class)) return int_;
|
||||||
|
if (clazz.equals(long.class)) return long_;
|
||||||
|
if (clazz.equals(float.class)) return float_;
|
||||||
|
if (clazz.equals(double.class)) return double_;
|
||||||
|
}
|
||||||
|
if (clazz.equals(void.class)) return null;
|
||||||
|
return new TargetRefType(clazz.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
String toSignature();
|
||||||
|
String toGenericSignature();
|
||||||
|
String getInternalName();
|
||||||
|
String name();
|
||||||
|
}
|
69
src/test/java/bytecode/OLFun2Test.java
Normal file
69
src/test/java/bytecode/OLFun2Test.java
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package bytecode;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import general.TestCleanUp;
|
||||||
|
import org.junit.*;
|
||||||
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* //ToDo Etienne: Beschreiben
|
||||||
|
*
|
||||||
|
* @since Studienarbeit Type Erasure
|
||||||
|
* @author etiennezink
|
||||||
|
*/
|
||||||
|
public class OLFun2Test {
|
||||||
|
private static String path;
|
||||||
|
private static File fileToTest;
|
||||||
|
private static JavaTXCompiler compiler;
|
||||||
|
private static ClassLoader loader;
|
||||||
|
private static Class<?> classToTest;
|
||||||
|
private static Class<?> classFun1IntInt;
|
||||||
|
private static Class<?> classFun1DoubleDouble;
|
||||||
|
private static Class<?> classFun1StringString;
|
||||||
|
|
||||||
|
private static String generatedByteCodeDirectory = System.getProperty("user.dir") + "/src/test/resources/testBytecode/generatedBC/";
|
||||||
|
|
||||||
|
//ToDo Etienne: Nach Anpassung des Bytecode die Tests hinzufügen
|
||||||
|
//ToDo Etienne: Aufruf von m testen
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUp() throws Exception {
|
||||||
|
path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/OLFun2.jav";
|
||||||
|
fileToTest = new File(path);
|
||||||
|
compiler = new JavaTXCompiler(fileToTest);
|
||||||
|
compiler.generateBytecode(generatedByteCodeDirectory);
|
||||||
|
loader = new URLClassLoader(new URL[] {new URL("file://"+generatedByteCodeDirectory)});
|
||||||
|
classToTest = loader.loadClass("OLFun2");
|
||||||
|
classFun1IntInt = loader.loadClass("Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$");
|
||||||
|
classFun1DoubleDouble = loader.loadClass("Fun1$$Ljava$lang$Double$_$Ljava$lang$Double$_$");
|
||||||
|
classFun1StringString = loader.loadClass("Fun1$$Ljava$lang$String$_$Ljava$lang$String$_$");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mExistsWithInteger() throws Exception{
|
||||||
|
Method m = classToTest.getDeclaredMethod("m", classFun1IntInt);
|
||||||
|
assertNotNull(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mExistsWithDouble() throws Exception{
|
||||||
|
Method m = classToTest.getDeclaredMethod("m", classFun1DoubleDouble);
|
||||||
|
assertNotNull(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mExistsWithString() throws Exception{
|
||||||
|
Method m = classToTest.getDeclaredMethod("m", classFun1StringString);
|
||||||
|
assertNotNull(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
//@AfterClass
|
||||||
|
public static void cleanUp(){
|
||||||
|
TestCleanUp.cleanUpDirectory(new File(generatedByteCodeDirectory), f -> f.getName().contains(".class"));
|
||||||
|
}
|
||||||
|
}
|
@ -1,52 +1,68 @@
|
|||||||
package bytecode;
|
package bytecode;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
|
|
||||||
import org.junit.Test;
|
import general.TestCleanUp;
|
||||||
|
import org.junit.*;
|
||||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* //ToDo Etienne: Beschreiben
|
||||||
|
*
|
||||||
|
* @since Studienarbeit Type Erasure
|
||||||
|
* @author etiennezink
|
||||||
|
*/
|
||||||
public class OLFunTest {
|
public class OLFunTest {
|
||||||
private static String path;
|
private static String path;
|
||||||
private static File fileToTest;
|
private static File fileToTest;
|
||||||
private static JavaTXCompiler compiler;
|
private static JavaTXCompiler compiler;
|
||||||
private static ClassLoader loader;
|
private static ClassLoader loader;
|
||||||
private static Class<?> classToTest;
|
private static Class<?> classToTest;
|
||||||
private static String pathToClassFile;
|
private static Class<?> classFun1IntInt;
|
||||||
private static Object instanceOfClass;
|
private static Class<?> classFun1DoubleDouble;
|
||||||
|
private static Class<?> classFun1StringString;
|
||||||
@Test
|
|
||||||
public void generateBC() throws Exception {
|
private static String generatedByteCodeDirectory = System.getProperty("user.dir") + "/src/test/resources/testBytecode/generatedBC/";
|
||||||
path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/OLFun.jav";
|
|
||||||
|
//ToDo Etienne: Nach Anpassung des Bytecode die Tests hinzufügen
|
||||||
|
//ToDo Etienne: Aufruf von m testen
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUp() throws Exception {
|
||||||
|
path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/OLFun.jav";
|
||||||
fileToTest = new File(path);
|
fileToTest = new File(path);
|
||||||
compiler = new JavaTXCompiler(fileToTest);
|
compiler = new JavaTXCompiler(fileToTest);
|
||||||
compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/");
|
compiler.generateBytecode(generatedByteCodeDirectory);
|
||||||
pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/";
|
loader = new URLClassLoader(new URL[] {new URL("file://"+generatedByteCodeDirectory)});
|
||||||
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
|
|
||||||
classToTest = loader.loadClass("OLFun");
|
classToTest = loader.loadClass("OLFun");
|
||||||
/*
|
classFun1IntInt = loader.loadClass("Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$");
|
||||||
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
|
classFun1DoubleDouble = loader.loadClass("Fun1$$Ljava$lang$Double$_$Ljava$lang$Double$_$");
|
||||||
|
classFun1StringString = loader.loadClass("Fun1$$Ljava$lang$String$_$Ljava$lang$String$_$");
|
||||||
Method m = classToTest.getDeclaredMethod("m");
|
|
||||||
Class<?> lambda = m.invoke(instanceOfClass).getClass();
|
|
||||||
Method apply = lambda.getMethod("apply", Object.class);
|
|
||||||
|
|
||||||
// Damit man auf die Methode zugreifen kann
|
|
||||||
apply.setAccessible(true);
|
|
||||||
|
|
||||||
Integer i = 77;
|
|
||||||
|
|
||||||
Integer result = (Integer) apply.invoke(m.invoke(instanceOfClass), i);
|
|
||||||
|
|
||||||
assertEquals(77, result);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mExistsWithInteger() throws Exception{
|
||||||
|
Method m = classToTest.getDeclaredMethod("m", classFun1IntInt ,Integer.class);
|
||||||
|
assertNotNull(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mExistsWithDouble() throws Exception{
|
||||||
|
Method m = classToTest.getDeclaredMethod("m", classFun1DoubleDouble ,Double.class);
|
||||||
|
assertNotNull(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mExistsWithString() throws Exception{
|
||||||
|
Method m = classToTest.getDeclaredMethod("m", classFun1StringString ,String.class);
|
||||||
|
assertNotNull(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
//@AfterClass
|
||||||
|
public static void cleanUp(){
|
||||||
|
TestCleanUp.cleanUpDirectory(new File(generatedByteCodeDirectory), f -> f.getName().contains(".class"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
14
src/test/java/general/TestCleanUp.java
Normal file
14
src/test/java/general/TestCleanUp.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package general;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileFilter;
|
||||||
|
|
||||||
|
public class TestCleanUp {
|
||||||
|
|
||||||
|
public static void cleanUpDirectory(File directory, FileFilter fileFilter){
|
||||||
|
if(!directory.isDirectory()) throw new RuntimeException("Directory for bytecode generation is wrong!");
|
||||||
|
for (File file: directory.listFiles(fileFilter)) {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
88
src/test/java/targetast/ASTToTypedTargetAST.java
Normal file
88
src/test/java/targetast/ASTToTypedTargetAST.java
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package targetast;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.*;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||||
|
import de.dhbwstuttgart.target.tree.TargetClass;
|
||||||
|
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class ASTToTypedTargetAST {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void emptyClass(){
|
||||||
|
ClassOrInterface emptyClass = new ClassOrInterface(0, new JavaClassName("EmptyClass"), new ArrayList<>(), java.util.Optional.empty(), new ArrayList<>(), new ArrayList<>(), new GenericDeclarationList(new ArrayList<>(), new NullToken()),
|
||||||
|
new RefType(new JavaClassName("Object"), new NullToken()), false, new ArrayList<>(), new NullToken());
|
||||||
|
ResultSet emptyResultSet = new ResultSet(new HashSet<>());
|
||||||
|
TargetClass emptyTargetClass = new ASTToTargetAST(List.of(emptyResultSet)).convert(emptyClass);
|
||||||
|
assert emptyTargetClass.getName().equals("EmptyClass");
|
||||||
|
assert emptyTargetClass.methods().size() == 0;
|
||||||
|
assert emptyTargetClass.fields().size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void overloading() throws Exception {
|
||||||
|
var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Overloading.jav").toFile();
|
||||||
|
var compiler = new JavaTXCompiler(file);
|
||||||
|
var resultSet = compiler.typeInference();
|
||||||
|
var converter = new ASTToTargetAST(resultSet);
|
||||||
|
var classes = compiler.sourceFiles.get(file).getClasses();
|
||||||
|
|
||||||
|
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);
|
||||||
|
var test2 = overloading.getDeclaredMethod("test", overloading2);
|
||||||
|
test2.setAccessible(true);
|
||||||
|
Object overloadingInstance = overloading.getDeclaredConstructor().newInstance();
|
||||||
|
Object overloading2Instance = overloading2.getDeclaredConstructor().newInstance();
|
||||||
|
assertEquals(test1.invoke(overloadingInstance, overloadingInstance), "Overloading");
|
||||||
|
assertEquals(test2.invoke(overloadingInstance, overloading2Instance), "Overloading2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void tphsAndGenerics() throws Exception {
|
||||||
|
var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Tph2.jav").toFile();
|
||||||
|
var compiler = new JavaTXCompiler(file);
|
||||||
|
var resultSet = compiler.typeInference();
|
||||||
|
var converter = new ASTToTargetAST(resultSet);
|
||||||
|
var classes = compiler.sourceFiles.get(file).getClasses();
|
||||||
|
|
||||||
|
var tphAndGenerics = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void cycles() throws Exception {
|
||||||
|
var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Cycle.jav").toFile();
|
||||||
|
var compiler = new JavaTXCompiler(file);
|
||||||
|
var resultSet = compiler.typeInference();
|
||||||
|
var converter = new ASTToTargetAST(resultSet);
|
||||||
|
var classes = compiler.sourceFiles.get(file).getClasses();
|
||||||
|
|
||||||
|
var cycle = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void infimum() throws Exception {
|
||||||
|
var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Infimum.jav").toFile();
|
||||||
|
var compiler = new JavaTXCompiler(file);
|
||||||
|
var resultSet = compiler.typeInference();
|
||||||
|
var converter = new ASTToTargetAST(resultSet);
|
||||||
|
var classes = compiler.sourceFiles.get(file).getClasses();
|
||||||
|
|
||||||
|
var infimum = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader());
|
||||||
|
}
|
||||||
|
}
|
3
src/test/java/targetast/Fun1$$.java
Normal file
3
src/test/java/targetast/Fun1$$.java
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
public interface Fun1$$<R, T> {
|
||||||
|
public R apply(T t);
|
||||||
|
}
|
135
src/test/java/targetast/GreaterEqualTest.java
Normal file
135
src/test/java/targetast/GreaterEqualTest.java
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
package targetast;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
133
src/test/java/targetast/GreaterThanTest.java
Normal file
133
src/test/java/targetast/GreaterThanTest.java
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
package targetast;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
103
src/test/java/targetast/InheritTest.java
Normal file
103
src/test/java/targetast/InheritTest.java
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package targetast;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
119
src/test/java/targetast/InheritTest2.java
Normal file
119
src/test/java/targetast/InheritTest2.java
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
package targetast;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
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("Inherit2.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");
|
||||||
|
}
|
||||||
|
}
|
112
src/test/java/targetast/LessEqualTest.java
Normal file
112
src/test/java/targetast/LessEqualTest.java
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
package targetast;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
120
src/test/java/targetast/LessThanTest.java
Normal file
120
src/test/java/targetast/LessThanTest.java
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
package targetast;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
72
src/test/java/targetast/OLTest.java
Normal file
72
src/test/java/targetast/OLTest.java
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package targetast;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
50
src/test/java/targetast/PostIncTest.java
Normal file
50
src/test/java/targetast/PostIncTest.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package targetast;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
50
src/test/java/targetast/PreIncTest.java
Normal file
50
src/test/java/targetast/PreIncTest.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package targetast;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
59
src/test/java/targetast/PutTest.java
Normal file
59
src/test/java/targetast/PutTest.java
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package targetast;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
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<Integer> v_invoke = new Vector<>();
|
||||||
|
m.invoke(instanceOfClass, 5, v_invoke);
|
||||||
|
Vector<Integer> 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<Integer> 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<Integer> v_invoke = new Vector<>();
|
||||||
|
m.invoke(instanceOfClass, 6, v_invoke);
|
||||||
|
Vector<Integer> 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<Integer> s_invoke = new Stack<>();
|
||||||
|
m.invoke(instanceOfClass, 6, s_invoke);
|
||||||
|
assertEquals(new Integer(6), s_invoke.pop());
|
||||||
|
}
|
||||||
|
}
|
351
src/test/java/targetast/TestCodegen.java
Normal file
351
src/test/java/targetast/TestCodegen.java
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
package targetast;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
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;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
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 {
|
||||||
|
|
||||||
|
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 classLoader.loadClass(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, Class<?>> 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 sourceFile = compiler.sourceFiles.get(file);
|
||||||
|
var converter = new ASTToTargetAST(resultSet, sourceFile, classLoader);
|
||||||
|
var classes = compiler.sourceFiles.get(file).getClasses();
|
||||||
|
|
||||||
|
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, new ByteArrayClassLoader()).getDeclaredMethod("main").invoke(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testArithmetic() throws Exception {
|
||||||
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Arithmetic");
|
||||||
|
|
||||||
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "add",
|
||||||
|
List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")),
|
||||||
|
TargetType.Integer,
|
||||||
|
new TargetBlock(List.of(new TargetReturn(
|
||||||
|
new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b")))
|
||||||
|
))
|
||||||
|
);
|
||||||
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "sub",
|
||||||
|
List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")),
|
||||||
|
TargetType.Integer,
|
||||||
|
new TargetBlock(List.of(new TargetReturn(
|
||||||
|
new TargetBinaryOp.Sub(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b")))
|
||||||
|
))
|
||||||
|
);
|
||||||
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "div",
|
||||||
|
List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")),
|
||||||
|
TargetType.Integer,
|
||||||
|
new TargetBlock(List.of(new TargetReturn(
|
||||||
|
new TargetBinaryOp.Div(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b")))
|
||||||
|
))
|
||||||
|
);
|
||||||
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "mul",
|
||||||
|
List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")),
|
||||||
|
TargetType.Integer,
|
||||||
|
new TargetBlock(List.of(new TargetReturn(
|
||||||
|
new TargetBinaryOp.Mul(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b")))
|
||||||
|
))
|
||||||
|
);
|
||||||
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "rem",
|
||||||
|
List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")),
|
||||||
|
TargetType.Integer,
|
||||||
|
new TargetBlock(List.of(new TargetReturn(
|
||||||
|
new TargetBinaryOp.Rem(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b")))
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
assertEquals(clazz.getDeclaredMethod("mul", Integer.class, Integer.class).invoke(null, 20, 10), 200);
|
||||||
|
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");
|
||||||
|
|
||||||
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "and",
|
||||||
|
List.of(new MethodParameter(TargetType.Boolean, "a"), new MethodParameter(TargetType.Boolean, "b")),
|
||||||
|
TargetType.Boolean,
|
||||||
|
new TargetBlock(List.of(new TargetReturn(
|
||||||
|
new TargetBinaryOp.And(TargetType.Boolean, new TargetLocalVar(TargetType.Boolean, "a"), new TargetLocalVar(TargetType.Boolean, "b")))
|
||||||
|
))
|
||||||
|
);
|
||||||
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "or",
|
||||||
|
List.of(new MethodParameter(TargetType.Boolean, "a"), new MethodParameter(TargetType.Boolean, "b")),
|
||||||
|
TargetType.Boolean,
|
||||||
|
new TargetBlock(List.of(new TargetReturn(
|
||||||
|
new TargetBinaryOp.Or(TargetType.Boolean, new TargetLocalVar(TargetType.Boolean, "a"), new TargetLocalVar(TargetType.Boolean, "b")))
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
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);
|
||||||
|
assertEquals(and.invoke(null, true, true), true);
|
||||||
|
assertEquals(or.invoke(null, false, false), false);
|
||||||
|
assertEquals(or.invoke(null, true, false), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// When adding two numbers and the return type is Long it needs to convert both values to Long
|
||||||
|
@Test
|
||||||
|
public void testArithmeticConvert() throws Exception {
|
||||||
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "ArithmeticConvert");
|
||||||
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "add", List.of(), TargetType.Long,
|
||||||
|
new TargetBlock(List.of(new TargetReturn(
|
||||||
|
new TargetBinaryOp.Add(TargetType.Long, new TargetLiteral.CharLiteral((char)10), new TargetLiteral.LongLiteral((long)20))
|
||||||
|
)))
|
||||||
|
);
|
||||||
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
||||||
|
assertEquals(clazz.getDeclaredMethod("add").invoke(null), (long)30);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMethodCall() throws Exception {
|
||||||
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "HelloWorld");
|
||||||
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "helloWorld", List.of(), null,
|
||||||
|
new TargetBlock(List.of(new TargetMethodCall(null,
|
||||||
|
new TargetFieldVar(
|
||||||
|
new TargetRefType("java.io.PrintStream"),
|
||||||
|
new TargetRefType("java.lang.System"),
|
||||||
|
true,
|
||||||
|
new TargetClassName(new TargetRefType("java.lang.System")),
|
||||||
|
"out"
|
||||||
|
),
|
||||||
|
List.of(new TargetLiteral.StringLiteral("Hello World!")),
|
||||||
|
new TargetRefType("java.io.PrintStream"),
|
||||||
|
"println",
|
||||||
|
false, false
|
||||||
|
)))
|
||||||
|
);
|
||||||
|
|
||||||
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
||||||
|
clazz.getDeclaredMethod("helloWorld").invoke(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIfStatement() throws Exception {
|
||||||
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "IfStmt");
|
||||||
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "ifStmt",
|
||||||
|
List.of(new MethodParameter(TargetType.Integer, "val")),
|
||||||
|
TargetType.Integer,
|
||||||
|
new TargetBlock(List.of(new TargetIf(
|
||||||
|
new TargetBinaryOp.Equal(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "val"), new TargetLiteral.IntLiteral(10)),
|
||||||
|
new TargetReturn(new TargetLiteral.IntLiteral(1)),
|
||||||
|
new TargetIf(
|
||||||
|
new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "val"), new TargetLiteral.IntLiteral(5)),
|
||||||
|
new TargetReturn(new TargetLiteral.IntLiteral(2)),
|
||||||
|
new TargetReturn(new TargetLiteral.IntLiteral(3))
|
||||||
|
)
|
||||||
|
)))
|
||||||
|
);
|
||||||
|
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);
|
||||||
|
assertEquals(ifStmt.invoke(null, 20), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFor() throws Exception {
|
||||||
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "For");
|
||||||
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "forLoop", List.of(), TargetType.Integer,
|
||||||
|
new TargetBlock(List.of(
|
||||||
|
new TargetVarDecl(TargetType.Integer, "sum", new TargetLiteral.IntLiteral(0)),
|
||||||
|
new TargetFor(
|
||||||
|
new TargetVarDecl(TargetType.Integer, "i", new TargetLiteral.IntLiteral(0)),
|
||||||
|
new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(10)),
|
||||||
|
new TargetAssign(TargetType.Integer,
|
||||||
|
new TargetLocalVar(TargetType.Integer, "i"),
|
||||||
|
new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(1))),
|
||||||
|
new TargetBlock(List.of(
|
||||||
|
new TargetAssign(TargetType.Integer,
|
||||||
|
new TargetLocalVar(TargetType.Integer, "sum"),
|
||||||
|
new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"), new TargetLocalVar(TargetType.Integer, "i"))
|
||||||
|
)
|
||||||
|
))
|
||||||
|
),
|
||||||
|
new TargetReturn(new TargetLocalVar(TargetType.Integer, "sum"))
|
||||||
|
))
|
||||||
|
);
|
||||||
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
||||||
|
assertEquals(clazz.getDeclaredMethod("forLoop").invoke(null), 45);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWhile() throws Exception {
|
||||||
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "While");
|
||||||
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "whileLoop", List.of(), TargetType.Integer,
|
||||||
|
new TargetBlock(List.of(
|
||||||
|
new TargetVarDecl(TargetType.Integer, "i", new TargetLiteral.IntLiteral(0)),
|
||||||
|
new TargetWhile(
|
||||||
|
new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(10)),
|
||||||
|
new TargetBlock(List.of(
|
||||||
|
new TargetAssign(TargetType.Integer,
|
||||||
|
new TargetLocalVar(TargetType.Integer, "i"),
|
||||||
|
new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(1))
|
||||||
|
)
|
||||||
|
))
|
||||||
|
),
|
||||||
|
new TargetReturn(new TargetLocalVar(TargetType.Integer, "i"))
|
||||||
|
))
|
||||||
|
);
|
||||||
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
||||||
|
assertEquals(clazz.getDeclaredMethod("whileLoop").invoke(null), 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNew() throws Exception {
|
||||||
|
var pointType = new TargetRefType("Point");
|
||||||
|
var pointTarget = new TargetClass(Opcodes.ACC_PUBLIC, "Point");
|
||||||
|
pointTarget.addField(Opcodes.ACC_PUBLIC, TargetType.Integer, "x");
|
||||||
|
pointTarget.addField(Opcodes.ACC_PUBLIC, TargetType.Integer, "y");
|
||||||
|
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, "<init>", false, false),
|
||||||
|
new TargetAssign(TargetType.Integer,
|
||||||
|
new TargetFieldVar(TargetType.Integer, pointType, false, new TargetThis(pointType), "x"),
|
||||||
|
new TargetLocalVar(TargetType.Integer, "x")
|
||||||
|
),
|
||||||
|
new TargetAssign(TargetType.Integer,
|
||||||
|
new TargetFieldVar(TargetType.Integer, pointType, false, new TargetThis(pointType), "y"),
|
||||||
|
new TargetLocalVar(TargetType.Integer, "y")
|
||||||
|
)
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
var mainTarget = new TargetClass(Opcodes.ACC_PUBLIC, "New");
|
||||||
|
mainTarget.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "makePoint",
|
||||||
|
List.of(new MethodParameter(TargetType.Integer, "x"), new MethodParameter(TargetType.Integer, "y")), pointType,
|
||||||
|
new TargetBlock(List.of(
|
||||||
|
new TargetReturn(new TargetNew(pointType, List.of(
|
||||||
|
new TargetLocalVar(TargetType.Integer, "x"),
|
||||||
|
new TargetLocalVar(TargetType.Integer, "y")
|
||||||
|
)))
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
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);
|
||||||
|
assertEquals(point.getClass().getDeclaredField("y").get(point), 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLambda() throws Exception {
|
||||||
|
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, "CGLambda");
|
||||||
|
targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of(
|
||||||
|
new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "<init>", false, false)
|
||||||
|
)));
|
||||||
|
targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer,
|
||||||
|
new TargetBlock(List.of(
|
||||||
|
new TargetVarDecl(interfaceType, "by2",
|
||||||
|
new TargetLambdaExpression(interfaceType, List.of(), List.of(new MethodParameter(TargetType.Integer, "num")), TargetType.Integer,
|
||||||
|
new TargetBlock(List.of(
|
||||||
|
new TargetReturn(new TargetBinaryOp.Mul(TargetType.Integer,
|
||||||
|
new TargetLocalVar(TargetType.Integer, "num"),
|
||||||
|
new TargetLiteral.IntLiteral(2)
|
||||||
|
))
|
||||||
|
)
|
||||||
|
))
|
||||||
|
),
|
||||||
|
new TargetReturn(new TargetCast(TargetType.Integer, new TargetMethodCall(TargetType.Object, TargetType.Object, List.of(TargetType.Object), new TargetLocalVar(interfaceType, "by2"), List.of(
|
||||||
|
new TargetLiteral.IntLiteral(10)
|
||||||
|
), interfaceType, "apply", false, true)))
|
||||||
|
))
|
||||||
|
);
|
||||||
|
var clazz = generateClass(targetClass, classLoader);
|
||||||
|
var instance = clazz.getConstructor().newInstance();
|
||||||
|
assertEquals(clazz.getDeclaredMethod("lambda").invoke(instance), 20);
|
||||||
|
}
|
||||||
|
}
|
468
src/test/java/targetast/TestComplete.java
Normal file
468
src/test/java/targetast/TestComplete.java
Normal file
@ -0,0 +1,468 @@
|
|||||||
|
package targetast;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.TypeVariable;
|
||||||
|
import java.util.Arrays;
|
||||||
|
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<Vector<Integer>> vv = new Vector<>();
|
||||||
|
Vector<Integer> v1 = new Vector<>();
|
||||||
|
v1.addElement(2);
|
||||||
|
v1.addElement(2);
|
||||||
|
Vector<Integer> 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<Vector<Integer>> vv1 = new Vector<>();
|
||||||
|
Vector<Integer> v3 = new Vector<>();
|
||||||
|
v3.addElement(2);
|
||||||
|
v3.addElement(2);
|
||||||
|
Vector<Integer> 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<Vector<Integer>> res = new Vector<>();
|
||||||
|
Vector<Integer> v5 = new Vector<>();
|
||||||
|
v5.addElement(10);
|
||||||
|
v5.addElement(10);
|
||||||
|
Vector<Integer> 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<Vector<Integer>> vv = new Vector<>();
|
||||||
|
Vector<Integer> v1 = new Vector<> ();
|
||||||
|
v1.addElement(2);
|
||||||
|
v1.addElement(2);
|
||||||
|
Vector<Integer> 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<Vector<Integer>> vv1 = new Vector<>();
|
||||||
|
Vector<Integer> v3 = new Vector<> ();
|
||||||
|
v3.addElement(2);
|
||||||
|
v3.addElement(2);
|
||||||
|
Vector<Integer> 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<Vector<Integer>> res = new Vector<>();
|
||||||
|
Vector<Integer> v5 = new Vector<> ();
|
||||||
|
v5.addElement(10);
|
||||||
|
v5.addElement(10);
|
||||||
|
Vector<Integer> 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 tph2Test() throws Exception {
|
||||||
|
var classFiles = generateClassFiles("Tph2.jav", new ByteArrayClassLoader());
|
||||||
|
var instance = classFiles.get("Tph2").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 tph4Test() throws Exception {
|
||||||
|
var classFiles = generateClassFiles("Tph4.jav", new ByteArrayClassLoader());
|
||||||
|
var tph4 = classFiles.get("Tph4");
|
||||||
|
var instance = tph4.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 Tph7Test() throws Exception {
|
||||||
|
var classFiles = TestCodegen.generateClassFiles("Tph7.jav", new ByteArrayClassLoader());
|
||||||
|
var classToTest = classFiles.get("Tph7");
|
||||||
|
var instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
|
||||||
|
|
||||||
|
//public <DZN, DZL, DZU extends DZN, DZM extends DZU> DZU m(DZL, DZM);
|
||||||
|
Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class);
|
||||||
|
|
||||||
|
//System.out.println(m.toString());
|
||||||
|
|
||||||
|
//Argumenttypes of the method m
|
||||||
|
var paraTypes = m.getGenericParameterTypes();
|
||||||
|
|
||||||
|
//Typeparameters of the method m
|
||||||
|
var typeParaTypes = m.getTypeParameters();
|
||||||
|
|
||||||
|
//Typeparameters are extracted from the argumenttypes
|
||||||
|
//Conditions for the extracted typeparameters are set
|
||||||
|
|
||||||
|
//paraTypes[0] = DLZ
|
||||||
|
var boundFstArg = Arrays.stream(typeParaTypes)
|
||||||
|
.filter(x -> x.equals(paraTypes[0])).findFirst().get().getBounds();
|
||||||
|
|
||||||
|
//Bound of DLZ has to be Object
|
||||||
|
assertEquals(Object.class, Arrays.stream(boundFstArg).findFirst().get());
|
||||||
|
|
||||||
|
//paraTypes[0] = DZM
|
||||||
|
var boundSndArg = Arrays.stream(typeParaTypes)
|
||||||
|
.filter(x -> x.equals(paraTypes[1])).findFirst().get().getBounds();
|
||||||
|
|
||||||
|
//Bound of DZM has to be the return type of m
|
||||||
|
assertEquals(Arrays.stream(boundSndArg).findFirst().get(), m.getGenericReturnType());
|
||||||
|
|
||||||
|
//Bound of the bound of DZM
|
||||||
|
var boundBoundSndArg = Arrays.stream(typeParaTypes).filter(x -> x.equals(Arrays.stream(boundSndArg)
|
||||||
|
.findFirst().get())).findFirst().get().getBounds();
|
||||||
|
|
||||||
|
//boundBoundSndArg have to be a type variable (type of the local variable c)
|
||||||
|
assertEquals(true, Arrays.stream(boundBoundSndArg).findFirst().get() instanceof TypeVariable);
|
||||||
|
m.getGenericParameterTypes();
|
||||||
|
|
||||||
|
//public <DZU> DZU m2(DZU);
|
||||||
|
Method m2 = classToTest.getDeclaredMethod("m2", Object.class);
|
||||||
|
|
||||||
|
//Argumenttypes of the method m2
|
||||||
|
var paraTypesm2 = m2.getGenericParameterTypes();
|
||||||
|
|
||||||
|
//Typeparameters of the method m2
|
||||||
|
var typeParaTypesm2 = m2.getTypeParameters();
|
||||||
|
|
||||||
|
//Typeparameters are extracted from the argumenttypes
|
||||||
|
//Conditions for the extracted typeparameters are set
|
||||||
|
|
||||||
|
//paraTypes[0] = DZU
|
||||||
|
var fstArgm2 = Arrays.stream(typeParaTypesm2)
|
||||||
|
.filter(x -> x.equals(paraTypesm2[0])).findFirst().get();
|
||||||
|
|
||||||
|
//Bound of DZU has to be Object
|
||||||
|
assertEquals(Object.class, Arrays.stream(fstArgm2.getBounds()).findFirst().get());
|
||||||
|
|
||||||
|
//DZU has to be the return type of m
|
||||||
|
assertEquals(fstArgm2, m2.getGenericReturnType());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@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();
|
||||||
|
}
|
||||||
|
}
|
114
src/test/java/targetast/TphTest.java
Normal file
114
src/test/java/targetast/TphTest.java
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
package targetast;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.TypeVariable;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
var classFiles = TestCodegen.generateClassFiles("Tph7.jav", new ByteArrayClassLoader());
|
||||||
|
var classToTest = classFiles.get("Tph7");
|
||||||
|
var instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
|
||||||
|
|
||||||
|
//public <DZN, DZL, DZU extends DZN, DZM extends DZU> DZU m(DZL, DZM);
|
||||||
|
Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class);
|
||||||
|
|
||||||
|
//System.out.println(m.toString());
|
||||||
|
|
||||||
|
//Argumenttypes of the method m
|
||||||
|
var paraTypes = m.getGenericParameterTypes();
|
||||||
|
|
||||||
|
//Typeparameters of the method m
|
||||||
|
var typeParaTypes = m.getTypeParameters();
|
||||||
|
|
||||||
|
//Typeparameters are extracted from the argumenttypes
|
||||||
|
//Conditions for the extracted typeparameters are set
|
||||||
|
|
||||||
|
//paraTypes[0] = DLZ
|
||||||
|
var boundFstArg = Arrays.stream(typeParaTypes)
|
||||||
|
.filter(x -> x.equals(paraTypes[0])).findFirst().get().getBounds();
|
||||||
|
|
||||||
|
//Bound of DLZ has to be Object
|
||||||
|
assertEquals(Object.class, Arrays.stream(boundFstArg).findFirst().get());
|
||||||
|
|
||||||
|
//paraTypes[0] = DZM
|
||||||
|
var boundSndArg = Arrays.stream(typeParaTypes)
|
||||||
|
.filter(x -> x.equals(paraTypes[1])).findFirst().get().getBounds();
|
||||||
|
|
||||||
|
//Bound of DZM has to be the return type of m
|
||||||
|
assertEquals(Arrays.stream(boundSndArg).findFirst().get(), m.getGenericReturnType());
|
||||||
|
|
||||||
|
//Bound of the bound of DZM
|
||||||
|
var boundBoundSndArg = Arrays.stream(typeParaTypes).filter(x -> x.equals(Arrays.stream(boundSndArg)
|
||||||
|
.findFirst().get())).findFirst().get().getBounds();
|
||||||
|
|
||||||
|
//boundBoundSndArg have to be a type variable (type of the local variable c)
|
||||||
|
assertEquals(true, Arrays.stream(boundBoundSndArg).findFirst().get() instanceof TypeVariable);
|
||||||
|
m.getGenericParameterTypes();
|
||||||
|
|
||||||
|
//public <DZU> DZU m2(DZU);
|
||||||
|
Method m2 = classToTest.getDeclaredMethod("m2", Object.class);
|
||||||
|
|
||||||
|
//Argumenttypes of the method m2
|
||||||
|
var paraTypesm2 = m2.getGenericParameterTypes();
|
||||||
|
|
||||||
|
//Typeparameters of the method m2
|
||||||
|
var typeParaTypesm2 = m2.getTypeParameters();
|
||||||
|
|
||||||
|
//Typeparameters are extracted from the argumenttypes
|
||||||
|
//Conditions for the extracted typeparameters are set
|
||||||
|
|
||||||
|
//paraTypes[0] = DZU
|
||||||
|
var fstArgm2 = Arrays.stream(typeParaTypesm2)
|
||||||
|
.filter(x -> x.equals(paraTypesm2[0])).findFirst().get();
|
||||||
|
|
||||||
|
//Bound of DZU has to be Object
|
||||||
|
assertEquals(Object.class, Arrays.stream(fstArgm2.getBounds()).findFirst().get());
|
||||||
|
|
||||||
|
//DZU has to be the return type of m
|
||||||
|
assertEquals(fstArgm2, m2.getGenericReturnType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
43
src/test/java/targetast/WhileTest.java
Normal file
43
src/test/java/targetast/WhileTest.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package targetast;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.ByteArrayClassLoader;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
9
src/test/resources/target/Test.java
Normal file
9
src/test/resources/target/Test.java
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
public class Test {
|
||||||
|
public void lambda() {
|
||||||
|
Interface<Integer, Integer> mul2 = (Integer a) -> a * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Interface<R, T> {
|
||||||
|
R apply(T t);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user