pulled {Method,Member,Field}Ref into Type.Class; made them inner classes; much cleaner
[org.ibex.classgen.git] / src / org / ibex / classgen / CPGen.java
index 08bb904..edc4d9c 100644 (file)
@@ -17,9 +17,6 @@ class CPGen {
     
     CPGen() { }
     
-    /*
-     * Entries 
-     */
     public abstract class Ent {
         int n; // this is the refcount if state == OPEN, index if >= STABLE
         int tag;
@@ -28,21 +25,21 @@ class CPGen {
         
         void dump(DataOutput o) throws IOException { o.writeByte(tag); }
         String debugToString() { return toString(); } // so we can remove this method when not debugging
-        abstract Object key() throws ClassGen.ClassReadExn; // be careful using this, it drags in a bunch of code
+        abstract Object key() throws ClassFile.ClassReadExn; // be careful using this, it drags in a bunch of code
     }
     
-    // INVARIANTS: tag == 3 || tag == 4
     class IntEnt extends Ent {
-        int i;
-        IntEnt(int tag) { super(tag); }
+        final int i;
+        IntEnt(int i) { super(3); this.i = i; }
         void dump(DataOutput o) throws IOException { super.dump(o); o.writeInt(i);  }
-        Object key() {
-            switch(tag) {
-                case 3: return new Integer(i);
-                case 4: return new Float(Float.intBitsToFloat(i));
-                default: throw new Error("should never happen");
-            }
-        }
+        Object key() { return new Integer(i); }
+    }
+
+    class FloatEnt extends Ent {
+        final float f;
+        FloatEnt(float f) { super(4); this.f = f; }
+        void dump(DataOutput o) throws IOException { super.dump(o); o.writeFloat(f);  }
+        Object key() { return new Float(f); }
     }
     
     // INVARIANTS: tag == 5 || tag == 6
@@ -84,20 +81,20 @@ class CPGen {
         }
         
         private String fixme() { throw new Error("fixme"); }
-        Object key() throws ClassGen.ClassReadExn {
+        Object key() throws ClassFile.ClassReadExn {
             switch(tag) {
                 case 7: return Type.instance(((Utf8Ent)e1).s);
                 case 8: return (((Utf8Ent)e1).s);
                 case 9: {
                     NameAndTypeKey nt = (NameAndTypeKey) e2.key();
                     Type t = Type.instance(nt.type);
-                    if(t == null) throw new ClassGen.ClassReadExn("invalid type descriptor");
-                    return new FieldRef((Type.Class)e1.key(), nt.name, t);
+                    if(t == null) throw new ClassFile.ClassReadExn("invalid type descriptor");
+                    return ((Type.Class)e1.key()).field(nt.name, t);
                 }
                 case 10: case 11: {
                     NameAndTypeKey nt = (NameAndTypeKey) e2.key();
                     if (e1.key() == null) throw new Error(e1.tag + " => " + e1.key());
-                    return new MethodRef((Type.Class)e1.key(), "methodname", Type.VOID, new Type[0]); // FIXME FIXME
+                    return ((Type.Class)e1.key()).method("methodname", Type.VOID, new Type[0]); // FIXME FIXME
                 }
                 case 12: {
                     return new NameAndTypeKey(((Utf8Ent)e1).s, ((Utf8Ent)e2).s); 
@@ -163,7 +160,7 @@ class CPGen {
         return ent.n;
     }
 
-    public final Type getType(int index) throws ClassGen.ClassReadExn {
+    public final Type getType(int index) throws ClassFile.ClassReadExn {
         Ent e = getByIndex(index);
         if (e instanceof Utf8Ent) return Type.instance(((Utf8Ent)e).s);
         else return (Type)e.key();
@@ -180,7 +177,8 @@ class CPGen {
     public final Ent addNameAndType(String name, String descriptor) { return add(new NameAndTypeKey(name, descriptor)); }
     public final Ent addUtf8(String s) { return add(new Utf8Key(s)); }
     
-    public final Ent add(Object o) {
+    public final Ent add(Object o) { return add(o, false); }
+    public final Ent add(Object o, boolean invokeInterface) {
         if(state == SEALED) throw new IllegalStateException("constant pool is sealed");
             
         Ent ent = get(o);
@@ -197,14 +195,8 @@ class CPGen {
             CPRefEnt ce = new CPRefEnt(8);
             ce.e1 = addUtf8((String)o);
             ent = ce;
-        } else if(o instanceof Integer) {
-            IntEnt ue = new IntEnt(3);
-            ue.i = ((Integer)o).intValue();
-            ent = ue;
-        } else if(o instanceof Float) {
-            IntEnt ue = new IntEnt(4);
-            ue.i = Float.floatToIntBits(((Float)o).floatValue());
-            ent = ue;
+        } else if(o instanceof Integer) {  ent = new IntEnt(((Integer)o).intValue());
+        } else if(o instanceof Float) {    ent = new FloatEnt(((Float)o).floatValue());
         } else if(o instanceof Long) {
             LongEnt le = new LongEnt(5);
             le.l = ((Long)o).longValue();
@@ -223,20 +215,20 @@ class CPGen {
             ce.e1 = addUtf8(key.name);
             ce.e2 = addUtf8(key.type);
             ent = ce;
-        } else if(o instanceof ClassGen.FieldOrMethodRef) {
-            ClassGen.FieldOrMethodRef key = (ClassGen.FieldOrMethodRef) o;
-            int tag = o instanceof FieldRef ? 9 : o instanceof MethodRef ? 10 : o instanceof MethodRef.I ? 11 : 0;
+        } else if(o instanceof Type.Class.Member) {
+            Type.Class.Member key = (Type.Class.Member) o;
+            int tag = invokeInterface ? 11 : o instanceof Type.Class.Field ? 9 : o instanceof Type.Class.Method ? 10 : 0;
             if(tag == 0) throw new Error("should never happen");
             CPRefEnt ce = new CPRefEnt(tag);
-            ce.e1 = add(key.klass);
-            ce.e2 = addNameAndType(key.name, key.descriptor);
+            ce.e1 = add(key.getDeclaringClass());
+            ce.e2 = addNameAndType(key.name, key.getDescriptor());
             ent = ce;
         } else {
             throw new IllegalArgumentException("Unknown type passed to add");
         }
         
         int spaces = ent instanceof LongEnt ? 2 : 1;        
-        if(usedSlots + spaces > 65536) throw new ClassGen.Exn("constant pool full");
+        if(usedSlots + spaces > 65536) throw new ClassFile.Exn("constant pool full");
         
         ent.n = state == OPEN ? 1 : usedSlots; // refcount or index
 
@@ -318,9 +310,9 @@ class CPGen {
         }
     }
     
-    CPGen(DataInput in) throws ClassGen.ClassReadExn, IOException {
+    CPGen(DataInput in) throws ClassFile.ClassReadExn, IOException {
         usedSlots = in.readUnsignedShort();
-        if(usedSlots==0) throw new ClassGen.ClassReadExn("invalid used slots");
+        if(usedSlots==0) throw new ClassFile.ClassReadExn("invalid used slots");
         
         // these are to remember the CPRefEnt e1 and e2s we have to fix up
         int[] e1s = new int[usedSlots];
@@ -334,8 +326,8 @@ class CPGen {
             switch(tag) {
                 case 7: // Object Type
                 case 8: // String
-                case 9: // FieldRef
-                case 10: // MethodRef
+                case 9: // Type.Class.Field
+                case 10: // Type.Class.Method
                 case 11: // Instance Method Ref
                 case 12: // NameAndType
                 {
@@ -345,11 +337,15 @@ class CPGen {
                     break;
                 }
                 case 3: // Integer
+                {
+                    FloatEnt ie;
+                    e = ie = new FloatEnt(in.readFloat());
+                    break;
+                }
                 case 4: // Float
                 {
                     IntEnt ie;
-                    e = ie = new IntEnt(tag);
-                    ie.i = in.readInt();
+                    e = ie = new IntEnt(in.readInt());
                     break;
                 }
                 case 5: // Long
@@ -368,7 +364,7 @@ class CPGen {
                     break;
                 }
                 default:
-                    throw new ClassGen.ClassReadExn("invalid cp ent tag");
+                    throw new ClassFile.ClassReadExn("invalid cp ent tag");
             }
             entriesByIndex[index] = e;
             if (e instanceof LongEnt) index++;
@@ -384,30 +380,30 @@ class CPGen {
             }
             if (!(e instanceof CPRefEnt)) continue;
             CPRefEnt ce = (CPRefEnt) e;
-            if(e1s[i] == 0 || e1s[i] >= usedSlots) throw new ClassGen.ClassReadExn("invalid cp index");
+            if(e1s[i] == 0 || e1s[i] >= usedSlots) throw new ClassFile.ClassReadExn("invalid cp index");
             ce.e1 = entriesByIndex[e1s[i]];
-            if(ce.e1 == null)  throw new ClassGen.ClassReadExn("invalid cp index");
+            if(ce.e1 == null)  throw new ClassFile.ClassReadExn("invalid cp index");
             if(ce.tag != 7 && ce.tag != 8) {
-                if(e2s[i] == 0 || e2s[i] >= usedSlots) throw new ClassGen.ClassReadExn("invalid cp index");
+                if(e2s[i] == 0 || e2s[i] >= usedSlots) throw new ClassFile.ClassReadExn("invalid cp index");
                 ce.e2 = entriesByIndex[e2s[i]];
-                if(ce.e2 == null)  throw new ClassGen.ClassReadExn("invalid cp index");
+                if(ce.e2 == null)  throw new ClassFile.ClassReadExn("invalid cp index");
             }
             switch(ce.tag) {
                 case 7:
                 case 8:
-                    if(!(ce.e1 instanceof Utf8Ent)) throw new ClassGen.ClassReadExn("expected a utf8 ent");
+                    if(!(ce.e1 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a utf8 ent");
                     break;
                 case 9:
                 case 10:
                 case 11:
                     if(!(ce.e1 instanceof CPRefEnt) || ((CPRefEnt)ce.e1).tag != 7)
-                        throw new ClassGen.ClassReadExn("expected a type ent");
+                        throw new ClassFile.ClassReadExn("expected a type ent");
                     if(!(ce.e2 instanceof CPRefEnt) || ((CPRefEnt)ce.e2).tag != 12)
-                        throw new ClassGen.ClassReadExn("expected a name and type ent");
+                        throw new ClassFile.ClassReadExn("expected a name and type ent");
                     break;
                 case 12:
-                    if(!(ce.e1 instanceof Utf8Ent)) throw new ClassGen.ClassReadExn("expected a utf8 ent");
-                    if(!(ce.e2 instanceof Utf8Ent)) throw new ClassGen.ClassReadExn("expected a utf8 ent");
+                    if(!(ce.e1 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a utf8 ent");
+                    if(!(ce.e2 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a utf8 ent");
                     break;
             }
         }