added refs to this and super

This commit is contained in:
Sander Hautvast 2020-11-09 15:20:35 +01:00
parent 50649ea1a8
commit 3e699d0754
7 changed files with 92 additions and 29 deletions

View file

@ -3,6 +3,7 @@ package nl.sander.beejava;
import nl.sander.beejava.api.BeeClass; import nl.sander.beejava.api.BeeClass;
import nl.sander.beejava.constantpool.ConstantPool; import nl.sander.beejava.constantpool.ConstantPool;
import nl.sander.beejava.constantpool.entry.NodeConstant; import nl.sander.beejava.constantpool.entry.NodeConstant;
import nl.sander.beejava.flags.ClassAccessFlag;
import nl.sander.beejava.util.ByteBuf; import nl.sander.beejava.util.ByteBuf;
import java.util.Set; import java.util.Set;
@ -33,9 +34,14 @@ public class Compiler {
buf.addU16(constantPool.getLength()); buf.addU16(constantPool.getLength());
buf.addU8(constantPool.getBytes()); 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); printBytes(buf);
return buf.toBytes(); return buf.toBytes();

View file

@ -15,7 +15,6 @@ public class ConstantPoolCreator {
public ConstantPool createConstantPool(Set<NodeConstant> constantTree) { public ConstantPool createConstantPool(Set<NodeConstant> constantTree) {
constantPool = new ConstantPool(); constantPool = new ConstantPool();
// constantPool.add(null); // dummy element to align it's index with the indexes in the elements themselves
index = 0; index = 0;
updateToplevelElements(constantTree); updateToplevelElements(constantTree);
return constantPool; return constantPool;

View file

@ -10,7 +10,7 @@ import java.util.Set;
/** /**
* Builds a set of a tree of constant pool entries that refer to each other. * Builds a set of a tree of constant pool entries that refer to each other.
* * <p>
* A client must supply a {@link BeeClass} containing a set of {@link CodeLine}s that is assumed to be correct. * 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. * It doesn't check if a valid state is reached.
*/ */
@ -20,6 +20,9 @@ import java.util.Set;
public class ConstantTreeCreator { public class ConstantTreeCreator {
private final Set<NodeConstant> constantTree = new LinkedHashSet<>(); private final Set<NodeConstant> constantTree = new LinkedHashSet<>();
private BeeClass beeClass; 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. * 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); beeClass.getConstructors().forEach(this::updateConstantTree);
// TODO update constantTree for fields ? // TODO update constantTree for fields ?
// TODO update constantTree for methods // TODO update constantTree for methods
constantTree.add(new ClassEntry(new Utf8Entry(internalName(beeClass.getName()))));
constantTree.add(getThisClassRef(beeClass));
return constantTree; 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) { private void updateConstantTree(ContainsCode codeContainer) {
codeContainer.getCode().forEach(this::updateConstantTree); codeContainer.getCode().forEach(this::updateConstantTree);
} }
@ -56,11 +79,11 @@ public class ConstantTreeCreator {
} }
private void addMethod(CodeLine codeline) { 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) { 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) { 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()))); return new NameAndTypeEntry(new Utf8Entry(codeline.getField().getName()), new Utf8Entry(TypeMapper.map(codeline.getField().getType())));
} }
private ClassEntry createClassName(CodeLine codeline) { private ClassEntry getOrCreateClassEntry(CodeLine codeline) {
return new ClassEntry(new Utf8Entry(internalName(getNameOfClass(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) { private ClassEntry createClassEntry(String name) {
if (codeline.getRef() == Ref.SUPER) { return new ClassEntry(new Utf8Entry(internalName(name)));
return beeClass.getSuperClass().getName();
} else if (codeline.getRef() == Ref.THIS) {
return beeClass.getName();
}
throw new RuntimeException("shouldn't be here");
} }
private String internalName(String name) { private String internalName(String name) {

View file

@ -90,6 +90,10 @@ public class CodeLine {
return ref; return ref;
} }
public boolean hasRef() {
return ref != null;
}
public boolean hasField() { public boolean hasField() {
return field != null; return field != null;
} }

View file

@ -6,25 +6,20 @@ import nl.sander.beejava.util.ByteBuf;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ConstantPool { public class ConstantPool extends ArrayList<NodeConstant>{
private final List<NodeConstant> entries = new ArrayList<>();
public int getIndex(NodeConstant entry) { public int getIndex(NodeConstant entry) {
for (int i = 0; i < entries.size(); i++) { for (int i = 0; i < size(); i++) {
if (entries.get(i) == entry) { if (get(i) == entry) {
return i + 1; return i + 1;
} }
} }
return -1; return -1;
} }
public void add(NodeConstant entry) {
entries.add(entry);
}
public byte[] getBytes() { public byte[] getBytes() {
ByteBuf bytes = new ByteBuf(); ByteBuf bytes = new ByteBuf();
entries.forEach(entry -> bytes.addU8(entry.getBytes())); forEach(entry -> bytes.addU8(entry.getBytes()));
return bytes.toBytes(); return bytes.toBytes();
} }
@ -32,6 +27,6 @@ public class ConstantPool {
* get the length +1 * get the length +1
*/ */
public int getLength() { public int getLength() {
return entries.size() + 1; return size() + 1;
} }
} }

View file

@ -1,6 +1,6 @@
package nl.sander.beejava.flags; package nl.sander.beejava.flags;
import nl.sander.beejava.flags.AccessFlag; import java.util.Collection;
public enum ClassAccessFlag implements AccessFlag { public enum ClassAccessFlag implements AccessFlag {
PUBLIC(0x0001), // Declared public; may be accessed from outside its package. PUBLIC(0x0001), // Declared public; may be accessed from outside its package.
@ -13,12 +13,17 @@ public enum ClassAccessFlag implements AccessFlag {
ENUM(0x4000), // Declared as an enum type. ENUM(0x4000), // Declared as an enum type.
MODULE(0x8000); // Is a module, not a class or interface. MODULE(0x8000); // Is a module, not a class or interface.
private final int bytecode; private final int bytecode;
ClassAccessFlag(int bytecode) { ClassAccessFlag(int bytecode) {
this.bytecode = bytecode; this.bytecode = bytecode;
} }
public static int getSum(Collection<ClassAccessFlag> flags) {
return flags.stream().mapToInt(ClassAccessFlag::getBytecode).reduce(0, (result, value) -> result | value);
}
@Override @Override
public int getBytecode() { public int getBytecode() {
return bytecode; return bytecode;

View file

@ -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)));
}
}