Merge branch 'bigRefactoring' of ssh://gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into bigRefactoring

This commit is contained in:
pl@gohorb.ba-horb.de 2022-12-05 17:23:06 +01:00
commit 7d50ddab51
85 changed files with 5516 additions and 63 deletions

12
pom.xml
View File

@ -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>

View File

@ -0,0 +1,6 @@
class Cycle {
m(x, y) {
y = x;
x = y;
}
}

View File

@ -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:
*/

View File

@ -0,0 +1,6 @@
class Infimum {
m(x, y, z) {
y = x;
z = x;
}
}

View File

@ -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);
} }
} }

View 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)
}
}

View File

@ -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;
*/
} }
} }

View File

@ -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){

View File

@ -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;
} }
*/
} }

View File

@ -0,0 +1,11 @@
public class Tph7 {
m(a,b){
var c = m2(b);
return m2(b);
}
m2(b){
return b;
}
}

View File

@ -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);

View File

@ -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 = "(";

View File

@ -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;

View 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);
}
}

View File

@ -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;
}
}

View File

@ -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){

View File

@ -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;
}
} }

View File

@ -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);
}
}

View File

@ -0,0 +1,7 @@
package de.dhbwstuttgart.target.bytecode;
public class CodeGenException extends RuntimeException {
public CodeGenException(String cause) {
super(cause);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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());
}
});
}
}

View File

@ -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);
}
}
}

View File

@ -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) {
}
}

View File

@ -0,0 +1,6 @@
package de.dhbwstuttgart.target.tree;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record MethodParameter(TargetType type, String name) {
}

View 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));
}
}

View File

@ -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);
}
}

View 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;
}
}

View File

@ -0,0 +1,6 @@
package de.dhbwstuttgart.target.tree;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetGeneric(String name, TargetType bound) {
}

View File

@ -0,0 +1,6 @@
package de.dhbwstuttgart.target.tree;
import java.util.List;
public record TargetInterface(String name, List<TargetMethod> methods, List<TargetInterface> extendedInterfaces) {
}

View 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;
}
}

View File

@ -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 {
}

View File

@ -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 {}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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 {
}

View File

@ -0,0 +1,6 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetClassName(TargetType type) implements TargetExpression {
}

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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 {
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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 {
}

View File

@ -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;
}
}
}

View File

@ -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 {
}

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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;
}
}

View File

@ -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 {
}

View File

@ -0,0 +1,6 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetSuper(TargetType type) implements TargetExpression {
}

View File

@ -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) {}
}

View File

@ -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 {
}

View File

@ -0,0 +1,6 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetThis(TargetType type) implements TargetExpression {
}

View File

@ -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 {}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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() + ";";
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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();
}

View 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"));
}
}

View File

@ -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"));
}
} }

View 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();
}
}
}

View 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());
}
}

View File

@ -0,0 +1,3 @@
public interface Fun1$$<R, T> {
public R apply(T t);
}

View 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);
}
}

View 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);
}
}

View 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");
}
}

View 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");
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}

View 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());
}
}

View 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);
}
}

View 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();
}
}

View 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);
}
}

View 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);
}
}

View 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);
}