|
|
@ -13,7 +13,9 @@ import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
|
|
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
|
|
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
|
|
|
import org.junit.Ignore;
|
|
|
|
import org.junit.Ignore;
|
|
|
|
import org.junit.Test;
|
|
|
|
import org.junit.Test;
|
|
|
|
|
|
|
|
|
|
|
|
import static org.junit.Assert.*;
|
|
|
|
import static org.junit.Assert.*;
|
|
|
|
|
|
|
|
|
|
|
|
import org.objectweb.asm.Opcodes;
|
|
|
|
import org.objectweb.asm.Opcodes;
|
|
|
|
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.IOException;
|
|
|
@ -29,185 +31,226 @@ import java.util.function.Function;
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
|
|
public class TestCodegen {
|
|
|
|
public class TestCodegen {
|
|
|
|
static final Path outputPath = Path.of(System.getProperty("user.dir"), "src/test/resources/target/");
|
|
|
|
static final Path outputPath = Path.of(System.getProperty("user.dir"), "src/test/resources/target/");
|
|
|
|
|
|
|
|
|
|
|
|
private static void writeClassFile(String name, byte[] code) throws IOException {
|
|
|
|
private static void writeClassFile(String name, byte[] code) throws IOException {
|
|
|
|
Files.createDirectories(outputPath);
|
|
|
|
Files.createDirectories(outputPath);
|
|
|
|
Files.write(outputPath.resolve(name + ".class"), code);
|
|
|
|
Files.write(outputPath.resolve(name + ".class"), code);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static Map<String, ? extends Class<?>> generateClassFiles(IByteArrayClassLoader classLoader, String... files) throws IOException, ClassNotFoundException {
|
|
|
|
public static Map<String, ? extends Class<?>> generateClassFiles(IByteArrayClassLoader classLoader, String... files) throws IOException, ClassNotFoundException {
|
|
|
|
var path = Path.of(System.getProperty("user.dir"), "resources/bytecode/javFiles/");
|
|
|
|
var path = Path.of(System.getProperty("user.dir"), "resources/bytecode/javFiles/");
|
|
|
|
var filenames = Arrays.stream(files).map(filename -> Path.of(path.toString(), filename).toFile()).toList();
|
|
|
|
var filenames = Arrays.stream(files).map(filename -> Path.of(path.toString(), filename).toFile()).toList();
|
|
|
|
var compiler = new JavaTXCompiler(filenames, List.of(path.toFile(), outputPath.toFile()));
|
|
|
|
var compiler = new JavaTXCompiler(filenames, List.of(path.toFile(), outputPath.toFile()));
|
|
|
|
var resultSet = compiler.typeInference();
|
|
|
|
var resultSet = compiler.typeInference();
|
|
|
|
|
|
|
|
|
|
|
|
var result = new HashMap<String, Class<?>>();
|
|
|
|
var result = new HashMap<String, Class<?>>();
|
|
|
|
for (var file : filenames) {
|
|
|
|
for (var file : filenames) {
|
|
|
|
var sourceFile = compiler.sourceFiles.get(file);
|
|
|
|
var sourceFile = compiler.sourceFiles.get(file);
|
|
|
|
var converter = new ASTToTargetAST(resultSet, sourceFile, classLoader);
|
|
|
|
var converter = new ASTToTargetAST(resultSet, sourceFile, classLoader);
|
|
|
|
var classes = compiler.sourceFiles.get(file).getClasses();
|
|
|
|
var classes = compiler.sourceFiles.get(file).getClasses();
|
|
|
|
|
|
|
|
|
|
|
|
result.putAll(classes.stream().map(cli -> {
|
|
|
|
result.putAll(classes.stream().map(cli -> {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
return generateClass(converter.convert(cli), classLoader);
|
|
|
|
return generateClass(converter.convert(cli), classLoader);
|
|
|
|
} catch (IOException exception) {
|
|
|
|
} catch (IOException exception) {
|
|
|
|
throw new RuntimeException(exception);
|
|
|
|
throw new RuntimeException(exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
}).collect(Collectors.toMap(Class::getName, Function.identity())));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (var entry : converter.auxiliaries.entrySet()) {
|
|
|
|
|
|
|
|
writeClassFile(entry.getKey(), entry.getValue());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}).collect(Collectors.toMap(Class::getName, Function.identity())));
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
for (var entry : converter.auxiliaries.entrySet()) {
|
|
|
|
|
|
|
|
writeClassFile(entry.getKey(), entry.getValue());
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static Class<?> generateClass(TargetClass clazz, IByteArrayClassLoader classLoader) throws IOException {
|
|
|
|
return result;
|
|
|
|
var codegen = new Codegen(clazz);
|
|
|
|
}
|
|
|
|
var code = codegen.generate();
|
|
|
|
|
|
|
|
writeClassFile(clazz.qualifiedName(), code);
|
|
|
|
public static Class<?> generateClass(TargetClass clazz, IByteArrayClassLoader classLoader) throws IOException {
|
|
|
|
return classLoader.loadClass(code);
|
|
|
|
var codegen = new Codegen(clazz);
|
|
|
|
|
|
|
|
var code = codegen.generate();
|
|
|
|
|
|
|
|
writeClassFile(clazz.qualifiedName(), code);
|
|
|
|
|
|
|
|
return classLoader.loadClass(code);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static Map<String, ? extends Class<?>> generateClassFiles(String filename, IByteArrayClassLoader classLoader) throws IOException, ClassNotFoundException {
|
|
|
|
|
|
|
|
var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/javFiles/", filename).toFile();
|
|
|
|
|
|
|
|
var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile()));
|
|
|
|
|
|
|
|
var resultSet = compiler.typeInference();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var sourceFile = compiler.sourceFiles.get(file);
|
|
|
|
|
|
|
|
var converter = new ASTToTargetAST(resultSet, sourceFile, classLoader);
|
|
|
|
|
|
|
|
var classes = compiler.sourceFiles.get(file).getClasses();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var result = 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()));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (var entry : converter.auxiliaries.entrySet()) {
|
|
|
|
|
|
|
|
writeClassFile(entry.getKey(), entry.getValue());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static Map<String, ? extends Class<?>> generateClassFiles(String filename, IByteArrayClassLoader classLoader) throws IOException, ClassNotFoundException {
|
|
|
|
return result;
|
|
|
|
var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/javFiles/", filename).toFile();
|
|
|
|
}
|
|
|
|
var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile()));
|
|
|
|
|
|
|
|
var resultSet = compiler.typeInference();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var sourceFile = compiler.sourceFiles.get(file);
|
|
|
|
@Test
|
|
|
|
var converter = new ASTToTargetAST(resultSet, sourceFile, classLoader);
|
|
|
|
public void testEmptyClass() throws Exception {
|
|
|
|
var classes = compiler.sourceFiles.get(file).getClasses();
|
|
|
|
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);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var result = classes.stream().map(cli -> {
|
|
|
|
@Test
|
|
|
|
try {
|
|
|
|
public void testArithmetic() throws Exception {
|
|
|
|
return generateClass(converter.convert(cli), classLoader);
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Arithmetic");
|
|
|
|
} catch (IOException exception) {
|
|
|
|
|
|
|
|
throw new RuntimeException(exception);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}).collect(Collectors.toMap(Class::getName, Function.identity()));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (var entry : converter.auxiliaries.entrySet()) {
|
|
|
|
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"))))));
|
|
|
|
writeClassFile(entry.getKey(), entry.getValue());
|
|
|
|
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"))))));
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
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
|
|
|
|
@Test
|
|
|
|
public void testEmptyClass() throws Exception {
|
|
|
|
public void testUnary() throws Exception {
|
|
|
|
var clazz = new TargetClass(Opcodes.ACC_PUBLIC, "Empty");
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Unary");
|
|
|
|
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
|
|
|
|
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"))))));
|
|
|
|
public void testArithmetic() throws Exception {
|
|
|
|
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"))))));
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Arithmetic");
|
|
|
|
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"))))));
|
|
|
|
|
|
|
|
|
|
|
|
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"))))));
|
|
|
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
|
|
|
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"))))));
|
|
|
|
assertEquals(clazz.getDeclaredMethod("not", Integer.class).invoke(null, 10), -11);
|
|
|
|
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"))))));
|
|
|
|
assertEquals(clazz.getDeclaredMethod("neg", Integer.class).invoke(null, 10), -10);
|
|
|
|
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"))))));
|
|
|
|
assertEquals(clazz.getDeclaredMethod("add", Integer.class).invoke(null, 10), 10);
|
|
|
|
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
|
|
|
|
@Test
|
|
|
|
public void testUnary() throws Exception {
|
|
|
|
public void testConditional() throws Exception {
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Unary");
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Conditional");
|
|
|
|
|
|
|
|
|
|
|
|
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, "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, "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, "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"))))));
|
|
|
|
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());
|
|
|
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
|
|
|
assertEquals(clazz.getDeclaredMethod("not", Integer.class).invoke(null, 10), -11);
|
|
|
|
var and = clazz.getDeclaredMethod("and", Boolean.class, Boolean.class);
|
|
|
|
assertEquals(clazz.getDeclaredMethod("neg", Integer.class).invoke(null, 10), -10);
|
|
|
|
var or = clazz.getDeclaredMethod("or", Boolean.class, Boolean.class);
|
|
|
|
assertEquals(clazz.getDeclaredMethod("add", Integer.class).invoke(null, 10), 10);
|
|
|
|
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
|
|
|
|
@Test
|
|
|
|
public void testConditional() throws Exception {
|
|
|
|
public void testMethodCall() throws Exception {
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Conditional");
|
|
|
|
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))));
|
|
|
|
|
|
|
|
|
|
|
|
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"))))));
|
|
|
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
|
|
|
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"))))));
|
|
|
|
clazz.getDeclaredMethod("helloWorld").invoke(null);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
|
|
|
@Test
|
|
|
|
var and = clazz.getDeclaredMethod("and", Boolean.class, Boolean.class);
|
|
|
|
public void testIfStatement() throws Exception {
|
|
|
|
var or = clazz.getDeclaredMethod("or", Boolean.class, Boolean.class);
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "IfStmt");
|
|
|
|
assertEquals(and.invoke(null, true, false), false);
|
|
|
|
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)))))));
|
|
|
|
assertEquals(and.invoke(null, true, true), true);
|
|
|
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
|
|
|
assertEquals(or.invoke(null, false, false), false);
|
|
|
|
var ifStmt = clazz.getDeclaredMethod("ifStmt", Integer.class);
|
|
|
|
assertEquals(or.invoke(null, true, false), true);
|
|
|
|
assertEquals(ifStmt.invoke(null, 10), 1);
|
|
|
|
}
|
|
|
|
assertEquals(ifStmt.invoke(null, 3), 2);
|
|
|
|
|
|
|
|
assertEquals(ifStmt.invoke(null, 20), 3);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// When adding two numbers and the return type is Long it needs to convert both values to Long
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void testFor() throws Exception {
|
|
|
|
public void testArithmeticConvert() throws Exception {
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "For");
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "ArithmeticConvert");
|
|
|
|
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")))));
|
|
|
|
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());
|
|
|
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
|
|
|
assertEquals(clazz.getDeclaredMethod("forLoop").invoke(null), 45);
|
|
|
|
assertEquals(clazz.getDeclaredMethod("add").invoke(null), (long) 30);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void testMethodCall() throws Exception {
|
|
|
|
public void testWhile() throws Exception {
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "HelloWorld");
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "While");
|
|
|
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "helloWorld", List.of(), null, new TargetBlock(List.of(new TargetMethodCall(null, new TargetFieldVar(new TargetRefType("java.io.PrintStream"), new TargetRefType("java.lang.System"), true, new TargetClassName(new TargetRefType("java.lang.System")), "out"), List.of(new TargetLiteral.StringLiteral("Hello World!")), new TargetRefType("java.io.PrintStream"), "println", false, false))));
|
|
|
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "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);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
|
|
|
@Test
|
|
|
|
clazz.getDeclaredMethod("helloWorld").invoke(null);
|
|
|
|
public void testClassicSwitch() throws Exception {
|
|
|
|
}
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC , "Switch");
|
|
|
|
|
|
|
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "switchClassic", List.of(new MethodParameter(TargetType.Integer, "i")), TargetType.Integer, new TargetBlock(List.of(
|
|
|
|
|
|
|
|
new TargetVarDecl(TargetType.Integer, "res", null),
|
|
|
|
|
|
|
|
new TargetSwitch(new TargetLocalVar(TargetType.Integer, "i"), List.of(
|
|
|
|
|
|
|
|
new TargetSwitch.Case(List.of(new TargetLiteral.IntLiteral(10)), new TargetBlock(
|
|
|
|
|
|
|
|
List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "res"), new TargetLiteral.IntLiteral(0)), new TargetBreak())
|
|
|
|
|
|
|
|
)),
|
|
|
|
|
|
|
|
new TargetSwitch.Case(List.of(new TargetLiteral.IntLiteral(20)), new TargetBlock(List.of())),
|
|
|
|
|
|
|
|
new TargetSwitch.Case(List.of(new TargetLiteral.IntLiteral(30)), new TargetBlock(
|
|
|
|
|
|
|
|
List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "res"), new TargetLiteral.IntLiteral(1)), new TargetBreak())
|
|
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
), new TargetBlock(
|
|
|
|
|
|
|
|
List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "res"), new TargetLiteral.IntLiteral(2)), new TargetBreak())
|
|
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
)));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void testIfStatement() throws Exception {
|
|
|
|
public void testTypeSwitch() throws Exception {
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "IfStmt");
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Switch");
|
|
|
|
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)))))));
|
|
|
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "switchType", List.of(new MethodParameter(TargetType.Object, "obj")), TargetType.Integer, new TargetBlock(List.of(
|
|
|
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
|
|
|
new TargetReturn(new TargetSwitch(new TargetLocalVar(TargetType.Object, "obj"), List.of(
|
|
|
|
var ifStmt = clazz.getDeclaredMethod("ifStmt", Integer.class);
|
|
|
|
new TargetSwitch.Case(List.of(new TargetSwitch.Pattern(TargetType.String, "aString")), new TargetBlock(
|
|
|
|
assertEquals(ifStmt.invoke(null, 10), 1);
|
|
|
|
List.of(new TargetLiteral.IntLiteral(0))
|
|
|
|
assertEquals(ifStmt.invoke(null, 3), 2);
|
|
|
|
)),
|
|
|
|
assertEquals(ifStmt.invoke(null, 20), 3);
|
|
|
|
new TargetSwitch.Case(List.of(new TargetSwitch.Pattern(TargetType.Integer, "anInteger")), new TargetBlock(
|
|
|
|
}
|
|
|
|
List.of(new TargetLiteral.IntLiteral(1))
|
|
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
), new TargetBlock(
|
|
|
|
|
|
|
|
List.of(new TargetLiteral.IntLiteral(2))
|
|
|
|
|
|
|
|
), TargetType.Integer)
|
|
|
|
|
|
|
|
))));
|
|
|
|
|
|
|
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
|
|
|
|
|
|
|
var m = clazz.getDeclaredMethod("switchType", Object.class);
|
|
|
|
|
|
|
|
assertEquals(m.invoke(null, "String"), 0);
|
|
|
|
|
|
|
|
assertEquals(m.invoke(null, 10), 1);
|
|
|
|
|
|
|
|
assertEquals(m.invoke(null, 'A'), 2);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void testFor() throws Exception {
|
|
|
|
@Ignore("The lambda class is not generated because we don't call ASTToTargetAST")
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "For");
|
|
|
|
public void testLambda() throws Exception {
|
|
|
|
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 classLoader = new ByteArrayClassLoader();
|
|
|
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
|
|
|
// var fun = classLoader.loadClass(Path.of(System.getProperty("user.dir"), "src/test/java/targetast/Fun1$$.class"));
|
|
|
|
assertEquals(clazz.getDeclaredMethod("forLoop").invoke(null), 45);
|
|
|
|
var interfaceType = TargetFunNType.fromParams(List.of(TargetType.Integer));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "CGLambda");
|
|
|
|
public void testWhile() throws Exception {
|
|
|
|
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))));
|
|
|
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "While");
|
|
|
|
targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(interfaceType, "by2", new TargetLambdaExpression(interfaceType, List.of(), List.of(new MethodParameter(TargetType.Integer, "num")), TargetType.Integer, new TargetBlock(List.of(new TargetReturn(new TargetBinaryOp.Mul(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "num"), new TargetLiteral.IntLiteral(2))))))), new TargetReturn(new TargetCast(TargetType.Integer, new TargetMethodCall(TargetType.Object, TargetType.Object, List.of(TargetType.Object), new TargetLocalVar(interfaceType, "by2"), List.of(new TargetLiteral.IntLiteral(10)), interfaceType, "apply", false, true))))));
|
|
|
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | 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, classLoader);
|
|
|
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
|
|
|
var instance = clazz.getConstructor().newInstance();
|
|
|
|
assertEquals(clazz.getDeclaredMethod("whileLoop").invoke(null), 10);
|
|
|
|
assertEquals(clazz.getDeclaredMethod("lambda").invoke(instance), 20);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
|
|
|
@Ignore("The lambda class is not generated because we don't call ASTToTargetAST")
|
|
|
|
|
|
|
|
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 = TargetFunNType.fromParams(List.of(TargetType.Integer));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|