
This file may be useful to those wanting to develop tools that use JBET. Data
structures and commonly used methods are discussed. It may be helpful to look
at jbet.cmd.property because it scans through instructions and performs a
simple transform. 

ClassInfo - represents one Java class file. Contains a list of methods, fields,
            interface names, and attributes. 
  ClassInfo (ClassPathElement outdir, String name): Make an empty class that
	will be written to outdir. Only directory (i.e. not jar-file)
        ClassPathElements can be stored to in the current version. A
        ClassPathElement for a directory can be constructed with 
        'ClassInfoLoader.directory (filename)'.
  methodAt (int n):  return MethodInfo for method n (of numMethods())
  fieldAt (int n): return FieldInfo for field n of numFields()
  interfaceAt (int n): return String (name of interface) for interface n
        (of numInterfaces())
  getSuperName(): name of superclass
  addMethod (MethodInfo): Add a new method to the class. No checking for
        duplicate descriptor is made.
  addField (FieldInfo): Add a new field to the class. No checking for duplicate
        name is made.
  removeMethod (MethodInfo): Remove a method
  removeField (FieldInfo): Remove a field
  findMethod (String name, Descriptor): Return a method with matching name and
        descriptor.
  findMethod (String name): Return a method with matching name. Throws an
        exception if more than one match.
  findField (String name): Return a field with matching name.
  setDirty(): Mark class as changed

MethodInfo - represents a Java method. Has the code block for the method as a
             Snippit structure. Derived from MethodSignature, which contains
             fields for the class and method names, descriptor, and access
             flags.
  MethodInfo (Lexer): Assemble a method.
  MethodInfo (String name, Descriptor, int access): Make an empty method.
  addLinesAsPCs(): Add line number records for each instruction using the
        bytecode index.  Useful for debugging as the line number is printed
        in JVM exception stack traces.
  isOverridden(): Returns true if the method overrides a base class method.
  Snippit code: Code block for this method

