diff --git a/README.md b/README.md index 56c7a25..46bebe5 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,9 @@ BeeConstructor createDefaultConstructor() { return BeeConstructor.builder() .withAccessFlags(MethodAccessFlags.PUBLIC) .withCode( - line(0, LD_VAR, Ref.THIS), - line(1, INVOKE, Ref.SUPER, "", "()"), - line(5, RETURN)) + line(LD_VAR, Ref.THIS), + line(INVOKE, Ref.SUPER, "", "()"), + line(RETURN)) .build(); } ``` @@ -50,10 +50,10 @@ BeeMethod print2 = BeeMethod.builder() .withName("print2") .withAccessFlags(MethodAccessFlags.PUBLIC) .withCode( - line(0, GET, "java.lang.System","out"), - line(1, LD_CONST, "2"), - line(2, INVOKE, "java.io.PrintStream", "println", "java.lang.String"), - line(3, RETURN)) + line(GET, "java.lang.System","out"), + line(LD_CONST, "2"), + line(INVOKE, "java.io.PrintStream", "println", "java.lang.String"), + line(RETURN)) .build(); ``` @@ -61,6 +61,6 @@ BeeMethod print2 = BeeMethod.builder() * MORE opcodes * invoke dynamic support (also in constant pool) * support for exceptions, class attributes -* figure out a nicer, better api, drop the line numbers +* figure out a nicer, better api * or instead drop this idea and let the developer write the raw bytecode. The constant pool would then be the only thing Beejava adds. * create a readable file format for opcode files diff --git a/src/main/java/nl/sander/beejava/ConstantPoolEntryCreator.java b/src/main/java/nl/sander/beejava/ConstantPoolEntryCreator.java index ed4a5b0..53e746d 100644 --- a/src/main/java/nl/sander/beejava/ConstantPoolEntryCreator.java +++ b/src/main/java/nl/sander/beejava/ConstantPoolEntryCreator.java @@ -127,7 +127,7 @@ class ConstantPoolEntryCreator { } else if (v instanceof Double) { return cache(new DoubleEntry((Double) v)); } - throw new RuntimeException(); // TODO find out why are you here + throw new IllegalStateException("shouldn't be here"); // TODO find out why are you here } /* diff --git a/src/main/java/nl/sander/beejava/JavaOpcode.java b/src/main/java/nl/sander/beejava/JavaOpcode.java index e581f73..dc8bdf1 100644 --- a/src/main/java/nl/sander/beejava/JavaOpcode.java +++ b/src/main/java/nl/sander/beejava/JavaOpcode.java @@ -14,7 +14,10 @@ public enum JavaOpcode { INVOKEVIRTUAL ( 0xb6, true, -1), INVOKESPECIAL ( 0xb7, true, -1), INVOKESTATIC ( 0xb8, true, -1), - INVOKEDYNAMIC ( 0xba,true,-1); + INVOKEDYNAMIC ( 0xba,true,-1), + + PUTFIELD(0xb5, true, -2); + private final int opcode; private final boolean wide; diff --git a/src/main/java/nl/sander/beejava/OpcodeMapper.java b/src/main/java/nl/sander/beejava/OpcodeMapper.java index cfd83f8..6ca6cb7 100644 --- a/src/main/java/nl/sander/beejava/OpcodeMapper.java +++ b/src/main/java/nl/sander/beejava/OpcodeMapper.java @@ -20,6 +20,7 @@ public class OpcodeMapper { case LD_CONST -> loadConst(codeLine); case INVOKE -> invoke(codeLine); case RETURN -> JavaOpcode.RETURN; //TODO not complete yet + case PUT -> JavaOpcode.PUTFIELD; default -> throw new IllegalStateException("something not implemented"); }; } diff --git a/src/main/java/nl/sander/beejava/api/CodeLine.java b/src/main/java/nl/sander/beejava/api/CodeLine.java index 3565e73..4241870 100644 --- a/src/main/java/nl/sander/beejava/api/CodeLine.java +++ b/src/main/java/nl/sander/beejava/api/CodeLine.java @@ -13,7 +13,6 @@ import java.util.List; import java.util.stream.Collectors; public final class CodeLine { - private final int linenumber; private final Opcode opcode; private Ref ref; private BeeParameter parameter; @@ -28,60 +27,46 @@ public final class CodeLine { private CodeContainer owner; private JavaOpcode javaOpcode; - CodeLine(int linenumber, Opcode opcode) { - this.linenumber = linenumber; + CodeLine(Opcode opcode) { this.opcode = opcode; } - public static CodeLine line(int nr, Opcode opcode, Ref ref) { - return new CodeLine(nr, opcode).withRef(ref); + public static CodeLine line(Opcode opcode, Ref ref) { + return new CodeLine(opcode).withRef(ref); } - public static CodeLine line(int nr, Opcode opcode, String fieldClass, String fieldName) { - return new CodeLine(nr, opcode).withExternalFieldRef(fieldClass, fieldName); + public static CodeLine line(Opcode opcode, String fieldClass, String fieldName) { + return new CodeLine(opcode).withExternalFieldRef(fieldClass, fieldName); } - public static CodeLine line(int nr, Opcode opcode, Object constValue) { - return new CodeLine(nr, opcode).withConstValue(constValue); + public static CodeLine line(Opcode opcode, Object constValue) { + return new CodeLine(opcode).withConstValue(constValue); } - public static CodeLine line(int nr, Opcode opcode, String className, String methodName, String inputSignature) throws ClassNotFoundException { - return new CodeLine(nr, opcode).withClassName(className).withMethodName(methodName).withInput(parse(inputSignature)).withVoidOutput(); + public static CodeLine line(Opcode opcode, String className, String methodName, String inputSignature) throws ClassNotFoundException { + return new CodeLine(opcode).withClassName(className).withMethodName(methodName).withInput(parse(inputSignature)).withVoidOutput(); } - private static List> parse(String inputSignature) throws ClassNotFoundException { - if ("()".equals(inputSignature)) { - return Collections.emptyList(); - } else { - String[] params = inputSignature.split(","); - List> paramClasses = new ArrayList<>(); - for (String param : params) { - paramClasses.add(Class.forName(param)); - } - return paramClasses; - } - } - - public static CodeLine line(int nr, Opcode opcode, + public static CodeLine line(Opcode opcode, Ref ref, String methodNameRef, String inputSignature) throws ClassNotFoundException { - return new CodeLine(nr, opcode).withRef(ref).withMethodName(methodNameRef).withInput(parse(inputSignature)).withVoidOutput(); + return new CodeLine(opcode).withRef(ref).withMethodName(methodNameRef).withInput(parse(inputSignature)).withVoidOutput(); } - public static CodeLine line(int nr, Opcode opcode, + public static CodeLine line(Opcode opcode, Ref ref, String methodNameRef, String inputSignature, String outputSignature) throws ClassNotFoundException { - return new CodeLine(nr, opcode).withRef(ref).withMethodName(methodNameRef).withInput(parse(inputSignature)).withOutput(outputSignature); + return new CodeLine(opcode).withRef(ref).withMethodName(methodNameRef).withInput(parse(inputSignature)).withOutput(outputSignature); } - public static CodeLine line(int nr, Opcode opcode) { - return new CodeLine(nr, opcode); + public static CodeLine line(Opcode opcode) { + return new CodeLine(opcode); } - public static CodeLine line(int nr, Opcode opcode, BeeParameter parameter) { - return new CodeLine(nr, opcode).withParameter(parameter); + public static CodeLine line(Opcode opcode, BeeParameter parameter) { + return new CodeLine(opcode).withParameter(parameter); } - public static CodeLine line(int nr, Opcode opcode, BeeField intField) { - return new CodeLine(nr, opcode).withRef(Ref.THIS).withOwnField(intField); + public static CodeLine line(Opcode opcode, BeeField intField) { + return new CodeLine(opcode).withRef(Ref.THIS).withOwnField(intField); } private CodeLine withRef(Ref ref) { @@ -249,4 +234,17 @@ public final class CodeLine { public void setJavaOpcode(JavaOpcode javaOpcode) { this.javaOpcode = javaOpcode; } + + private static List> parse(String inputSignature) throws ClassNotFoundException { + if ("()".equals(inputSignature)) { + return Collections.emptyList(); + } else { + String[] params = inputSignature.split(","); + List> paramClasses = new ArrayList<>(); + for (String param : params) { + paramClasses.add(Class.forName(param)); + } + return paramClasses; + } + } } diff --git a/src/test/java/nl/sander/beejava/CompilerTests.java b/src/test/java/nl/sander/beejava/CompilerTests.java deleted file mode 100644 index 528888f..0000000 --- a/src/test/java/nl/sander/beejava/CompilerTests.java +++ /dev/null @@ -1,66 +0,0 @@ -package nl.sander.beejava; - -import nl.sander.beejava.api.*; -import nl.sander.beejava.constantpool.entry.*; -import org.junit.jupiter.api.Test; - -import java.util.Iterator; -import java.util.Set; - -import static nl.sander.beejava.api.CodeLine.line; -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class CompilerTests { - - // creates simplest class possible and checks the tree, that the ConstantTreeCreator emits - @Test // This is not a maintainable test - public void testMethodRefEntryForSuperConstructor() throws ClassNotFoundException { - // Arrange - BeeSource classWithIntField = TestData.createEmptyClass(); - - // Act - CompiledClass compiledClass = Compiler.compile(classWithIntField); - - // Assert - Set constantTree = compiledClass.getConstantTree(); - assertEquals(3, constantTree.size()); - ConstantPoolEntry superConstructor = constantTree.iterator().next(); - - assertEquals(MethodRefEntry.class, superConstructor.getClass()); - MethodRefEntry methodRefEntry = (MethodRefEntry) superConstructor; - - Set methodRefEntryChildren = methodRefEntry.getChildren(); - assertEquals(2, methodRefEntryChildren.size()); - - Iterator firstChildren = methodRefEntryChildren.iterator(); - ConstantPoolEntry child1 = firstChildren.next(); - assertEquals(ClassEntry.class, child1.getClass()); - ClassEntry classEntry = (ClassEntry) child1; - - Set classEntryChildren = classEntry.getChildren(); - assertEquals(1, classEntryChildren.size()); - ConstantPoolEntry child2 = classEntryChildren.iterator().next(); - - assertEquals(Utf8Entry.class, child2.getClass()); - Utf8Entry className = (Utf8Entry) child2; - assertEquals("java/lang/Object", className.getUtf8()); - - ConstantPoolEntry child3 = firstChildren.next(); - assertEquals(NameAndTypeEntry.class, child3.getClass()); - NameAndTypeEntry nameAndTypeEntry = (NameAndTypeEntry) child3; - - Set nameAndTypeEntryChildren = nameAndTypeEntry.getChildren(); - assertEquals(2, nameAndTypeEntryChildren.size()); - Iterator nameAndTypeChildrenIterator = nameAndTypeEntryChildren.iterator(); - - ConstantPoolEntry child4 = nameAndTypeChildrenIterator.next(); - assertEquals(Utf8Entry.class, child4.getClass()); - Utf8Entry name = (Utf8Entry) child4; - assertEquals("", name.getUtf8()); - - ConstantPoolEntry child5 = nameAndTypeChildrenIterator.next(); - assertEquals(Utf8Entry.class, child5.getClass()); - Utf8Entry type = (Utf8Entry) child5; - assertEquals("()V", type.getUtf8()); - } -} diff --git a/src/test/java/nl/sander/beejava/TestData.java b/src/test/java/nl/sander/beejava/TestData.java index 5cbf797..69dd540 100644 --- a/src/test/java/nl/sander/beejava/TestData.java +++ b/src/test/java/nl/sander/beejava/TestData.java @@ -40,10 +40,10 @@ public class TestData { .withName("print1") .withAccessFlags(MethodAccessFlags.PUBLIC) .withCode( - line(0, GET, "java.lang.System","out"), - line(1, LD_CONST, "1"), - line(2, INVOKE, "java.io.PrintStream", "println", "java.lang.String"), - line(3, RETURN)) + line(GET, "java.lang.System","out"), + line(LD_CONST, "1"), + line(INVOKE, "java.io.PrintStream", "println", "java.lang.String"), + line(RETURN)) .build(); // INVOKE System.out.println("1") @@ -53,10 +53,10 @@ public class TestData { .withName("print2") .withAccessFlags(MethodAccessFlags.PUBLIC) .withCode( - line(0, GET, "java.lang.System","out"), - line(1, LD_CONST, "2"), - line(2, INVOKE, "java.io.PrintStream", "println", "java.lang.String"), - line(3, RETURN)) + line(GET, "java.lang.System","out"), + line(LD_CONST, "2"), + line(INVOKE, "java.io.PrintStream", "println", "java.lang.String"), + line(RETURN)) .build(); return BeeSource.builder() @@ -82,12 +82,12 @@ public class TestData { .withAccessFlags(MethodAccessFlags.PUBLIC) .withFormalParameters(parameter) .withCode( - line(0, LD_VAR, Ref.THIS), - line(1, INVOKE, Ref.SUPER, "", "()"), - line(2, LD_VAR, Ref.THIS), - line(3, LD_VAR, parameter), - line(4, PUT, field), - line(5, RETURN)) + line(LD_VAR, Ref.THIS), + line(INVOKE, Ref.SUPER, "", "()"), + line(LD_VAR, Ref.THIS), + line(LD_VAR, parameter), + line(PUT, field), + line(RETURN)) .build(); return BeeSource.builder() @@ -105,9 +105,9 @@ public class TestData { return BeeConstructor.builder() .withAccessFlags(MethodAccessFlags.PUBLIC) .withCode( - line(0, LD_VAR, Ref.THIS), - line(1, INVOKE, Ref.SUPER, "", "()"), - line(5, RETURN)) + line(LD_VAR, Ref.THIS), + line(INVOKE, Ref.SUPER, "", "()"), + line(RETURN)) .build(); } } diff --git a/src/test/java/nl/sander/beejava/e2e/EmptyBeanTest.java b/src/test/java/nl/sander/beejava/e2e/EmptyBeanTest.java index 670f930..1cf2ced 100644 --- a/src/test/java/nl/sander/beejava/e2e/EmptyBeanTest.java +++ b/src/test/java/nl/sander/beejava/e2e/EmptyBeanTest.java @@ -61,9 +61,9 @@ public class EmptyBeanTest { return BeeConstructor.builder() .withAccessFlags(MethodAccessFlags.PUBLIC) .withCode( - line(0, LD_VAR, Ref.THIS), - line(1, INVOKE, Ref.SUPER, "", "()"), - line(5, RETURN)) + line(LD_VAR, Ref.THIS), + line(INVOKE, Ref.SUPER, "", "()"), + line(RETURN)) .build(); } }