pulled {Method,Member,Field}Ref into Type.Class; made them inner classes; much cleaner
[org.ibex.classgen.git] / src / org / ibex / classgen / MethodGen.java
index 88c35bb..ba055bf 100644 (file)
@@ -4,20 +4,21 @@ import java.io.*;
 import java.util.*;
 
 /** A class representing a method in a generated classfile
-    @see ClassGen#addMethod */
+    @see ClassFile#addMethod */
 public class MethodGen implements CGConst {
     private final static boolean EMIT_NOPS = false;
     
     private static final int NO_CODE = -1;
     private static final int FINISHED = -2;
-    
+
+    private final ClassFile owner;
     private final CPGen cp;
     private final String name;
     private final Type ret;
     private final Type[] args;
     private final int flags;
-    private final ClassGen.AttrGen attrs;
-    private final ClassGen.AttrGen codeAttrs;
+    private final ClassFile.AttrGen attrs;
+    private final ClassFile.AttrGen codeAttrs;
     private final Hashtable exnTable = new Hashtable();
     private final Hashtable thrownExceptions = new Hashtable();
     
@@ -29,8 +30,41 @@ public class MethodGen implements CGConst {
     private byte[] op;
     private Object[] arg;
     
-    MethodGen(DataInput in) { throw new Error("Brian is lame"); }
-    MethodGen(ClassGen owner, String name, Type ret, Type[] args, int flags) {
+    public String toString() { StringBuffer sb = new StringBuffer(); toString(sb, "<init>"); return sb.toString(); }
+    public void   toString(StringBuffer sb, String constructorName) {
+        sb.append(ClassFile.flagsToString(flags));
+        sb.append(ret);
+        sb.append(" ");
+
+        if (name.equals("<clinit>")) sb.append("static ");
+        else {
+            if (name.equals("<init>")) sb.append(constructorName);
+            else sb.append(name);
+            sb.append("(");
+            for(int i=0; i<args.length; i++)
+                sb.append((i==0?"":", ")+args[i]);
+            sb.append(") ");
+        }
+        sb.append("{");
+        sb.append("}");
+        // FIXME: attrs, body
+    }
+
+    MethodGen(CPGen cp, DataInput in, ClassFile owner) throws IOException {
+        this.cp = cp;
+        this.owner = owner;
+        flags = in.readShort();
+        name = cp.getUtf8ByIndex(in.readShort());
+        String descriptor = cp.getUtf8ByIndex(in.readShort());
+        String ret = descriptor.substring(descriptor.indexOf(')')+1);
+        this.ret = Type.instance(ret);
+        //String args = descriptor.substring(1, descriptor.indexOf(')'));
+        args = new Type[0]; // FIXME
+        codeAttrs = null;
+        attrs = new ClassFile.AttrGen(cp, in);
+    }
+
+    MethodGen(ClassFile owner, String name, Type ret, Type[] args, int flags) {
         if((flags & ~(ACC_PUBLIC|ACC_PRIVATE|ACC_PROTECTED|ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE|ACC_ABSTRACT|ACC_STRICT)) != 0)
             throw new IllegalArgumentException("invalid flags");
         this.cp = owner.cp;
@@ -38,21 +72,19 @@ public class MethodGen implements CGConst {
         this.ret = ret;
         this.args = args;
         this.flags = flags;
+        this.owner = owner;
         
-        attrs = new ClassGen.AttrGen(cp);
-        codeAttrs = new ClassGen.AttrGen(cp);
+        attrs = new ClassFile.AttrGen(cp);
+        codeAttrs = new ClassFile.AttrGen(cp);
         
         cp.addUtf8(name);
-        cp.addUtf8(getDescriptor());
+        cp.addUtf8(owner.getType().method(name, ret, args).getDescriptor());
         
         if((owner.flags & ACC_INTERFACE) != 0 || (flags & (ACC_ABSTRACT|ACC_NATIVE)) != 0) size = capacity = -1;
         
         maxLocals = Math.max(args.length + (flags&ACC_STATIC)==0 ? 1 : 0, 4);
     }
     
-    /** Returns the descriptor string for this method */
-    public String getDescriptor() { return MethodRef.getDescriptor(ret, args); }
-    
     private class ExnTableEnt {
         public int start;
         public int end;
@@ -78,7 +110,7 @@ public class MethodGen implements CGConst {
         @param handler The instruction of the excepton handler
         @param type The type of exception that is to be handled (MUST inherit from Throwable)
     */
-    public final void addExceptionHandler(int start, int end, int handler, Type.Object type) {
+    public final void addExceptionHandler(int start, int end, int handler, Type.Class type) {
         exnTable.put(type, new ExnTableEnt(start, end, handler, cp.add(type)));
     }
     
@@ -86,7 +118,7 @@ public class MethodGen implements CGConst {
         NOTE: This isn't enforced by the JVM. This is for reference only. A method can throw exceptions not declared to be thrown 
         @param type The type of exception that can be thrown 
     */
-    public final void addThrow(Type.Object type) {
+    public final void addThrow(Type.Class type) {
         thrownExceptions.put(type, cp.add(type));
     }
     
@@ -243,13 +275,15 @@ public class MethodGen implements CGConst {
                 
                 if(arg instanceof Long || arg instanceof Double) op = LDC2_W;
                 break;
-            case INVOKEINTERFACE:
-                if(arg instanceof MethodRef) arg = new MethodRef.I((MethodRef)arg);
+            case INVOKEINTERFACE: {
                 break;
+            }
         }
         int opdata = OP_DATA[op&0xff];
-        if((opdata&OP_CPENT_FLAG) != 0 && !(arg instanceof CPGen.Ent))
-            arg = cp.add(arg);
+        if((opdata&OP_CPENT_FLAG) != 0 && !(arg instanceof CPGen.Ent)) {
+            if (op==INVOKEINTERFACE) arg = cp.add(arg, true);
+            else arg = cp.add(arg);
+        }
         else if((opdata&OP_VALID_FLAG) == 0)
             throw new IllegalArgumentException("unknown bytecode");
         this.op[pos] = op;
@@ -479,7 +513,7 @@ public class MethodGen implements CGConst {
         }
         int codeSize = p;
         
-        if(codeSize >= 65536) throw new ClassGen.Exn("method too large in size");
+        if(codeSize >= 65536) throw new ClassFile.Exn("method too large in size");
         
         o.writeShort(maxStack);
         o.writeShort(maxLocals);
@@ -501,7 +535,7 @@ public class MethodGen implements CGConst {
             switch(op) {
                 case IINC: {
                     Pair pair = (Pair) arg;
-                    if(pair.i1 > 255 || pair.i2 < -128 || pair.i2 > 127) throw new ClassGen.Exn("overflow of iinc arg"); 
+                    if(pair.i1 > 255 || pair.i2 < -128 || pair.i2 > 127) throw new ClassFile.Exn("overflow of iinc arg"); 
                     o.writeByte(pair.i1);
                     o.writeByte(pair.i2);
                     break;
@@ -539,7 +573,7 @@ public class MethodGen implements CGConst {
                     if((opdata & OP_BRANCH_FLAG) != 0) {
                         int v = pc[((Integer)arg).intValue()] - pc[i];
                         if(argLength == 2) {
-                            if(v < -32768 || v > 32767) throw new ClassGen.Exn("overflow of s2 offset");
+                            if(v < -32768 || v > 32767) throw new ClassFile.Exn("overflow of s2 offset");
                             o.writeShort(v);
                         } else if(argLength == 4) {
                             o.writeInt(v);
@@ -556,10 +590,10 @@ public class MethodGen implements CGConst {
                     } else {
                         int iarg  = ((Integer)arg).intValue();
                         if(argLength == 1) {
-                            if(iarg < -128 || iarg >= 256) throw new ClassGen.Exn("overflow of s/u1 option");
+                            if(iarg < -128 || iarg >= 256) throw new ClassFile.Exn("overflow of s/u1 option");
                             o.writeByte(iarg);
                         } else if(argLength == 2) {
-                            if(iarg < -32768 || iarg >= 65536) throw new ClassGen.Exn("overflow of s/u2 option"); 
+                            if(iarg < -32768 || iarg >= 65536) throw new ClassFile.Exn("overflow of s/u2 option"); 
                             o.writeShort(iarg);
                         } else {
                             throw new Error("should never happen");
@@ -595,7 +629,7 @@ public class MethodGen implements CGConst {
     void dump(DataOutput o) throws IOException {
         o.writeShort(flags);
         o.writeShort(cp.getUtf8Index(name));
-        o.writeShort(cp.getUtf8Index(getDescriptor()));
+        o.writeShort(cp.getUtf8Index(owner.getType().method(name, ret, args).getDescriptor()));
         o.writeShort(attrs.size());
         attrs.dump(o);
     }