diff --git a/src/main/java/nl/sander/beejava/BytecodeGenerator.java b/src/main/java/nl/sander/beejava/BytecodeGenerator.java index 6540616..ac6ecdc 100644 --- a/src/main/java/nl/sander/beejava/BytecodeGenerator.java +++ b/src/main/java/nl/sander/beejava/BytecodeGenerator.java @@ -1,9 +1,8 @@ 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.flags.ClassAccessFlag; +import nl.sander.beejava.flags.AccessFlags; import nl.sander.beejava.util.ByteBuf; public class BytecodeGenerator { @@ -23,19 +22,20 @@ public class BytecodeGenerator { private byte[] generate() { ByteBuf buf = new ByteBuf(); buf.addU8(0xCA, 0xFE, 0xBA, 0xBE); - buf.addU16(compiledClass.getBeeClass().getClassFileVersion().getMinor()); - buf.addU16(compiledClass.getBeeClass().getClassFileVersion().getMajor()); - + buf.addU16(compiledClass.getSource().getClassFileVersion().getMinor()); + buf.addU16(compiledClass.getSource().getClassFileVersion().getMajor()); ConstantPool constantPool = constantPoolCreator.createConstantPool(compiledClass.getConstantTree()); buf.addU16(constantPool.getLength()); - buf.addU8(constantPool.getBytes()); - buf.addU16(ClassAccessFlag.getSum(compiledClass.getBeeClass().getAccessFlags())); + constantPool.addTo(buf); + buf.addU16(AccessFlags.combine(compiledClass.getSource().getAccessFlags())); buf.addU16(compiledClass.geThisIndex()); buf.addU16(compiledClass.getSuperIndex()); buf.addU16(compiledClass.getInterfaces().size()); compiledClass.getInterfaces().forEach(interfase -> buf.addU16(interfase.getIndex())); + buf.addU16(compiledClass.getFields().size()); + compiledClass.getFields().forEach(fieldInfo -> fieldInfo.addBytes(buf)); int x = 1; for (ConstantPoolEntry e : constantPool) { diff --git a/src/main/java/nl/sander/beejava/CodeContainer.java b/src/main/java/nl/sander/beejava/CodeContainer.java index e974c2e..79f3dd6 100644 --- a/src/main/java/nl/sander/beejava/CodeContainer.java +++ b/src/main/java/nl/sander/beejava/CodeContainer.java @@ -5,6 +5,9 @@ import nl.sander.beejava.api.CodeLine; import java.util.LinkedList; import java.util.List; +/** + * parent of a constructor or a method. + */ public abstract class CodeContainer { protected final List code = new LinkedList<>(); diff --git a/src/main/java/nl/sander/beejava/CompiledClass.java b/src/main/java/nl/sander/beejava/CompiledClass.java index 7d31cd3..83dc265 100644 --- a/src/main/java/nl/sander/beejava/CompiledClass.java +++ b/src/main/java/nl/sander/beejava/CompiledClass.java @@ -1,6 +1,7 @@ package nl.sander.beejava; -import nl.sander.beejava.api.BeeClass; +import nl.sander.beejava.api.BeeSource; +import nl.sander.beejava.classinfo.FieldInfo; import nl.sander.beejava.constantpool.entry.ClassEntry; import nl.sander.beejava.constantpool.entry.ConstantPoolEntry; @@ -11,12 +12,13 @@ import java.util.Set; class CompiledClass { private final Set constantTree = new LinkedHashSet<>(); private final Set interfaces = new HashSet<>(); - private final BeeClass beeClass; + private final Set fields = new HashSet<>(); + private final BeeSource beeSource; private ClassEntry thisClass; private ClassEntry superClass; - CompiledClass(BeeClass beeClass) { - this.beeClass = beeClass; + CompiledClass(BeeSource beeSource) { + this.beeSource = beeSource; } int getSuperIndex() { @@ -49,12 +51,8 @@ class CompiledClass { interfaces.add(interfaceEntry); } - BeeClass getBeeClass() { - return beeClass; - } - - ClassEntry getThisClass() { - return thisClass; + BeeSource getSource() { + return beeSource; } public void setThisClass(ClassEntry newThisClass) { @@ -62,4 +60,12 @@ class CompiledClass { thisClass = newThisClass; } } + + public void addField(FieldInfo fieldInfo) { + fields.add(fieldInfo); + } + + public Set getFields() { + return fields; + } } diff --git a/src/main/java/nl/sander/beejava/Compiler.java b/src/main/java/nl/sander/beejava/Compiler.java index d47c6c2..c43cb85 100644 --- a/src/main/java/nl/sander/beejava/Compiler.java +++ b/src/main/java/nl/sander/beejava/Compiler.java @@ -1,12 +1,12 @@ package nl.sander.beejava; -import nl.sander.beejava.api.BeeClass; +import nl.sander.beejava.api.BeeSource; import nl.sander.beejava.api.CodeLine; /** * 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. + * A client must supply a {@link BeeSource} containing a set of {@link CodeLine}s that is assumed to be correct. * It doesn't check if a valid state is reached. */ /* So the name isn't entirely correct. Waiting for inspiration. @@ -16,36 +16,45 @@ public class Compiler { private final CompiledClass compiledClass; private final ConstantPoolEntryCreator constantPoolEntryCreator; - Compiler(CompiledClass compiledClass) { + /** + * construct a compiler object. + */ + /* + * At this moment I'm not sure if this class will be able to reused. + */ + public Compiler(CompiledClass compiledClass) { this.compiledClass = compiledClass; this.constantPoolEntryCreator = new ConstantPoolEntryCreator(compiledClass); } /** - * Creates a Set of nested entries that make up a single reference. For instance a class reference whose name is a utf8 reference. - * In the constant pool they are consecutive entries, but they are created like nodes in a tree structure that models their relation. + * compile a BeeSource object into a CompiledClass object. * - * @param beeClass the Class object for which the constant pool needs to be created - * @return a Set of constant pool entries + * @param beeSource the Class object for which the constant pool needs to be created + * @return a CompiledClass object (that can be turned into bytecode) */ - public static CompiledClass compile(BeeClass beeClass) { - return new Compiler(new CompiledClass(beeClass)).compile(); + public static CompiledClass compile(BeeSource beeSource) { + return new Compiler(new CompiledClass(beeSource)).compile(); } - CompiledClass compile() { - compiledClass.getBeeClass().getConstructors().forEach(this::updateConstantPool); - compiledClass.getBeeClass().getMethods().forEach(this::updateConstantPool); + /** + * construct a CompiledClass object that contains all information for generating the bytecode + */ + public CompiledClass compile() { + compiledClass.getSource().getConstructors().forEach(this::updateConstantPool); + compiledClass.getSource().getMethods().forEach(this::updateConstantPool); // TODO update constant pool for fields ? - // TODO update constant pool for methods - constantPoolEntryCreator.addThisClass(); + compiledClass.setThisClass(constantPoolEntryCreator.addThisClass()); constantPoolEntryCreator.addInterfaces(); constantPoolEntryCreator.addFields(); return compiledClass; } - + /* + * inspect a method or constructor, extract items that need to be added, and add them to the constant pool + */ private void updateConstantPool(CodeContainer codeContainer) { codeContainer.getCode().forEach(this::updateConstantPool); } diff --git a/src/main/java/nl/sander/beejava/ConstantPoolEntryCreator.java b/src/main/java/nl/sander/beejava/ConstantPoolEntryCreator.java index ece8fdf..4a71d6b 100644 --- a/src/main/java/nl/sander/beejava/ConstantPoolEntryCreator.java +++ b/src/main/java/nl/sander/beejava/ConstantPoolEntryCreator.java @@ -2,6 +2,7 @@ package nl.sander.beejava; import nl.sander.beejava.api.CodeLine; import nl.sander.beejava.api.Ref; +import nl.sander.beejava.classinfo.FieldInfo; import nl.sander.beejava.constantpool.entry.*; import java.util.HashMap; @@ -51,13 +52,12 @@ class ConstantPoolEntryCreator { private ClassEntry getOrCreateClassEntry(CodeLine codeline) { if (codeline.hasRef()) { if (codeline.getRef() == Ref.SUPER) { //this and super are rather special - ClassEntry superClass = getClassEntry(compiledClass.getBeeClass().getSuperClass().getName()); + ClassEntry superClass = getClassEntry(compiledClass.getSource().getSuperClass().getName()); compiledClass.setSuperClass(superClass); return superClass; } else if (codeline.getRef() == Ref.THIS) { - addThisClass(); - return compiledClass.getThisClass(); + return addThisClass(); } } else if (codeline.hasClassName()) { return getClassEntry(codeline.getClassName()); @@ -66,24 +66,32 @@ class ConstantPoolEntryCreator { throw new RuntimeException("shouldn't be here"); } - void addThisClass() { - ClassEntry classEntry = getClassEntry(compiledClass.getBeeClass().getName()); + ClassEntry addThisClass() { + ClassEntry classEntry = getClassEntry(compiledClass.getSource().getName()); compiledClass.addConstantPoolEntry(classEntry); - compiledClass.setThisClass(classEntry); + return classEntry; } private ClassEntry getClassEntry(String externalClassName) { return cache(new ClassEntry(cache(new Utf8Entry(internalName(externalClassName))))); } + /* + * Adds interfaces to the constant pool as well as the class. + * + * interfaces[] in the class file is an array of cp entries + */ public void addInterfaces() { - compiledClass.getBeeClass().getInterfaces().forEach(interfase -> { + compiledClass.getSource().getInterfaces().forEach(interfase -> { ClassEntry interfaceEntry = cache(new ClassEntry(cache(new Utf8Entry(internalName(interfase.getName()))))); compiledClass.addInterface(interfaceEntry); compiledClass.addConstantPoolEntry(interfaceEntry); }); } + /* + * If a constant is in the codeline, it needs to be added to the constant pool. + */ public ConstantPoolEntry getOrCreatePrimitiveEntry(CodeLine codeline) { Object v = codeline.getConstValue(); @@ -102,9 +110,12 @@ class ConstantPoolEntryCreator { } public void addFields() { - compiledClass.getBeeClass().getFields().forEach(field -> { - // TODO - }); + compiledClass.getSource().getFields() + .forEach(f -> { + Utf8Entry name = cache(new Utf8Entry(f.getName())); + Utf8Entry descriptor = cache(new Utf8Entry(internalName(f.getType().getName()))); + compiledClass.addField(new FieldInfo(name, descriptor).addAccessFlags(f.getAccessFlags())); + }); } private String internalName(String name) { @@ -116,8 +127,7 @@ class ConstantPoolEntryCreator { // First create an object using the supplier, but if it's found in cache, return the cached entry and discard the first. // Can't check for equality unless you create a potential new entry first int hash = newEntry.hashCode(); - T a = (T) cache.computeIfAbsent(hash, k -> newEntry); - return a; + return (T) cache.computeIfAbsent(hash, k -> newEntry); // a hashmap with key hash of value is weird right? // A HashSet is a HashMap with entry: key = value, which would work, but I cannot _get_ anything from a set. } diff --git a/src/main/java/nl/sander/beejava/api/BeeConstructor.java b/src/main/java/nl/sander/beejava/api/BeeConstructor.java index a28355f..0c9b554 100644 --- a/src/main/java/nl/sander/beejava/api/BeeConstructor.java +++ b/src/main/java/nl/sander/beejava/api/BeeConstructor.java @@ -1,7 +1,7 @@ package nl.sander.beejava.api; import nl.sander.beejava.CodeContainer; -import nl.sander.beejava.flags.MethodAccessFlag; +import nl.sander.beejava.flags.MethodAccessFlags; import java.util.*; @@ -9,10 +9,10 @@ import java.util.*; * Models a constructor */ public class BeeConstructor extends CodeContainer { - private final Set accessFlags = new HashSet<>(); + private final Set accessFlags = new HashSet<>(); private final Set formalParameters = new HashSet<>(); - private BeeConstructor(Set accessFlags, + private BeeConstructor(Set accessFlags, List formalParameters, List code) { this.formalParameters.addAll(formalParameters); @@ -24,7 +24,7 @@ public class BeeConstructor extends CodeContainer { return new Builder(); } - Set getAccessFlags() { + Set getAccessFlags() { return accessFlags; } @@ -53,7 +53,7 @@ public class BeeConstructor extends CodeContainer { } public static class Builder { - private final Set accessFlags = new HashSet<>(); + private final Set accessFlags = new HashSet<>(); private final List formalParameters = new LinkedList<>(); private final List code = new LinkedList<>(); @@ -66,7 +66,7 @@ public class BeeConstructor extends CodeContainer { return this; } - public Builder withAccessFlags(MethodAccessFlag... accessFlags) { + public Builder withAccessFlags(MethodAccessFlags... accessFlags) { this.accessFlags.addAll(Arrays.asList(accessFlags)); return this; } diff --git a/src/main/java/nl/sander/beejava/api/BeeField.java b/src/main/java/nl/sander/beejava/api/BeeField.java index 1f40c91..adc6e03 100644 --- a/src/main/java/nl/sander/beejava/api/BeeField.java +++ b/src/main/java/nl/sander/beejava/api/BeeField.java @@ -1,6 +1,6 @@ package nl.sander.beejava.api; -import nl.sander.beejava.flags.FieldAccessFlag; +import nl.sander.beejava.flags.FieldAccessFlags; import java.util.Arrays; import java.util.HashSet; @@ -9,11 +9,11 @@ import java.util.Set; public class BeeField { - private final Set accessFlags = new HashSet<>(); + private final Set accessFlags = new HashSet<>(); private final Class type; private final String name; - private BeeField(Set accessFlags, Class type, String name) { + private BeeField(Set accessFlags, Class type, String name) { this.accessFlags.addAll(accessFlags); this.type = type; this.name = name; @@ -23,7 +23,7 @@ public class BeeField { return new Builder(); } - public Set getAccessFlags() { + public Set getAccessFlags() { return accessFlags; } @@ -49,7 +49,7 @@ public class BeeField { } public static class Builder { - private final Set accessFlags = new HashSet<>(); + private final Set accessFlags = new HashSet<>(); private Class type; private String name; @@ -57,7 +57,7 @@ public class BeeField { } - public BeeField.Builder withAccessFlags(FieldAccessFlag... accessFlags) { + public BeeField.Builder withAccessFlags(FieldAccessFlags... accessFlags) { this.accessFlags.addAll(Arrays.asList(accessFlags)); return this; } diff --git a/src/main/java/nl/sander/beejava/api/BeeMethod.java b/src/main/java/nl/sander/beejava/api/BeeMethod.java index 400fd66..aa0f2ba 100644 --- a/src/main/java/nl/sander/beejava/api/BeeMethod.java +++ b/src/main/java/nl/sander/beejava/api/BeeMethod.java @@ -1,16 +1,16 @@ package nl.sander.beejava.api; import nl.sander.beejava.CodeContainer; -import nl.sander.beejava.flags.MethodAccessFlag; +import nl.sander.beejava.flags.MethodAccessFlags; import java.util.*; public final class BeeMethod extends CodeContainer { - private final Set accessFlags = new HashSet<>(); + private final Set accessFlags = new HashSet<>(); private final Set formalParameters = new HashSet<>(); private final Class returnType; - private BeeMethod(Set accessFlags, + private BeeMethod(Set accessFlags, List formalParameters, Class returnType, List code) { this.accessFlags.addAll(accessFlags); @@ -24,7 +24,7 @@ public final class BeeMethod extends CodeContainer { } public static class Builder { - private final Set accessFlags = new HashSet<>(); + private final Set accessFlags = new HashSet<>(); private final List formalParameters = new LinkedList<>(); private final List code = new LinkedList<>(); private Class returnType; @@ -32,7 +32,7 @@ public final class BeeMethod extends CodeContainer { private Builder() { } - public Builder withAccessFlags(MethodAccessFlag... accessFlags) { + public Builder withAccessFlags(MethodAccessFlags... accessFlags) { this.accessFlags.addAll(Arrays.asList(accessFlags)); return this; } diff --git a/src/main/java/nl/sander/beejava/api/BeeClass.java b/src/main/java/nl/sander/beejava/api/BeeSource.java similarity index 77% rename from src/main/java/nl/sander/beejava/api/BeeClass.java rename to src/main/java/nl/sander/beejava/api/BeeSource.java index d4877b9..5dc57fd 100644 --- a/src/main/java/nl/sander/beejava/api/BeeClass.java +++ b/src/main/java/nl/sander/beejava/api/BeeSource.java @@ -1,16 +1,15 @@ package nl.sander.beejava.api; -import nl.sander.beejava.flags.ClassAccessFlag; +import nl.sander.beejava.flags.ClassAccessFlags; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Set; -public class BeeClass { +public class BeeSource { private final Version classFileVersion; private final BeePackage beePackage; - private final Set accessFlags = new HashSet<>(); + private final Set accessFlags = new HashSet<>(); private final String simpleName; private final Class superClass; private final Set> interfaces = new HashSet<>(); @@ -18,9 +17,9 @@ public class BeeClass { private final Set constructors = new HashSet<>(); private final Set methods = new HashSet<>(); - private BeeClass(Version classFileVersion, - BeePackage beePackage, Set accessFlags, String simpleName, Class superClass, - Set> interfaces, Set fields, Set constructors, Set methods) { + private BeeSource(Version classFileVersion, + BeePackage beePackage, Set accessFlags, String simpleName, Class superClass, + Set> interfaces, Set fields, Set constructors, Set methods) { this.classFileVersion = classFileVersion; this.beePackage = beePackage; this.accessFlags.addAll(accessFlags); @@ -32,7 +31,7 @@ public class BeeClass { this.methods.addAll(methods); } - public static BeeClass.Builder builder() { + public static BeeSource.Builder builder() { return new Builder(); } @@ -59,7 +58,7 @@ public class BeeClass { return methods; } - public Set getAccessFlags() { + public Set getAccessFlags() { return accessFlags; } @@ -83,7 +82,7 @@ public class BeeClass { } public static class Builder { - private final Set accessFlags = new HashSet<>(); + private final Set accessFlags = new HashSet<>(); private final Set> interfaces = new HashSet<>(); private final Set fields = new HashSet<>(); private Version version; @@ -101,17 +100,17 @@ public class BeeClass { return this; } - public BeeClass.Builder withPackage(String beePackage) { + public BeeSource.Builder withPackage(String beePackage) { this.beePackage = new BeePackage(beePackage); return this; } - public BeeClass.Builder withAccessFlags(ClassAccessFlag... accessFlags) { + public BeeSource.Builder withAccessFlags(ClassAccessFlags... accessFlags) { this.accessFlags.addAll(Arrays.asList(accessFlags)); return this; } - public BeeClass.Builder withSimpleName(String simpleName) { + public BeeSource.Builder withSimpleName(String simpleName) { this.simpleName = simpleName; return this; } @@ -141,8 +140,8 @@ public class BeeClass { return this; } - public BeeClass build() { - return new BeeClass(version, beePackage, accessFlags, simpleName, superClass, interfaces, fields, constructors, methods); + public BeeSource build() { + return new BeeSource(version, beePackage, accessFlags, simpleName, superClass, interfaces, fields, constructors, methods); } } diff --git a/src/main/java/nl/sander/beejava/classinfo/AttributeInfo.java b/src/main/java/nl/sander/beejava/classinfo/AttributeInfo.java new file mode 100644 index 0000000..089ed97 --- /dev/null +++ b/src/main/java/nl/sander/beejava/classinfo/AttributeInfo.java @@ -0,0 +1,11 @@ +package nl.sander.beejava.classinfo; + +import nl.sander.beejava.constantpool.entry.Utf8Entry; +import nl.sander.beejava.util.ByteBuf; + +public abstract class AttributeInfo { + private Utf8Entry nameEntry; + private int length; + + public abstract void addBytes(ByteBuf buf); +} diff --git a/src/main/java/nl/sander/beejava/classinfo/FieldInfo.java b/src/main/java/nl/sander/beejava/classinfo/FieldInfo.java new file mode 100644 index 0000000..68ffd2a --- /dev/null +++ b/src/main/java/nl/sander/beejava/classinfo/FieldInfo.java @@ -0,0 +1,50 @@ +package nl.sander.beejava.classinfo; + +import nl.sander.beejava.constantpool.entry.Utf8Entry; +import nl.sander.beejava.flags.AccessFlags; +import nl.sander.beejava.flags.FieldAccessFlags; +import nl.sander.beejava.util.ByteBuf; + +import java.util.HashSet; +import java.util.Set; + +public class FieldInfo { + private final Set accessFlags=new HashSet<>(); + private final Utf8Entry nameEntry; + private final Utf8Entry descriptorEntry; + private final Set attributes=new HashSet<>(); + + + public FieldInfo(Utf8Entry nameEntry, Utf8Entry descriptorEntry) { + this.nameEntry = nameEntry; + this.descriptorEntry = descriptorEntry; + } + public FieldInfo addAccessFlags(Set accessFlags){ + this.accessFlags.addAll(accessFlags); + return this; + } + + public Set getAccessFlags() { + return accessFlags; + } + + public Utf8Entry getNameEntry() { + return nameEntry; + } + + public Utf8Entry getDescriptorEntry() { + return descriptorEntry; + } + + public Set getAttributes() { + return attributes; + } + + public void addBytes(ByteBuf buf) { + buf.addU16(AccessFlags.combine(accessFlags)); + buf.addU16(nameEntry.getIndex()); + buf.addU16(descriptorEntry.getIndex()); + buf.addU16(attributes.size()); + attributes.forEach(ai -> ai.addBytes(buf)); + } +} diff --git a/src/main/java/nl/sander/beejava/constantpool/ConstantPool.java b/src/main/java/nl/sander/beejava/constantpool/ConstantPool.java index 5263ad2..39aa3bb 100644 --- a/src/main/java/nl/sander/beejava/constantpool/ConstantPool.java +++ b/src/main/java/nl/sander/beejava/constantpool/ConstantPool.java @@ -7,10 +7,12 @@ import java.util.ArrayList; public class ConstantPool extends ArrayList{ - public byte[] getBytes() { - ByteBuf bytes = new ByteBuf(); - forEach(entry -> bytes.addU8(entry.getBytes())); - return bytes.toBytes(); + /** + * Add the bytes for all entries to the given ByteBuf + * @param buf the buffer that will contain the bytes for the constant pool + */ + public void addTo(ByteBuf buf) { + forEach(entry -> buf.addU8(entry.getBytes())); } /** diff --git a/src/main/java/nl/sander/beejava/flags/AccessFlag.java b/src/main/java/nl/sander/beejava/flags/AccessFlag.java deleted file mode 100644 index f72a126..0000000 --- a/src/main/java/nl/sander/beejava/flags/AccessFlag.java +++ /dev/null @@ -1,13 +0,0 @@ -package nl.sander.beejava.flags; - -import java.util.Set; - -// TODO all access flags can be moved together -public interface AccessFlag { - - int getBytecode(); - - default int getCombineBytecode(Set accessflags) { - return accessflags.stream().mapToInt(AccessFlag::getBytecode).sum(); - } -} diff --git a/src/main/java/nl/sander/beejava/flags/AccessFlags.java b/src/main/java/nl/sander/beejava/flags/AccessFlags.java new file mode 100644 index 0000000..cedd1c3 --- /dev/null +++ b/src/main/java/nl/sander/beejava/flags/AccessFlags.java @@ -0,0 +1,12 @@ +package nl.sander.beejava.flags; + +import java.util.Collection; + +public interface AccessFlags { + static int combine(Collection flags) { + return flags.stream().mapToInt(AccessFlags::getBytecode).reduce(0, (result, value) -> result | value); + } + + int getBytecode(); + +} diff --git a/src/main/java/nl/sander/beejava/flags/ClassAccessFlag.java b/src/main/java/nl/sander/beejava/flags/ClassAccessFlags.java similarity index 72% rename from src/main/java/nl/sander/beejava/flags/ClassAccessFlag.java rename to src/main/java/nl/sander/beejava/flags/ClassAccessFlags.java index 92f6af8..740a169 100644 --- a/src/main/java/nl/sander/beejava/flags/ClassAccessFlag.java +++ b/src/main/java/nl/sander/beejava/flags/ClassAccessFlags.java @@ -1,8 +1,6 @@ package nl.sander.beejava.flags; -import java.util.Collection; - -public enum ClassAccessFlag implements AccessFlag { +public enum ClassAccessFlags implements AccessFlags { PUBLIC(0x0001), // Declared public; may be accessed from outside its package. FINAL(0x0010), // Declared final; no subclasses allowed. SUPER(0x0020), // Treat superclass methods specially when invoked by the invokespecial instruction. @@ -16,13 +14,11 @@ public enum ClassAccessFlag implements AccessFlag { private final int bytecode; - ClassAccessFlag(int bytecode) { + ClassAccessFlags(int bytecode) { this.bytecode = bytecode; } - public static int getSum(Collection flags) { - return flags.stream().mapToInt(ClassAccessFlag::getBytecode).reduce(0, (result, value) -> result | value); - } + @Override public int getBytecode() { diff --git a/src/main/java/nl/sander/beejava/flags/FieldAccessFlag.java b/src/main/java/nl/sander/beejava/flags/FieldAccessFlags.java similarity index 87% rename from src/main/java/nl/sander/beejava/flags/FieldAccessFlag.java rename to src/main/java/nl/sander/beejava/flags/FieldAccessFlags.java index 235e246..3038899 100644 --- a/src/main/java/nl/sander/beejava/flags/FieldAccessFlag.java +++ b/src/main/java/nl/sander/beejava/flags/FieldAccessFlags.java @@ -1,8 +1,6 @@ package nl.sander.beejava.flags; -import nl.sander.beejava.flags.AccessFlag; - -public enum FieldAccessFlag implements AccessFlag { +public enum FieldAccessFlags implements AccessFlags { PUBLIC(0x0001), // Declared public; may be accessed from outside itspackage. PRIVATE(0x0002), // Declared private; accessible only within the defining class and other classes belonging to the samenest (§5.4.4). PROTECTED(0x0004), // Declared protected; may be accessed within subclasses. @@ -15,7 +13,7 @@ public enum FieldAccessFlag implements AccessFlag { private final int bytecode; - FieldAccessFlag(int bytecode) { + FieldAccessFlags(int bytecode) { this.bytecode = bytecode; } diff --git a/src/main/java/nl/sander/beejava/flags/MethodAccessFlag.java b/src/main/java/nl/sander/beejava/flags/MethodAccessFlags.java similarity index 89% rename from src/main/java/nl/sander/beejava/flags/MethodAccessFlag.java rename to src/main/java/nl/sander/beejava/flags/MethodAccessFlags.java index 9136c0d..9ca0a77 100644 --- a/src/main/java/nl/sander/beejava/flags/MethodAccessFlag.java +++ b/src/main/java/nl/sander/beejava/flags/MethodAccessFlags.java @@ -1,8 +1,6 @@ package nl.sander.beejava.flags; -import nl.sander.beejava.flags.AccessFlag; - -public enum MethodAccessFlag implements AccessFlag { +public enum MethodAccessFlags implements AccessFlags { PUBLIC(0x0001), // Declared public; may be accessed from outside its package. PRIVATE(0x0002), // Declared private; accessible only within the defining class and other classes belonging to the same nest (§5.4.4). PROTECTED(0x0004), // Declared protected; may be accessed within subclasses. @@ -18,7 +16,7 @@ public enum MethodAccessFlag implements AccessFlag { private final int bytecode; - MethodAccessFlag(int bytecode) { + MethodAccessFlags(int bytecode) { this.bytecode = bytecode; } diff --git a/src/test/java/nl/sander/beejava/BytecodeGeneratorTests.java b/src/test/java/nl/sander/beejava/BytecodeGeneratorTests.java index d8c194b..7388a67 100644 --- a/src/test/java/nl/sander/beejava/BytecodeGeneratorTests.java +++ b/src/test/java/nl/sander/beejava/BytecodeGeneratorTests.java @@ -21,4 +21,9 @@ public class BytecodeGeneratorTests { public void testInterface() { BytecodeGenerator.generate(Compiler.compile(TestData.emptyClassWithInterface())); } + + @Test + public void testFields() { + BytecodeGenerator.generate(Compiler.compile(TestData.createClassWithField(int.class))); + } } diff --git a/src/test/java/nl/sander/beejava/CompilerTests.java b/src/test/java/nl/sander/beejava/CompilerTests.java index f3e6b85..ae54faa 100644 --- a/src/test/java/nl/sander/beejava/CompilerTests.java +++ b/src/test/java/nl/sander/beejava/CompilerTests.java @@ -16,7 +16,7 @@ public class CompilerTests { @Test // This is not a maintainable test public void testMethodRefEntryForSuperConstructor() { // Arrange - BeeClass classWithIntField = TestData.emptyClass(); + BeeSource classWithIntField = TestData.emptyClass(); // Act CompiledClass compiledClass = Compiler.compile(classWithIntField); diff --git a/src/test/java/nl/sander/beejava/ConstantPoolUniquenessTests.java b/src/test/java/nl/sander/beejava/ConstantPoolUniquenessTests.java index b0cc285..134dd6d 100644 --- a/src/test/java/nl/sander/beejava/ConstantPoolUniquenessTests.java +++ b/src/test/java/nl/sander/beejava/ConstantPoolUniquenessTests.java @@ -1,6 +1,6 @@ package nl.sander.beejava; -import nl.sander.beejava.api.BeeClass; +import nl.sander.beejava.api.BeeSource; import nl.sander.beejava.constantpool.ConstantPool; import nl.sander.beejava.constantpool.entry.ClassEntry; import org.junit.jupiter.api.Test; @@ -14,7 +14,7 @@ public class ConstantPoolUniquenessTests { @Test public void test() { // Arrange - BeeClass someClass = TestData.createClassWithTwoReferencesToSomeClass(); + BeeSource someClass = TestData.createClassWithTwoReferencesToSomeClass(); // Act CompiledClass compiledClass = Compiler.compile(someClass); diff --git a/src/test/java/nl/sander/beejava/TestData.java b/src/test/java/nl/sander/beejava/TestData.java index 6b51390..13f64ac 100644 --- a/src/test/java/nl/sander/beejava/TestData.java +++ b/src/test/java/nl/sander/beejava/TestData.java @@ -1,18 +1,18 @@ package nl.sander.beejava; import nl.sander.beejava.api.*; -import nl.sander.beejava.flags.FieldAccessFlag; -import nl.sander.beejava.flags.MethodAccessFlag; +import nl.sander.beejava.flags.FieldAccessFlags; +import nl.sander.beejava.flags.MethodAccessFlags; import java.io.Serializable; import static nl.sander.beejava.api.CodeLine.line; import static nl.sander.beejava.api.Opcode.*; -import static nl.sander.beejava.flags.ClassAccessFlag.PUBLIC; +import static nl.sander.beejava.flags.ClassAccessFlags.PUBLIC; public class TestData { - public static BeeClass emptyClass() { - return BeeClass.builder() + public static BeeSource emptyClass() { + return BeeSource.builder() .withClassFileVersion(Version.V14) .withPackage("nl.sander.beejava.test") .withAccessFlags(PUBLIC) @@ -22,8 +22,8 @@ public class TestData { .build(); } - public static BeeClass emptyClassWithInterface() { - return BeeClass.builder() + public static BeeSource emptyClassWithInterface() { + return BeeSource.builder() .withClassFileVersion(Version.V14) .withPackage("nl.sander.beejava.test") .withAccessFlags(PUBLIC) @@ -34,9 +34,9 @@ public class TestData { .build(); } - public static BeeClass createClassWithTwoReferencesToSomeClass() { + public static BeeSource createClassWithTwoReferencesToSomeClass() { BeeMethod print1 = BeeMethod.builder() - .withAccessFlags(MethodAccessFlag.PUBLIC) + .withAccessFlags(MethodAccessFlags.PUBLIC) .withCode( line(0, GET, "java.lang.System","out"), line(1, LD_CONST, "1"), @@ -45,7 +45,7 @@ public class TestData { .build(); BeeMethod print2 = BeeMethod.builder() - .withAccessFlags(MethodAccessFlag.PUBLIC) + .withAccessFlags(MethodAccessFlags.PUBLIC) .withCode( line(0, GET, "java.lang.System","out"), line(1, LD_CONST, "2"), @@ -53,7 +53,7 @@ public class TestData { line(3, RETURN)) .build(); - return BeeClass.builder() + return BeeSource.builder() .withClassFileVersion(Version.V14) .withPackage("nl.sander.beejava.test") .withAccessFlags(PUBLIC) @@ -63,9 +63,9 @@ public class TestData { .build(); } - public static BeeClass createClassWithField(Class fieldType) { + public static BeeSource createClassWithField(Class fieldType) { BeeField field = BeeField.builder() - .withAccessFlags(FieldAccessFlag.PRIVATE) + .withAccessFlags(FieldAccessFlags.PRIVATE) .withType(fieldType) .withName("field") .build(); @@ -73,7 +73,7 @@ public class TestData { BeeParameter parameter = BeeParameter.create(fieldType, "value"); BeeConstructor constructor = BeeConstructor.builder() - .withAccessFlags(MethodAccessFlag.PUBLIC) + .withAccessFlags(MethodAccessFlags.PUBLIC) .withFormalParameters(parameter) .withCode( line(0, LD_VAR, Ref.THIS), @@ -84,7 +84,7 @@ public class TestData { line(5, RETURN)) .build(); - return BeeClass.builder() + return BeeSource.builder() .withClassFileVersion(Version.V14) .withPackage("nl.sander.beejava.test") .withAccessFlags(PUBLIC) @@ -97,7 +97,7 @@ public class TestData { private static BeeConstructor createConstructor() { return BeeConstructor.builder() - .withAccessFlags(MethodAccessFlag.PUBLIC) + .withAccessFlags(MethodAccessFlags.PUBLIC) .withCode( line(0, LD_VAR, Ref.THIS), line(1, INVOKE, Ref.SUPER, "", "()"), diff --git a/src/test/java/nl/sander/beejava/TypeMapperTest.java b/src/test/java/nl/sander/beejava/TypeMapperTest.java index 8468404..a31f18a 100644 --- a/src/test/java/nl/sander/beejava/TypeMapperTest.java +++ b/src/test/java/nl/sander/beejava/TypeMapperTest.java @@ -1,6 +1,6 @@ package nl.sander.beejava; -import nl.sander.beejava.api.BeeClass; +import nl.sander.beejava.api.BeeSource; import nl.sander.beejava.constantpool.ConstantPool; import nl.sander.beejava.constantpool.entry.NameAndTypeEntry; import org.junit.jupiter.api.Test; @@ -13,10 +13,10 @@ public class TypeMapperTest { @Test public void test_int() { // Arrange - BeeClass beeClass = TestData.createClassWithField(int.class); + BeeSource beeSource = TestData.createClassWithField(int.class); // Act - ConstantPool constantPool = createConstantPool(beeClass); + ConstantPool constantPool = createConstantPool(beeSource); // Assert NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); @@ -26,10 +26,10 @@ public class TypeMapperTest { @Test public void test_double() { // Arrange - BeeClass beeClass = TestData.createClassWithField(double.class); + BeeSource beeSource = TestData.createClassWithField(double.class); // Act - ConstantPool constantPool = createConstantPool(beeClass); + ConstantPool constantPool = createConstantPool(beeSource); // Assert NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); @@ -39,10 +39,10 @@ public class TypeMapperTest { @Test public void test_float() { // Arrange - BeeClass beeClass = TestData.createClassWithField(float.class); + BeeSource beeSource = TestData.createClassWithField(float.class); // Act - ConstantPool constantPool = createConstantPool(beeClass); + ConstantPool constantPool = createConstantPool(beeSource); // Assert NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); @@ -52,10 +52,10 @@ public class TypeMapperTest { @Test public void test_byte() { // Arrange - BeeClass beeClass = TestData.createClassWithField(byte.class); + BeeSource beeSource = TestData.createClassWithField(byte.class); // Act - ConstantPool constantPool = createConstantPool(beeClass); + ConstantPool constantPool = createConstantPool(beeSource); // Assert NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); @@ -65,10 +65,10 @@ public class TypeMapperTest { @Test public void test_short() { // Arrange - BeeClass beeClass = TestData.createClassWithField(short.class); + BeeSource beeSource = TestData.createClassWithField(short.class); // Act - ConstantPool constantPool = createConstantPool(beeClass); + ConstantPool constantPool = createConstantPool(beeSource); // Assert NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); @@ -78,10 +78,10 @@ public class TypeMapperTest { @Test public void test_long() { // Arrange - BeeClass beeClass = TestData.createClassWithField(long.class); + BeeSource beeSource = TestData.createClassWithField(long.class); // Act - ConstantPool constantPool = createConstantPool(beeClass); + ConstantPool constantPool = createConstantPool(beeSource); // Assert NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); @@ -91,10 +91,10 @@ public class TypeMapperTest { @Test public void test_char() { // Arrange - BeeClass beeClass = TestData.createClassWithField(char.class); + BeeSource beeSource = TestData.createClassWithField(char.class); // Act - ConstantPool constantPool = createConstantPool(beeClass); + ConstantPool constantPool = createConstantPool(beeSource); // Assert NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); @@ -104,10 +104,10 @@ public class TypeMapperTest { @Test public void test_boolean() { // Arrange - BeeClass beeClass = TestData.createClassWithField(boolean.class); + BeeSource beeSource = TestData.createClassWithField(boolean.class); // Act - ConstantPool constantPool = createConstantPool(beeClass); + ConstantPool constantPool = createConstantPool(beeSource); // Assert NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); @@ -117,10 +117,10 @@ public class TypeMapperTest { @Test public void test_Object() { // Arrange - BeeClass beeClass = TestData.createClassWithField(Object.class); + BeeSource beeSource = TestData.createClassWithField(Object.class); // Act - ConstantPool constantPool = createConstantPool(beeClass); + ConstantPool constantPool = createConstantPool(beeSource); // Assert NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); @@ -130,10 +130,10 @@ public class TypeMapperTest { @Test public void test_int_array() { // Arrange - BeeClass beeClass = TestData.createClassWithField(int[].class); + BeeSource beeSource = TestData.createClassWithField(int[].class); // Act - ConstantPool constantPool = createConstantPool(beeClass); + ConstantPool constantPool = createConstantPool(beeSource); // Assert NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); @@ -143,18 +143,18 @@ public class TypeMapperTest { @Test public void test_Object_array() { // Arrange - BeeClass beeClass = TestData.createClassWithField(String[].class); + BeeSource beeSource = TestData.createClassWithField(String[].class); // Act - ConstantPool constantPool = createConstantPool(beeClass); + ConstantPool constantPool = createConstantPool(beeSource); // Assert NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); assertEquals("[Ljava/lang/String;", fieldEntry.getType()); } - private ConstantPool createConstantPool(BeeClass beeClass) { - CompiledClass compiledClass = Compiler.compile(beeClass); + private ConstantPool createConstantPool(BeeSource beeSource) { + CompiledClass compiledClass = Compiler.compile(beeSource); return ConstantPoolCreator.create(compiledClass.getConstantTree()); } diff --git a/src/test/java/nl/sander/beejava/flags/ClassAccessFlagTest.java b/src/test/java/nl/sander/beejava/flags/ClassAccessFlagTest.java deleted file mode 100644 index 7f868f6..0000000 --- a/src/test/java/nl/sander/beejava/flags/ClassAccessFlagTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package nl.sander.beejava.flags; - -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 test_mustOr1Value() { - assertEquals(1, ClassAccessFlag.getSum(Collections.singletonList(ClassAccessFlag.PUBLIC))); - } - - @Test - public void test_mustOr2Values() { - assertEquals(17, ClassAccessFlag.getSum(Arrays.asList(ClassAccessFlag.PUBLIC, ClassAccessFlag.FINAL))); - } - - - -} diff --git a/src/test/java/nl/sander/beejava/flags/ClassAccessFlagsTest.java b/src/test/java/nl/sander/beejava/flags/ClassAccessFlagsTest.java new file mode 100644 index 0000000..0db09cb --- /dev/null +++ b/src/test/java/nl/sander/beejava/flags/ClassAccessFlagsTest.java @@ -0,0 +1,22 @@ +package nl.sander.beejava.flags; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ClassAccessFlagsTest { + @Test + public void test_mustOr1Value() { + assertEquals(1, AccessFlags.combine(List.of(ClassAccessFlags.PUBLIC))); + } + + @Test + public void test_mustOr2Values() { + assertEquals(17, AccessFlags.combine(List.of(ClassAccessFlags.PUBLIC, ClassAccessFlags.FINAL))); + } + + + +}