misc cleanup and javadoc comments
authorbrian <brian@brianweb.net>
Sun, 30 May 2004 21:31:56 +0000 (21:31 +0000)
committerbrian <brian@brianweb.net>
Sun, 30 May 2004 21:31:56 +0000 (21:31 +0000)
darcs-hash:20040530213156-24bed-baadb0715b22ee43eb469ca0e918596c49a0bca9.gz

Makefile
src/org/ibex/classgen/ClassGen.java
src/org/ibex/classgen/FieldGen.java
src/org/ibex/classgen/FieldRef.java
src/org/ibex/classgen/MethodGen.java
src/org/ibex/classgen/MethodRef.java
src/org/ibex/classgen/Type.java
src/org/ibex/classgen/package.html [new file with mode: 0644]

index 2c9e9b5..c0b0454 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -15,6 +15,13 @@ test: $(classes)
 clean: 
        rm -rf build/*
 
 clean: 
        rm -rf build/*
 
+.PHONY: doc
+doc: doc/index.html
+
+doc/index.html: $(sources) src/org/ibex/classgen/package.html
+       mkdir -p doc
+       javadoc -d doc $(sources)
+
 sizecheck:
        @for c in $(jar_classes); do \
                for f in `echo $$c|sed 's,\.class$$,,;'`*.class; do gzip -c $$f; done | wc -c | tr -d '\n'; \
 sizecheck:
        @for c in $(jar_classes); do \
                for f in `echo $$c|sed 's,\.class$$,,;'`*.class; do gzip -c $$f; done | wc -c | tr -d '\n'; \
index 1ae9741..d579b99 100644 (file)
@@ -3,23 +3,30 @@ package org.ibex.classgen;
 import java.util.*;
 import java.io.*;
 
 import java.util.*;
 import java.io.*;
 
+/** Class generation object representing the whole classfile */
 public class ClassGen implements CGConst {
 public class ClassGen implements CGConst {
-    private Type.Object thisType;
-    private Type.Object superType;
-    int flags;
-    private String sourceFile; 
+    private final Type.Object thisType;
+    private final Type.Object superType;
+    final int flags;
     
     
-    private Vector interfaces = new Vector();
-    private Vector fields = new Vector();
-    private Vector methods = new Vector();
+    private String sourceFile; 
+    private final Vector interfaces = new Vector();
+    private final Vector fields = new Vector();
+    private final Vector methods = new Vector();
     
     final CPGen cp;
     private final AttrGen attributes;
     
     
     final CPGen cp;
     private final AttrGen attributes;
     
+    /** @see #ClassGen(Type.Object,Type.Object,int) */
     public ClassGen(String name, String superName, int flags) {
         this(new Type.Object(name),new Type.Object(superName),flags);
     }
     
     public ClassGen(String name, String superName, int flags) {
         this(new Type.Object(name),new Type.Object(superName),flags);
     }
     
+    /** Creates a new ClassGen object 
+        @param thisType The type of the class to generate
+        @param superType The superclas of the generated class (commonly Type.OBJECT) 
+        @param flags The access flags for this class (ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, and ACC_ABSTRACT)
+    */
     public ClassGen(Type.Object thisType,Type.Object superType, int flags) {
         if((flags & ~(ACC_PUBLIC|ACC_FINAL|ACC_SUPER|ACC_INTERFACE|ACC_ABSTRACT)) != 0)
             throw new IllegalArgumentException("invalid flags");
     public ClassGen(Type.Object thisType,Type.Object superType, int flags) {
         if((flags & ~(ACC_PUBLIC|ACC_FINAL|ACC_SUPER|ACC_INTERFACE|ACC_ABSTRACT)) != 0)
             throw new IllegalArgumentException("invalid flags");
@@ -31,21 +38,53 @@ public class ClassGen implements CGConst {
         attributes = new AttrGen(cp);
     }
     
         attributes = new AttrGen(cp);
     }
     
+    /** Adds a new method to this class 
+        @param name The name of the method (not the signature, just the name)
+        @param ret The return type of the method
+        @param args The arguments to the method
+        @param flags The flags for the method
+                     (ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT, ACC_STRICT)
+        @return A new MethodGen object for the method
+        @exception IllegalArgumentException if illegal flags are specified
+        @see MethodGen
+        @see CGConst
+    */
     public final MethodGen addMethod(String name, Type ret, Type[] args, int flags) {
         MethodGen mg = new MethodGen(this,name,ret,args,flags);
         methods.addElement(mg);
         return mg;
     }
     
     public final MethodGen addMethod(String name, Type ret, Type[] args, int flags) {
         MethodGen mg = new MethodGen(this,name,ret,args,flags);
         methods.addElement(mg);
         return mg;
     }
     
+    /** Adds a new field to this class 
+        @param name The name of the filed (not the signature, just the name)
+        @param type The type of the field
+        @param flags The flags for the field
+        (ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_VOLATILE, ACC_TRANSIENT)
+        @return A new FieldGen object for the method
+        @exception IllegalArgumentException if illegal flags are specified
+        @see FieldGen
+        @see CGConst
+        */  
     public final FieldGen addField(String name, Type type, int flags) {
         FieldGen fg = new FieldGen(this,name,type,flags);
         fields.addElement(fg);
         return fg;
     }
     
     public final FieldGen addField(String name, Type type, int flags) {
         FieldGen fg = new FieldGen(this,name,type,flags);
         fields.addElement(fg);
         return fg;
     }
     
+    /** Sets the source value of the SourceFile attribute of this class 
+        @param sourceFile The string to be uses as the SourceFile of this class
+    */
     public void setSourceFile(String sourceFile) { this.sourceFile = sourceFile; }
     
     public void setSourceFile(String sourceFile) { this.sourceFile = sourceFile; }
     
-    public void dump(String s) throws IOException { dump(new File(s)); }
+    /** Writes the classfile data to the file specifed
+        @see ClassGen#dump(OutputStream)
+    */
+    public void dump(String file) throws IOException { dump(new File(file)); }
+    
+    /** Writes the classfile data to the file specified
+        If <i>f</i> is a directory directory components under it are created for the package the class is in (like javac's -d option)
+        @see ClassGen#dump(OutputStream)
+    */
     public void dump(File f) throws IOException {
         if(f.isDirectory()) {
             String[] a = thisType.components();
     public void dump(File f) throws IOException {
         if(f.isDirectory()) {
             String[] a = thisType.components();
@@ -58,7 +97,13 @@ public class ClassGen implements CGConst {
         }
         dump(new FileOutputStream(f));
     }
         }
         dump(new FileOutputStream(f));
     }
-    
+   
+    /** Writes the classfile data to the outputstream specified
+        @param os The stream to write the class to
+        @exception IOException if an IOException occures while writing the class data
+        @exception IllegalStateException if the data for a method is in an inconsistent state (required arguments missing, etc)
+        @exception Exn if the classfile could not be written for any other reason (constant pool full, etc)
+    */
     public void dump(OutputStream os) throws IOException {
         DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(os));
         _dump(dos);
     public void dump(OutputStream os) throws IOException {
         DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(os));
         _dump(dos);
@@ -102,10 +147,18 @@ public class ClassGen implements CGConst {
         attributes.dump(o); // attributes        
     }
     
         attributes.dump(o); // attributes        
     }
     
+    /** Thrown when class generation fails for a reason not under the control of the user
+        (IllegalStateExceptions are thrown in those cases */
     public static class Exn extends RuntimeException {
         public Exn(String s) { super(s); }
     }
     
     public static class Exn extends RuntimeException {
         public Exn(String s) { super(s); }
     }
     
+    /** A class representing a field or method reference. This is used as an argument to the INVOKE*, GET*, and PUT* bytecodes
+        @see MethodRef
+        @see FieldRef
+        @see MethodRef.I
+        @see FieldRef
+    */
     public static abstract class FieldOrMethodRef {
         Type.Object klass;
         String name;
     public static abstract class FieldOrMethodRef {
         Type.Object klass;
         String name;
index b2d25bc..826eb78 100644 (file)
@@ -2,6 +2,8 @@ package org.ibex.classgen;
 
 import java.io.*;
 
 
 import java.io.*;
 
+/** Class representing a field in a generated classfile
+    @see ClassGen#addField */
 public class FieldGen implements CGConst {
     private final CPGen cp;
     private final String name;
 public class FieldGen implements CGConst {
     private final CPGen cp;
     private final String name;
index 6c2d8cf..10b1b1e 100644 (file)
@@ -1,6 +1,17 @@
 package org.ibex.classgen;
 
 package org.ibex.classgen;
 
+/** This class represents Field references. It is used as an argument to the 
+GETFIELD, PUTFIELD, GETSTATIC, and PUTSTATCI bytecodes 
+@see CGConst#GETFIELD
+@see CGConst#PUTFIELD
+@see CGConst#GETSTATIC
+@see CGConst#PUTSTATIC
+*/
 public class FieldRef extends ClassGen.FieldOrMethodRef {
 public class FieldRef extends ClassGen.FieldOrMethodRef {
+    /** Create a reference to field <i>name</i> of class <i>c</i> with the type <i>t</i>  */    
     public FieldRef(Type.Object c, String name, Type t) { super(c,name,t.getDescriptor()); }
     public FieldRef(Type.Object c, String name, Type t) { super(c,name,t.getDescriptor()); }
+    /** Equivalent to FieldRef(new Type.Object(s),...)
+        @see #FieldRef(Type.Object,String,Type,)
+    */
     public FieldRef(String s, String name, Type t) { this(new Type.Object(s),name,t); }
 }
     public FieldRef(String s, String name, Type t) { this(new Type.Object(s),name,t); }
 }
index 0fc8606..383ed57 100644 (file)
@@ -3,6 +3,10 @@ package org.ibex.classgen;
 import java.io.*;
 import java.util.*;
 
 import java.io.*;
 import java.util.*;
 
+// FEATURE: Support WIDE bytecodes
+
+/** A class representing a method in a generated classfile
+    @see ClassGen#addMethod */
 public class MethodGen implements CGConst {
     private final static boolean EMIT_NOPS = false;
     
 public class MethodGen implements CGConst {
     private final static boolean EMIT_NOPS = false;
     
@@ -47,6 +51,7 @@ public class MethodGen implements CGConst {
         maxLocals = Math.max(args.length + (flags&ACC_STATIC)==0 ? 1 : 0,4);
     }
     
         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 String getDescriptor() { return MethodRef.getDescriptor(ret,args); }
     
     private class ExnTableEnt {
@@ -68,10 +73,20 @@ public class MethodGen implements CGConst {
         }
     }
     
         }
     }
     
-    public final void addExceptionHandler(int startPC, int endPC, int handlerPC, Type.Object type) {
-        exnTable.put(type, new ExnTableEnt(startPC,endPC,handlerPC,cp.add(type)));
+    /** Adds an exception handler for the range [<i>start</i>,<i>end</i>) pointing to <i>handler</i>
+        @param start The instruction to start at (inclusive)
+        @param end The instruction to end at (exclusive)
+        @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) {
+        exnTable.put(type, new ExnTableEnt(start,end,handler,cp.add(type)));
     }
     
     }
     
+    /** Adds a exception type that can be thrown from this method
+        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) {
         thrownExceptions.put(type,cp.add(type));
     }
     public final void addThrow(Type.Object type) {
         thrownExceptions.put(type,cp.add(type));
     }
@@ -93,9 +108,14 @@ public class MethodGen implements CGConst {
         
         capacity = newCap;
     }
         
         capacity = newCap;
     }
+    
+    /** Returns the size (in instructions) of this method 
+        @return The size of the method (in instructions)
+    */
     public final int size() { return size; }
     
     // These two are optimized for speed, they don't call set() below
     public final int size() { return size; }
     
     // These two are optimized for speed, they don't call set() below
+    /** Add a bytecode (with no argument) to the method */
     public final int add(byte op) {
         int s = size;
         if(s == capacity) grow();
     public final int add(byte op) {
         int s = size;
         if(s == capacity) grow();
@@ -103,22 +123,57 @@ public class MethodGen implements CGConst {
         size++;
         return s;
     }
         size++;
         return s;
     }
+    /** Set the bytecode at position <i>pos</i> to <i>op</i> */
     public final void set(int pos, byte op) { this.op[pos] = op; }
         
     public final void set(int pos, byte op) { this.op[pos] = op; }
         
+    /** Adds a bytecode, <i>op</i>, with argument <i>arg</i> to the method 
+        @return The position of the new bytecode
+        */
     public final int add(byte op, Object arg) { if(capacity == size) grow(); set(size,op,arg); return size++; }
     public final int add(byte op, Object arg) { if(capacity == size) grow(); set(size,op,arg); return size++; }
+    /** Adds a bytecode with a boolean argument - equivalent to add(op,arg?1:0);
+        @return The position of the new bytecode
+        @see #add(byte,int)
+    */
     public final int add(byte op, boolean arg) { if(capacity == size) grow(); set(size,op,arg); return size++; }
     public final int add(byte op, boolean arg) { if(capacity == size) grow(); set(size,op,arg); return size++; }
+    /** Adds a bytecode with an integer argument. This is equivalent to add(op,new Integer(arg)), but optimized to prevent the allocation when possible
+        @return The position of the new bytecode
+        @see #add(byte,Object)
+    */
     public final int add(byte op, int arg) { if(capacity == size) grow(); set(size,op,arg); return size++; }
     
     public final int add(byte op, int arg) { if(capacity == size) grow(); set(size,op,arg); return size++; }
     
+    /** Gets the bytecode at position <i>pos</i>
+        @exception ArrayIndexOutOfBoundException if pos < 0 || pos >= size()
+    */
     public final byte get(int pos) { return op[pos]; }
     public final byte get(int pos) { return op[pos]; }
+    
+    /** Gets the bytecode at position <i>pos</i>. NOTE: This isn't necessarily the same object that was set with add or set.
+        Arguments for instructions which access the constant pool (LDC, INVOKEVIRTUAL, etc) are converted to a more efficient
+        interal form when they are added. The value returned from this method for these instruction can be reused, but there
+        is no way to retrieve the original object 
+        @exception ArrayIndexOutOfBoundException if pos < 0 || pos >= size()
+    */    
     public final Object getArg(int pos) { return arg[pos]; }
     
     public final Object getArg(int pos) { return arg[pos]; }
     
+    /** Sets the argument for <i>pos</i> to <i>arg</i>. This is equivalent to set(pos,op,new Integer(arg)), but optimized to prevent the allocation when possible.
+        @exception ArrayIndexOutOfBoundException if pos < 0 || pos >= size()
+        @see #setArg(int,Object) */
     public final void setArg(int pos, int arg) { set(pos,op[pos],N(arg)); }
     public final void setArg(int pos, int arg) { set(pos,op[pos],N(arg)); }
+    /** Sets the argument for <i>pos</i> to <i>arg</i>.
+        @exception ArrayIndexOutOfBoundException if pos < 0 || pos >= size()
+    */
     public final void setArg(int pos, Object arg) { set(pos,op[pos],arg); }
     
     public final void setArg(int pos, Object arg) { set(pos,op[pos],arg); }
     
-    
-    public final void set(int pos, byte op, boolean b) { set(pos,op,b?1:0); }
+    /** Sets the bytecode and argument  at <i>pos</i> to <i>op</i> and <i>arg</i> respectivly. 
+        This is equivalent to set(pos,op,arg?1:0) 
+        @exception ArrayIndexOutOfBoundException if pos < 0 || pos >= size()
+    */
+    public final void set(int pos, byte op, boolean arg) { set(pos,op,arg?1:0); }
     
     // This MUST handle x{LOAD,STORE} and LDC with an int arg WITHOUT falling back to set(int,byte,Object)
     
     // This MUST handle x{LOAD,STORE} and LDC with an int arg WITHOUT falling back to set(int,byte,Object)
+    /** Sets the bytecode and argument  at <i>pos</i> to <i>op</i> and <i>n</i> respectivly.
+        This is equivalent to set(pos,op, new Integer(n)), but optimized to prevent the allocation when possible.
+        @exception ArrayIndexOutOfBoundException if pos < 0 || pos >= size()
+    */
     public final void set(int pos, byte op, int n) {
         Object arg = null;
         OUTER: switch(op) {
     public final void set(int pos, byte op, int n) {
         Object arg = null;
         OUTER: switch(op) {
@@ -166,6 +221,9 @@ public class MethodGen implements CGConst {
         this.arg[pos] = arg;
     }
     
         this.arg[pos] = arg;
     }
     
+    /** Sets the bytecode and argument  at <i>pos</i> to <i>op</i> and <i>arg</i> respectivly.
+        @exception ArrayIndexOutOfBoundException if pos < 0 || pos >= size()
+        */
     public final void set(int pos, byte op, Object arg) {
         switch(op) {
             case ILOAD: case ISTORE: case LLOAD: case LSTORE: case FLOAD:
     public final void set(int pos, byte op, Object arg) {
         switch(op) {
             case ILOAD: case ISTORE: case LLOAD: case LSTORE: case FLOAD:
@@ -199,6 +257,10 @@ public class MethodGen implements CGConst {
         this.arg[pos] = arg;
     }
     
         this.arg[pos] = arg;
     }
     
+    /** This class represents the arguments to the TABLESWITH and LOOKUPSWITCH bytecodes
+        @see MethodGen.TSI
+        @see MethodGen.LSI
+    */
     public static class SI {
         public final Object[] targets;
         public Object defaultTarget;
     public static class SI {
         public final Object[] targets;
         public Object defaultTarget;
@@ -214,6 +276,7 @@ public class MethodGen implements CGConst {
         public int getDefaultTarget() { return ((Integer)defaultTarget).intValue(); }        
     }
     
         public int getDefaultTarget() { return ((Integer)defaultTarget).intValue(); }        
     }
     
+    /** This class represents the arguments to the TABLESWITCH bytecode */
     public static class TSI extends SI {
         public final int lo;
         public final int hi;
     public static class TSI extends SI {
         public final int lo;
         public final int hi;
@@ -226,6 +289,7 @@ public class MethodGen implements CGConst {
         public void setTargetForVal(int val, int n) { setTarget(val-lo,n); }
     }
     
         public void setTargetForVal(int val, int n) { setTarget(val-lo,n); }
     }
     
+    /** This class represents the arguments to the LOOKUPSWITCH bytecode */
     public static class LSI extends SI {
         public final int[] vals;
         public LSI(int size) {
     public static class LSI extends SI {
         public final int[] vals;
         public LSI(int size) {
@@ -235,15 +299,23 @@ public class MethodGen implements CGConst {
         public final void setVal(int pos, int val) { vals[pos] = val; }
     }
     
         public final void setVal(int pos, int val) { vals[pos] = val; }
     }
     
+    /** This class represents the arguments to byecodes that take two integer arguments. */
     public static class Pair {
         public int i1;
         public int i2;
         public Pair(int i1, int i2) { this.i1 = i1; this.i2 = i2; }
     }
         
     public static class Pair {
         public int i1;
         public int i2;
         public Pair(int i1, int i2) { this.i1 = i1; this.i2 = i2; }
     }
         
+    /** Sets the maximum number of locals in the function to <i>maxLocals</i>. NOTE: This defaults to 0 and is automatically increased as
+        necessary when *LOAD/*STORE bytecodes are added. You do not need to call this function in most cases */
     public void setMaxLocals(int maxLocals) { this.maxLocals = maxLocals; }
     public void setMaxLocals(int maxLocals) { this.maxLocals = maxLocals; }
+    /** Sets the maxinum size of th stack for this function  to <i>maxStack</i>. This defaults to 16< */
     public void setMaxStack(int maxStack) { this.maxStack = maxStack; }
     
     public void setMaxStack(int maxStack) { this.maxStack = maxStack; }
     
+    /** Computes the final bytecode for this method. 
+        @exception IllegalStateException if the data for a method is in an inconsistent state (required arguments missing, etc)
+        @exception Exn if the byteocode could not be generated for any other reason (constant pool full, etc)
+    */
     public void finish() {
         try {
             _finish();
     public void finish() {
         try {
             _finish();
@@ -479,7 +551,7 @@ public class MethodGen implements CGConst {
         size = capacity = FINISHED;        
     }
         
         size = capacity = FINISHED;        
     }
         
-    public void dump(DataOutput o) throws IOException {
+    void dump(DataOutput o) throws IOException {
         o.writeShort(flags);
         o.writeShort(cp.getUtf8Index(name));
         o.writeShort(cp.getUtf8Index(getDescriptor()));
         o.writeShort(flags);
         o.writeShort(cp.getUtf8Index(name));
         o.writeShort(cp.getUtf8Index(getDescriptor()));
@@ -487,6 +559,8 @@ public class MethodGen implements CGConst {
         attrs.dump(o);
     }
     
         attrs.dump(o);
     }
     
+    /** Negates the IF* instruction, <i>op</i>  (IF_ICMPGT -> IF_ICMPLE, IFNE -> IFEQ,  etc)
+        @exception IllegalArgumentException if <i>op</i> isn't an IF* instruction */
     public static byte negate(byte op) {
         switch(op) {
             case IFEQ: return IFNE;
     public static byte negate(byte op) {
         switch(op) {
             case IFEQ: return IFNE;
@@ -509,6 +583,8 @@ public class MethodGen implements CGConst {
         }
     }
     
         }
     }
     
+    /** Class that represents a target that isn't currently know. The target MUST be set with setTarget() before the classfile is written. 
+        This class is more or less a mutable integer */
     public static class PhantomTarget {
         private int target = -1;
         public void setTarget(int target) { this.target = target; }
     public static class PhantomTarget {
         private int target = -1;
         public void setTarget(int target) { this.target = target; }
index c866adc..75d58f3 100644 (file)
@@ -1,9 +1,21 @@
 package org.ibex.classgen;
 
 package org.ibex.classgen;
 
+/** This class represents Method references. It is used as an argument to the 
+    INVOKESTATIC, INVOKEVIRTUAL, INVOKESPEICAL, and INVOKEINTERFACE bytecodes 
+    @see CGConst#INVOKESTATIC
+    @see CGConst#INVOKEVIRTUAL
+    @see CGConst#INVOKESPECIAL
+    @see CGConst#INVOKEINTERFACE
+*/
 public class MethodRef extends ClassGen.FieldOrMethodRef {
 public class MethodRef extends ClassGen.FieldOrMethodRef {
+    /** Create a reference to method <i>name</i> of class <i>c</i> with the return type <i>ret</i> and the
+        arguments <i>args</i> */
     public MethodRef(Type.Object c, String name, Type ret, Type[] args) {
         super(c,name,getDescriptor(ret,args));
     }
     public MethodRef(Type.Object c, String name, Type ret, Type[] args) {
         super(c,name,getDescriptor(ret,args));
     }
+    /** Equivalent to MethodRef(new Type.Object(s),...)
+        @see #MethodRef(Type.Object,String,Type,Type[])
+    */
     public MethodRef(String s, String name, Type ret, Type[] args) {
         this(new Type.Object(s),name,ret,args);
     }
     public MethodRef(String s, String name, Type ret, Type[] args) {
         this(new Type.Object(s),name,ret,args);
     }
@@ -18,6 +30,10 @@ public class MethodRef extends ClassGen.FieldOrMethodRef {
         return sb.toString();
     }
     
         return sb.toString();
     }
     
+    /** MethodRef class used for the INVOKEINTERFACE bytecode. Although this contains the same
+        data as a normal MethodRef, these are treated differently in the byte code format. In general,
+        users don't need to be concerned with this though because MethodRef's are automatically converted
+        to MethodRef.I's when they are applied to an INVOKEINTERFACE bytecode */
     public static class I extends MethodRef {
         public I(Type.Object c, String name, Type ret, Type[] args) { super(c,name,ret,args); }
         public I(String s, String name, Type ret, Type[] args) { super(s,name,ret,args); }
     public static class I extends MethodRef {
         public I(Type.Object c, String name, Type ret, Type[] args) { super(c,name,ret,args); }
         public I(String s, String name, Type ret, Type[] args) { super(s,name,ret,args); }
index 33af24d..ec6d834 100644 (file)
@@ -9,6 +9,9 @@ public class Type {
     public static final Type BOOLEAN = new Type("Z");
     public static final Type DOUBLE = new Type("D");
     public static final Type FLOAT = new Type("F");
     public static final Type BOOLEAN = new Type("Z");
     public static final Type DOUBLE = new Type("D");
     public static final Type FLOAT = new Type("F");
+    public static final Type BYTE = new Type("B");
+    public static final Type CHAR = new Type("C");
+    public static final Type SHORT = new Type("S");
     
     public static final Type.Object OBJECT = new Type.Object("java.lang.Object");
     public static final Type.Object STRING = new Type.Object("java.lang.String");
     
     public static final Type.Object OBJECT = new Type.Object("java.lang.Object");
     public static final Type.Object STRING = new Type.Object("java.lang.String");
@@ -17,17 +20,28 @@ public class Type {
     public static final Type.Object DOUBLE_OBJECT = new Type.Object("java.lang.Double");
     public static final Type.Object FLOAT_OBJECT = new Type.Object("java.lang.Float");
     
     public static final Type.Object DOUBLE_OBJECT = new Type.Object("java.lang.Double");
     public static final Type.Object FLOAT_OBJECT = new Type.Object("java.lang.Float");
     
+    /** A zero element Type[] array (can be passed as the "args" param when a method takes no arguments */
     public static final Type[] NO_ARGS = new Type[0];
     
     final String descriptor;
     
     Type(String descriptor) { this.descriptor = descriptor; }
     
     public static final Type[] NO_ARGS = new Type[0];
     
     final String descriptor;
     
     Type(String descriptor) { this.descriptor = descriptor; }
     
+    /** Returns the Java descriptor string for this object ("I", or "Ljava/lang/String", "[[J", etc */
     public final String getDescriptor() { return descriptor; }
     public int hashCode() { return descriptor.hashCode(); }
     public boolean equals(java.lang.Object o) { return o instanceof Type && ((Type)o).descriptor.equals(descriptor); }
     
     public final String getDescriptor() { return descriptor; }
     public int hashCode() { return descriptor.hashCode(); }
     public boolean equals(java.lang.Object o) { return o instanceof Type && ((Type)o).descriptor.equals(descriptor); }
     
+    /** Returns a one dimensional array type for the base type <i>base</i>
+        @param base The base type
+        @return A one dimensional array of the base type
+    */
     public static Type arrayType(Type base) { return arrayType(base,1); }
     public static Type arrayType(Type base) { return arrayType(base,1); }
+    /** Returns a <i>dim</i> dimensional array type for the base type <i>base</i>
+        @param base The base type
+        @param dim Number if dimensions
+        @return A one dimensional array of the base type
+    */
     public static Type arrayType(Type base, int dim) {
         StringBuffer sb = new StringBuffer(base.descriptor.length() + dim);
         for(int i=0;i<dim;i++) sb.append("[");
     public static Type arrayType(Type base, int dim) {
         StringBuffer sb = new StringBuffer(base.descriptor.length() + dim);
         for(int i=0;i<dim;i++) sb.append("[");
@@ -35,7 +49,11 @@ public class Type {
         return new Type(sb.toString());
     }
     
         return new Type(sb.toString());
     }
     
+    /** Class representing Objec types (any non-primitive type) */
     public static class Object extends Type {
     public static class Object extends Type {
+        /** Create an Type.Object instance for the specified string. <i>s</i> can be a string in the form
+            "java.lang.String", "java/lang/String", or "Ljava/lang/String;".
+            @param s The type */
         public Object(String s) { super(_initHelper(s)); }
         
         private static String _initHelper(String s) {
         public Object(String s) { super(_initHelper(s)); }
         
         private static String _initHelper(String s) {
@@ -44,14 +62,14 @@ public class Type {
             return s;
         }
 
             return s;
         }
 
-        public String[] components() {
+        String[] components() {
             StringTokenizer st = new StringTokenizer(descriptor.substring(1,descriptor.length()-1),"/");
             String[] a = new String[st.countTokens()];
             for(int i=0;st.hasMoreTokens();i++) a[i] = st.nextToken();
             return a;
         }
         
             StringTokenizer st = new StringTokenizer(descriptor.substring(1,descriptor.length()-1),"/");
             String[] a = new String[st.countTokens()];
             for(int i=0;st.hasMoreTokens();i++) a[i] = st.nextToken();
             return a;
         }
         
-        public String internalForm() { return descriptor.substring(1,descriptor.length()-1); }
+        String internalForm() { return descriptor.substring(1,descriptor.length()-1); }
         
         // FEATURE: Do a proper check here (invalid chars, etc)
         static boolean validDescriptorString(String s) {
         
         // FEATURE: Do a proper check here (invalid chars, etc)
         static boolean validDescriptorString(String s) {
diff --git a/src/org/ibex/classgen/package.html b/src/org/ibex/classgen/package.html
new file mode 100644 (file)
index 0000000..c921dab
--- /dev/null
@@ -0,0 +1,83 @@
+<body>
+Example Usage:<br/>
+
+The following:<br/>
+<pre>
+        ClassGen cg = new ClassGen("Test1","java.lang.Object",ACC_PUBLIC|ACC_SUPER);
+        
+        FieldGen fg = cg.addField("message",Type.STRING,ACC_PRIVATE|ACC_STATIC);
+        fg.setConstantValue("Hello, World");
+        
+        MethodGen mg = cg.addMethod("main",Type.VOID,new Type[]{Type.arrayType(Type.STRING)},ACC_STATIC|ACC_PUBLIC);
+        mg.add(LDC,10);
+        mg.add(ISTORE_0);
+        
+        int top = mg.size();
+        mg.add(GETSTATIC,new FieldRef("java.lang.System","out",new Type.Object("java.io.PrintStream")));
+        mg.add(NEW,Type.STRINGBUFFER);
+        mg.add(DUP);
+        mg.add(INVOKESPECIAL,new MethodRef(Type.STRINGBUFFER,"<init>",Type.VOID,Type.NO_ARGS));
+        mg.add(GETSTATIC,new FieldRef("Test1","message",Type.STRING));
+        mg.add(INVOKEVIRTUAL,new MethodRef(Type.STRINGBUFFER,"append",Type.STRINGBUFFER,new Type[]{Type.STRING}));
+        mg.add(LDC," - ");
+        mg.add(INVOKEVIRTUAL,new MethodRef(Type.STRINGBUFFER,"append",Type.STRINGBUFFER,new Type[]{Type.STRING}));
+        mg.add(ILOAD_0);
+        mg.add(INVOKEVIRTUAL,new MethodRef(Type.STRINGBUFFER,"append",Type.STRINGBUFFER,new Type[]{Type.INT}));
+        
+        mg.add(ILOAD_0);
+        mg.add(ICONST_1);
+        mg.add(IAND);
+        int b1 = mg.add(IFNE);
+        mg.add(LDC,'!');
+        mg.add(INVOKEVIRTUAL,new MethodRef(Type.STRINGBUFFER,"append",Type.STRINGBUFFER,new Type[]{Type.CHAR}));
+        mg.setArg(b1,mg.size());
+        
+        mg.add(INVOKEVIRTUAL,new MethodRef(Type.STRINGBUFFER,"toString",Type.STRING,Type.NO_ARGS));
+        mg.add(INVOKEVIRTUAL,new MethodRef("java.io.PrintStream","println",Type.VOID,new Type[]{Type.STRING}));
+        
+        mg.add(IINC,new MethodGen.Pair(0,-1));
+
+        mg.add(ILOAD_0);
+        mg.add(IFGT,top);
+        
+        mg.add(RETURN);
+        
+        cg.dump("Test1.class");
+</pre>
+
+Will create this bytecode:
+<pre>
+public class Test1 extends java.lang.Object{
+private static java.lang.String message;
+
+public static void main(java.lang.String[]);
+   throws 
+  Code:
+   0:   bipush  10
+   2:   istore_0
+   3:   getstatic       #10; //Field java/lang/System.out:Ljava/io/PrintStream;
+   6:   new     #12; //class StringBuffer
+   9:   dup
+   10:  invokespecial   #16; //Method java/lang/StringBuffer."<init>":()V
+   13:  getstatic       #20; //Field message:Ljava/lang/String;
+   16:  invokevirtual   #24; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
+   19:  ldc     #26; //String  - 
+   21:  invokevirtual   #24; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
+   24:  iload_0
+   25:  invokevirtual   #29; //Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;
+   28:  iload_0
+   29:  iconst_1
+   30:  iand
+   31:  ifne    39
+   34:  bipush  33
+   36:  invokevirtual   #32; //Method java/lang/StringBuffer.append:(C)Ljava/lang/StringBuffer;
+   39:  invokevirtual   #36; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
+   42:  invokevirtual   #42; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
+   45:  iinc    0, -1
+   48:  iload_0
+   49:  ifgt    3
+   52:  return
+
+}
+</pre>
+</body>