diff --git a/src/main/java/nl/sander/beejava/Compiler.java b/src/main/java/nl/sander/beejava/Compiler.java index e755772..534255a 100644 --- a/src/main/java/nl/sander/beejava/Compiler.java +++ b/src/main/java/nl/sander/beejava/Compiler.java @@ -2,7 +2,7 @@ package nl.sander.beejava; import nl.sander.beejava.api.BeeClass; import nl.sander.beejava.constantpool.ConstantPool; -import nl.sander.beejava.constantpool.entry.ConstantPoolEntry; +import nl.sander.beejava.constantpool.entry.NodeConstant; import nl.sander.beejava.util.ByteBuf; import java.util.Set; @@ -28,7 +28,7 @@ public class Compiler { buf.add(beeClass.getClassFileVersion().getMinor()); buf.add(beeClass.getClassFileVersion().getMajor()); - Set constantTree = constantTreeCreator.createConstantTree(beeClass); + Set constantTree = constantTreeCreator.createConstantTree(beeClass); ConstantPool constantPool = constantPoolCreator.createConstantPool(constantTree); buf.add(constantPool.getBytes()); diff --git a/src/main/java/nl/sander/beejava/ConstantPoolCreator.java b/src/main/java/nl/sander/beejava/ConstantPoolCreator.java index c77b38b..552c007 100644 --- a/src/main/java/nl/sander/beejava/ConstantPoolCreator.java +++ b/src/main/java/nl/sander/beejava/ConstantPoolCreator.java @@ -1,7 +1,7 @@ package nl.sander.beejava; import nl.sander.beejava.constantpool.ConstantPool; -import nl.sander.beejava.constantpool.entry.ConstantPoolEntry; +import nl.sander.beejava.constantpool.entry.NodeConstant; import java.util.Set; @@ -9,10 +9,11 @@ import java.util.Set; * Transforms the hierachical constant tree into a flat datastructure. The walks the tree adding indexes to each element. */ public class ConstantPoolCreator { - private ConstantPool constantPool; - private int index; + private ConstantPool constantPool; // the constant pool that is being created + private int index; // the current index that will be assigned to a constant pool entry. It needs to be unique for each entry. + // References to other elements in the pool are made through indexes, so they have to be valid to guarantee that the class can be loaded by the JVM. - public ConstantPool createConstantPool(Set constantTree) { + public ConstantPool createConstantPool(Set constantTree) { constantPool = new ConstantPool(); constantPool.add(null); // dummy element to align it's index with the indexes in the elements themselves index = 0; @@ -20,26 +21,26 @@ public class ConstantPoolCreator { return constantPool; } - private void updateToplevelElements(Set children) { - for (ConstantPoolEntry child : children) { + private void updateToplevelElements(Set children) { + for (NodeConstant child : children) { addToPool(child); updateChildElements(child.getChildren()); // first the complete toplevel element including it's children, then next toplevel element } } - private void updateChildElements(Set children) { + private void updateChildElements(Set children) { // first all direct children - for (ConstantPoolEntry child : children) { + for (NodeConstant child : children) { addToPool(child); } // then further lineage - for (ConstantPoolEntry child : children) { + for (NodeConstant child : children) { updateChildElements(child.getChildren()); } } - private void addToPool(ConstantPoolEntry entry) { + private void addToPool(NodeConstant entry) { index += 1; entry.setIndex(index); constantPool.add(entry); diff --git a/src/main/java/nl/sander/beejava/ConstantTreeCreator.java b/src/main/java/nl/sander/beejava/ConstantTreeCreator.java index e5ac480..bea2cd6 100644 --- a/src/main/java/nl/sander/beejava/ConstantTreeCreator.java +++ b/src/main/java/nl/sander/beejava/ConstantTreeCreator.java @@ -18,7 +18,7 @@ import java.util.Set; * also TODO make sure entries aren't duplicates */ public class ConstantTreeCreator { - private final Set constantTree = new LinkedHashSet<>(); + private final Set constantTree = new LinkedHashSet<>(); private BeeClass beeClass; /** @@ -28,7 +28,7 @@ public class ConstantTreeCreator { * @param beeClass the Class object for which the constant pool needs to be created * @return a Set of constant pool entries */ - public Set createConstantTree(BeeClass beeClass) { + public Set createConstantTree(BeeClass beeClass) { constantTree.clear(); this.beeClass = beeClass; beeClass.getConstructors().forEach(this::updateConstantTree); @@ -55,23 +55,23 @@ public class ConstantTreeCreator { } private void addMethod(CodeLine codeline) { - constantTree.add(new MethodRefEntry(createClassName(codeline), createMethodNameAndType(codeline))); + constantTree.add(new ConstantMethodRef(createClassName(codeline), createMethodNameAndType(codeline))); } private void addField(CodeLine codeline) { - constantTree.add(new FieldRefEntry(createClassName(codeline), createFieldNameAndType(codeline))); + constantTree.add(new ConstantFieldRef(createClassName(codeline), createFieldNameAndType(codeline))); } - private NameAndTypeEntry createMethodNameAndType(CodeLine codeline) { - return new NameAndTypeEntry(new Utf8Entry(codeline.getMethodName()), new Utf8Entry(codeline.getMethodSignature())); + private ConstantNameAndType createMethodNameAndType(CodeLine codeline) { + return new ConstantNameAndType(new ConstantUtf8(codeline.getMethodName()), new ConstantUtf8(codeline.getMethodSignature())); } - private NameAndTypeEntry createFieldNameAndType(CodeLine codeline) { - return new NameAndTypeEntry(new Utf8Entry(codeline.getField().getName()), new Utf8Entry(TypeMapper.map(codeline.getField().getType()))); + private ConstantNameAndType createFieldNameAndType(CodeLine codeline) { + return new ConstantNameAndType(new ConstantUtf8(codeline.getField().getName()), new ConstantUtf8(TypeMapper.map(codeline.getField().getType()))); } - private ClassEntry createClassName(CodeLine codeline) { - return new ClassEntry(new Utf8Entry(internalName(getNameOfClass(codeline)))); + private ConstantClass createClassName(CodeLine codeline) { + return new ConstantClass(new ConstantUtf8(internalName(getNameOfClass(codeline)))); } private String getNameOfClass(CodeLine codeline) { diff --git a/src/main/java/nl/sander/beejava/constantpool/ConstantPool.java b/src/main/java/nl/sander/beejava/constantpool/ConstantPool.java index 3af37e1..3ac6e0a 100644 --- a/src/main/java/nl/sander/beejava/constantpool/ConstantPool.java +++ b/src/main/java/nl/sander/beejava/constantpool/ConstantPool.java @@ -1,14 +1,14 @@ package nl.sander.beejava.constantpool; -import nl.sander.beejava.constantpool.entry.ConstantPoolEntry; +import nl.sander.beejava.constantpool.entry.NodeConstant; import java.util.ArrayList; import java.util.List; public class ConstantPool { - private final List entries=new ArrayList<>(); + private final List entries=new ArrayList<>(); - public int getIndex(ConstantPoolEntry entry){ + public int getIndex(NodeConstant entry){ for (int i=0; i constantTree = new ConstantTreeCreator().createConstantTree(classWithIntField); + Set constantTree = new ConstantTreeCreator().createConstantTree(classWithIntField); assertEquals(1, constantTree.size()); - ConstantPoolEntry superConstructor = constantTree.iterator().next(); + NodeConstant superConstructor = constantTree.iterator().next(); - assertEquals(MethodRefEntry.class, superConstructor.getClass()); - MethodRefEntry methodRefEntry = (MethodRefEntry) superConstructor; + assertEquals(ConstantMethodRef.class, superConstructor.getClass()); + ConstantMethodRef constantMethodRef = (ConstantMethodRef) superConstructor; - Set methodRefEntryChildren = methodRefEntry.getChildren(); + Set methodRefEntryChildren = constantMethodRef.getChildren(); assertEquals(2, methodRefEntryChildren.size()); - Iterator firstChildren = methodRefEntryChildren.iterator(); - ConstantPoolEntry child1 = firstChildren.next(); - assertEquals(ClassEntry.class, child1.getClass()); - ClassEntry classEntry = (ClassEntry) child1; + Iterator firstChildren = methodRefEntryChildren.iterator(); + NodeConstant child1 = firstChildren.next(); + assertEquals(ConstantClass.class, child1.getClass()); + ConstantClass constantClass = (ConstantClass) child1; - Set classEntryChildren = classEntry.getChildren(); + Set classEntryChildren = constantClass.getChildren(); assertEquals(1, classEntryChildren.size()); - ConstantPoolEntry child2 = classEntryChildren.iterator().next(); + NodeConstant child2 = classEntryChildren.iterator().next(); - assertEquals(Utf8Entry.class, child2.getClass()); - Utf8Entry className = (Utf8Entry) child2; + assertEquals(ConstantUtf8.class, child2.getClass()); + ConstantUtf8 className = (ConstantUtf8) child2; assertEquals("java/lang/Object", className.getUtf8()); - ConstantPoolEntry child3 = firstChildren.next(); - assertEquals(NameAndTypeEntry.class, child3.getClass()); - NameAndTypeEntry nameAndTypeEntry = (NameAndTypeEntry) child3; + NodeConstant child3 = firstChildren.next(); + assertEquals(ConstantNameAndType.class, child3.getClass()); + ConstantNameAndType constantNameAndType = (ConstantNameAndType) child3; - Set nameAndTypeEntryChildren = nameAndTypeEntry.getChildren(); + Set nameAndTypeEntryChildren = constantNameAndType.getChildren(); assertEquals(2, nameAndTypeEntryChildren.size()); - Iterator nameAndTypeChildrenIterator = nameAndTypeEntryChildren.iterator(); + Iterator nameAndTypeChildrenIterator = nameAndTypeEntryChildren.iterator(); - ConstantPoolEntry child4 = nameAndTypeChildrenIterator.next(); - assertEquals(Utf8Entry.class, child4.getClass()); - Utf8Entry name = (Utf8Entry) child4; + NodeConstant child4 = nameAndTypeChildrenIterator.next(); + assertEquals(ConstantUtf8.class, child4.getClass()); + ConstantUtf8 name = (ConstantUtf8) child4; assertEquals("", name.getUtf8()); - ConstantPoolEntry child5 = nameAndTypeChildrenIterator.next(); - assertEquals(Utf8Entry.class, child5.getClass()); - Utf8Entry type = (Utf8Entry) child5; + NodeConstant child5 = nameAndTypeChildrenIterator.next(); + assertEquals(ConstantUtf8.class, child5.getClass()); + ConstantUtf8 type = (ConstantUtf8) child5; assertEquals("()V", type.getUtf8()); } diff --git a/src/test/java/nl/sander/beejava/constantpool/entry/TagCorrectnessTest.java b/src/test/java/nl/sander/beejava/constantpool/entry/TagCorrectnessTest.java new file mode 100644 index 0000000..c917317 --- /dev/null +++ b/src/test/java/nl/sander/beejava/constantpool/entry/TagCorrectnessTest.java @@ -0,0 +1,49 @@ +package nl.sander.beejava.constantpool.entry; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * make sure tags were put in the code according to spec (§4.4) + */ +public class TagCorrectnessTest { + @Test + public void testSpec() { + assertEquals(7, classEntry().getTag()); + assertEquals(9, fieldRef().getTag()); + assertEquals(10, new ConstantMethodRef(classEntry(), nameAndType()).getTag()); + assertEquals(11, new ConstantInterfaceMethodRef(classEntry(), nameAndType()).getTag()); + assertEquals(8, new ConstantString(utf8()).getTag()); + assertEquals(3, new ConstantInteger(0).getTag()); + assertEquals(4, new ConstantFloat(0).getTag()); + assertEquals(5, new ConstantLong(0).getTag()); + assertEquals(6, new ConstantDouble(0).getTag()); + assertEquals(12, nameAndType().getTag()); + assertEquals(1, utf8().getTag()); + assertEquals(15, new ConstantMethodHandle(0).getTag()); //TODO + assertEquals(16, new ConstantMethodType(utf8()).getTag()); //TODO + assertEquals(17, new ConstantDynamic(0, nameAndType()).getTag()); //TODO + assertEquals(18, new ConstantInvokeDynamic(0, nameAndType()).getTag()); //TODO + assertEquals(19, new ConstantModule(utf8()).getTag()); + assertEquals(20, new ConstantPackage(utf8()).getTag()); + + } + + private ConstantFieldRef fieldRef() { + return new ConstantFieldRef(classEntry(), nameAndType()); + } + + private ConstantNameAndType nameAndType() { + return new ConstantNameAndType(utf8(), utf8()); + } + + + private ConstantClass classEntry() { + return new ConstantClass(utf8()); + } + + private ConstantUtf8 utf8() { + return new ConstantUtf8(""); + } +}