Snippit - a code block. Each method has a Snippit (unless abstract or native).
  first(): Return start of instruction list. Each instruction has a "next"
           field.
  last(): Return end of instruction list.
  push (Instruction): Add a new instruction to the end.
  pop(): Delete the last instruction.
  unshift (Instruction): Add instruction before the first.
  shift(): Delete the first instruction.
  remove(Instruction): Delete that instruction.
  
    Functions that insert other Snippits destroy the argument Snippits.
  insertAt (Instruction, Snippit): Inserts the snippit before the instruction.
  insertAfter (Instruction, Snippit)): Inserts the snippit after the
           instruction.
  insertOver (Instruction, Snippit): Replace the instruction with the snippit.
  append (Snippit): Add snippit after the last instruction.
  prepend (Snippit): Add snippit before the first instruction.

    Convenience functions
  println (String): Insert code equivalent to "System.out.println (string);".
  println (Type t): Insert code equivalent to "System.out.println (x);",
        where x is a value of type t that would be on top of the stack
	(e.g. code.setIpush(5); code.println(Type.INT); would generate code
        to print 5.
  comment (String): Insert a "comment" into the code block. A comment is stored
	as a ldc (load string constant) followed by a pop.
        'jbet print' prints that combination specially.

Type - a data type (int, long, etc.). Type objects are not considered "owned"
       by any other data structure, and so should never be modified unless
       newly constructed.
  toString(): return the JNI type string corresponding to this object
  declaration(): return the Java source for declaring a value of this type
  isa (Type t): return true iff this is-a t
  Type (ClassInfo):  make a type for a reference to the classinfo type
  Type (String):  parse a JNI type string

    Constants
  Type.INT, Type.LONG, Type.FLOAT, Type.DOUBLE, Type.BYTE, Type.CHAR,
  Type.BOOLEAN, Type.VOID, Type.OBJECT: Commonly used type objects
        (there are others; see Type.java).
  Type.VM_INT, Type.VM_ADDRESS, Type.VM_LONG, Type.VM_FLOAT, Type.VM_DOUBLE,
    Type.VM_RETADDR: Types used by the JVM instructions. 

Descriptor - a method descriptor in JNI format
  Descriptor (Type):  make a method descriptor for a method returning that Type
  Descriptor (Type p1, Type ret): make a method descriptor taking p1 and
        returning ret
  Descriptor (String): parse a JNI descriptor string
  toString(): return the JNI descriptor syntax

Instruction - represents one JVM instruction. Understands syntax and some
        semantics.
  set<opcode>(...): make a newly constructed Instruction object have that
        opcode. See Instruction.java for the syntax of each opcode and the
        format of the operands. Many JVM instructions that are typed
        (e.g. ireturn, lreturn, dreturn, etc.) have generic 'constructors' that
        take a Type object and use the basetype of that for the instruction,
        e.g. setReturn (Type).
  recString(): Return a readable string of this instruction and the operands.
        This is what is printed by 'jbet print'.

    These methods have corresponding setter methods to change the data, and are
    not valid for all instructions:
  classRef(): Return the classname associated with this instruction,
        if appropriate (invoke*, new, checkcast, etc.) 
  elemName(): Return the field or method name associated with this instruction,
        if appropriate.
  descriptor(): Return the method descriptor associated with this instruction,
        if appropriate.
  type(): Return the field type associated with this instruction, if
        appropriate.
  opCode(): Return the numeric opcode.
        Instruction.OP_??? constants are available.
  immediate(), immediate_l(), immediate_f(), immediate_s():
        Return the int, long, float, or String associated with this
        instruction, if appropriate.
  branchTarget(): Return the branch target of this instruction.
        Switch instructions return the 'default' target here.
  lvtIndex(): Return the local variable (register) number associated with this
	instruction, if appropriate.

BranchTarget - represents a jump target. BranchTargets are assigned to Instructions that
	involve branching (including switch statements, but not method calls).

The class loader

JBET has an internal class loader, for managing ClassInfo objects. It is
designed to be used in the same way as the Java loader, with class paths
and subdirectories translating to package names. Zip (or jar) files are also
supported. The loader also supports writing class files: modified classes are
written to the same place they were read from (currently, writing into zip
files is not supported); new classes are stored in the default output
directory. Classes are written with proper package and file names, ready to be
used by Java.

The loader can be invoked in several ways:
  Jbet.loader.getClass (String name):  Return a ClassInfo object for name. If
        already loaded return that instance, otherwise read one from disk.
  Jbet.loader.getCopy (String name):   Return a copy of the object returned by
        getClass. Future calls to the loader for the same class will get a
        different object. If modified, in order for the class to be written
        to disk, it should be passed to putClass.
  Jbet.loader.putClass (ClassInfo):    Give a class to the loader and replace
        any existing class of the same name. This is typically used when
        creating classes from scratch to cause them to be written to the
        output directory.
  Jbet.loader.getMethod (String class, String method, Descriptor): Get a method
        by class, type and descriptor. If the descriptor is null, returns the
        method if not ambiguous.

The loader keeps track of loaded classes, so if a class has been modified by an
earlier operation, the modified version is returned on subsequent calls to
getClass().

Command Line interface

Look at the commands (jbet/cmd/*.java) for short examples on how to use the
data structures. New feature development is easiest with the Command interface
because of all the setup (class path, etc.) done in jbet/Main. New commands can
be placed in the jbet/cmd directory on the classpath, or in another location
and then accessed with jbet -C <command package> <other options> <command>...

The usual sequence of command processing is:
1. Parse the options
   Single characters can be read with lexer.match('x').
   Most commands have a switch statement on lexer.read().type, for matching
   options. Token.END_OF_OPTS is returned after that last option is read.
   (See jbet/cmd/print.java for an example of this option parsing).
2. Parse the arguments with the Lexer class
3. Perform the operation, calling ClassRep::setDirty() on any classes that were
   changed to cause them to be written out at exit. This flag covers the
   methods and fields in that class. Creating new classes should be done with
   Jbet.loader.putClass().

The Lexer class
   getThing(): parses and loads a class, method, or field using the same syntax
   	as 'jbet print' uses for its input. The returned object should be
        tested with instanceof or getClass:
   	it is either a ClassInfo, MethodInfo, or FieldInfo.
   parse_descriptor(): parses a Descriptor object.
   parse_type(): parses a Type object.
   parse_name(): parses an identifier.
   parse_string(): parses a quoted string.
   getClasses(): parse a class specification with wildcards and multiple names
        allowed. This can parse an arbitrarily long string, so a separator
        character will be needed before any additional arguments. The separator
        can be matched with 'lexer.match(':')' or similar.
   match(char): Match a specific character in the input stream.
        A ParseException is thrown if the input is different.
   match(int): Match various token types (see definitions in Token.java) 
   read(): Get the next Token (of any type) from the input stream.
