diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SwitchBlock.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SwitchBlock.java index 39af78a8..afe87e89 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SwitchBlock.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SwitchBlock.java @@ -11,20 +11,20 @@ public class SwitchBlock extends Block { private List labels = new ArrayList<>(); - private Boolean defaultBlock = false; + private boolean defaultBlock = false; public SwitchBlock(List labels, Block statements, Token offset) { super(statements.getStatements(), offset); this.labels = labels; } - public SwitchBlock(List labels, Block statements, Boolean isDefault, Token offset) { + public SwitchBlock(List labels, Block statements, boolean isDefault, Token offset) { super(statements.getStatements(), offset); this.labels = labels; this.defaultBlock = isDefault; } - public Boolean isDefault() { + public boolean isDefault() { return defaultBlock; } diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index f93778a5..d479c186 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -10,9 +10,11 @@ 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.expression.TargetSwitch; import de.dhbwstuttgart.target.tree.type.*; import de.dhbwstuttgart.typeinference.result.*; +import java.lang.annotation.Target; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -205,6 +207,10 @@ public class ASTToTargetAST { return result; } + protected TargetSwitch.Case convert(SwitchBlock block) { + return new TargetSwitch.Case(block.getLabels().stream().map(this::convert).toList(), convert((Block) block)); + } + protected TargetBlock convert(Block block) { return new TargetBlock(block.statements.stream().map(this::convert).toList()); } diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 2e2b7b09..dbcb991f 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -74,41 +74,6 @@ public class StatementToTargetExpression implements StatementVisitor { @Override public void visit(LambdaExpression lambda) { } // Don't look at lambda expressions - - @Override - public void visit(Switch switchStmt) { - // TODO Auto-generated method stub - } - - @Override - public void visit(SwitchBlock switchBlock) { - // TODO Auto-generated method stub - } - - @Override - public void visit(SwitchLabel switchLabel) { - // TODO Auto-generated method stub - } - - @Override - public void visit(Yield aYield) { - // TODO Auto-generated method stub - } - - @Override - public void visit(Pattern aPattern) { - // TODO Auto-generated method stub - } - - @Override - public void visit(RecordPattern aRecordPattern) { - // TODO Auto-generated method stub - } - - @Override - public void visit(GuardedPattern aGuardedPattern) { - // TODO Auto-generated method stub - } }); result = new TargetLambdaExpression(converter.convert(lambdaExpression.getType()), captures, parameters, converter.convert(lambdaExpression.getReturnType()), converter.convert(lambdaExpression.methodBody)); @@ -378,18 +343,16 @@ public class StatementToTargetExpression implements StatementVisitor { @Override public void visit(Switch switchStmt) { - // TODO Auto-generated method stub + var cases = switchStmt.getBlocks().stream().filter(s -> !s.isDefault()).map(converter::convert).toList(); + var default_ = switchStmt.getBlocks().stream().filter(SwitchBlock::isDefault).map(s -> converter.convert((Block) s)).findFirst().orElse(null); + result = new TargetSwitch(converter.convert(switchStmt.getSwitch()), cases, default_, converter.convert(switchStmt.getType()), !switchStmt.getStatement()); } @Override - public void visit(SwitchBlock switchBlock) { - // TODO Auto-generated method stub - } + public void visit(SwitchBlock switchBlock) {} @Override - public void visit(SwitchLabel switchLabel) { - // TODO Auto-generated method stub - } + public void visit(SwitchLabel switchLabel) {} @Override public void visit(Yield aYield) { @@ -398,16 +361,21 @@ public class StatementToTargetExpression implements StatementVisitor { @Override public void visit(Pattern aPattern) { - // TODO Auto-generated method stub + result = new TargetSwitch.Pattern(converter.convert(aPattern.getType()), aPattern.getName()); } @Override public void visit(RecordPattern aRecordPattern) { - // TODO Auto-generated method stub + result = new TargetSwitch.ComplexPattern( + converter.convert(aRecordPattern.getType()), + aRecordPattern.getSubPattern().stream().map(x -> (TargetSwitch.Pattern) converter.convert(x)).toList() + ); } @Override public void visit(GuardedPattern aGuardedPattern) { - // TODO Auto-generated method stub + //FIXME This isn't done properly inside the parser, really you should only have one guard (Chaining them together with && just yields another expression) + //And then it also needs to be able to accept complex patterns. Because of this we only accept one condition for now. + result = new TargetSwitch.Guard(new TargetSwitch.Pattern(converter.convert(aGuardedPattern.getType()), aGuardedPattern.getName()), converter.convert(aGuardedPattern.getConditions().get(0))); } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBlock.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBlock.java index 87cc3b5e..670ebf66 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBlock.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBlock.java @@ -5,8 +5,4 @@ import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; public record TargetBlock(List statements) implements TargetExpression { - @Override - public TargetType type() { - return null; - } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBreak.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBreak.java index ae918c44..200742cb 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBreak.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBreak.java @@ -3,9 +3,4 @@ package de.dhbwstuttgart.target.tree.expression; import de.dhbwstuttgart.target.tree.type.TargetType; public record TargetBreak() implements TargetExpression { - - @Override - public TargetType type() { - return null; - } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetContinue.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetContinue.java index 42ebc995..6c490061 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetContinue.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetContinue.java @@ -3,9 +3,4 @@ package de.dhbwstuttgart.target.tree.expression; import de.dhbwstuttgart.target.tree.type.TargetType; public record TargetContinue() implements TargetExpression { - - @Override - public TargetType type() { - return null; - } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java index 64146f7e..d226e456 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java @@ -3,7 +3,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 { + permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetSwitch.ComplexPattern, TargetSwitch.Guard, TargetSwitch.Pattern, TargetTernary, TargetThis, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield { - TargetType type(); + default TargetType type() { + return null; + }; } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFor.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFor.java index 2ce402ab..0efdd61d 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFor.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFor.java @@ -3,9 +3,4 @@ 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; - } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetForEach.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetForEach.java index 392b84e4..ce50403c 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetForEach.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetForEach.java @@ -3,9 +3,4 @@ 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; - } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetIf.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetIf.java index 78bc766b..1961177d 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetIf.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetIf.java @@ -3,8 +3,4 @@ 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; - } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetReturn.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetReturn.java index c419cc1c..99682ec1 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetReturn.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetReturn.java @@ -3,8 +3,4 @@ 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; - } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSwitch.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSwitch.java index a6823913..03ed6148 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSwitch.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSwitch.java @@ -1,16 +1,27 @@ 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 cases, Expression default_) implements TargetExpression { +public record TargetSwitch(TargetExpression expr, List cases, TargetBlock default_, TargetType type, boolean isExpression) implements TargetExpression { - @Override - public TargetType type() { - return null; + public TargetSwitch(TargetExpression expr, List cases, TargetBlock default_) { + this(expr, cases, default_, null, false); } - record Case(Expression value, Expression body) {} + public TargetSwitch(TargetExpression expr, List cases, TargetBlock default_, TargetType type) { + this(expr, cases, default_, type, true); + } + + public TargetSwitch(TargetExpression expr, List cases, TargetBlock default_, boolean isExpression) { + this(expr, cases, default_, null, isExpression); + } + + public record Case(List labels, TargetBlock body) {} + + public record Pattern(TargetType type, String name) implements TargetExpression {} + public record ComplexPattern(TargetType type, List subPatterns) implements TargetExpression {} + + public record Guard(TargetExpression inner, TargetExpression expression) implements TargetExpression {} } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java index 62ff90dc..e1a3690c 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java @@ -3,9 +3,4 @@ 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; - } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetYield.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetYield.java new file mode 100644 index 00000000..108e7710 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetYield.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.target.tree.expression; + +public record TargetYield(TargetExpression expression) implements TargetExpression { +} diff --git a/src/test/java/targetast/TestCodegen.java b/src/test/java/targetast/TestCodegen.java index 92336170..9e593afd 100644 --- a/src/test/java/targetast/TestCodegen.java +++ b/src/test/java/targetast/TestCodegen.java @@ -13,7 +13,9 @@ import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.target.tree.type.TargetType; import org.junit.Ignore; import org.junit.Test; + import static org.junit.Assert.*; + import org.objectweb.asm.Opcodes; import java.io.IOException; @@ -29,185 +31,226 @@ import java.util.function.Function; import java.util.stream.Collectors; 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 { - Files.createDirectories(outputPath); - Files.write(outputPath.resolve(name + ".class"), code); - } + private static void writeClassFile(String name, byte[] code) throws IOException { + Files.createDirectories(outputPath); + Files.write(outputPath.resolve(name + ".class"), code); + } - public static Map> generateClassFiles(IByteArrayClassLoader classLoader, String... files) throws IOException, ClassNotFoundException { - 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 compiler = new JavaTXCompiler(filenames, List.of(path.toFile(), outputPath.toFile())); - var resultSet = compiler.typeInference(); + public static Map> generateClassFiles(IByteArrayClassLoader classLoader, String... files) throws IOException, ClassNotFoundException { + 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 compiler = new JavaTXCompiler(filenames, List.of(path.toFile(), outputPath.toFile())); + var resultSet = compiler.typeInference(); - var result = new HashMap>(); - for (var file : filenames) { - var sourceFile = compiler.sourceFiles.get(file); - var converter = new ASTToTargetAST(resultSet, sourceFile, classLoader); - var classes = compiler.sourceFiles.get(file).getClasses(); + var result = new HashMap>(); + for (var file : filenames) { + var sourceFile = compiler.sourceFiles.get(file); + var converter = new ASTToTargetAST(resultSet, sourceFile, classLoader); + var classes = compiler.sourceFiles.get(file).getClasses(); - result.putAll(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()); - } + result.putAll(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()))); - return result; + for (var entry : converter.auxiliaries.entrySet()) { + writeClassFile(entry.getKey(), entry.getValue()); + } } - public static Class generateClass(TargetClass clazz, IByteArrayClassLoader classLoader) throws IOException { - var codegen = new Codegen(clazz); - var code = codegen.generate(); - writeClassFile(clazz.qualifiedName(), code); - return classLoader.loadClass(code); + return result; + } + + public static Class generateClass(TargetClass clazz, IByteArrayClassLoader classLoader) throws IOException { + var codegen = new Codegen(clazz); + var code = codegen.generate(); + writeClassFile(clazz.qualifiedName(), code); + return classLoader.loadClass(code); + } + + public static Map> 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> 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(); + return result; + } - var sourceFile = compiler.sourceFiles.get(file); - var converter = new ASTToTargetAST(resultSet, sourceFile, classLoader); - var classes = compiler.sourceFiles.get(file).getClasses(); + @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); + } - 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())); + @Test + public void testArithmetic() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Arithmetic"); - for (var entry : converter.auxiliaries.entrySet()) { - writeClassFile(entry.getKey(), entry.getValue()); - } + 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")))))); - 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 - 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 testUnary() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Unary"); - @Test - public void testArithmetic() throws Exception { - var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Arithmetic"); + 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")))))); - 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("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); - 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"); + @Test + public void testConditional() throws Exception { + 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, "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")))))); + 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()); - 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); + 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 testConditional() throws Exception { - var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Conditional"); + @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)))); - 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()); + clazz.getDeclaredMethod("helloWorld").invoke(null); + } - 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); - } + @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); + } - // 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 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 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)))); + @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); + } - var clazz = generateClass(targetClass, new ByteArrayClassLoader()); - clazz.getDeclaredMethod("helloWorld").invoke(null); - } + @Test + 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 - 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 testTypeSwitch() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Switch"); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "switchType", List.of(new MethodParameter(TargetType.Object, "obj")), TargetType.Integer, new TargetBlock(List.of( + new TargetReturn(new TargetSwitch(new TargetLocalVar(TargetType.Object, "obj"), List.of( + new TargetSwitch.Case(List.of(new TargetSwitch.Pattern(TargetType.String, "aString")), new TargetBlock( + List.of(new TargetLiteral.IntLiteral(0)) + )), + 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 - 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 + @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)); - @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 - @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, "", 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); - } + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "CGLambda"); + targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of(new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "", false, false)))); + targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(interfaceType, "by2", 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); + } }