From 3e699d0754cfa13fc5121bff8891afede1b92ceb Mon Sep 17 00:00:00 2001 From: Sander Hautvast Date: Mon, 9 Nov 2020 15:20:35 +0100 Subject: [PATCH] added refs to this and super --- src/main/java/nl/sander/beejava/Compiler.java | 10 +++- .../sander/beejava/ConstantPoolCreator.java | 1 - .../sander/beejava/ConstantTreeCreator.java | 58 ++++++++++++++----- .../java/nl/sander/beejava/api/CodeLine.java | 4 ++ .../beejava/constantpool/ConstantPool.java | 15 ++--- .../sander/beejava/flags/ClassAccessFlag.java | 9 ++- .../beejava/flags/ClassAccessFlagTest.java | 24 ++++++++ 7 files changed, 92 insertions(+), 29 deletions(-) create mode 100644 src/test/java/nl/sander/beejava/flags/ClassAccessFlagTest.java diff --git a/src/main/java/nl/sander/beejava/Compiler.java b/src/main/java/nl/sander/beejava/Compiler.java index a223a6e..68a72db 100644 --- a/src/main/java/nl/sander/beejava/Compiler.java +++ b/src/main/java/nl/sander/beejava/Compiler.java @@ -3,6 +3,7 @@ package nl.sander.beejava; import nl.sander.beejava.api.BeeClass; import nl.sander.beejava.constantpool.ConstantPool; import nl.sander.beejava.constantpool.entry.NodeConstant; +import nl.sander.beejava.flags.ClassAccessFlag; import nl.sander.beejava.util.ByteBuf; import java.util.Set; @@ -33,9 +34,14 @@ public class Compiler { buf.addU16(constantPool.getLength()); buf.addU8(constantPool.getBytes()); + buf.addU16(ClassAccessFlag.getSum(beeClass.getAccessFlags())); + buf.addU16(constantTreeCreator.getThisClass().getIndex()); + buf.addU16(constantTreeCreator.getSuperClass().getIndex()); - - + int x = 1; + for (NodeConstant e : constantPool) { + System.out.println((x++) + ":" + e); + } printBytes(buf); return buf.toBytes(); diff --git a/src/main/java/nl/sander/beejava/ConstantPoolCreator.java b/src/main/java/nl/sander/beejava/ConstantPoolCreator.java index d654a2e..927360f 100644 --- a/src/main/java/nl/sander/beejava/ConstantPoolCreator.java +++ b/src/main/java/nl/sander/beejava/ConstantPoolCreator.java @@ -15,7 +15,6 @@ public class ConstantPoolCreator { 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; updateToplevelElements(constantTree); return constantPool; diff --git a/src/main/java/nl/sander/beejava/ConstantTreeCreator.java b/src/main/java/nl/sander/beejava/ConstantTreeCreator.java index 544af84..db10258 100644 --- a/src/main/java/nl/sander/beejava/ConstantTreeCreator.java +++ b/src/main/java/nl/sander/beejava/ConstantTreeCreator.java @@ -10,7 +10,7 @@ import java.util.Set; /** * Builds a set of a tree of constant pool entries that refer to each other. - * + *

* A client must supply a {@link BeeClass} containing a set of {@link CodeLine}s that is assumed to be correct. * It doesn't check if a valid state is reached. */ @@ -20,6 +20,9 @@ import java.util.Set; public class ConstantTreeCreator { private final Set constantTree = new LinkedHashSet<>(); private BeeClass beeClass; + private ClassEntry thisClass; + private ClassEntry superClass; + /** * Creates a Set of nested entries that make up a single reference. For instance a class reference whose name is a utf8 reference. @@ -34,10 +37,30 @@ public class ConstantTreeCreator { beeClass.getConstructors().forEach(this::updateConstantTree); // TODO update constantTree for fields ? // TODO update constantTree for methods - constantTree.add(new ClassEntry(new Utf8Entry(internalName(beeClass.getName())))); + + constantTree.add(getThisClassRef(beeClass)); return constantTree; } + /* + * might be null if no methods refer to _this_ + */ + private ClassEntry getThisClassRef(BeeClass beeClass) { + if (thisClass == null) { + thisClass = new ClassEntry(new Utf8Entry(internalName(beeClass.getName()))); + } + return thisClass; + } + + + public ClassEntry getThisClass() { + return thisClass; + } + + public ClassEntry getSuperClass() { + return superClass; + } + private void updateConstantTree(ContainsCode codeContainer) { codeContainer.getCode().forEach(this::updateConstantTree); } @@ -46,7 +69,7 @@ public class ConstantTreeCreator { * scan code line for items that need adding to the constant pool */ private void updateConstantTree(CodeLine codeline) { - if (codeline.hasMethod()){ + if (codeline.hasMethod()) { addMethod(codeline); } @@ -56,11 +79,11 @@ public class ConstantTreeCreator { } private void addMethod(CodeLine codeline) { - constantTree.add(new MethodRefEntry(createClassName(codeline), createMethodNameAndType(codeline))); + constantTree.add(new MethodRefEntry(getOrCreateClassEntry(codeline), createMethodNameAndType(codeline))); } private void addField(CodeLine codeline) { - constantTree.add(new FieldRefEntry(createClassName(codeline), createFieldNameAndType(codeline))); + constantTree.add(new FieldRefEntry(getOrCreateClassEntry(codeline), createFieldNameAndType(codeline))); } private NameAndTypeEntry createMethodNameAndType(CodeLine codeline) { @@ -71,17 +94,24 @@ public class ConstantTreeCreator { return new NameAndTypeEntry(new Utf8Entry(codeline.getField().getName()), new Utf8Entry(TypeMapper.map(codeline.getField().getType()))); } - private ClassEntry createClassName(CodeLine codeline) { - return new ClassEntry(new Utf8Entry(internalName(getNameOfClass(codeline)))); + private ClassEntry getOrCreateClassEntry(CodeLine codeline) { + if (codeline.getRef() == Ref.SUPER) { + if (superClass == null) { + superClass = createClassEntry(beeClass.getSuperClass().getName()); + } + return superClass; + } else if (codeline.getRef() == Ref.THIS) { + if (thisClass == null) { + thisClass = createClassEntry(beeClass.getName()); + } + return thisClass; + } + //TODO other cases + throw new RuntimeException("shouldn't be here"); } - private String getNameOfClass(CodeLine codeline) { - if (codeline.getRef() == Ref.SUPER) { - return beeClass.getSuperClass().getName(); - } else if (codeline.getRef() == Ref.THIS) { - return beeClass.getName(); - } - throw new RuntimeException("shouldn't be here"); + private ClassEntry createClassEntry(String name) { + return new ClassEntry(new Utf8Entry(internalName(name))); } private String internalName(String name) { diff --git a/src/main/java/nl/sander/beejava/api/CodeLine.java b/src/main/java/nl/sander/beejava/api/CodeLine.java index a8c67a8..92fcb88 100644 --- a/src/main/java/nl/sander/beejava/api/CodeLine.java +++ b/src/main/java/nl/sander/beejava/api/CodeLine.java @@ -90,6 +90,10 @@ public class CodeLine { return ref; } + public boolean hasRef() { + return ref != null; + } + public boolean hasField() { return field != null; } diff --git a/src/main/java/nl/sander/beejava/constantpool/ConstantPool.java b/src/main/java/nl/sander/beejava/constantpool/ConstantPool.java index 49f96e6..cbc968b 100644 --- a/src/main/java/nl/sander/beejava/constantpool/ConstantPool.java +++ b/src/main/java/nl/sander/beejava/constantpool/ConstantPool.java @@ -6,25 +6,20 @@ import nl.sander.beejava.util.ByteBuf; import java.util.ArrayList; import java.util.List; -public class ConstantPool { - private final List entries = new ArrayList<>(); +public class ConstantPool extends ArrayList{ public int getIndex(NodeConstant entry) { - for (int i = 0; i < entries.size(); i++) { - if (entries.get(i) == entry) { + for (int i = 0; i < size(); i++) { + if (get(i) == entry) { return i + 1; } } return -1; } - public void add(NodeConstant entry) { - entries.add(entry); - } - public byte[] getBytes() { ByteBuf bytes = new ByteBuf(); - entries.forEach(entry -> bytes.addU8(entry.getBytes())); + forEach(entry -> bytes.addU8(entry.getBytes())); return bytes.toBytes(); } @@ -32,6 +27,6 @@ public class ConstantPool { * get the length +1 */ public int getLength() { - return entries.size() + 1; + return size() + 1; } } diff --git a/src/main/java/nl/sander/beejava/flags/ClassAccessFlag.java b/src/main/java/nl/sander/beejava/flags/ClassAccessFlag.java index e67f38a..92f6af8 100644 --- a/src/main/java/nl/sander/beejava/flags/ClassAccessFlag.java +++ b/src/main/java/nl/sander/beejava/flags/ClassAccessFlag.java @@ -1,6 +1,6 @@ package nl.sander.beejava.flags; -import nl.sander.beejava.flags.AccessFlag; +import java.util.Collection; public enum ClassAccessFlag implements AccessFlag { PUBLIC(0x0001), // Declared public; may be accessed from outside its package. @@ -13,10 +13,15 @@ public enum ClassAccessFlag implements AccessFlag { ENUM(0x4000), // Declared as an enum type. MODULE(0x8000); // Is a module, not a class or interface. + private final int bytecode; ClassAccessFlag(int bytecode) { - this.bytecode=bytecode; + this.bytecode = bytecode; + } + + public static int getSum(Collection flags) { + return flags.stream().mapToInt(ClassAccessFlag::getBytecode).reduce(0, (result, value) -> result | value); } @Override diff --git a/src/test/java/nl/sander/beejava/flags/ClassAccessFlagTest.java b/src/test/java/nl/sander/beejava/flags/ClassAccessFlagTest.java new file mode 100644 index 0000000..6a691c6 --- /dev/null +++ b/src/test/java/nl/sander/beejava/flags/ClassAccessFlagTest.java @@ -0,0 +1,24 @@ +package nl.sander.beejava.flags; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Collections; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ClassAccessFlagTest { + @Test + public void mustOr1Value() { + assertEquals(1, ClassAccessFlag.getSum(Collections.singletonList(ClassAccessFlag.PUBLIC))); + } + + @Test + public void mustOr2Values() { + assertEquals(17, ClassAccessFlag.getSum(Arrays.asList(ClassAccessFlag.PUBLIC, ClassAccessFlag.FINAL))); + } + + + +}