[bytecode] 01/09: Imported Upstream version 0.92.svn.20090106

Olivier Sallou osallou at debian.org
Tue Jun 21 08:49:54 UTC 2016


This is an automated email from the git hooks/post-receive script.

osallou pushed a commit to branch master
in repository bytecode.

commit 61d724b5998b2e943cd88dd53d4956c413727934
Author: Olivier Sallou <olivier.sallou at debian.org>
Date:   Tue Jun 21 09:42:13 2016 +0200

    Imported Upstream version 0.92.svn.20090106
---
 build.xml                                          |  355 +++
 manifest/defaultmanifest.txt                       |    0
 opcodes.txt                                        |  229 ++
 src/org/biojava/utils/bytecode/BranchFixup.java    |   47 +
 src/org/biojava/utils/bytecode/ByteCode.java       | 2348 ++++++++++++++++++++
 .../biojava/utils/bytecode/ByteInstruction.java    |   53 +
 src/org/biojava/utils/bytecode/ChildContext.java   |  213 ++
 .../biojava/utils/bytecode/ClassInstruction.java   |   55 +
 src/org/biojava/utils/bytecode/CodeClass.java      |  125 ++
 src/org/biojava/utils/bytecode/CodeContext.java    |  207 ++
 src/org/biojava/utils/bytecode/CodeException.java  |   34 +
 src/org/biojava/utils/bytecode/CodeField.java      |   98 +
 src/org/biojava/utils/bytecode/CodeGenerator.java  |   63 +
 src/org/biojava/utils/bytecode/CodeMethod.java     |   87 +
 src/org/biojava/utils/bytecode/CodeUtils.java      |  169 ++
 src/org/biojava/utils/bytecode/ConstantPool.java   |  385 ++++
 .../biojava/utils/bytecode/DoubleInstruction.java  |   48 +
 .../biojava/utils/bytecode/ExceptionMemento.java   |   45 +
 .../biojava/utils/bytecode/FieldInstruction.java   |   54 +
 .../utils/bytecode/FloatConstantInstruction.java   |   55 +
 .../utils/bytecode/GeneratedClassLoader.java       |   83 +
 .../biojava/utils/bytecode/GeneratedCodeClass.java |  506 +++++
 .../utils/bytecode/GeneratedCodeMethod.java        |  187 ++
 src/org/biojava/utils/bytecode/IfExpression.java   |  103 +
 src/org/biojava/utils/bytecode/Instruction.java    |   30 +
 .../biojava/utils/bytecode/InstructionVector.java  |  132 ++
 .../utils/bytecode/IntConstantInstruction.java     |   55 +
 .../utils/bytecode/IntrospectedCodeClass.java      |  341 +++
 .../bytecode/IntrospectedCodeConstructor.java      |   77 +
 .../utils/bytecode/IntrospectedCodeMethod.java     |   81 +
 src/org/biojava/utils/bytecode/Label.java          |   64 +
 .../biojava/utils/bytecode/LabelInstruction.java   |   57 +
 src/org/biojava/utils/bytecode/LocalVariable.java  |   98 +
 .../utils/bytecode/LocalVariableInstruction.java   |   66 +
 .../utils/bytecode/LongConstantInstruction.java    |   49 +
 src/org/biojava/utils/bytecode/MarkLabel.java      |   50 +
 .../biojava/utils/bytecode/MethodInstruction.java  |   76 +
 .../biojava/utils/bytecode/MethodRootContext.java  |  234 ++
 .../utils/bytecode/NoOperandsInstruction.java      |   50 +
 .../utils/bytecode/OutstandingReference.java       |   32 +
 .../utils/bytecode/PParametricCodeGenerator.java   |   27 +
 .../utils/bytecode/ParametricCodeGenerator.java    |   26 +
 src/org/biojava/utils/bytecode/ParametricType.java |  191 ++
 src/org/biojava/utils/bytecode/ParentContext.java  |   33 +
 .../biojava/utils/bytecode/ShortInstruction.java   |   53 +
 .../biojava/utils/bytecode/SimpleReference.java    |   46 +
 .../utils/bytecode/StringConstantInstruction.java  |   58 +
 src/org/biojava/utils/bytecode/package.html        |  199 ++
 test/MakeHelloWorld.java                           |   83 +
 test/Runner.java                                   |   12 +
 50 files changed, 7769 insertions(+)

diff --git a/build.xml b/build.xml
new file mode 100755
index 0000000..ba7cbb5
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,355 @@
+<?xml version="1.0"?>
+
+<!--
+
+
+  Ant build file for the entire biojava tree
+
+  see:
+  <a href="http://jakarta.apache.org/ant">Ant Project Homepage</a>
+  <a href="http://home.wxs.nl/~ajkuiper/ant.html">Ant User Manual</a>
+  <a href="http://jakarta.apache.org/builds/tomcat/nightly/ant.zip">Download</a>
+
+  targets:
+
+    compile
+    compile-tests compiles JUnit tests
+    compile-demos compiles the demo files
+    package       builds the biojava.jar file (default)
+    package-demos builds the demos.jar file
+    runtests      runs JUnit tests
+    javadocs
+    dist
+    dist-zip     'binary' release (jar & documentation) in zip format
+    dist-tgz     'binary' release (jar & documentation) in tar.gz format
+    dist-both    both dist-zip & dist-tgz
+    clean        cleans up the build & dist directories
+
+  author:  Matthew Pocock - "modified from biojava-live/build.xml"
+  version: $Id: build.xml 4369 2003-07-07 15:55:08Z mrp $
+
+  portions Copyright (c) 1999-2000 The Apache Software Foundation.
+
+-->
+
+<project default="package" basedir=".">
+
+  <target name="init">
+    <tstamp />
+    <property name="name" value="bytecode" />
+    <property name="version" value="0.1" />
+
+    <property name="build.compiler" value="modern" />
+
+    <!-- We are bootstrapping some of the biojava exception handeling code -->
+    <property name="classpath" value="biojava.jar" />
+
+    <!-- Save the current system classpath to pass to forked VMs -->
+    <property name="env.classpath" value="${java.class.path}" />
+
+    <!-- Check the current system classpath for JUnit -->
+    <available classpath="${env.classpath}"
+               classname="junit.framework.TestCase"
+               property="junit.present" />
+
+    <!-- Check the current system classpath for JUnit support in Ant (only in >= 1.3) -->
+    <available classpath="${env.classpath}"
+               classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTest"
+               property="junit.support" />
+
+    <available classpath="${env.classpath}"
+               classname="java.nio.Buffer"
+               property="java14">
+    </available>
+
+    <property name="readme" value="./README" />
+    <property name="license" value="./LICENSE" />
+    <property name="src.dir" value="./src" />
+    <property name="tests.dir" value="./tests" />
+    <property name="demos.dir" value="./demos" />
+    <property name="reports.dir" value="./reports" />
+    <property name="manifest.dir" value="./manifest" />
+    <property name="manifest.file" value="defaultmanifest.txt" />
+    <property name="resources.dir" value="./resources" />
+
+    <property name="packages" value="org.*" />
+
+    <property name="build.dir" value="./ant-build" />
+    <!-- Subdirectories for main source and classes -->
+    <property name="build.src.main" value="./ant-build/src/main" />
+    <property name="build.dest.main" value="./ant-build/classes/main" />
+    <!-- Subdirectories for tests source and classes -->
+    <property name="build.src.tests" value="./ant-build/src/tests" />
+    <property name="build.dest.tests" value="./ant-build/classes/tests" />
+    <property name="build.src.demos" value="./ant-build/src/demos" />
+    <property name="build.dest.demos" value="./ant-build/classes/demos" />
+    <!-- Subdirectory for Javadocs -->
+    <property name="build.javadocs" value="./ant-build/docs" />
+    <!-- Subdirectory for test reports -->
+    <property name="reports.tests" value="./reports/tests" />
+
+    <property name="dist.root" value="./dist" />
+    <property name="dist.dir" value="${dist.root}/${name}-${version}" />
+  </target>
+
+  <!-- Prepares the build directory -->
+  <target name="prepare" depends="init">
+    <mkdir dir="${build.dir}" />
+  </target>
+
+  <!-- Prepares the source code -->
+  <target name="prepare-core" depends="init,prepare">
+
+    <!-- Creates directories -->
+    <mkdir dir="${build.src.main}" />
+    <mkdir dir="${build.dest.main}" />
+    <mkdir dir="${build.src.tests}" />
+    <mkdir dir="${build.dest.tests}" />
+    <mkdir dir="${reports.tests}" />
+    <mkdir dir="${build.src.demos}" />
+    <mkdir dir="${build.dest.demos}" />
+
+    <!-- Copies src files -->
+    <!-- copydir src="${src.dir}" dest="${build.src}" excludes="CVS,cvs"/ -->
+    <copy todir="${build.src.main}">
+      <fileset dir="${src.dir}">
+        <exclude name="**/CVS/**" />
+      </fileset>
+    </copy>
+
+    <!-- Copies test src files -->
+    <copy todir="${build.src.tests}">
+      <fileset dir="${tests.dir}">
+        <exclude name="**/CVS/**" />
+      </fileset>
+    </copy>
+
+    <!-- Copies demos files -->
+    <copy todir="${build.src.demos}">
+      <fileset dir="${demos.dir}">
+        <exclude name="**/CVS/**" />
+      </fileset>
+    </copy>
+
+    <!-- Copies manifest -->
+    <!-- copydir src="${manifest.dir}" dest="${build.src}" includes="${manifest.file}"/ -->
+    <copy todir="${build.src.main}">
+      <fileset dir="${manifest.dir}">
+        <include name="${manifest.file}" />
+      </fileset>
+    </copy>
+
+    <!-- Copies demo manifest -->
+    <copy todir="${build.src.demos}">
+      <fileset dir="${manifest.dir}">
+        <include name="${demosmanifest.file}" />
+      </fileset>
+    </copy>
+    
+    <!-- Copies resources -->
+    <!-- copydir src="${resources.dir}" dest="${build.src}" excludes="CVS,cvs"/ -->
+    <copy todir="${build.dest.main}">
+      <fileset dir="${resources.dir}">
+        <exclude name="**/CVS/**" />
+      </fileset>
+    </copy>
+  </target>
+
+  <target name="prepare-src" depends="init,prepare-core" />
+
+  <!-- Compiles the source directory -->
+  <target name="compile" depends="init,prepare-src">
+    <javac
+      srcdir="${build.src.main}"
+      destdir="${build.dest.main}"
+      classpath="${classpath}"
+      deprecation="false"
+      depend="no"
+      debug="true"
+    />
+  </target>
+
+  <!-- Compiles the tests directory -->
+  <target name="compile-tests" depends="init,prepare-src,compile">
+    <javac
+      srcdir="${build.src.tests}"
+      destdir="${build.dest.tests}"
+      deprecation="true"
+      depend="yes">
+      <classpath>
+        <pathelement path="${classpath}" />
+        <pathelement path="${build.dest.main}" />
+      </classpath>
+    </javac>
+  </target>
+
+  <!-- Compiles the demos directory -->
+  <target name="compile-demos" depends="init,prepare-src,compile">
+    <javac
+      srcdir="${build.src.demos}"
+      destdir="${build.dest.demos}"
+      deprecation="true"
+      depend="yes">
+      <classpath>
+        <pathelement path="${classpath}" />
+        <pathelement path="${build.dest.main}" />
+      </classpath>
+    </javac>
+  </target>
+
+  <!-- Creates the class package (tests are left in the parallel tree) -->
+  <target name="package" depends="init,compile">
+    <jar
+      jarfile="${build.dir}/${name}.jar"
+      basedir="${build.dest.main}"
+      manifest="${build.src.main}/${manifest.file}"
+      includes="**"
+    />
+  </target>
+  
+  <!-- Create the demo package -->
+  <target name="package-demos" depends="init,package,compile-demos">
+    <jar
+      jarfile="${build.dir}/demo.jar"
+      basedir="${build.dest.demos}"
+      manifest="${build.src.demos}/${demosmanifest.file}"
+      includes="**"
+    />
+  </target>
+
+  <!-- Runs tests if the Ant optional JUnit support is available -->
+  <target name="runtests" depends="init,compile-tests" >
+    <echo message="JUnit present: ${junit.present}"/>
+    <junit printsummary="yes" haltonfailure="no" dir="${build.dest.tests}">
+      <formatter type="plain" usefile="true" />
+      <classpath>
+        <!-- main classes from build -->
+        <pathelement path="${build.dest.main}" />
+        <!-- test classes from build -->
+        <pathelement path="${build.dest.tests}" />
+        <!-- test data from build -->
+        <pathelement path="${build.src.tests}" />
+        <!-- classes specified in this file -->
+        <pathelement path="${classpath}" />
+        <!-- classes specified in system classpath -->
+        <pathelement path="${env.classpath}" />
+      </classpath>
+      <!-- The junit task doesn't support 'if' so we test for JUnit here -->
+      <batchtest fork="yes" todir="${reports.tests}" if="junit.present">
+        <fileset dir="${build.dest.tests}">
+          <include name="**/*Test*" />
+        </fileset>
+      </batchtest>
+    </junit>
+  </target>
+
+  <target name="seqtests" depends="init,compile-tests" if="junit.support">
+    <junit printsummary="yes" haltonfailure="no" dir="${build.dest.tests}">
+      <formatter type="plain" usefile="true" />
+      <classpath>
+        <!-- main classes from build -->
+        <pathelement path="${build.dest.main}" />
+        <!-- test classes from build -->
+        <pathelement path="${build.dest.tests}" />
+        <!-- test data from build -->
+        <pathelement path="${build.src.tests}" />
+        <!-- classes specified in this file -->
+        <pathelement path="${classpath}" />
+        <!-- classes specified in system classpath -->
+        <pathelement path="${env.classpath}" />
+      </classpath>
+      <!-- The junit task doesn't support 'if' so we test for JUnit here -->
+      <batchtest fork="yes" todir="${reports.tests}" if="junit.present">
+        <fileset dir="${build.dest.tests}">
+          <include name="org/biojava/bio/seq/*Test*" />
+        </fileset>
+      </batchtest>
+    </junit>
+  </target>
+  
+  <target name="symboltests" depends="init,compile-tests" if="junit.support">
+    <junit printsummary="yes" haltonfailure="no" dir="${build.dest.tests}">
+      <formatter type="plain" usefile="true" />
+      <classpath>
+        <!-- main classes from build -->
+        <pathelement path="${build.dest.main}" />
+        <!-- test classes from build -->
+        <pathelement path="${build.dest.tests}" />
+        <!-- test data from build -->
+        <pathelement path="${build.src.tests}" />
+        <!-- classes specified in this file -->
+        <pathelement path="${classpath}" />
+        <!-- classes specified in system classpath -->
+        <pathelement path="${env.classpath}" />
+      </classpath>
+      <!-- The junit task doesn't support 'if' so we test for JUnit here -->
+      <batchtest fork="yes" todir="${reports.tests}" if="junit.present">
+        <fileset dir="${build.dest.tests}">
+          <include name="org/biojava/bio/symbol/*Test*" />
+        </fileset>
+      </batchtest>
+    </junit>
+  </target>
+
+  <!-- Creates the API documentation -->
+  <target name="javadocs" depends="init,prepare-src">
+    <mkdir dir="${build.javadocs}" />
+    <javadoc
+      packagenames="${packages}"
+      sourcepath="${build.src.main}"
+      classpath="${classpath}"
+      destdir="${build.javadocs}"
+      author="true"
+      version="true"
+      use="true"
+      windowtitle="${name} API"
+      doctitle="${name}"
+      link="http://java.sun.com/j2se/1.4.2/docs/api/"
+      maxmemory="96m">
+    </javadoc>
+  </target>
+
+  <!-- Creates the distribution -->
+  <target name="dist" depends="init,package,runtests,javadocs">
+    <mkdir dir="${dist.root}" />
+    <mkdir dir="${dist.dir}" />
+    <mkdir dir="${dist.dir}/lib" />
+    <mkdir dir="${dist.dir}/docs" />
+
+    <copyfile src="${readme}" dest="${dist.dir}" />
+    <copyfile src="${license}" dest="${dist.dir}" />
+
+    <copyfile src="${build.dir}/${name}.jar" dest="${dist.dir}/lib/${name}.jar" />
+    <copydir src="${build.javadocs}" dest="${dist.dir}/docs" />
+  </target>
+
+  <!-- zips the dist -->
+  <target name="dist-zip" depends="init,dist">
+    <zip zipfile="${name}-${version}.zip" basedir="${dist.dir}" includes="**" />
+  </target>
+
+  <!-- tgzs the dist -->
+  <target name="dist-tgz" depends="init,dist">
+    <tar tarfile="${name}-${version}.tar" basedir="${dist.root}" includes="**" />
+    <gzip zipfile="${name}-${version}.tar.gz" src="${name}-${version}.tar" />
+  </target>
+
+  <!-- zip & tgz -->
+  <target name="dist-both" depends="init,dist-zip,dist-tgz" />
+
+  <!-- Cleans everything -->
+  <target name="clean" depends="init">
+    <delete dir="${build.dir}" />
+    <delete dir="${dist.root}" />
+    <delete file="${name}-${version}.tar.gz" />
+    <delete file="${name}-${version}.tar" />
+    <delete file="${name}-${version}.zip" />
+  </target>
+
+  <target name="sync">
+    <cvs command="update" />
+    <AntCall target="package"/>
+    <cvs command="commit" />
+  </target>
+
+</project>
diff --git a/manifest/defaultmanifest.txt b/manifest/defaultmanifest.txt
new file mode 100644
index 0000000..e69de29
diff --git a/opcodes.txt b/opcodes.txt
new file mode 100755
index 0000000..b3d77c9
--- /dev/null
+++ b/opcodes.txt
@@ -0,0 +1,229 @@
+0 nop 0
+1 aconst_null 0
+2 iconst_m1 0
+3 iconst_0 0
+4 iconst_1 0
+5 iconst_2 0
+6 iconst_3 0
+7 iconst_4 0
+8 iconst_5 0
+9 lconst_0 0
+10 lconst_1 0
+11 fconst_0 0
+12 fconst_1 0
+13 fconst_2 0
+14 dconst_0 0
+15 dconst_1 0
+16 bipush 1
+17 sipush 2
+18 ldc 1
+19 ldc_w 2
+20 ldc2_w 2
+21 iload 1
+22 lload 1
+23 fload 1
+24 dload 1
+25 aload 1
+26 iload_0 0
+27 iload_1 0
+28 iload_2 0
+29 iload_3 0
+30 lload_0 0
+31 lload_1 0
+32 lload_2 0
+33 lload_3 0
+34 fload_0 0
+35 fload_1 0
+36 fload_2 0
+37 fload_3 0
+38 dload_0 0
+39 dload_1 0
+40 dload_2 0
+41 dload_3 0
+42 aload_0 0
+43 aload_1 0
+44 aload_2 0
+45 aload_3 0
+46 iaload 0
+47 laload 0
+48 faload 0
+49 daload 0
+50 aaload 0
+51 baload 0
+52 caload 0
+53 saload 0
+54 istore 1
+55 lstore 1
+56 fstore 1
+57 dstore 1
+58 astore 1
+59 istore_0 0
+60 istore_1 0
+61 istore_2 0
+62 istore_3 0
+63 lstore_0 0
+64 lstore_1 0
+65 lstore_2 0
+66 lstore_3 0
+67 fstore_0 0
+68 fstore_1 0
+69 fstore_2 0
+70 fstore_3 0
+71 dstore_0 0
+72 dstore_1 0
+73 dstore_2 0
+74 dstore_3 0
+75 astore_0 0
+76 astore_1 0
+77 astore_2 0
+78 astore_3 0
+79 iastore 0
+80 lastore 0
+81 fastore 0
+82 dastore 0
+83 aastore 0
+84 bastore 0
+85 castore 0
+86 sastore 0
+87 pop 0
+88 pop2 0
+89 dup 0
+90 dup_x1 0
+91 dup_x2 0
+92 dup2 0
+93 dup2_x1 0
+94 dup2_x2 0
+95 swap 0
+96 iadd 0
+97 ladd 0
+98 fadd 0
+99 dadd 0
+100 isub 0
+101 lsub 0
+102 fsub 0
+103 dsub 0
+104 imul 0
+105 lmul 0
+106 fmul 0
+107 dmul 0
+108 idiv 0
+109 ldiv 0
+110 fdiv 0
+111 ddiv 0
+112 irem 0
+113 lrem 0
+114 frem 0
+115 drem 0
+116 ineg 0
+117 lneg 0
+118 fneg 0
+119 dneg 0
+120 ishl 0
+121 lshl 0
+122 ishr 0
+123 lshr 0
+124 iushr 0
+125 lushr 0
+126 iand 0
+127 land 0
+128 ior 0
+129 lor 0
+130 ixor 0
+131 lxor 0
+132 iinc 2
+133 i2l 0
+134 i2f 0
+135 i2d 0
+136 l2i 0
+137 l2f 0
+138 l2d 0
+139 f2i 0
+140 f2l 0
+141 f2d 0
+142 d2i 0
+143 d2l 0
+144 d2f 0
+145 i2b 0
+146 i2c 0
+147 i2s 0
+148 lcmp 0
+149 fcmpl 0
+150 fcmpg 0
+151 dcmpl 0
+152 dcmpg 0
+153 ifeq 2
+154 ifne 2
+155 iflt 2
+156 ifge 2
+157 ifgt 2
+158 ifle 2
+159 if_icmpeq 2
+160 if_icmpne 2
+161 if_icmplt 2
+162 if_icmpge 2
+163 if_icmpgt 2
+164 if_icmple 2
+165 if_acmpeq 2
+166 if_acmpne 2
+167 goto 2
+168 jsr 2
+169 ret 1
+170 tableswitch -
+171 lookupswitch -
+172 ireturn 0
+173 lreturn 0
+174 freturn 0
+175 dreturn 0
+176 areturn 0
+177 return 0
+178 getstatic 2
+179 putstatic 2
+180 getfield 2
+181 putfield 2
+182 invokevirtual 2
+183 invokespecial 2
+184 invokestatic 2
+185 invokeinterface 2
+187 new 2
+188 newarray 1
+189 anewarray 2
+190 arraylength 0
+191 athrow 0
+192 checkcast 2
+193 instanceof 2
+194 monitorenter 0
+195 monitorexit 0
+196 wide 0
+197 multianewarray 3
+198 ifnull 2
+199 ifnonnull 2
+200 goto_w 4
+201 jsr_w 4
+202 breakpoint 0
+203 ldc_quick 1
+204 ldc_w_quick 2
+205 ldc2_w_quick 2
+206 getfield_quick 2
+207 putfield_quick 2
+208 getfield2_quick 2
+209 putfield2_quick 2
+210 getstatic_quick 2
+211 putstatic_quick 2
+212 getstatic2_quick 2
+213 putstatic2_quick 2
+214 invokevirtual_quick 2
+215 invokenonvirtual_quick 2
+216 invokesuper_quick 2
+217 invokestatic_quick 2
+218 invokeinterface_quick 2
+219 invokevirtualobject_quick 2
+221 new_quick 2
+222 anewarray_quick 2
+223 multianewarray_quick 3
+224 checkcast_quick 2
+225 instanceof_quick 2
+226 invokevirtual_quick_w 0
+227 getfield_quick_w 2
+228 putfield_quick_w 2
+254 impdep1 0
+255 impdep2 0
diff --git a/src/org/biojava/utils/bytecode/BranchFixup.java b/src/org/biojava/utils/bytecode/BranchFixup.java
new file mode 100755
index 0000000..cae6f9c
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/BranchFixup.java
@@ -0,0 +1,47 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Encapsulate a refererence to a Label which has not been resolved.
+ *
+ * @author Thomas Down
+ */
+
+class BranchFixup implements OutstandingReference {
+    private final Label label;
+    private final int branchSource;
+    private final ParentContext cc;
+
+    public BranchFixup(Label l, int bs, ParentContext cc) {
+	this.label = l;
+	this.branchSource = bs;
+	this.cc = cc;
+    }
+
+    public Label getLabel() {
+	return label;
+    }
+
+    public void resolve(int offset) throws CodeException {
+	cc.writeShortAt(branchSource, offset - branchSource + 1);
+    }
+}
diff --git a/src/org/biojava/utils/bytecode/ByteCode.java b/src/org/biojava/utils/bytecode/ByteCode.java
new file mode 100755
index 0000000..240498d
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/ByteCode.java
@@ -0,0 +1,2348 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Factory for objects which encapsulate individual Java bytecode instructions.
+ * Most methods in this class are auto-generated.
+ *
+ * <p>There are two classes of methods. The first ones are for creating objects
+ * that directly represent opcodes. These effectively wrap one of the opcode
+ * constants. The others do something more clever. For example, make_if emits
+ * something that is equivalent to a normal Java if statement.</p>
+ *
+ * <p>Generic types are supported using the factory methods that take
+ * ParametricType arguments.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+public class ByteCode {
+    //
+    // iconst and friends
+    //
+
+    public static Instruction make_iconst(int i) {
+      if (i >= -1 && i <= 5) {
+        return new NoOperandsInstruction((byte) (op_iconst_0 + i), 1);
+      } else if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE) {
+        return new ByteInstruction(op_bipush, (byte) i, 1);
+      } else if (i >= Short.MIN_VALUE && i <= Short.MAX_VALUE) {
+        return new ShortInstruction(op_sipush, i, 1);
+      }
+      
+      return new IntConstantInstruction(i);
+    }
+
+    //
+    // String constants
+    //
+
+    public static Instruction make_sconst(String s) {
+	return new StringConstantInstruction(s);
+    }
+
+    //
+    // Double constants
+    //
+
+    public static Instruction make_dconst(double d) {
+      if (d == 0.0) {
+        return new NoOperandsInstruction(op_dconst_0, 1);
+      } else if (d == 1.0) {
+        return new NoOperandsInstruction(op_dconst_1, 1);
+      } else {
+        return new DoubleInstruction(d);
+      }
+    }
+
+    //
+    // Long constants
+    //
+
+    public static Instruction make_lconst(long l) {
+      if (l == 0L) {
+        return new NoOperandsInstruction(op_lconst_0, 1);
+      } else if (l == 1L) {
+        return new NoOperandsInstruction(op_lconst_1, 1);
+      } else {
+        return new LongConstantInstruction(l);
+      }
+    }
+
+    //
+    // Float constants
+    //
+
+    public static Instruction make_fconst(float f) {
+      if (f == 0.0F) {
+        return new NoOperandsInstruction(op_fconst_0, 1);
+      } else if (f == 1.0F) {
+        return new NoOperandsInstruction(op_fconst_1, 1);
+      } else if (f == 2.0F) {
+        return new NoOperandsInstruction(op_fconst_2, 1);
+      } else {
+        return new FloatConstantInstruction(f);
+      }
+    }
+
+    //
+    // Generate instruction objects for invokes
+    //
+
+    public static Instruction make_invokevirtual(CodeMethod cm) {
+	return new MethodInstruction(op_invokevirtual, cm);
+    }
+
+    public static Instruction make_invokespecial(CodeMethod cm) {
+	return new MethodInstruction(op_invokespecial, cm);
+    }
+
+    public static Instruction make_invokestatic(CodeMethod cm) {
+	return new MethodInstruction(op_invokestatic, cm);
+    }
+
+    public static Instruction make_invokeinterface(CodeMethod cm) {
+	return new MethodInstruction(op_invokeinterface, cm);
+    }
+
+    //
+    // Generate instruction objects for fields
+    //
+
+    public static Instruction make_getfield(CodeField cf) {
+	return new FieldInstruction(op_getfield, cf);
+    }
+
+    public static Instruction make_putfield(CodeField cf) {
+	return new FieldInstruction(op_putfield, cf);
+    }
+
+    public static Instruction make_getstatic(CodeField cf) {
+	return new FieldInstruction(op_getstatic, cf);
+    }
+
+    public static Instruction make_putstatic(CodeField cf) {
+	return new FieldInstruction(op_putstatic, cf);
+    }
+
+    //
+    // Generate instruction objects for loads
+    //
+
+    public static Instruction make_iload(LocalVariable lv) 
+        throws CodeException
+    {
+	CodeClass cc = lv.getType();
+	if (cc != CodeUtils.TYPE_INT && 
+	    cc != CodeUtils.TYPE_SHORT && 
+	    cc != CodeUtils.TYPE_CHAR &&
+	    cc != CodeUtils.TYPE_BYTE &&
+	    cc != CodeUtils.TYPE_BOOLEAN)
+	{
+	    throw new CodeException(cc.getName() + " is not a VM `i' type");
+	}
+
+	return new LocalVariableInstruction(op_iload, op_iload_0, lv);
+    }
+
+    public static Instruction make_lload(LocalVariable lv) 
+        throws CodeException
+    {
+	if (lv.getType() != CodeUtils.TYPE_LONG) {
+	    throw new CodeException(lv.getType().getName() + " is not a long");
+	}
+
+	return new LocalVariableInstruction(op_lload, op_lload_0, lv);
+    }
+
+    public static Instruction make_fload(LocalVariable lv) 
+        throws CodeException
+    {
+	if (lv.getType() != CodeUtils.TYPE_FLOAT) {
+	    throw new CodeException(lv.getType().getName() + " is not a float");
+	}
+
+	return new LocalVariableInstruction(op_fload, op_fload_0, lv);
+    }
+
+    public static Instruction make_dload(LocalVariable lv) 
+        throws CodeException
+    {
+	if (lv.getType() != CodeUtils.TYPE_DOUBLE) {
+	    throw new CodeException(lv.getType().getName() + " is not a double");
+	}
+
+	return new LocalVariableInstruction(op_dload, op_dload_0, lv);
+    }
+
+    public static Instruction make_aload(LocalVariable lv) 
+        throws CodeException
+    {
+	if (lv.getType().isPrimitive()) {
+	    throw new CodeException(lv.getType().getName() + " is a primitive type");
+	}
+
+	return new LocalVariableInstruction(op_aload, op_aload_0, lv);
+    }
+
+    //
+    // Generate instruction objects for stores
+    //
+
+    public static Instruction make_istore(LocalVariable lv) 
+        throws CodeException
+    {
+	CodeClass cc = lv.getType();
+	if (cc != CodeUtils.TYPE_INT && 
+	    cc != CodeUtils.TYPE_SHORT && 
+	    cc != CodeUtils.TYPE_CHAR &&
+	    cc != CodeUtils.TYPE_BYTE &&
+	    cc != CodeUtils.TYPE_BOOLEAN)
+	{
+	    throw new CodeException(cc.getName() + " is not a VM `i' type");
+	}
+
+
+	return new LocalVariableInstruction(op_istore, op_istore_0, lv);
+    }
+
+    public static Instruction make_lstore(LocalVariable lv)
+        throws CodeException
+    {
+	if (lv.getType() != CodeUtils.TYPE_LONG) {
+	    throw new CodeException(lv.getType().getName() + " is not a long");
+	}
+
+	return new LocalVariableInstruction(op_lstore, op_lstore_0, lv);
+    }
+
+    public static Instruction make_fstore(LocalVariable lv) 
+        throws CodeException
+    {
+	if (lv.getType() != CodeUtils.TYPE_FLOAT) {
+	    throw new CodeException(lv.getType().getName() + " is not a float");
+	}
+
+	return new LocalVariableInstruction(op_fstore, op_fstore_0, lv);
+    }
+
+    public static Instruction make_dstore(LocalVariable lv) 
+        throws CodeException
+    {
+	if (lv.getType() != CodeUtils.TYPE_DOUBLE) {
+	    throw new CodeException(lv.getType().getName() + " is not a double");
+	}
+
+	return new LocalVariableInstruction(op_dstore, op_dstore_0, lv);
+    }
+
+    public static Instruction make_astore(LocalVariable lv) 
+        throws CodeException
+    {
+	if (lv.getType().isPrimitive()) {
+	    throw new CodeException(lv.getType().getName() + " is a primitive type");
+	}
+
+	return new LocalVariableInstruction(op_astore, op_astore_0, lv);
+    }
+
+    //
+    // Generate the Instruction objects for all this `if's
+    //
+
+    /**
+     * Return the Instruction object for the ifeq instruction.
+     */
+
+    public static Instruction make_ifeq(Label lab) {
+        return make_if(op_ifeq, lab);
+    }
+
+    /**
+     * Return the Instruction object for the ifne instruction.
+     */
+
+    public static Instruction make_ifne(Label lab) {
+        return make_if(op_ifne, lab);
+    }
+
+    /**
+     * Return the Instruction object for the iflt instruction.
+     *
+     */
+
+    public static Instruction make_iflt(Label lab) {
+        return new LabelInstruction(op_iflt, lab, -1);
+    }
+
+    /**
+     * Return the Instruction object for the ifge instruction.
+     *
+     */
+
+    public static Instruction make_ifge(Label lab) {
+        return new LabelInstruction(op_ifge, lab, -1);
+    }
+
+    /**
+     * Return the Instruction object for the ifgt instruction.
+     *
+     */
+
+    public static Instruction make_ifgt(Label lab) {
+        return new LabelInstruction(op_ifgt, lab, -1);
+    }
+
+    /**
+     * Return the Instruction object for the ifle instruction.
+     */
+
+    public static Instruction make_ifle(Label lab) {
+        return new LabelInstruction(op_ifle, lab, -1);
+    }
+
+    /**
+     * Return the Instruction object for the if_icmpeq instruction.
+     */
+
+    public static Instruction make_if_icmpeq(Label l) {
+        return new LabelInstruction(op_if_icmpeq, l, -2);
+    }
+
+    /**
+     * Return the Instruction object for the if_icmpne instruction.
+     */
+
+    public static Instruction make_if_icmpne(Label l) {
+        return new LabelInstruction(op_if_icmpne, l, -2);
+    }
+
+    /**
+     * Return the Instruction object for the if_icmplt instruction.
+     */
+
+    public static Instruction make_if_icmplt(Label l) {
+        return new LabelInstruction(op_if_icmplt, l, -2);
+    }
+
+    /**
+     * Return the Instruction object for the if_icmpge instruction.
+     */
+
+    public static Instruction make_if_icmpge(Label l) {
+        return new LabelInstruction(op_if_icmpge, l, -2);
+    }
+
+    /**
+     * Return the Instruction object for the if_icmpgt instruction.
+     */
+
+    public static Instruction make_if_icmpgt(Label l) {
+        return new LabelInstruction(op_if_icmpgt, l, -2);
+    }
+
+    /**
+     * Return the Instruction object for the if_icmple instruction.
+     */
+
+    public static Instruction make_if_icmple(Label l) {
+        return new LabelInstruction(op_if_icmple, l, -2);
+    }
+
+    /**
+     * Return the Instruction object for the if_acmpeq instruction.
+     */
+
+    public static Instruction make_if_acmpeq(Label l) {
+        return new LabelInstruction(op_if_acmpeq, l, -2);
+    }
+
+    /**
+     * Return the Instruction object for the if_acmpne instruction.
+     */
+
+    public static Instruction make_if_acmpne(Label l) {
+        return new LabelInstruction(op_if_acmpne, l, -2);
+    }
+
+    /**
+     * Return the Instruction object for the ifnull instruction.
+     */
+
+    public static Instruction make_ifnull(Label l) {
+        return new LabelInstruction(op_ifnull, l, -1);
+    }
+
+    /**
+     * Return the Instruction object for the ifnonnull instruction.
+     */
+
+    public static Instruction make_ifnonnull(Label l) {
+        return new LabelInstruction(op_ifnonnull, l, -1);
+    }
+
+    //
+    // The other label instructions
+    //
+
+    public static Instruction make_goto(Label l) {
+        return new LabelInstruction(op_goto, l, 0);
+    }
+
+    public static Instruction make_jsr(Label l) {
+        return new LabelInstruction(op_jsr, l, 1);
+    }
+
+    //
+    // Generate the Instruction objects for all the no-operands instructions
+    //
+
+    /**
+     * Return the Instruction object for the nop instruction.
+     */
+
+    public static Instruction make_nop() {
+        return new NoOperandsInstruction(op_nop, 0);
+    }
+
+    /**
+     * Return the Instruction object for the aconst_null instruction.
+     */
+
+    public static Instruction make_aconst_null() {
+        return new NoOperandsInstruction(op_aconst_null, 1);
+    }
+
+    /**
+     * Return the Instruction object for the iaload instruction.
+     */
+
+    public static Instruction make_iaload() {
+        return new NoOperandsInstruction(op_iaload, -1);
+    }
+
+    /**
+     * Return the Instruction object for the laload instruction.
+     */
+
+    public static Instruction make_laload() {
+        return new NoOperandsInstruction(op_laload, -1);
+    }
+
+    /**
+     * Return the Instruction object for the faload instruction.
+     */
+
+    public static Instruction make_faload() {
+        return new NoOperandsInstruction(op_faload, -1);
+    }
+
+    /**
+     * Return the Instruction object for the daload instruction.
+     */
+
+    public static Instruction make_daload() {
+        return new NoOperandsInstruction(op_daload, -1);
+    }
+
+    /**
+     * Return the Instruction object for the aaload instruction.
+     */
+
+    public static Instruction make_aaload() {
+        return new NoOperandsInstruction(op_aaload, -1);
+    }
+
+    /**
+     * Return the Instruction object for the baload instruction.
+     */
+
+    public static Instruction make_baload() {
+        return new NoOperandsInstruction(op_baload, -1);
+    }
+
+    /**
+     * Return the Instruction object for the caload instruction.
+     */
+
+    public static Instruction make_caload() {
+        return new NoOperandsInstruction(op_caload, -1);
+    }
+
+    /**
+     * Return the Instruction object for the saload instruction.
+     */
+
+    public static Instruction make_saload() {
+        return new NoOperandsInstruction(op_saload, -1);
+    }
+
+    /**
+     * Return the Instruction object for the iastore instruction.
+     */
+
+    public static Instruction make_iastore() {
+        return new NoOperandsInstruction(op_iastore, -3);
+    }
+
+    /**
+     * Return the Instruction object for the lastore instruction.
+     */
+
+    public static Instruction make_lastore() {
+        return new NoOperandsInstruction(op_lastore, -3);
+    }
+
+    /**
+     * Return the Instruction object for the fastore instruction.
+     */
+
+    public static Instruction make_fastore() {
+        return new NoOperandsInstruction(op_fastore, -3);
+    }
+
+    /**
+     * Return the Instruction object for the dastore instruction.
+     */
+
+    public static Instruction make_dastore() {
+        return new NoOperandsInstruction(op_dastore, -3);
+    }
+
+    /**
+     * Return the Instruction object for the aastore instruction.
+     */
+
+    public static Instruction make_aastore() {
+        return new NoOperandsInstruction(op_aastore, -3);
+    }
+
+    /**
+     * Return the Instruction object for the bastore instruction.
+     */
+
+    public static Instruction make_bastore() {
+        return new NoOperandsInstruction(op_bastore, -3);
+    }
+
+    /**
+     * Return the Instruction object for the castore instruction.
+     */
+
+    public static Instruction make_castore() {
+        return new NoOperandsInstruction(op_castore, -3);
+    }
+
+    /**
+     * Return the Instruction object for the sastore instruction.
+     */
+
+    public static Instruction make_sastore() {
+        return new NoOperandsInstruction(op_sastore, -3);
+    }
+
+    /**
+     * Return the Instruction object for the pop instruction.
+     */
+
+    public static Instruction make_pop() {
+        return new NoOperandsInstruction(op_pop, -1);
+    }
+
+    /**
+     * Return the Instruction object for the pop2 instruction.
+     */
+
+    public static Instruction make_pop2() {
+        return new NoOperandsInstruction(op_pop2, -2);
+    }
+
+    /**
+     * Return the Instruction object for the dup instruction.
+     */
+
+    public static Instruction make_dup() {
+        return new NoOperandsInstruction(op_dup, 1);
+    }
+
+    /**
+     * Return the Instruction object for the dup_x1 instruction.
+     */
+
+    public static Instruction make_dup_x1() {
+        return new NoOperandsInstruction(op_dup_x1, 1);
+    }
+
+    /**
+     * Return the Instruction object for the dup_x2 instruction.
+     */
+
+    public static Instruction make_dup_x2() {
+        return new NoOperandsInstruction(op_dup_x2, 1);
+    }
+
+    /**
+     * Return the Instruction object for the dup2 instruction.
+     */
+
+    public static Instruction make_dup2() {
+      return new NoOperandsInstruction(op_dup2, 2);
+    }
+
+    /**
+     * Return the Instruction object for the dup2_x1 instruction.
+     */
+
+    public static Instruction make_dup2_x1() {
+      return new NoOperandsInstruction(op_dup2_x1, 2);
+    }
+
+    /**
+     * Return the Instruction object for the dup2_x2 instruction.
+     */
+
+    public static Instruction make_dup2_x2() {
+        return new NoOperandsInstruction(op_dup2_x2, 2);
+    }
+
+    /**
+     * Return the Instruction object for the swap instruction.
+     */
+
+    public static Instruction make_swap() {
+        return new NoOperandsInstruction(op_swap, 0);
+    }
+
+    /**
+     * Return the Instruction object for the iadd instruction.
+     */
+
+    public static Instruction make_iadd() {
+        return new NoOperandsInstruction(op_iadd, -1);
+    }
+
+    /**
+     * Return the Instruction object for the ladd instruction.
+     */
+
+    public static Instruction make_ladd() {
+        return new NoOperandsInstruction(op_ladd, -1);
+    }
+
+    /**
+     * Return the Instruction object for the fadd instruction.
+     */
+
+    public static Instruction make_fadd() {
+        return new NoOperandsInstruction(op_fadd, -1);
+    }
+
+    /**
+     * Return the Instruction object for the dadd instruction.
+     */
+
+    public static Instruction make_dadd() {
+        return new NoOperandsInstruction(op_dadd, -1);
+    }
+
+    /**
+     * Return the Instruction object for the isub instruction.
+     */
+
+    public static Instruction make_isub() {
+        return new NoOperandsInstruction(op_isub, -1);
+    }
+
+    /**
+     * Return the Instruction object for the lsub instruction.
+     */
+
+    public static Instruction make_lsub() {
+        return new NoOperandsInstruction(op_lsub, -1);
+    }
+
+    /**
+     * Return the Instruction object for the fsub instruction.
+     */
+
+    public static Instruction make_fsub() {
+        return new NoOperandsInstruction(op_fsub, -1);
+    }
+
+    /**
+     * Return the Instruction object for the dsub instruction.
+     */
+
+    public static Instruction make_dsub() {
+        return new NoOperandsInstruction(op_dsub, -1);
+    }
+
+    /**
+     * Return the Instruction object for the imul instruction.
+     */
+
+    public static Instruction make_imul() {
+        return new NoOperandsInstruction(op_imul, -1);
+    }
+
+    /**
+     * Return the Instruction object for the lmul instruction.
+     */
+
+    public static Instruction make_lmul() {
+        return new NoOperandsInstruction(op_lmul, -1);
+    }
+
+    /**
+     * Return the Instruction object for the fmul instruction.
+     */
+
+    public static Instruction make_fmul() {
+        return new NoOperandsInstruction(op_fmul, -1);
+    }
+
+    /**
+     * Return the Instruction object for the dmul instruction.
+     */
+
+    public static Instruction make_dmul() {
+        return new NoOperandsInstruction(op_dmul, -1);
+    }
+
+    /**
+     * Return the Instruction object for the idiv instruction.
+     */
+
+    public static Instruction make_idiv() {
+        return new NoOperandsInstruction(op_idiv, -1);
+    }
+
+    /**
+     * Return the Instruction object for the ldiv instruction.
+     */
+
+    public static Instruction make_ldiv() {
+        return new NoOperandsInstruction(op_ldiv, -1);
+    }
+
+    /**
+     * Return the Instruction object for the fdiv instruction.
+     */
+
+    public static Instruction make_fdiv() {
+        return new NoOperandsInstruction(op_fdiv, -1);
+    }
+
+    /**
+     * Return the Instruction object for the ddiv instruction.
+     */
+
+    public static Instruction make_ddiv() {
+        return new NoOperandsInstruction(op_ddiv, -1);
+    }
+
+    /**
+     * Return the Instruction object for the irem instruction.
+     */
+
+    public static Instruction make_irem() {
+        return new NoOperandsInstruction(op_irem, -1);
+    }
+
+    /**
+     * Return the Instruction object for the lrem instruction.
+     */
+
+    public static Instruction make_lrem() {
+        return new NoOperandsInstruction(op_lrem, -1);
+    }
+
+    /**
+     * Return the Instruction object for the frem instruction.
+     */
+
+    public static Instruction make_frem() {
+        return new NoOperandsInstruction(op_frem, -1);
+    }
+
+    /**
+     * Return the Instruction object for the drem instruction.
+     */
+
+    public static Instruction make_drem() {
+        return new NoOperandsInstruction(op_drem, -1);
+    }
+
+    /**
+     * Return the Instruction object for the ineg instruction.
+     */
+
+    public static Instruction make_ineg() {
+        return new NoOperandsInstruction(op_ineg, 0);
+    }
+
+    /**
+     * Return the Instruction object for the lneg instruction.
+     */
+
+    public static Instruction make_lneg() {
+        return new NoOperandsInstruction(op_lneg, 0);
+    }
+
+    /**
+     * Return the Instruction object for the fneg instruction.
+     */
+
+    public static Instruction make_fneg() {
+        return new NoOperandsInstruction(op_fneg, 0);
+    }
+
+    /**
+     * Return the Instruction object for the dneg instruction.
+     */
+
+    public static Instruction make_dneg() {
+        return new NoOperandsInstruction(op_dneg, 0);
+    }
+
+    /**
+     * Return the Instruction object for the ishl instruction.
+     */
+
+    public static Instruction make_ishl() {
+        return new NoOperandsInstruction(op_ishl, -1);
+    }
+
+    /**
+     * Return the Instruction object for the lshl instruction.
+     */
+
+    public static Instruction make_lshl() {
+        return new NoOperandsInstruction(op_lshl, -1);
+    }
+
+    /**
+     * Return the Instruction object for the ishr instruction.
+     */
+
+    public static Instruction make_ishr() {
+        return new NoOperandsInstruction(op_ishr, -1);
+    }
+
+    /**
+     * Return the Instruction object for the lshr instruction.
+     */
+
+    public static Instruction make_lshr() {
+        return new NoOperandsInstruction(op_lshr, -1);
+    }
+
+    /**
+     * Return the Instruction object for the iushr instruction.
+     */
+
+    public static Instruction make_iushr() {
+        return new NoOperandsInstruction(op_iushr, -1);
+    }
+
+    /**
+     * Return the Instruction object for the lushr instruction.
+     */
+
+    public static Instruction make_lushr() {
+        return new NoOperandsInstruction(op_lushr, -1);
+    }
+
+    /**
+     * Return the Instruction object for the iand instruction.
+     */
+
+    public static Instruction make_iand() {
+        return new NoOperandsInstruction(op_iand, -1);
+    }
+
+    /**
+     * Return the Instruction object for the land instruction.
+     */
+
+    public static Instruction make_land() {
+        return new NoOperandsInstruction(op_land, -1);
+    }
+
+    /**
+     * Return the Instruction object for the ior instruction.
+     */
+
+    public static Instruction make_ior() {
+        return new NoOperandsInstruction(op_ior, -1);
+    }
+
+    /**
+     * Return the Instruction object for the lor instruction.
+     */
+
+    public static Instruction make_lor() {
+        return new NoOperandsInstruction(op_lor, -1);
+    }
+
+    /**
+     * Return the Instruction object for the ixor instruction.
+     */
+
+    public static Instruction make_ixor() {
+        return new NoOperandsInstruction(op_ixor, -1);
+    }
+
+    /**
+     * Return the Instruction object for the lxor instruction.
+     */
+
+    public static Instruction make_lxor() {
+        return new NoOperandsInstruction(op_lxor, -1);
+    }
+
+    /**
+     * Return the Instruction object for the i2l instruction.
+     */
+
+    public static Instruction make_i2l() {
+        return new NoOperandsInstruction(op_i2l, 0);
+    }
+
+    /**
+     * Return the Instruction object for the i2f instruction.
+     */
+
+    public static Instruction make_i2f() {
+        return new NoOperandsInstruction(op_i2f, 0);
+    }
+
+    /**
+     * Return the Instruction object for the i2d instruction.
+     */
+
+    public static Instruction make_i2d() {
+        return new NoOperandsInstruction(op_i2d, 0);
+    }
+
+    /**
+     * Return the Instruction object for the l2i instruction.
+     */
+
+    public static Instruction make_l2i() {
+        return new NoOperandsInstruction(op_l2i, 0);
+    }
+
+    /**
+     * Return the Instruction object for the l2f instruction.
+     */
+
+    public static Instruction make_l2f() {
+        return new NoOperandsInstruction(op_l2f, 0);
+    }
+
+    /**
+     * Return the Instruction object for the l2d instruction.
+     */
+
+    public static Instruction make_l2d() {
+        return new NoOperandsInstruction(op_l2d, 0);
+    }
+
+    /**
+     * Return the Instruction object for the f2i instruction.
+     */
+
+    public static Instruction make_f2i() {
+        return new NoOperandsInstruction(op_f2i, 0);
+    }
+
+    /**
+     * Return the Instruction object for the f2l instruction.
+     */
+
+    public static Instruction make_f2l() {
+        return new NoOperandsInstruction(op_f2l, 0);
+    }
+
+    /**
+     * Return the Instruction object for the f2d instruction.
+     */
+
+    public static Instruction make_f2d() {
+        return new NoOperandsInstruction(op_f2d, 0);
+    }
+
+    /**
+     * Return the Instruction object for the d2i instruction.
+     */
+
+    public static Instruction make_d2i() {
+        return new NoOperandsInstruction(op_d2i, 0);
+    }
+
+    /**
+     * Return the Instruction object for the d2l instruction.
+     */
+
+    public static Instruction make_d2l() {
+        return new NoOperandsInstruction(op_d2l, 0);
+    }
+
+    /**
+     * Return the Instruction object for the d2f instruction.
+     */
+
+    public static Instruction make_d2f() {
+        return new NoOperandsInstruction(op_d2f, 0);
+    }
+
+    /**
+     * Return the Instruction object for the i2b instruction.
+     */
+
+    public static Instruction make_i2b() {
+        return new NoOperandsInstruction(op_i2b, 0);
+    }
+
+    /**
+     * Return the Instruction object for the i2c instruction.
+     */
+
+    public static Instruction make_i2c() {
+        return new NoOperandsInstruction(op_i2c, 0);
+    }
+
+    /**
+     * Return the Instruction object for the i2s instruction.
+     */
+
+    public static Instruction make_i2s() {
+        return new NoOperandsInstruction(op_i2s, 0);
+    }
+
+    /**
+     * Return the Instruction object for the lcmp instruction.
+     */
+
+    public static Instruction make_lcmp() {
+        return new NoOperandsInstruction(op_lcmp, -1);
+    }
+
+    /**
+     * Return the Instruction object for the fcmpl instruction.
+     */
+
+    public static Instruction make_fcmpl() {
+        return new NoOperandsInstruction(op_fcmpl, -1);
+    }
+
+    /**
+     * Return the Instruction object for the fcmpg instruction.
+     */
+
+    public static Instruction make_fcmpg() {
+        return new NoOperandsInstruction(op_fcmpg, -1);
+    }
+
+    /**
+     * Return the Instruction object for the dcmpl instruction.
+     */
+
+    public static Instruction make_dcmpl() {
+        return new NoOperandsInstruction(op_dcmpl, -1);
+    }
+
+    /**
+     * Return the Instruction object for the dcmpg instruction.
+     */
+
+    public static Instruction make_dcmpg() {
+        return new NoOperandsInstruction(op_dcmpg, -1);
+    }
+
+    /**
+     * Return the Instruction object for the ireturn instruction.
+     */
+
+    public static Instruction make_ireturn() {
+        return new NoOperandsInstruction(op_ireturn, -1);
+    }
+
+    /**
+     * Return the Instruction object for the lreturn instruction.
+     */
+
+    public static Instruction make_lreturn() {
+        return new NoOperandsInstruction(op_lreturn, -1);
+    }
+
+    /**
+     * Return the Instruction object for the freturn instruction.
+     */
+
+    public static Instruction make_freturn() {
+        return new NoOperandsInstruction(op_freturn, -1);
+    }
+
+    /**
+     * Return the Instruction object for the dreturn instruction.
+     */
+
+    public static Instruction make_dreturn() {
+        return new NoOperandsInstruction(op_dreturn, -1);
+    }
+
+    /**
+     * Return the Instruction object for the areturn instruction.
+     */
+
+    public static Instruction make_areturn() {
+        return new NoOperandsInstruction(op_areturn, -1);
+    }
+
+    /**
+     * Return the Instruction object for the return instruction.
+     */
+
+    public static Instruction make_return() {
+        return new NoOperandsInstruction(op_return, 0);
+    }
+    
+    /**
+     * Return the Instruction object for the arraylength instruction.
+     */
+
+    public static Instruction make_arraylength() {
+        return new NoOperandsInstruction(op_arraylength, 0);
+    }
+
+    /**
+     * Return the Instruction object for the athrow instruction.
+     */
+
+    public static Instruction make_athrow() {
+        return new NoOperandsInstruction(op_athrow, 0);
+    }
+
+    /**
+     * Return the Instruction object for the monitorenter instruction.
+     *
+     */
+
+    public static Instruction make_monitorenter() {
+        return new NoOperandsInstruction(op_monitorenter, -1);
+    }
+
+    /**
+     * Return the Instruction object for the monitorexit instruction.
+     */
+
+    public static Instruction make_monitorexit() {
+        return new NoOperandsInstruction(op_monitorexit, -1);
+    }
+
+    /**
+     * Return the Instruction object for the wide instruction.
+     */
+
+    public static Instruction make_wide() {
+        return new NoOperandsInstruction(op_wide, 0);
+    }
+
+    /**
+     * Return the Instruction object for the breakpoint instruction.
+     */
+
+    public static Instruction make_breakpoint() {
+        return new NoOperandsInstruction(op_breakpoint, 0);
+    }
+
+    /**
+     * Return the Instruction object for the invokevirtual_quick_w instruction.
+     *
+     * Apparently now undocumented. Presumably deprecated.
+     */
+
+    public static Instruction make_invokevirtual_quick_w() {
+        // fixme - I have no idea what the stack-depth change is here
+        // should we even be using this class?
+        return new NoOperandsInstruction(op_invokevirtual_quick_w, 0);
+    }
+
+    /**
+     * Return the Instruction object for the impdep1 instruction.
+     */
+
+    public static Instruction make_impdep1() {
+        return new NoOperandsInstruction(op_impdep1, 0);
+    }
+
+    /**
+     * Return the Instruction object for the impdep2 instruction.
+     */
+
+    public static Instruction make_impdep2() {
+        return new NoOperandsInstruction(op_impdep2, 0);
+    }
+
+  public static Instruction make_checkcast(CodeClass clazz) {
+    return new ClassInstruction(op_checkcast, clazz, 0);
+  }
+
+  public static Instruction make_instanceof(CodeClass clazz) {
+    return new ClassInstruction(op_instanceof, clazz, 0);
+  }
+    // new instruction added by hand - mrp
+    
+    public static Instruction make_new(CodeClass clazz) {
+      return new ClassInstruction(op_new, clazz, 1);
+    }
+
+    public static Instruction make_newarray(CodeClass clazz) 
+        throws CodeException
+    {
+      if (clazz.isPrimitive()) {
+        int type = -1;
+        if (clazz == CodeUtils.TYPE_BOOLEAN) {
+          type = 4;
+        } else if (clazz == CodeUtils.TYPE_CHAR) {
+          type = 5;
+        } else if (clazz == CodeUtils.TYPE_FLOAT) {
+          type = 6;
+        } else if (clazz == CodeUtils.TYPE_DOUBLE) {
+          type = 7;
+        } else if (clazz == CodeUtils.TYPE_BYTE) {
+          type = 8;
+        } else if (clazz == CodeUtils.TYPE_SHORT) {
+          type = 9;
+        } else if (clazz == CodeUtils.TYPE_INT) {
+          type = 10;
+        } else if (clazz == CodeUtils.TYPE_LONG) {
+          type = 11;
+        } 
+        if (type < 0) { 
+          throw new CodeException("Invalid type " + clazz.getName());
+        }
+       
+        return new ByteInstruction(op_newarray, (byte) type, 0);
+      } else {
+        return new ClassInstruction(op_anewarray, clazz, 0);
+      }
+    }
+
+    /**
+     * A convenient one-stop method to get a return statement suitable for a
+     * method.
+     *
+     * @param method  the CodeMethod to return from
+     * @return a return Instruction that fits this method's return type
+     */
+    public static Instruction make_return(CodeMethod method) {
+      return make_return(method.getReturnType());
+    }
+    
+    /**
+     * Creates the return Instruction suitable for a given class or type.
+     *
+     * @param clazz  the CodeClass representing the class or type to return
+     * @return  the apropreate return instruction
+     */
+    public static Instruction make_return(CodeClass clazz) {
+      if (false) {
+      } else if(CodeUtils.TYPE_VOID.equals(clazz)) {
+        return make_return();
+      } else if(
+        CodeUtils.TYPE_BYTE.equals(clazz) ||
+        CodeUtils.TYPE_SHORT.equals(clazz) ||
+        CodeUtils.TYPE_CHAR.equals(clazz) ||
+        CodeUtils.TYPE_BOOLEAN.equals(clazz) ||
+        CodeUtils.TYPE_INT.equals(clazz)
+      ) {
+        return make_ireturn();
+      } else if(CodeUtils.TYPE_LONG.equals(clazz)) {
+        return make_lreturn();
+      } else if(CodeUtils.TYPE_FLOAT.equals(clazz)) {
+        return make_freturn();
+      } else if(CodeUtils.TYPE_DOUBLE.equals(clazz)) {
+        return make_dreturn();
+      }
+
+      return make_areturn();
+    }
+
+    /**
+     * Make an invoke opcode that is suited to the method.
+     *
+     * <p>Constructors and private methods are invoked by invokespecial.
+     * Static methods are invoked by invokestatic. Methods referred to by
+     * interface are invoked by invokeinterface, and methods referred to
+     * by classes are invoked by invokeabstract.</p>
+     *
+     * @param cm  the CodeMethod to invoke
+     * @return an invocation Instruction suited to the method
+     */
+    public static Instruction make_invoke(CodeMethod cm) {
+      int modifiers = cm.getModifiers();
+
+      if( (CodeUtils.ACC_STATIC & modifiers) != 0 ) {
+        return make_invokestatic(cm);
+      } else if( (CodeUtils.ACC_INTERFACE) != 0 ) {
+        return make_invokeinterface(cm);
+      } else if( (CodeUtils.ACC_PRIVATE) != 0 ) {
+        return make_invokespecial(cm);
+      } else {
+        return make_invokevirtual(cm);
+      }
+    }
+    
+    /**
+     * Synchronize the processing of an entire block of code on a local
+     * variable. The local variable must refer to a Java object. It is safe to
+     * replace the value of the local variable within the block.
+     *
+     * @param lockVar  Label for the local variable to lock on
+     * @param code the CodeGenerator that will make the body of the synchronized
+     *   block
+     * @throws CodeException if locVar holds a primative value
+     */
+    public static CodeGenerator make_synchronizedBlock(
+      LocalVariable lockVar,
+      CodeGenerator code
+    ) throws CodeException {
+      InstructionVector block = new InstructionVector();
+      block.add(make_aload(lockVar));
+      block.add(make_dup()); // defencive copy incase the local is re-assigned
+      block.add(make_monitorenter());
+      block.add(code);
+      block.add(make_monitorexit());
+      
+      return block;
+    }
+    
+    /**
+     * Synchronize the processing of an entire block of code on the object on
+     * the top of the stack.
+     *
+     * @param lockVar  Label for the local variable to lock on
+     * @param code the CodeGenerator that will make the body of the synchronized
+     *   block
+     */
+    public static CodeGenerator make_synchronizedBlock(CodeGenerator code) {
+      InstructionVector block = new InstructionVector();
+      block.add(make_dup());
+      block.add(make_monitorenter());
+      block.add(code);
+      block.add(make_monitorexit());
+      
+      return block;
+    }
+    
+    public static CodeGenerator make_markLabel(Label lab) {
+      return new MarkLabel(lab);
+    }
+
+    /**
+     * Make an if Instruction for the opcode and label.
+     *
+     * <p>Obcodes for IF jump to the label if the condition is true, or execute
+     * the next instruction ontherwise. In this case, op will be used to compare
+     * the top of the stack and if the condition is true, will cause a jump to
+     * the label. Otherwise, the next instruction in the stream will be used.
+     * </p>
+     *
+     * @param op  if opcode
+     * @param lab Label to jump to
+     * @return an Instruction that will perform an if 
+     * @throws IllegalArgumentException if the op code is not an if instruction
+     */
+    public static Instruction make_if(byte op, Label lab) {
+      if(op >= op_ifeq && op <= op_ifle) {
+        return new LabelInstruction(op, lab, -1);
+      } else if(op >= op_if_icmpeq && op <= op_if_acmpne) {
+        return new LabelInstruction(op, lab, -2);
+      } else {
+        throw new IllegalArgumentException("Opcode must be an if. " + op);
+      }
+    }
+    
+    public static ParametricCodeGenerator make_newraray(final ParametricType type) {
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDepth() { return 0; }
+        public int stackDelta() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          make_newarray(cc).writeCode(ctx);
+        }
+      };
+    }
+    
+    /**
+     * Load an element of a parametric type to an array.
+     *
+     * <p>This is the parametric version of the make_<x>aload() factory
+     * methods.</p>
+     *
+     * @param type  the ParametricType giving the element type of the array
+     * @return a ParametricCodeGenerator that will load the correct type.
+     */
+    public static ParametricCodeGenerator make_array_load(final ParametricType type) {
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDepth() { return 0; }
+        public int stackDelta() { return -1; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          if(!cc.isPrimitive()) {
+            ctx.writeByte(op_aaload);
+          } else if(cc == CodeUtils.TYPE_INT) {
+            ctx.writeByte(op_iaload);
+          } else if(cc == CodeUtils.TYPE_LONG) {
+            ctx.writeByte(op_daload);
+          } else if(cc == CodeUtils.TYPE_FLOAT) {
+            ctx.writeByte(op_faload);
+          } else if(cc == CodeUtils.TYPE_DOUBLE) {
+            ctx.writeByte(op_daload);
+          } else if(cc == CodeUtils.TYPE_BYTE) {
+            ctx.writeByte(op_baload);
+          } else if(cc == CodeUtils.TYPE_CHAR) {
+            ctx.writeByte(op_caload);
+          } else if(cc == CodeUtils.TYPE_SHORT) {
+            ctx.writeByte(op_saload);
+          } else {
+            throw new CodeException("Confused. Don't recognize type: " + cc);
+          }
+        }
+      };
+    }
+
+    /**
+     * Store an element of a parametric type to an array.
+     *
+     * <p>This is the parametric version of the make_<x>astore() factory
+     * methods.</p>
+     *
+     * @param type  the ParametricType giving the element type of the array
+     * @return a ParametricCodeGenerator that will store the correct type.
+     */
+    public static ParametricCodeGenerator make_arrayStore(final ParametricType type) {
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDepth() { return 0; }
+        public int stackDelta() { return -3; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          if(!cc.isPrimitive()) {
+            ctx.writeByte(op_aastore);
+          } else if(cc == CodeUtils.TYPE_INT) {
+            ctx.writeByte(op_iastore);
+          } else if(cc == CodeUtils.TYPE_LONG) {
+            ctx.writeByte(op_dastore);
+          } else if(cc == CodeUtils.TYPE_FLOAT) {
+            ctx.writeByte(op_fastore);
+          } else if(cc == CodeUtils.TYPE_DOUBLE) {
+            ctx.writeByte(op_dastore);
+          } else if(cc == CodeUtils.TYPE_BYTE) {
+            ctx.writeByte(op_bastore);
+          } else if(cc == CodeUtils.TYPE_CHAR) {
+            ctx.writeByte(op_castore);
+          } else if(cc == CodeUtils.TYPE_SHORT) {
+            ctx.writeByte(op_sastore);
+          } else {
+            throw new CodeException("Confused. Don't recognize type: " + cc);
+          }
+        }
+      };
+    }
+    
+    /**
+     * Load an item of a parametric type from a local variable.
+     *
+     * <p>This is the parametric version of the make_<x>load() factory
+     * methods.</p>
+     *
+     * @param type  the ParametricType giving the type to load
+     * @param lv  the LocalVariable to load from
+     * @return a ParametricCodeGenerator that will load the correct type.
+     */
+    public ParametricCodeGenerator make_load(
+      final ParametricType type,
+      final LocalVariable lv
+    ) throws CodeException {
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDepth() { return 1; }
+        public int stackDelta() { return 1; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          Instruction ins;
+          if(!cc.isPrimitive()) {
+            ins = make_aload(lv);
+          } else if(cc == CodeUtils.TYPE_INT) {
+            ins = make_iload(lv);
+          } else if(cc == CodeUtils.TYPE_LONG) {
+            ins = make_lload(lv);
+          } else if(cc == CodeUtils.TYPE_FLOAT) {
+            ins = make_fload(lv);
+          } else if(cc == CodeUtils.TYPE_DOUBLE) {
+            ins = make_dload(lv);
+          } else if(cc == CodeUtils.TYPE_BYTE) {
+            ins = make_iload(lv);
+          } else if(cc == CodeUtils.TYPE_CHAR) {
+            ins = make_iload(lv);
+          } else if(cc == CodeUtils.TYPE_SHORT) {
+            ins = make_iload(lv);
+          } else {
+            throw new CodeException("Confused. Don't recognize type: " + cc);
+          }
+          
+          ins.writeCode(ctx);
+        }
+      };
+    }
+    
+    /**
+     * Store an item of a parametric type to a local variable.
+     *
+     * <p>This is the parametric version of the make_<x>save() factory
+     * methods.</p>
+     *
+     * @param type  the ParametricType giving the type to save
+     * @param lv  the LocalVariable to load from
+     * @return a ParametricCodeGenerator that will save the correct type.
+     */
+    public ParametricCodeGenerator make_save(
+      final ParametricType type,
+      final LocalVariable lv
+    ) throws CodeException {
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDepth() { return 0; }
+        public int stackDelta() { return -1; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          Instruction ins;
+          if(!cc.isPrimitive()) {
+            ins = make_astore(lv);
+          } else if(cc == CodeUtils.TYPE_INT) {
+            ins = make_istore(lv);
+          } else if(cc == CodeUtils.TYPE_LONG) {
+            ins = make_lstore(lv);
+          } else if(cc == CodeUtils.TYPE_FLOAT) {
+            ins = make_fstore(lv);
+          } else if(cc == CodeUtils.TYPE_DOUBLE) {
+            ins = make_dstore(lv);
+          } else if(cc == CodeUtils.TYPE_BYTE) {
+            ins = make_istore(lv);
+          } else if(cc == CodeUtils.TYPE_CHAR) {
+            ins = make_istore(lv);
+          } else if(cc == CodeUtils.TYPE_SHORT) {
+            ins = make_istore(lv);
+          } else {
+            throw new CodeException("Confused. Don't recognize type: " + cc);
+          }
+          
+          ins.writeCode(ctx);
+        }
+      };
+    }
+    
+    /**
+     * Make a return statement for the parametric type.
+     *
+     * @param type  the ParametricType to return
+     */
+    public ParametricCodeGenerator make_return(final ParametricType type) {
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDepth() { return 0; }
+        public int stackDelta() { return -1; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          if(!cc.isPrimitive()) {
+            ctx.writeByte(op_areturn);
+          } else if(cc == CodeUtils.TYPE_INT) {
+            ctx.writeByte(op_ireturn);
+          } else if(cc == CodeUtils.TYPE_LONG) {
+            ctx.writeByte(op_lreturn);
+          } else if(cc == CodeUtils.TYPE_FLOAT) {
+            ctx.writeByte(op_freturn);
+          } else if(cc == CodeUtils.TYPE_DOUBLE) {
+            ctx.writeByte(op_dreturn);
+          } else if(cc == CodeUtils.TYPE_BYTE) {
+            ctx.writeByte(op_ireturn);
+          } else if(cc == CodeUtils.TYPE_CHAR) {
+            ctx.writeByte(op_ireturn);
+          } else if(cc == CodeUtils.TYPE_SHORT) {
+            ctx.writeByte(op_ireturn);
+          } else {
+            throw new CodeException("Confused. Don't recognize type: " + cc);
+          }
+        }
+      };
+    }
+    
+    public PParametricCodeGenerator make_cast(
+      final ParametricType from,
+      final ParametricType to
+    ) throws CodeException {
+      if(from.isObject()) {
+        throw new CodeException("Can not cast from non-primative type: " + from);
+      }
+      
+      if(to.isObject()) {
+        throw new CodeException("Can not cast to non-primative type: " + to);
+      }
+      
+      return new PParametricCodeGenerator() {
+        public ParametricType getType1() { return from; }
+        public ParametricType getType2() { return to; }
+        public int stackDepth() { return 0; }
+        public int stackDelta() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          if(from == to) {
+            return;
+          }
+          
+          CodeClass fromc = ctx.resolveParametricType(from);
+          CodeClass toc = ctx.resolveParametricType(to);
+          
+          if(!fromc.isPrimitive()) {
+            throw new CodeException("Can't cast from non-primitive type: " + fromc);
+          }
+          
+          if(!toc.isPrimitive()) {
+            throw new CodeException("Can't cast to non-primitive type: " + toc);
+          }
+          
+          if(fromc == CodeUtils.TYPE_DOUBLE) {
+            if(toc == CodeUtils.TYPE_FLOAT) {
+              ctx.writeByte(op_d2f);
+            } else if(toc == CodeUtils.TYPE_LONG) {
+              ctx.writeByte(op_d2l);
+            } else {
+              ctx.writeByte(op_d2i);
+            }
+          } else if(fromc == CodeUtils.TYPE_LONG) {
+            if(toc == CodeUtils.TYPE_FLOAT) {
+              ctx.writeByte(op_l2f);
+            } else if(toc == CodeUtils.TYPE_DOUBLE) {
+              ctx.writeByte(op_l2d);
+            } else {
+              ctx.writeByte(op_d2i);
+            }
+          } else { // something equivalent to integer
+            if(toc == CodeUtils.TYPE_FLOAT) {
+              ctx.writeByte(op_i2f);
+            } else if(toc == CodeUtils.TYPE_DOUBLE) {
+              ctx.writeByte(op_i2d);
+            } else if(toc == CodeUtils.TYPE_LONG) {
+              ctx.writeByte(op_i2l);
+            } else if(toc == CodeUtils.TYPE_BYTE) {
+              ctx.writeByte(op_i2b);
+            } else if(toc == CodeUtils.TYPE_CHAR) {
+              ctx.writeByte(op_i2c);
+            } else if(toc == CodeUtils.TYPE_SHORT) {
+              ctx.writeByte(op_i2s);
+            }
+          }
+        }
+      };
+    }
+    
+    public ParametricCodeGenerator make_add(final ParametricType type)
+    throws CodeException {
+      if(type.isObject()) {
+        throw new CodeException("Can't add non-primitive type: " + type);
+      }
+      
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDelta() { return -1; }
+        public int stackDepth() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          
+          if(!cc.isPrimitive()) {
+            throw new CodeException(
+              "We can only add primitive types: " +
+              type + " : " + cc );
+          }
+          
+          if(cc == CodeUtils.TYPE_DOUBLE) {
+            ctx.writeByte(op_dadd);
+          } else if(cc == CodeUtils.TYPE_LONG) {
+            ctx.writeByte(op_ladd);
+          } else if(cc == CodeUtils.TYPE_FLOAT) {
+            ctx.writeByte(op_fadd);
+          } else {
+            ctx.writeByte(op_iadd);
+          }
+        }
+      };
+    }
+    
+    public ParametricCodeGenerator make_sub(final ParametricType type)
+    throws CodeException {
+      if(type.isObject()) {
+        throw new CodeException("Can't sub non-primitive type: " + type);
+      }
+      
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDelta() { return -1; }
+        public int stackDepth() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          
+          if(!cc.isPrimitive()) {
+            throw new CodeException(
+              "We can only sub primitive types: " +
+              type + " : " + cc );
+          }
+          
+          if(cc == CodeUtils.TYPE_DOUBLE) {
+            ctx.writeByte(op_dsub);
+          } else if(cc == CodeUtils.TYPE_LONG) {
+            ctx.writeByte(op_lsub);
+          } else if(cc == CodeUtils.TYPE_FLOAT) {
+            ctx.writeByte(op_fsub);
+          } else {
+            ctx.writeByte(op_isub);
+          }
+        }
+      };
+    }
+
+    
+    public ParametricCodeGenerator make_mul(final ParametricType type)
+    throws CodeException {
+      if(type.isObject()) {
+        throw new CodeException("Can't mul non-primitive type: " + type);
+      }
+      
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDelta() { return -1; }
+        public int stackDepth() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          
+          if(!cc.isPrimitive()) {
+            throw new CodeException(
+              "We can only mul primitive types: " +
+              type + " : " + cc );
+          }
+          
+          if(cc == CodeUtils.TYPE_DOUBLE) {
+            ctx.writeByte(op_dmul);
+          } else if(cc == CodeUtils.TYPE_LONG) {
+            ctx.writeByte(op_lmul);
+          } else if(cc == CodeUtils.TYPE_FLOAT) {
+            ctx.writeByte(op_fmul);
+          } else {
+            ctx.writeByte(op_imul);
+          }
+        }
+      };
+    }
+    
+    
+    public ParametricCodeGenerator make_div(final ParametricType type)
+    throws CodeException {
+      if(type.isObject()) {
+        throw new CodeException("Can't div non-primitive type: " + type);
+      }
+      
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDelta() { return -1; }
+        public int stackDepth() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          
+          if(!cc.isPrimitive()) {
+            throw new CodeException(
+              "We can only div primitive types: " +
+              type + " : " + cc );
+          }
+          
+          if(cc == CodeUtils.TYPE_DOUBLE) {
+            ctx.writeByte(op_ddiv);
+          } else if(cc == CodeUtils.TYPE_LONG) {
+            ctx.writeByte(op_ldiv);
+          } else if(cc == CodeUtils.TYPE_FLOAT) {
+            ctx.writeByte(op_fdiv);
+          } else {
+            ctx.writeByte(op_idiv);
+          }
+        }
+      };
+    }
+    
+    public ParametricCodeGenerator make_rem(final ParametricType type)
+    throws CodeException {
+      if(type.isObject()) {
+        throw new CodeException("Can't rem non-primitive type: " + type);
+      }
+      
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDelta() { return -1; }
+        public int stackDepth() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          
+          if(!cc.isPrimitive()) {
+            throw new CodeException(
+              "We can only rem primitive types: " +
+              type + " : " + cc );
+          }
+          
+          if(cc == CodeUtils.TYPE_DOUBLE) {
+            ctx.writeByte(op_drem);
+          } else if(cc == CodeUtils.TYPE_LONG) {
+            ctx.writeByte(op_lrem);
+          } else if(cc == CodeUtils.TYPE_FLOAT) {
+            ctx.writeByte(op_frem);
+          } else {
+            ctx.writeByte(op_irem);
+          }
+        }
+      };
+    }
+    
+    public ParametricCodeGenerator make_neg(final ParametricType type)
+    throws CodeException {
+      if(type.isObject()) {
+        throw new CodeException("Can't add non-primitive type: " + type);
+      }
+      
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDelta() { return 0; }
+        public int stackDepth() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          
+          if(!cc.isPrimitive()) {
+            throw new CodeException(
+              "We can only add primitive types: " +
+              type + " : " + cc );
+          }
+          
+          if(cc == CodeUtils.TYPE_DOUBLE) {
+            ctx.writeByte(op_dneg);
+          } else if(cc == CodeUtils.TYPE_LONG) {
+            ctx.writeByte(op_lneg);
+          } else if(cc == CodeUtils.TYPE_FLOAT) {
+            ctx.writeByte(op_fneg);
+          } else {
+            ctx.writeByte(op_ineg);
+          }
+        }
+      };
+    }
+
+    public ParametricCodeGenerator make_shiftLeft(final ParametricType type)
+    throws CodeException {
+      if(type.isObject()) {
+        throw new CodeException("Can't shift non-primitive type: " + type);
+      }
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDelta() { return -1; }
+        public int stackDepth() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          
+          if(!cc.isPrimitive()) {
+            throw new CodeException("Can't shift non-primitive type: " + cc);
+          }
+          
+          if(CodeUtils.isFloatType(cc)) {
+            throw new CodeException("Can't shift floating point type: " + cc);
+          }
+          
+          if(cc == CodeUtils.TYPE_LONG) {
+            ctx.writeByte(op_lshl);
+          } else  {
+            ctx.writeByte(op_ishl);
+          }
+        }
+      };
+    }
+    
+    public ParametricCodeGenerator make_shiftRight(final ParametricType type)
+    throws CodeException {
+      if(type.isObject()) {
+        throw new CodeException("Can't shift non-primitive type: " + type);
+      }
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDelta() { return -1; }
+        public int stackDepth() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          
+          if(!cc.isPrimitive()) {
+            throw new CodeException("Can't shift non-primitive type: " + cc);
+          }
+          
+          if(CodeUtils.isFloatType(cc)) {
+            throw new CodeException("Can't shift floating point type: " + cc);
+          }
+          
+          if(cc == CodeUtils.TYPE_LONG) {
+            ctx.writeByte(op_lshr);
+          } else {
+            ctx.writeByte(op_ishr);
+          }
+        }
+      };
+    }
+    
+    public ParametricCodeGenerator make_shiftRightLogical(final ParametricType type)
+    throws CodeException {
+      if(type.isObject()) {
+        throw new CodeException("Can't shift non-primitive type: " + type);
+      }
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDelta() { return -1; }
+        public int stackDepth() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          
+          if(!cc.isPrimitive()) {
+            throw new CodeException("Can't shift non-primitive type: " + cc);
+          }
+          
+          if(CodeUtils.isFloatType(cc)) {
+            throw new CodeException("Can't shift floating point type: " + cc);
+          }
+          
+          if(cc == CodeUtils.TYPE_LONG) {
+            ctx.writeByte(op_lushr);
+          } else {
+            ctx.writeByte(op_iushr);
+          }
+        }
+      };
+    }
+    
+    public ParametricCodeGenerator make_and(final ParametricType type)
+    throws CodeException {
+      if(type.isObject()) {
+        throw new CodeException("Can't and non-primitive type: " + type);
+      }
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDelta() { return -1; }
+        public int stackDepth() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          
+          if(!cc.isPrimitive()) {
+            throw new CodeException("Can't and non-primitive type: " + cc);
+          }
+          
+          if(CodeUtils.isFloatType(cc)) {
+            throw new CodeException("Can't and floating point type: " + cc);
+          }
+          
+          
+          if(cc == CodeUtils.TYPE_LONG) {
+            ctx.writeByte(op_land);
+          } else {
+            ctx.writeByte(op_iand);
+          }
+        }
+      };
+    }
+    
+    public ParametricCodeGenerator make_or(final ParametricType type)
+    throws CodeException {
+      if(type.isObject()) {
+        throw new CodeException("Can't and non-primitive type: " + type);
+      }
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDelta() { return -1; }
+        public int stackDepth() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          
+          if(!cc.isPrimitive()) {
+            throw new CodeException("Can't or non-primitive type: " + cc);
+          }
+          
+          if(CodeUtils.isFloatType(cc)) {
+            throw new CodeException("Can't or floating point type: " + cc);
+          }
+          
+          
+          if(cc == CodeUtils.TYPE_LONG) {
+            ctx.writeByte(op_lor);
+          } else {
+            ctx.writeByte(op_ior);
+          }
+        }
+      };
+    }
+    
+    public ParametricCodeGenerator make_xor(final ParametricType type)
+    throws CodeException {
+      if(type.isObject()) {
+        throw new CodeException("Can't and non-primitive type: " + type);
+      }
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDelta() { return -1; }
+        public int stackDepth() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          
+          if(!cc.isPrimitive()) {
+            throw new CodeException("Can't xor non-primitive type: " + cc);
+          }
+
+          if(CodeUtils.isFloatType(cc)) {
+            throw new CodeException("Can't xor floating point type: " + cc);
+          }
+          
+          
+          if(cc == CodeUtils.TYPE_LONG) {
+            ctx.writeByte(op_lxor);
+          } else  {
+            ctx.writeByte(op_ixor);
+          }
+        }
+      };
+    }
+    
+    public ParametricCodeGenerator make_cmpg(final ParametricType type)
+    throws CodeException {
+      if(type.isObject()) {
+        throw new CodeException("Can't cmpg non-primitive type: " + type);
+      }
+      
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDelta() { return -1; }
+        public int stackDepth() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          
+          if(!CodeUtils.isFloatType(cc)) {
+            throw new CodeException("Can only cmpg floating point types: " + cc);
+          }
+          
+          if(cc == CodeUtils.TYPE_DOUBLE) {
+            ctx.writeByte(op_dcmpg);
+          } else  {
+            ctx.writeByte(op_fcmpg);
+          }
+        }
+      };
+    }
+    
+    public ParametricCodeGenerator make_cmpl(final ParametricType type)
+    throws CodeException {
+      if(type.isObject()) {
+        throw new CodeException("Can't cmpl non-primitive type: " + type);
+      }
+      
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDelta() { return -1; }
+        public int stackDepth() { return 0; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          
+          if(!CodeUtils.isFloatType(cc)) {
+            throw new CodeException("Can only cmpl floating point types: " + cc);
+          }
+          
+          if(cc == CodeUtils.TYPE_DOUBLE) {
+            ctx.writeByte(op_dcmpl);
+          } else  {
+            ctx.writeByte(op_fcmpl);
+          }
+        }
+      };
+    }
+    
+    public ParametricCodeGenerator make_dup(final ParametricType type)
+    throws CodeException {
+      return new ParametricCodeGenerator() {
+        public ParametricType getType() { return type; }
+        public int stackDelta() { return 1; }
+        public int stackDepth() { return 1; }
+        public void writeCode(CodeContext ctx) throws CodeException {
+          CodeClass cc = ctx.resolveParametricType(type);
+          
+          if(CodeUtils.wordsForType(cc) == 2) {
+            ctx.writeByte(op_dup2);
+          } else  {
+            ctx.writeByte(op_dup);
+          }
+        }
+      };
+    }
+    
+    //
+    // Java opcodes
+    //
+
+    public final static byte op_nop = 0;
+    public final static byte op_aconst_null = 1;
+    public final static byte op_iconst_m1 = 2;
+    public final static byte op_iconst_0 = 3;
+    public final static byte op_iconst_1 = 4;
+    public final static byte op_iconst_2 = 5;
+    public final static byte op_iconst_3 = 6;
+    public final static byte op_iconst_4 = 7;
+    public final static byte op_iconst_5 = 8;
+    public final static byte op_lconst_0 = 9;
+    public final static byte op_lconst_1 = 10;
+    public final static byte op_fconst_0 = 11;
+    public final static byte op_fconst_1 = 12;
+    public final static byte op_fconst_2 = 13;
+    public final static byte op_dconst_0 = 14;
+    public final static byte op_dconst_1 = 15;
+    public final static byte op_bipush = 16;
+    public final static byte op_sipush = 17;
+    public final static byte op_ldc = 18;
+    public final static byte op_ldc_w = 19;
+    public final static byte op_ldc2_w = 20;
+    public final static byte op_iload = 21;
+    public final static byte op_lload = 22;
+    public final static byte op_fload = 23;
+    public final static byte op_dload = 24;
+    public final static byte op_aload = 25;
+    public final static byte op_iload_0 = 26;
+    public final static byte op_iload_1 = 27;
+    public final static byte op_iload_2 = 28;
+    public final static byte op_iload_3 = 29;
+    public final static byte op_lload_0 = 30;
+    public final static byte op_lload_1 = 31;
+    public final static byte op_lload_2 = 32;
+    public final static byte op_lload_3 = 33;
+    public final static byte op_fload_0 = 34;
+    public final static byte op_fload_1 = 35;
+    public final static byte op_fload_2 = 36;
+    public final static byte op_fload_3 = 37;
+    public final static byte op_dload_0 = 38;
+    public final static byte op_dload_1 = 39;
+    public final static byte op_dload_2 = 40;
+    public final static byte op_dload_3 = 41;
+    public final static byte op_aload_0 = 42;
+    public final static byte op_aload_1 = 43;
+    public final static byte op_aload_2 = 44;
+    public final static byte op_aload_3 = 45;
+    public final static byte op_iaload = 46;
+    public final static byte op_laload = 47;
+    public final static byte op_faload = 48;
+    public final static byte op_daload = 49;
+    public final static byte op_aaload = 50;
+    public final static byte op_baload = 51;
+    public final static byte op_caload = 52;
+    public final static byte op_saload = 53;
+    public final static byte op_istore = 54;
+    public final static byte op_lstore = 55;
+    public final static byte op_fstore = 56;
+    public final static byte op_dstore = 57;
+    public final static byte op_astore = 58;
+    public final static byte op_istore_0 = 59;
+    public final static byte op_istore_1 = 60;
+    public final static byte op_istore_2 = 61;
+    public final static byte op_istore_3 = 62;
+    public final static byte op_lstore_0 = 63;
+    public final static byte op_lstore_1 = 64;
+    public final static byte op_lstore_2 = 65;
+    public final static byte op_lstore_3 = 66;
+    public final static byte op_fstore_0 = 67;
+    public final static byte op_fstore_1 = 68;
+    public final static byte op_fstore_2 = 69;
+    public final static byte op_fstore_3 = 70;
+    public final static byte op_dstore_0 = 71;
+    public final static byte op_dstore_1 = 72;
+    public final static byte op_dstore_2 = 73;
+    public final static byte op_dstore_3 = 74;
+    public final static byte op_astore_0 = 75;
+    public final static byte op_astore_1 = 76;
+    public final static byte op_astore_2 = 77;
+    public final static byte op_astore_3 = 78;
+    public final static byte op_iastore = 79;
+    public final static byte op_lastore = 80;
+    public final static byte op_fastore = 81;
+    public final static byte op_dastore = 82;
+    public final static byte op_aastore = 83;
+    public final static byte op_bastore = 84;
+    public final static byte op_castore = 85;
+    public final static byte op_sastore = 86;
+    public final static byte op_pop = 87;
+    public final static byte op_pop2 = 88;
+    public final static byte op_dup = 89;
+    public final static byte op_dup_x1 = 90;
+    public final static byte op_dup_x2 = 91;
+    public final static byte op_dup2 = 92;
+    public final static byte op_dup2_x1 = 93;
+    public final static byte op_dup2_x2 = 94;
+    public final static byte op_swap = 95;
+    public final static byte op_iadd = 96;
+    public final static byte op_ladd = 97;
+    public final static byte op_fadd = 98;
+    public final static byte op_dadd = 99;
+    public final static byte op_isub = 100;
+    public final static byte op_lsub = 101;
+    public final static byte op_fsub = 102;
+    public final static byte op_dsub = 103;
+    public final static byte op_imul = 104;
+    public final static byte op_lmul = 105;
+    public final static byte op_fmul = 106;
+    public final static byte op_dmul = 107;
+    public final static byte op_idiv = 108;
+    public final static byte op_ldiv = 109;
+    public final static byte op_fdiv = 110;
+    public final static byte op_ddiv = 111;
+    public final static byte op_irem = 112;
+    public final static byte op_lrem = 113;
+    public final static byte op_frem = 114;
+    public final static byte op_drem = 115;
+    public final static byte op_ineg = 116;
+    public final static byte op_lneg = 117;
+    public final static byte op_fneg = 118;
+    public final static byte op_dneg = 119;
+    public final static byte op_ishl = 120;
+    public final static byte op_lshl = 121;
+    public final static byte op_ishr = 122;
+    public final static byte op_lshr = 123;
+    public final static byte op_iushr = 124;
+    public final static byte op_lushr = 125;
+    public final static byte op_iand = 126;
+    public final static byte op_land = 127;
+    public final static byte op_ior = (byte) 128;
+    public final static byte op_lor = (byte) 129;
+    public final static byte op_ixor = (byte) 130;
+    public final static byte op_lxor = (byte) 131;
+    public final static byte op_iinc = (byte) 132;
+    public final static byte op_i2l = (byte) 133;
+    public final static byte op_i2f = (byte) 134;
+    public final static byte op_i2d = (byte) 135;
+    public final static byte op_l2i = (byte) 136;
+    public final static byte op_l2f = (byte) 137;
+    public final static byte op_l2d = (byte) 138;
+    public final static byte op_f2i = (byte) 139;
+    public final static byte op_f2l = (byte) 140;
+    public final static byte op_f2d = (byte) 141;
+    public final static byte op_d2i = (byte) 142;
+    public final static byte op_d2l = (byte) 143;
+    public final static byte op_d2f = (byte) 144;
+    public final static byte op_i2b = (byte) 145;
+    public final static byte op_i2c = (byte) 146;
+    public final static byte op_i2s = (byte) 147;
+    public final static byte op_lcmp = (byte) 148;
+    public final static byte op_fcmpl = (byte) 149;
+    public final static byte op_fcmpg = (byte) 150;
+    public final static byte op_dcmpl = (byte) 151;
+    public final static byte op_dcmpg = (byte) 152;
+    public final static byte op_ifeq = (byte) 153;
+    public final static byte op_ifne = (byte) 154;
+    public final static byte op_iflt = (byte) 155;
+    public final static byte op_ifge = (byte) 156;
+    public final static byte op_ifgt = (byte) 157;
+    public final static byte op_ifle = (byte) 158;
+    public final static byte op_if_icmpeq = (byte) 159;
+    public final static byte op_if_icmpne = (byte) 160;
+    public final static byte op_if_icmplt = (byte) 161;
+    public final static byte op_if_icmpge = (byte) 162;
+    public final static byte op_if_icmpgt = (byte) 163;
+    public final static byte op_if_icmple = (byte) 164;
+    public final static byte op_if_acmpeq = (byte) 165;
+    public final static byte op_if_acmpne = (byte) 166;
+    public final static byte op_goto = (byte) 167;
+    public final static byte op_jsr = (byte) 168;
+    public final static byte op_ret = (byte) 169;
+    public final static byte op_tableswitch = (byte) 170;
+    public final static byte op_lookupswitch = (byte) 171;
+    public final static byte op_ireturn = (byte) 172;
+    public final static byte op_lreturn = (byte) 173;
+    public final static byte op_freturn = (byte) 174;
+    public final static byte op_dreturn = (byte) 175;
+    public final static byte op_areturn = (byte) 176;
+    public final static byte op_return = (byte) 177;
+    public final static byte op_getstatic = (byte) 178;
+    public final static byte op_putstatic = (byte) 179;
+    public final static byte op_getfield = (byte) 180;
+    public final static byte op_putfield = (byte) 181;
+    public final static byte op_invokevirtual = (byte) 182;
+    public final static byte op_invokespecial = (byte) 183;
+    public final static byte op_invokestatic = (byte) 184;
+    public final static byte op_invokeinterface = (byte) 185;
+    public final static byte op_new = (byte) 187;
+    public final static byte op_newarray = (byte) 188;
+    public final static byte op_anewarray = (byte) 189;
+    public final static byte op_arraylength = (byte) 190;
+    public final static byte op_athrow = (byte) 191;
+    public final static byte op_checkcast = (byte) 192;
+    public final static byte op_instanceof = (byte) 193;
+    public final static byte op_monitorenter = (byte) 194;
+    public final static byte op_monitorexit = (byte) 195;
+    public final static byte op_wide = (byte) 196;
+    public final static byte op_multianewarray = (byte) 197;
+    public final static byte op_ifnull = (byte) 198;
+    public final static byte op_ifnonnull = (byte) 199;
+    public final static byte op_goto_w = (byte) 200;
+    public final static byte op_jsr_w = (byte) 201;
+    public final static byte op_breakpoint = (byte) 202;
+    public final static byte op_ldc_quick = (byte) 203;
+    public final static byte op_ldc_w_quick = (byte) 204;
+    public final static byte op_ldc2_w_quick = (byte) 205;
+    public final static byte op_getfield_quick = (byte) 206;
+    public final static byte op_putfield_quick = (byte) 207;
+    public final static byte op_getfield2_quick = (byte) 208;
+    public final static byte op_putfield2_quick = (byte) 209;
+    public final static byte op_getstatic_quick = (byte) 210;
+    public final static byte op_putstatic_quick = (byte) 211;
+    public final static byte op_getstatic2_quick = (byte) 212;
+    public final static byte op_putstatic2_quick = (byte) 213;
+    public final static byte op_invokevirtual_quick = (byte) 214;
+    public final static byte op_invokenonvirtual_quick = (byte) 215;
+    public final static byte op_invokesuper_quick = (byte) 216;
+    public final static byte op_invokestatic_quick = (byte) 217;
+    public final static byte op_invokeinterface_quick = (byte) 218;
+    public final static byte op_invokevirtualobject_quick = (byte) 219;
+    public final static byte op_new_quick = (byte) 221;
+    public final static byte op_anewarray_quick = (byte) 222;
+    public final static byte op_multianewarray_quick = (byte) 223;
+    public final static byte op_checkcast_quick = (byte) 224;
+    public final static byte op_instanceof_quick = (byte) 225;
+    public final static byte op_invokevirtual_quick_w = (byte) 226;
+    public final static byte op_getfield_quick_w = (byte) 227;
+    public final static byte op_putfield_quick_w = (byte) 228;
+    public final static byte op_impdep1 = (byte) 254;
+    public final static byte op_impdep2 = (byte) 255;
+}
diff --git a/src/org/biojava/utils/bytecode/ByteInstruction.java b/src/org/biojava/utils/bytecode/ByteInstruction.java
new file mode 100755
index 0000000..2b711cc
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/ByteInstruction.java
@@ -0,0 +1,53 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Instructions which take a one-byte operand.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+class ByteInstruction implements Instruction {
+  private final byte opcode;
+  private final byte val;
+  private final int delta;
+  
+  ByteInstruction(byte opcode, byte val, int delta) {
+    this.opcode = opcode;
+    this.val = val;
+    this.delta = delta;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    ctx.writeByte(opcode);
+    ctx.writeByte(val);
+  }
+  
+  public int stackDepth() {
+    return Math.max(delta, 0);
+  }
+  
+  public int stackDelta() {
+    return delta;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/ChildContext.java b/src/org/biojava/utils/bytecode/ChildContext.java
new file mode 100755
index 0000000..db0b8c6
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/ChildContext.java
@@ -0,0 +1,213 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+import java.util.*;
+
+/**
+ * CodeContext implementation which provides a lightweight subContext of any
+ * ParentContext.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+class ChildContext implements CodeContext, ParentContext {
+  ParentContext ourParent;
+  
+  private List outstandingRefs;
+  private Map markedLabels;
+  
+  private Map localVariables;
+  private int usedLocals;
+  
+  private Map resolvedParametrics;
+  
+  {
+    outstandingRefs = new ArrayList();
+    markedLabels = new HashMap();
+    localVariables = new HashMap();
+    resolvedParametrics = new HashMap();
+  }
+
+  ChildContext(ParentContext p) {
+    this.ourParent = p;
+    usedLocals = ourParent.getUsedLocals();
+  }
+
+  public CodeClass getCodeClass() {
+    return ourParent.getCodeClass();
+  }
+  
+  public CodeMethod getCodeMethod() {
+    return ourParent.getCodeMethod();
+  }
+  
+  public ConstantPool getConstants() {
+    return ourParent.getConstants();
+  }
+  
+  public void writeByte(byte b) throws CodeException {
+    ourParent.writeByte(b);
+  }
+  
+  public void writeShort(int i) throws CodeException {
+    ourParent.writeShort(i);
+  }
+  
+  public void writeShortAt(int pos, int i) {
+    ourParent.writeShortAt(pos, i);
+  }
+  
+  public void markLabel(Label l) throws CodeException {
+    if (markedLabels.containsKey(l))
+      throw new CodeException("Attempt to duplicate marked label");
+    markedLabels.put(l, new Integer(getOffset()));
+  }
+  
+  public void promoteOutstandingReference(OutstandingReference or) {
+    outstandingRefs.add(or);
+  }
+  
+  public void writeLabel(Label l) throws CodeException {
+    outstandingRefs.add(new BranchFixup(l, getOffset(), this));
+    writeShort(0);
+  }
+  
+  public int getOffset() {
+    return ourParent.getOffset();
+  }
+  
+  public void open() {
+  }
+  
+  public void close() throws CodeException {
+    for (ListIterator li = outstandingRefs.listIterator(); li.hasNext(); ) {
+      OutstandingReference or = (OutstandingReference) li.next();
+      Integer off = (Integer) markedLabels.get(or.getLabel());
+      if (off != null) {
+        or.resolve(off.intValue());
+      } else {
+        ourParent.promoteOutstandingReference(or); // See if parent can resolve this.
+      }
+    }
+  }
+  
+  public CodeContext subContext() {
+    return new ChildContext(this);
+  }
+  
+  public int resolveLocal(LocalVariable lv) {
+    // System.out.println("ChildContext.resolveLocal(" + lv + ")");
+    Integer slot = (Integer) localVariables.get(lv);
+    if (slot != null) {
+      // System.out.println("resolved to " + slot);
+      return slot.intValue();
+    }
+    
+    // System.out.println("Trying to resolve slot in parent " + ourParent);
+    int locSlot = ourParent.resolveLocalNoCreate(lv);
+    if (locSlot >= 0) {
+      // System.out.println("Parent had local " + lv + " at " + locSlot);
+    } else {
+      // Need to create the variable;
+      locSlot = usedLocals;
+      usedLocals += lv.needSlots();
+      setMaxLocals(usedLocals);
+      // System.out.println("Generated new slot for local " + lv + " at " + locSlot);
+    }
+    
+    // We'll add the slot to our map, even if it's just a copy from the parent.
+    
+    localVariables.put(lv, new Integer(locSlot));
+    // System.out.println("ChildContext: Resolved local variable " + lv + " to slot " + locSlot);
+    return locSlot;
+  }
+  
+  public int resolveLocalNoCreate(LocalVariable lv) {
+    Integer slot = (Integer) localVariables.get(lv);
+    if (slot != null) {
+      return slot.intValue();
+    } else {
+      return ourParent.resolveLocalNoCreate(lv); 
+    }
+  }
+  
+  public void registerParametricType(
+    ParametricType type,
+    CodeClass concreteType
+  ) throws CodeException {
+    if(resolvedParametrics.containsKey(type)) {
+      throw new CodeException("Failed to regiter parametric type " + type +
+        ". Attempted to register for " + concreteType +
+        " but it is already registered for " + resolvedParametrics.get(type) );
+    }
+    
+    if(!type.canAccept(concreteType)) {
+      throw new CodeException(
+        "Parametric type is not compattible with concrete type: " +
+        type + " : " + concreteType );
+    }
+
+    resolvedParametrics.put(type, concreteType);
+  }
+  
+  public CodeClass resolveParametricType(ParametricType type)
+  throws CodeException {
+    CodeClass cc = (CodeClass) resolvedParametrics.get(type);
+    
+    if(cc == null) {
+      return ourParent.resolveParametricType(type);
+    }
+    
+    return cc;
+  }
+  
+  public int getUsedLocals() {
+    return usedLocals;
+  }
+  
+  public void setMaxLocals(int m) {
+    ourParent.setMaxLocals(m);
+  }
+  
+  public void addExceptionTableEntry(Label startHandled, 
+  Label endHandled,
+  CodeClass eClass, 
+  Label handler)
+  {
+    SimpleReference rStartHandled = new SimpleReference(startHandled);
+    SimpleReference rEndHandled = new SimpleReference(endHandled);
+    SimpleReference rHandler = new SimpleReference(handler);
+    outstandingRefs.add(rStartHandled);
+    outstandingRefs.add(rEndHandled);
+    outstandingRefs.add(rHandler);
+    
+    addExceptionTableEntry(new ExceptionMemento(rStartHandled,
+    rEndHandled,
+    eClass,
+    rHandler));
+  }
+  
+  public void addExceptionTableEntry(ExceptionMemento em) {
+    ourParent.addExceptionTableEntry(em);
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/ClassInstruction.java b/src/org/biojava/utils/bytecode/ClassInstruction.java
new file mode 100755
index 0000000..376c576
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/ClassInstruction.java
@@ -0,0 +1,55 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Instructions which use a Class.
+ *
+ * @author Matthew Pocock
+ */
+
+class ClassInstruction implements Instruction {
+  private final CodeClass clazz;
+  private final byte opcode;
+  private final int delta;
+  
+  ClassInstruction(byte op, CodeClass c, int delta) {
+    if(c == null) {
+      throw new NullPointerException("CodeClass can not be null");
+    }
+    this.opcode = op;
+    this.clazz = c;
+    this.delta = delta;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    ctx.writeByte(opcode);
+    ctx.writeShort(ctx.getConstants().resolveClass(clazz));
+  }
+  
+  public int stackDepth() {
+    return Math.max(delta, 0);
+  }
+  
+  public int stackDelta() {
+    return delta;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/CodeClass.java b/src/org/biojava/utils/bytecode/CodeClass.java
new file mode 100755
index 0000000..48bc626
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/CodeClass.java
@@ -0,0 +1,125 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+import java.util.*;
+
+/**
+ * Interface for Java classes within the bytecode generation framework.
+ * Any class (or interface) can be viewed as a CodeClass, whether it
+ * is pre-existing or being generated.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+public interface CodeClass {
+  String getName();
+
+  String getJName();
+
+  String getDescriptor();
+
+  CodeClass getSuperClass();
+
+  List getInterfaces();
+
+  /**
+   * Get all methods declared by this class and its super classes, removing
+   * all super class methods that are over ridden.
+   *
+   * <p>
+   * This should return methods, regardless of their accessability.
+   * </p>
+   *
+   * @return a Set containing all methods
+   */
+  Set getMethods();
+
+  /**
+   * Get the name of all methods that could be invoked through this class with
+   * a given name.
+   *
+   * @param name  the name of the method
+   * @return a Set of CodeMethod instances with that name
+   */
+  Set getMethodsByName(String name);
+
+  /**
+   * Get a method by name and argument list.
+   *
+   * @param name  the name of the method
+   * @param args  the arguments it takes
+   * @return      a matching method
+   * @throws NoSuchMethodException  if there is no maching method
+   */
+  CodeMethod getMethod(String name, CodeClass[] args)
+          throws NoSuchMethodException;
+
+  /**
+   * Get a constructor by argument list.
+   *
+   * @param args  the arguments it takes
+   * @return      a matching constructor
+   * @throws NoSuchMethodException  if there is no matching constructor
+   */
+  CodeMethod getConstructor(CodeClass[] args)
+          throws NoSuchMethodException;
+
+  /**
+   * Get a field by its name.
+   *
+   * @param name  the field name
+   * @return      a CodeField representing the field
+   * @throws NoSuchFieldException if there is no field by that name accessible
+   *   through this class
+   */
+  CodeField getFieldByName(String name)
+          throws NoSuchFieldException;
+
+  /**
+   * Get all fields accessible through this class.
+   *
+   * @return  a Set of all accessible fields
+   */
+  Set getFields();
+
+  /**
+   * Get the modifiers associated with the class.
+   *
+   * @return  the modifier integer
+   */
+  int getModifiers();
+
+  /**
+   * Discover if the class represents a primitive type.
+   *
+   * @return  true if the class represents a primative type
+   */
+  public boolean isPrimitive();
+
+  /**
+   * Discover if the class is an array type.
+   *
+   * @return  true if the class is an array type
+   */
+  public boolean isArray();
+}
diff --git a/src/org/biojava/utils/bytecode/CodeContext.java b/src/org/biojava/utils/bytecode/CodeContext.java
new file mode 100755
index 0000000..9d3ff06
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/CodeContext.java
@@ -0,0 +1,207 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Interface which encapsulates the stream to which Java bytecode can
+ * be written.
+ *
+ * <p>
+ * The context takes care of all the book-keeping tasks associated with emitting
+ * well-formed byte code. For example, the context manages jumps and local
+ * variables.
+ * </p>
+ *
+ * <p>
+ * Most of the funcionality here is very low level. You will almost certainly
+ * want to use CodeGenerator instances to manipulate a CodeContext, rather than
+ * writing to it yourself.
+ * </p>
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+public interface CodeContext {
+  /**
+   * Get the class for which a method is being generated.
+   *
+   * @return the current class
+   */
+  public CodeClass getCodeClass();
+
+  /**
+   * Get the method which is being generated.
+   *
+   * @return the current method
+   */
+  public CodeMethod getCodeMethod();
+
+  /**
+   * Get the constants pool for this context.
+   *
+   * @return the contant pool
+   */
+  public ConstantPool getConstants();
+
+  // Write methods.
+
+  /**
+   * Write a single byte to the context.
+   *
+   * <p>
+   * This can be used both to write opcodes and to write byte data to the
+   * context.
+   * </p>
+   *
+   * @param  b the byte to write
+   */
+  public void writeByte(byte b) throws CodeException;
+
+  /**
+   * Write a short (2 bytes) to the context.
+   *
+   * @param i  the short to write
+   */
+  public void writeShort(int i) throws CodeException;
+
+  /**
+   * Write the offset of a Label to the context.
+   *
+   * <p>This can be called before or after markLabel is invoked for the
+   * corresponding label. The context will ensure that the offset is
+   * correctly written before the method is fully emitted.</p>
+   *
+   * @param lab  the Label to write
+   */
+  public void writeLabel(Label lab) throws CodeException;
+
+  /**
+   * Resolve a local variable to the local variable slot assigned to it.
+   *
+   * <p>The context will ensure that local variables are stored in their
+   * own bits of the local variable area. It may chose to re-use portions
+   * of this area as local variables go out of scope.</p>
+   *
+   * @param lv  the LocalVariable to resolve
+   * @return the index of the local variable slot
+   */
+  public int resolveLocal(LocalVariable lv) throws CodeException;
+
+  /**
+   * Mark a label at the current point in the stream.
+   *
+   * <p>This can be used as the target for branching instructions, such as
+   * GOTO and IF.</p>
+   *
+   * @param lab the Label to mark
+   * @throws CodeException if the label has previously been marked
+   */
+  public void markLabel(Label lab) throws CodeException;
+
+  /**
+   * Register a concrete type for a parametric type.
+   *
+   * <p>This is the mechanism where-by real CodeClass types are associated
+   * with the virtual ParametricType types. If type pubishes that it
+   * is a primative, an object or an array, then the concreteType must be
+   * compattible. It's an error to bind the VOID type.</p>
+   *
+   * @for.developer
+   *  You should probably call
+   * <code>ParametricType.canAccept(concreteType)</code> to make sure of this.
+   * This implementation will shield you from any modifications to the exact
+   * semantics of ParametricType.
+   *
+   * @param type  ParametricType the parametric type to register
+   * @param concreteType  the CodeClass that it resolves to
+   * @throws CodeException if the type has already been registered or if the
+   *   guarantees about type made in the parametric type are violated
+   */
+  public void registerParametricType(ParametricType type, CodeClass concreteType)
+          throws CodeException;
+
+  /**
+   * Resolve a parametric type to a concrete class.
+   *
+   * <p>The type will be resolved by first searching through all those
+   * registered with this context. If it found there, this value is returned.
+   * If it is not, then the emediate parent context is searched. This parent
+   * is responsible for searching its parent and so on. If a context has no
+   * parent and the type is not registered with this context, it should raise
+   * a CodeException.</p>
+   *
+   * @param type  the ParametricType to resolve
+   * @return the  ColdeClass associated with that parametric type
+   * @throws CodeException if the type has not been registered
+   */
+  public CodeClass resolveParametricType(ParametricType type)
+          throws CodeException;
+
+  /**
+   * Open a sub context.
+   *
+   * <p>The sub context should inherit all the state of the parent context.
+   * Modifications to the state of the child (for example, local variable
+   * management or registered labels) should not be propogated to the parent.
+   * Modifications to the parent should not be propogated to the child.
+   * However, contexts should be used serialy, and only one context should be
+   * accessible to a code generator at a time, so in practice, there should be
+   * no way for a code generator using a child context to alter the state of
+   * or discover the state of the parent context.</p>
+   */
+  public CodeContext subContext();
+
+  /**
+   * Open the context for writing.
+   *
+   * <p>This must be called before any code writing methods are called. It
+   * can not be called more than once.</p>
+   */
+  public void open() throws CodeException;
+
+  /**
+   * Close the context for writing. It is at this point that any process
+   * necisary for comitting the bytecode will be executed.
+   *
+   * <p>This must be called after all code writing methods have been called.
+   * It can not be called more than once.</p>
+   */
+  public void close() throws CodeException;
+
+  // Exception tables
+
+  /**
+   * Add an exception table entry.
+   *
+   * @param startHandled    the beginning of the try block
+   * @param endHandled      the end of the try block
+   * @param eClass          the exception class
+   * @param handler         the beginning of the exception handler
+   * @throws CodeException
+   */ 
+  public void addExceptionTableEntry(Label startHandled,
+                                     Label endHandled,
+                                     CodeClass eClass,
+                                     Label handler)
+          throws CodeException;
+
+}
diff --git a/src/org/biojava/utils/bytecode/CodeException.java b/src/org/biojava/utils/bytecode/CodeException.java
new file mode 100755
index 0000000..3bf9227
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/CodeException.java
@@ -0,0 +1,34 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * An exception indicating that something went wrong generating byte code.
+ */
+public class CodeException extends Exception {
+  public CodeException() {
+    super();
+  }
+
+  public CodeException(String msg) {
+    super(msg);
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/CodeField.java b/src/org/biojava/utils/bytecode/CodeField.java
new file mode 100755
index 0000000..32d55da
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/CodeField.java
@@ -0,0 +1,98 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Wrap up details about a field in a Java class file.
+ *
+ * <p>
+ * Instances of this type will be instantiated by CodeClass instances, using
+ * the getField() methods.
+ * </p>
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+public final class CodeField {
+  private final String name;
+  private final CodeClass clazz;
+  private final int modifiers;
+  private final CodeClass container;
+
+  CodeField(CodeClass container, String name, CodeClass clazz, int mods) {
+    this.container = container;
+    this.name = name;
+    this.clazz = clazz;
+    this.modifiers = mods;
+  }
+
+  /**
+   * Get the name of the field.
+   *
+   * @return  the name of the field
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Get the fully qualified name of the field.
+   *
+   * @return the fully qualified name
+   */
+  public String getFullName() {
+    return container.getName() + "." + getName();
+  }
+
+  /**
+   * Get the class that contains this field.
+   *
+   * @return the containing class
+   */
+  public CodeClass getContainingClass() {
+    return container;
+  }
+
+  /**
+   * Get the type of the field.
+   *
+   * @return
+   */
+  public CodeClass getType() {
+    return clazz;
+  }
+
+  /**
+   * Get the moddifiers applied to this field.
+   *
+   * @return the modifiers
+   */
+  public int getModifiers() {
+    return modifiers;
+  }
+
+  public String toString() {
+    return super.toString() +
+            " type: " + getType() +
+            " class: " + clazz.getName() +
+            " name: " + getName();
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/CodeGenerator.java b/src/org/biojava/utils/bytecode/CodeGenerator.java
new file mode 100755
index 0000000..b5852ff
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/CodeGenerator.java
@@ -0,0 +1,63 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Interface for an object which can produce Java bytecode.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+public interface CodeGenerator {
+    /**
+     * Write the byte or bytes for this CodeGenerator to a CodeContext.
+     *
+     * @param ctx  a CodeContext to write to
+     * @throws CodeException if there was some failure in writing to the context
+     */
+    public void writeCode(CodeContext ctx) throws CodeException;
+    
+    /**
+     * Return the total depth of the stack required by this CodeGenerator.
+     *
+     * <p>For single byte-code instructions, this will be the same as
+     * stackDelta() if stackDelta() is positive, zero otherwise. For a
+     * compound instruction, this will be the maximum stack depth required to
+     * execute all sub-instructions.</p>
+     *
+     * @return the stack depth needed
+     */
+    public int stackDepth();
+    
+    /**
+     * Return the change in the stack dept this generator will cause.
+     *
+     * <p>In the case of an instruction that adds items to the stack, stackDelta
+     * will be positive. For instructions that removes items from the stack,
+     * this will be negative.</p>
+     *
+     * @return the change between stack depth before and after execution of this
+     *   code
+     */
+    public int stackDelta();
+}
+
diff --git a/src/org/biojava/utils/bytecode/CodeMethod.java b/src/org/biojava/utils/bytecode/CodeMethod.java
new file mode 100755
index 0000000..bc0c506
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/CodeMethod.java
@@ -0,0 +1,87 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Wrap up details about a method in a Java class file
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+public interface CodeMethod {
+  /**
+   * The name of the method.
+   *
+   * @return the method name
+   */
+  public String getName();
+
+  /**
+   * The class that contains this method
+   *
+   * @return the containing class
+   */
+  public CodeClass getContainingClass();
+
+  /**
+   * The fully qualified name for this class
+   *
+   * @return the full name
+   */
+  public String getFullName();
+
+  /**
+   * A human-readable description of the class
+   *
+   * @return the class description
+   */
+  public String getDescriptor();
+
+  /**
+   * Get the modifiers, such as PUBLIC, ABSTRACT and so on
+   *
+   * @return the class modifiers
+   */
+  public int getModifiers();
+
+  /**
+   * Get the return type
+   *
+   * @return the return type
+   */
+  public CodeClass getReturnType();
+
+  /**
+   * Get the number of parameters taken by this method
+   *
+   * @return the number of parameters
+   */
+  public int numParameters();
+
+  /**
+   * Get the type of the parameter at a given position
+   *
+   * @param pos  the position to fetch the parameter type for
+   * @return the type of the parameter at that position
+   */
+  public CodeClass getParameterType(int pos);
+}
diff --git a/src/org/biojava/utils/bytecode/CodeUtils.java b/src/org/biojava/utils/bytecode/CodeUtils.java
new file mode 100755
index 0000000..7b6519f
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/CodeUtils.java
@@ -0,0 +1,169 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Utility code for things you will frequently need.
+ *
+ * <p>
+ * This class provides common constants representing access modifiers and
+ * types. There are also some utility methods for munging data.
+ * </p>
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+public class CodeUtils {
+  public static final int ACC_PUBLIC       = 0x0001;
+  public static final int ACC_PRIVATE      = 0x0002;
+  public static final int ACC_PROTECTED    = 0x0004;
+  public static final int ACC_STATIC       = 0x0008;
+  public static final int ACC_FINAL        = 0x0010;
+  public static final int ACC_SUPER        = 0x0020;
+  public static final int ACC_SYNCHRONIZED = 0x0020;
+  public static final int ACC_VOLATILE     = 0x0040;
+  public static final int ACC_TRANSIENT    = 0x0080;
+  public static final int ACC_NATIVE       = 0x0100;
+  public static final int ACC_INTERFACE    = 0x0200;
+  public static final int ACC_ABSTRACT     = 0x0400;
+  public static final int ACC_STRICT       = 0x0800;
+  
+  public static final CodeClass TYPE_VOID;
+  public static final CodeClass TYPE_INT;
+  public static final CodeClass TYPE_FLOAT;
+  public static final CodeClass TYPE_DOUBLE;
+  public static final CodeClass TYPE_LONG;
+  public static final CodeClass TYPE_BYTE;
+  public static final CodeClass TYPE_SHORT;
+  public static final CodeClass TYPE_CHAR;
+  public static final CodeClass TYPE_BOOLEAN;
+  public static final CodeClass TYPE_OBJECT;
+  public static final CodeClass[] EMPTY_LIST;
+  public static final CodeGenerator DO_NOTHING;
+  
+  static {
+    TYPE_VOID = IntrospectedCodeClass.forClass(Void.TYPE);
+    TYPE_BYTE = IntrospectedCodeClass.forClass(Byte.TYPE);
+    TYPE_INT = IntrospectedCodeClass.forClass(Integer.TYPE);
+    TYPE_FLOAT = IntrospectedCodeClass.forClass(Float.TYPE);
+    TYPE_DOUBLE = IntrospectedCodeClass.forClass(Double.TYPE);
+    TYPE_LONG = IntrospectedCodeClass.forClass(Long.TYPE);
+    TYPE_SHORT = IntrospectedCodeClass.forClass(Short.TYPE);
+    TYPE_CHAR = IntrospectedCodeClass.forClass(Character.TYPE);
+    TYPE_BOOLEAN = IntrospectedCodeClass.forClass(Boolean.TYPE);
+    TYPE_OBJECT = IntrospectedCodeClass.forClass(Object.class);
+    
+    EMPTY_LIST = new CodeClass[0];
+    
+    DO_NOTHING = new CodeGenerator() {
+      public void writeCode(CodeContext cxt) { return; }
+      public int stackDepth() { return 0; }
+      public int stackDelta() { return 0; }
+    };
+  }
+  
+  /**
+   * Format an array of classes as a comma-seperated list.
+   *
+   * <p>
+   * The names of each class in classes will be seperated by a comma and a space
+   * and will use CodeClass.getName() to produce strings for each one. Their
+   * names will be present in the return value in the same order they are found
+   * in the classes array
+   * </p>
+   *
+   * @param classes  the array of classes to format
+   * @return a String containing the list of class names
+   */
+  public static String classListToString(CodeClass[] classes) {
+    StringBuffer sb = new StringBuffer();
+    if(classes.length > 0) {
+      sb.append(classes[0].getName());
+    }
+    
+    for(int a = 1; a < classes.length; a++) {
+      sb.append(", ");
+      sb.append(classes[a].getName());
+    }
+    
+    return sb.toString();
+  }
+  
+  /**
+   * Number of words needed for local variables of this type.
+   *
+   * <p>Longs and doubles require 2 words (64 bits), where as everything
+   * else needs 1 word (32 bits). Void needs no words.
+   * This just hides that knowledge.</p>
+   *
+   * @param cc the CodeClass to check word size for
+   * @return number of words needed for this type
+   */
+  public static int wordsForType(CodeClass cc) {
+    if(
+      (cc == TYPE_DOUBLE) ||
+      (cc == TYPE_LONG)
+    ) {
+      return 2;
+    } else if(cc == TYPE_VOID) {
+      return 0;
+    } else {
+      return 1;
+    }
+  }
+
+  /**
+   * Returns true if the class is a floating point number.
+   *
+   * <p>
+   * Double and Float are floating point numbers. All other classes are not.
+   * </p>
+   *
+   * @param cc  the class to check
+   * @return  true if the class can be used to represent floating point numbers
+   */
+  public static boolean isFloatType(CodeClass cc) {
+    return
+      cc == TYPE_DOUBLE ||
+      cc == TYPE_FLOAT;
+  }
+
+  /**
+   * Returns true if the class is an integer number.
+   *
+   * <p>
+   * All numeric types are integer (whole number) types, except for the floating
+   * point types. All other classes are not integer types.
+   * </p>
+   *
+   * @param cc  the class to check
+   * @return  true if the class can be used to represent integer numbers
+   */
+  public static boolean isIntegerType(CodeClass cc) {
+    return
+      cc == TYPE_LONG ||
+      cc == TYPE_BOOLEAN ||
+      cc == TYPE_BYTE ||
+      cc == TYPE_CHAR ||
+      cc == TYPE_LONG ||
+      cc == TYPE_SHORT;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/ConstantPool.java b/src/org/biojava/utils/bytecode/ConstantPool.java
new file mode 100755
index 0000000..8f9b7dc
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/ConstantPool.java
@@ -0,0 +1,385 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * Build a Java class file constant pool.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+public class ConstantPool {
+    private static final byte CONSTANT_Class = 7;
+    private static final byte CONSTANT_Fieldref = 9;
+    private static final byte CONSTANT_Methodref = 10;
+    private static final byte CONSTANT_InterfaceMethodref = 11;
+    private static final byte CONSTANT_String = 8;
+    private static final byte CONSTANT_Integer = 3;
+    private static final byte CONSTANT_Float = 4;
+    private static final byte CONSTANT_Long = 5;
+    private static final byte CONSTANT_Double = 6;
+    private static final byte CONSTANT_NameAndType = 12;
+    private static final byte CONSTANT_Utf8 = 1;
+
+    private List constants;
+
+    {
+	constants = new ArrayList();
+	constants.add(null); // Initial padder.
+    }
+   
+    // Publically visible constant types
+
+    public int resolveClass(CodeClass c) {
+	return resolve(new CPTypedStringEntry(CONSTANT_Class, resolveUtf8(c.getJName())));
+    }
+
+    public int resolveField(CodeField f) {
+      try {
+        return resolve(new CPRefEntry(CONSTANT_Fieldref, resolveClass(f.getContainingClass()), resolveNameAndType(f.getName(), f.getType().getDescriptor())));
+      } catch (NullPointerException npe) {
+        throw new Error("Can't resolve filed " + f);
+      }
+    }
+
+    public int resolveMethod(CodeMethod m) {
+	return resolve(new CPRefEntry(CONSTANT_Methodref, resolveClass(m.getContainingClass()), resolveNameAndType(m.getName(), m.getDescriptor())));
+    }
+
+    public int resolveInterfaceMethod(CodeMethod m) {
+	return resolve(new CPRefEntry(CONSTANT_InterfaceMethodref, resolveClass(m.getContainingClass()), resolveNameAndType(m.getName(), m.getDescriptor())));
+    }
+
+    public int resolveString(String s) {
+	return resolve(new CPTypedStringEntry(CONSTANT_String, resolveUtf8(s)));
+    }
+
+    public int resolveInt(int i) {
+	return resolve(new CPIntEntry(i));
+    }
+
+    public int resolveFloat(float f) {
+	return resolve(new CPFloatEntry(f));
+    }
+
+    public int resolveLong(long l) {
+	return resolve(new CPLongEntry(l));
+    }
+
+    public int resolveDouble(double d) {
+	return resolve(new CPDoubleEntry(d));
+    }
+
+    // internal resolvers
+
+    public int resolveUtf8(String s) {
+	return resolve(new CPUtf8Entry(s));
+    }
+
+    public int resolveNameAndType(String name, String desc) {
+	return resolve(new CPNameAndTypeEntry(resolveUtf8(name), resolveUtf8(desc)));
+    }
+
+    // The master resolver
+
+    private int resolve(CPEntry e) {
+	for (int i = 1; i < constants.size(); ++i) {
+	    CPEntry e2 = (CPEntry) constants.get(i);
+	    if (e2 != null && e.equals(e2))
+		return i;
+	}
+	int i = constants.size();
+	constants.add(e);
+	for (int k = 1; k < e.needSlots(); ++k)
+	    constants.add(null);
+	return i;
+    }
+
+    // Output again
+
+    public int constantPoolSize() {
+	return constants.size();
+    }
+
+  public void writeConstantPool(DataOutput d) throws IOException {
+//    int count = 1;
+    for (Iterator i = constants.iterator(); i.hasNext(); ) {
+	    CPEntry e = (CPEntry) i.next();
+	    if (e != null) {
+//        System.out.println("Writing constant " + count + " " + e);
+//        count += e.needSlots();
+        e.write(d);
+      }
+    }
+  }
+  
+    // Types for storing the cpool
+
+    private static interface CPEntry {
+	public void write(DataOutput d) throws IOException;
+	public int needSlots();
+    }
+
+    private static class CPTypedStringEntry implements CPEntry {
+	byte tag;
+	int name;
+
+        CPTypedStringEntry(byte tag, int name) {
+	    this.tag = tag;
+	    this.name = name;
+	}
+
+	public boolean equals(Object o) {
+	    if (! (o instanceof CPTypedStringEntry))
+		return false;
+
+	    CPTypedStringEntry cte = (CPTypedStringEntry) o;
+	    return (cte.name == name && cte.tag == tag);
+	}
+
+	public void write(DataOutput d) throws IOException {
+	    d.writeByte(tag);
+	    d.writeShort(name);
+	}
+
+	public int needSlots() {
+	    return 1;
+	}
+  
+  public String toString() {
+    return "CPTypedStringEntry tag=" + tag + " name=" + name;
+  }
+    }
+
+    private static class CPRefEntry implements CPEntry {
+	byte tag;
+	int clazz;
+	int name;
+
+        CPRefEntry(byte tag, int clazz, int name) {
+	    this.tag = tag;
+	    this.clazz = clazz;
+	    this.name = name;
+	}
+
+	public boolean equals(Object o) {
+	    if (! (o instanceof CPRefEntry))
+		return false;
+
+	    CPRefEntry cte = (CPRefEntry) o;
+	    return (cte.clazz == clazz && cte.name == name && cte.tag == tag);
+	}
+
+	public void write(DataOutput d) throws IOException {
+	    d.writeByte(tag);
+	    d.writeShort(clazz);
+	    d.writeShort(name);
+	}
+
+	public int needSlots() {
+	    return 1;
+	}
+  
+  public String toString() {
+    return "CPRefEntry tag=" + tag + " class=" + clazz + " name=" + name;
+  }
+    }
+
+    private static class CPIntEntry implements CPEntry {
+	int val;
+
+        CPIntEntry(int val) {
+	    this.val = val;
+	}
+
+	public boolean equals(Object o) {
+	    if (! (o instanceof CPIntEntry))
+		return false;
+
+	    return (((CPIntEntry) o).val == val);
+	}
+
+	public void write(DataOutput d) throws IOException {
+	    d.writeByte(CONSTANT_Integer);
+	    d.writeInt(val);
+	}
+
+	public int needSlots() {
+	    return 1;
+	}
+  
+  public String toString() {
+    return "CPIntEntry val=" + val;
+  }
+    }
+
+    private static class CPLongEntry implements CPEntry {
+	long val;
+
+        CPLongEntry(long val) {
+	    this.val = val;
+	}
+
+	public boolean equals(Object o) {
+	    if (! (o instanceof CPLongEntry))
+		return false;
+
+	    return (((CPLongEntry) o).val == val);
+	}
+
+	public void write(DataOutput d) throws IOException {
+	    d.writeByte(CONSTANT_Long);
+	    d.writeLong(val);
+	}
+
+	public int needSlots() {
+	    return 2;
+	}
+  
+  public String toString() {
+    return "CPLongEntry val=" + val;
+  }
+    }
+
+    private static class CPFloatEntry implements CPEntry {
+	float val;
+
+        CPFloatEntry(float val) {
+	    this.val = val;
+	}
+
+	public boolean equals(Object o) {
+	    if (! (o instanceof CPFloatEntry))
+		return false;
+
+	    return
+        (((CPFloatEntry) o).val == val) ||
+        (Float.isNaN(((CPFloatEntry) o).val) && Float.isNaN(val));
+	}
+
+	public void write(DataOutput d) throws IOException {
+	    d.writeByte(CONSTANT_Float);
+	    d.writeFloat(val);
+	}
+
+	public int needSlots() {
+	    return 1;
+	}
+  
+  public String toString() {
+    return "CPFloatEntry val=" + val;
+  }
+    }
+
+    private static class CPDoubleEntry implements CPEntry {
+	double val;
+
+        CPDoubleEntry(double val) {
+	    this.val = val;
+	}
+
+	public boolean equals(Object o) {
+	    if (! (o instanceof CPDoubleEntry))
+		return false;
+
+	    return
+        (((CPDoubleEntry) o).val == val) ||
+        (Double.isNaN(((CPDoubleEntry) o).val) && Double.isNaN(val));
+	}
+
+	public void write(DataOutput d) throws IOException {
+	    d.writeByte(CONSTANT_Double);
+	    d.writeDouble(val);
+	}
+
+	public int needSlots() {
+	    return 2;
+	}
+  
+  public String toString() {
+    return "CPDoubleEntry val=" + val;
+  }
+    }
+
+    private static class CPUtf8Entry implements CPEntry {
+	String val;
+
+        CPUtf8Entry(String val) {
+	    this.val = val;
+	}
+
+	public boolean equals(Object o) {
+	    if (! (o instanceof CPUtf8Entry))
+		return false;
+
+	    return (((CPUtf8Entry) o).val.equals(val));
+	}
+
+	public void write(DataOutput d) throws IOException {
+	    d.writeByte(CONSTANT_Utf8);
+	    d.writeUTF(val);
+	}
+
+	public int needSlots() {
+	    return 1;
+	}
+  
+  public String toString() {
+    return "CPUtf8Entry val=" + val;
+  }
+    }
+
+    private static class CPNameAndTypeEntry implements CPEntry {
+	int name;
+	int desc;
+
+        CPNameAndTypeEntry(int name, int desc) {
+	    this.name = name;
+	    this.desc = desc;
+	}
+
+	public boolean equals(Object o) {
+	    if (! (o instanceof CPNameAndTypeEntry))
+		return false;
+
+	    CPNameAndTypeEntry cpnte = (CPNameAndTypeEntry) o;
+	    return (cpnte.desc == desc && cpnte.name == name);
+	}
+
+	public void write(DataOutput d) throws IOException {
+	    d.writeByte(CONSTANT_NameAndType);
+	    d.writeShort(name);
+	    d.writeShort(desc);
+	}
+
+	public int needSlots() {
+	    return 1;
+	}
+  
+  public String toString() {
+    return "CPNameAndTypeEntry name=" + name + " desc=" + desc;
+  }
+    }
+}
diff --git a/src/org/biojava/utils/bytecode/DoubleInstruction.java b/src/org/biojava/utils/bytecode/DoubleInstruction.java
new file mode 100755
index 0000000..431d3b0
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/DoubleInstruction.java
@@ -0,0 +1,48 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Instructions which retrieve a double from the constant pool.
+ *
+ * @author Matthew Pocock
+ */
+
+class DoubleInstruction implements Instruction {
+  private double val;
+  
+  DoubleInstruction(double val) {
+    this.val = val;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    ctx.writeByte(ByteCode.op_ldc2_w);
+    ctx.writeShort(ctx.getConstants().resolveDouble(val));
+  }
+  
+  public int stackDepth() {
+    return stackDelta();
+  }
+  
+  public int stackDelta() {
+    return 1;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/ExceptionMemento.java b/src/org/biojava/utils/bytecode/ExceptionMemento.java
new file mode 100755
index 0000000..f446db4
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/ExceptionMemento.java
@@ -0,0 +1,45 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+class ExceptionMemento {
+    SimpleReference startHandled;
+    SimpleReference endHandled;
+    CodeClass eClass;
+    SimpleReference handler;
+
+    public ExceptionMemento(SimpleReference startHandled,
+			    SimpleReference endHandled,
+			    CodeClass eClass,
+			    SimpleReference handler)
+    {
+	this.startHandled = startHandled;
+	this.endHandled = endHandled;
+	this.eClass = eClass;
+	this.handler = handler;
+    }
+
+    public boolean isFullyResolved() {
+	return startHandled.isResolved() &&
+	       endHandled.isResolved() &&
+	       handler.isResolved();
+    }
+}
diff --git a/src/org/biojava/utils/bytecode/FieldInstruction.java b/src/org/biojava/utils/bytecode/FieldInstruction.java
new file mode 100755
index 0000000..19a5a56
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/FieldInstruction.java
@@ -0,0 +1,54 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Instructions which act on fields.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+class FieldInstruction implements Instruction {
+  private final CodeField field;
+  private final byte opcode;
+  
+  FieldInstruction(byte op, CodeField f) {
+    if(f == null) {
+      throw new NullPointerException("CodeField can not be null");
+    }
+    this.opcode = op;
+    this.field = f;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    ctx.writeByte(opcode);
+    ctx.writeShort(ctx.getConstants().resolveField(field));
+  }
+  
+  public int stackDepth() {
+    return stackDelta();
+  }
+  
+  public int stackDelta() {
+    return 1;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/FloatConstantInstruction.java b/src/org/biojava/utils/bytecode/FloatConstantInstruction.java
new file mode 100755
index 0000000..ae1d51c
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/FloatConstantInstruction.java
@@ -0,0 +1,55 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Instructions which load float constants
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+class FloatConstantInstruction implements Instruction {
+  private final float val;
+  
+  FloatConstantInstruction(float val) {
+    this.val = val;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    int i_indx = ctx.getConstants().resolveFloat(val);
+    if (i_indx < 256) {
+      ctx.writeByte(ByteCode.op_ldc);
+      ctx.writeByte((byte) i_indx);
+    } else {
+      ctx.writeByte(ByteCode.op_ldc_w);
+      ctx.writeShort(i_indx);
+    }
+  }
+  
+  public int stackDepth() {
+    return stackDelta();
+  }
+  
+  public int stackDelta() {
+    return 1;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/GeneratedClassLoader.java b/src/org/biojava/utils/bytecode/GeneratedClassLoader.java
new file mode 100755
index 0000000..05410c4
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/GeneratedClassLoader.java
@@ -0,0 +1,83 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * A class loader that actually produces real Java classes from
+ * GeneratedCodeClass instances.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+public class GeneratedClassLoader extends ClassLoader {
+  private Set generatedClasses = new HashSet();
+
+  /**
+   * Create a new loader with the default parent.
+   */
+  public GeneratedClassLoader() {
+    super();
+  }
+
+  /**
+   * Create a new loader with an explicitly set parent class loader.
+   *
+   * @param parent  the parent ClassLoader
+   */
+  public GeneratedClassLoader(ClassLoader parent) {
+    super(parent);
+  }
+
+  /**
+   * Define a class based upon a GeneratedCodeClass.
+   *
+   * @param cc  the GeneratedCodeClass to define
+   * @return    the newly defined class
+   * @throws CodeException  if there was a failure defining the class
+   */
+  public Class defineClass(GeneratedCodeClass cc) throws CodeException {
+    try {
+	    ByteArrayOutputStream bos = new ByteArrayOutputStream();
+	    cc.createCode(bos);
+	    byte[] code = bos.toByteArray();
+      Class clazz = defineClass(cc.getName(), code, 0, code.length);
+      generatedClasses.add(clazz.getName());
+      return clazz;
+    } catch (IOException ex) {
+	    // Seems unlikely...
+	    throw new CodeException();
+    }
+  }
+
+  /**
+   * Discover if a class for this name has already been defined by this class
+   * loader.
+   *
+   * @param name  the name of the class
+   * @return      true if the class has already been defined by this loader
+   */
+  public boolean hasGeneratedClass(String name) {
+    return generatedClasses.contains(name);
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/GeneratedCodeClass.java b/src/org/biojava/utils/bytecode/GeneratedCodeClass.java
new file mode 100755
index 0000000..008bfb3
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/GeneratedCodeClass.java
@@ -0,0 +1,506 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * A CodeClass implementation that is used to generate new classes.
+ *
+ * <p>
+ * When creating classes, instantiate one of these, add fields and methods.
+ * Associate CodeGenerator instances with methods. Then, use
+ * GeneratedClassLoader to make a new class.
+ * </p>
+ *
+ * @author Matthew Pocock
+ */
+public class GeneratedCodeClass implements CodeClass {
+  private String name;
+  private CodeClass superClass;
+  private List interfaces;
+  private int modifiers;
+  private Map methods;
+  private Map fields;
+  private String sourceFile;
+  private boolean deprecated;
+
+  {
+    methods = new HashMap();
+    fields = new HashMap();
+    sourceFile = null;
+  }
+
+  public GeneratedCodeClass(
+          String name,
+          Class superClass,
+          Class[] interfaces,
+          int modifiers
+          ) throws CodeException
+  {
+    this.name = name;
+    this.modifiers = modifiers;
+    this.superClass = IntrospectedCodeClass.forClass(superClass);
+    this.interfaces = new ArrayList(Arrays.asList(interfaces));
+    for (Iterator i = this.interfaces.iterator(); i.hasNext();) {
+      Class clazz = (Class) i.next();
+      if (!clazz.isInterface()) {
+        throw new CodeException(
+                "Attempted to create class implemneting non-interface " + clazz
+        );
+      }
+    }
+  }
+
+  public GeneratedCodeClass(String name,
+                            CodeClass superClass,
+                            CodeClass[] interfaces,
+                            int modifiers)
+          throws CodeException
+  {
+    this.name = name;
+    this.modifiers = modifiers;
+    this.superClass = superClass;
+    this.interfaces = new ArrayList(Arrays.asList(interfaces));
+    for (Iterator i = this.interfaces.iterator(); i.hasNext();) {
+      Object obj = i.next();
+      if (!(obj instanceof CodeClass)) {
+        throw new CodeException(
+                "Interface list must contain CodeClass instances"
+        );
+      }
+    }
+  }
+
+  /**
+   * Set the source file associated with this code class.
+   *
+   * <p>
+   * The source file appears in debugging output and stack traces. Use this
+   * method to set the source file that this generated class will clame to be
+   * from. You can use non-file names e.g. uri:myGenerator:proxy/foo
+   * </p>
+   *
+   * <p>
+   * To un-set the source file, use null.
+   * </p>
+   *
+   * @param sourceFile  the source file for this class
+   */
+  public void setSourceFile(String sourceFile) {
+    this.sourceFile = sourceFile;
+  }
+
+  /**
+   * Get the source file associated with this code class.
+   *
+   * <p>
+   * Null indicates that no source file is set.
+   * </p>
+   *
+   * @return the source file for this code class
+   */
+  public String getSourceFile() {
+    return sourceFile;
+  }
+
+  /**
+   * Set the deprecation flag.
+   *
+   * <p>
+   * If deprecated is true, the class will be flagged as deprecated.
+   * </p>
+   *
+   * @param deprecated  the new value of the deprecation
+   */
+  public void setDeprecated(boolean deprecated) {
+    this.deprecated = deprecated;
+  }
+
+  /**
+   * Get the deprecation flag.
+   *
+   * @return  wether or not this class is deprecated
+   */
+  public boolean isDeprecated() {
+    return deprecated;
+  }
+
+  public List getInterfaces() {
+    return Collections.unmodifiableList(interfaces);
+  }
+
+  public Set getMethods() {
+    return methods.keySet();
+  }
+
+  public Set getMethodsByName(String name) {
+    Set all = getMethods();
+    Set some = new HashSet();
+    for (Iterator i = all.iterator(); i.hasNext();) {
+      CodeMethod m = (CodeMethod) i.next();
+      if (m.getName().equals(name)) {
+        some.add(m);
+      }
+    }
+    return some;
+  }
+
+  public CodeMethod getConstructor(CodeClass[] args)
+          throws NoSuchMethodException
+  {
+    return getMethod("<init>", args);
+  }
+
+  public CodeMethod getMethod(String name, CodeClass[] args)
+          throws NoSuchMethodException
+  {
+    Set poss = getMethodsByName(name);
+    METHOD_LOOP:
+     for (Iterator i = poss.iterator(); i.hasNext();) {
+       CodeMethod meth = (CodeMethod) i.next();
+       if (meth.numParameters() != args.length) {
+         continue METHOD_LOOP;
+       }
+       for (int j = 0; j < args.length; j++) {
+         if (!meth.getParameterType(j).equals(args[j])) {
+           continue METHOD_LOOP;
+         }
+       }
+       return meth;
+     }
+
+    StringBuffer methodSig = new StringBuffer(
+            "Could not find method " + getName() + "." + name + "("
+    );
+    if (args.length > 0) {
+      methodSig.append(args[0].getName());
+    }
+    for (int i = 1; i < args.length; i++) {
+      methodSig.append(",");
+      methodSig.append(args[i].getName());
+    }
+    methodSig.append(")");
+    throw new NoSuchMethodException(methodSig.toString());
+  }
+
+  public Set getFields() {
+    return fields.keySet();
+  }
+
+  public CodeClass getSuperClass() {
+    return superClass;
+  }
+
+  public CodeField getFieldByName(String name)
+          throws NoSuchFieldException
+  {
+    CodeField f = (CodeField) fields.get(name);
+    if (f == null) {
+      throw new NoSuchFieldException("No field for " + name + " in class " + getName());
+    }
+    return f;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public String getJName() {
+    String name = getName();
+    StringBuffer sb = new StringBuffer();
+    for (int i = 0; i < name.length(); ++i) {
+      char c = name.charAt(i);
+      if (c == '.')
+        sb.append('/');
+      else
+        sb.append(c);
+    }
+    return sb.toString();
+  }
+
+  public int getModifiers() {
+    return modifiers;
+  }
+
+  public String getDescriptor() {
+    String name = getName();
+    StringBuffer sb = new StringBuffer();
+    sb.append('L');
+    for (int i = 0; i < name.length(); ++i) {
+      char c = name.charAt(i);
+      if (c == '.')
+        sb.append('/');
+      else
+        sb.append(c);
+    }
+    sb.append(';');
+    return sb.toString();
+  }
+
+  /**
+   * Create a new method.
+   *
+   * <p>
+   * This defines the shape of a method that will be generated. Use
+   * {@link #setCodeGenerator} to associate code with the method.
+   * </p>
+   *
+   * <p>
+   * The argNames will become the names of local variables for each argument.
+   * </p>
+   *
+   * @param name      the method name
+   * @param type      the return type
+   * @param args      arguments taken
+   * @param argNames  names of the arguments
+   * @param mods      access modifiers
+   * @return          a new GeneratedCodeMethod
+   * @throws CodeException if the method could not be created
+   */
+  public GeneratedCodeMethod createMethod(
+          String name,
+          CodeClass type,
+          CodeClass[] args,
+          String[] argNames,
+          int mods
+          )
+          throws CodeException
+  {
+    GeneratedCodeMethod cm = new GeneratedCodeMethod(this, name, type, args, argNames, mods);
+    if (methods.containsKey(cm)) {
+      throw new CodeException("Attempt to create multiple methods with same signatures.");
+    }
+
+    methods.put(cm, null);
+    return cm;
+  }
+
+  /**
+   * Create a new method.
+   *
+   * <p>
+   * This defines the shape of a method that will be generated. Use
+   * {@link #setCodeGenerator} to associate code with the method.
+   * </p>
+   *
+   * @param name      the method name
+   * @param type      the return type
+   * @param args      arguments taken
+   * @param mods      access modifiers
+   * @return          a new GeneratedCodeMethod
+   * @throws CodeException if the method could not be created
+   */
+  public GeneratedCodeMethod createMethod(
+          String name,
+          CodeClass type,
+          CodeClass[] args,
+          int mods
+          )
+          throws CodeException
+  {
+    return createMethod(name, type, args, new String[0], mods);
+  }
+
+  public CodeField createField(String name, CodeClass clazz, int mods)
+          throws CodeException
+  {
+    if (fields.containsKey(name)) {
+      throw new CodeException("Attempt to create multiple fields named " + name);
+    }
+
+    CodeField cf = new CodeField(this, name, clazz, mods);
+    fields.put(name, cf);
+    return cf;
+  }
+
+  public void setCodeGenerator(CodeMethod method, CodeGenerator cg)
+          throws CodeException
+  {
+    if (!methods.containsKey(method)) {
+      throw new CodeException("Class doesn't provide method " + method.getName());
+    }
+
+    methods.put(method, cg);
+  }
+
+  public void createCode(OutputStream os)
+          throws IOException, CodeException
+  {
+    DataOutputStream dos = new DataOutputStream(os);
+
+    // Write classfile header
+
+    dos.writeInt((int) (0xcafebabe));    // Magic
+    dos.writeShort(3);                  // Minor  version
+    dos.writeShort(45);                   // Major version (check!)
+
+    ConstantPool cp = new ConstantPool();
+
+    // The rest of the classfile gets written to a buffer, accumulating a constant pool along the way
+
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    DataOutputStream bdos = new DataOutputStream(baos);
+
+    bdos.writeShort(modifiers);
+    bdos.writeShort(cp.resolveClass(this));         // this-class ID
+    bdos.writeShort(cp.resolveClass(superClass));   // super-class ID
+    bdos.writeShort(interfaces.size());             // number_of_interfaces
+    for (Iterator i = interfaces.iterator(); i.hasNext();) {
+      bdos.writeShort(cp.resolveClass((CodeClass) i.next())); // interface ID
+    }
+
+    // Write the fields
+
+    bdos.writeShort(fields.size());
+    for (Iterator i = fields.values().iterator(); i.hasNext();) {
+      CodeField cf = (CodeField) i.next();
+      bdos.writeShort(cf.getModifiers());
+      bdos.writeShort(cp.resolveUtf8(cf.getName()));
+      bdos.writeShort(cp.resolveUtf8(cf.getType().getDescriptor()));
+      bdos.writeShort(0); // No attributes right now
+    }
+
+    // Write the methods (wahey!)
+
+    Set methSet = methods.entrySet();
+    bdos.writeShort(methSet.size());
+    for (Iterator i = methSet.iterator(); i.hasNext();) {
+      Map.Entry me = (Map.Entry) i.next();
+      GeneratedCodeMethod cm = (GeneratedCodeMethod) me.getKey();
+      CodeGenerator cg = (CodeGenerator) me.getValue();
+
+      bdos.writeShort(cm.getModifiers());                   // access_flags
+      bdos.writeShort(cp.resolveUtf8(cm.getName()));        // name_index
+      bdos.writeShort(cp.resolveUtf8(cm.getDescriptor()));  // descriptor_index
+
+      // Actually generate the code
+      MethodRootContext ctx = new MethodRootContext(this, cm, cp);
+      ctx.open();
+
+      LocalVariable thisP = cm.getThis();
+      if (thisP != null) {
+        // Non-static method
+        ctx.resolveLocal(thisP);
+      }
+      for (int parm = 0; parm < cm.numParameters(); ++parm) {
+        ctx.resolveLocal(cm.getVariable(parm));
+      }
+
+      cg.writeCode(ctx);
+      ctx.close();
+
+      Set thrownExceptions = cm.getThrownExceptions();
+
+      // number of method attirbutes
+      int numMethAttrs = 1; // we always have code
+
+      // do we have exceptions?
+      if(!thrownExceptions.isEmpty()) {
+        numMethAttrs++;
+      }
+
+      bdos.writeShort(numMethAttrs);                        // attributes_count
+
+      // start attribute_info for method
+
+      // Code attribute
+      List exceptionTable = ctx.getExceptionTable();
+
+      bdos.writeShort(cp.resolveUtf8("Code"));
+      bdos.writeInt(12 + ctx.getOffset() + exceptionTable.size() * 8);
+      bdos.writeShort(cg.stackDepth());
+      bdos.writeShort(ctx.getMaxLocals());
+      bdos.writeInt(ctx.getOffset());
+      ctx.writeTo(bdos);
+      bdos.writeShort(exceptionTable.size());
+      for (Iterator ei = exceptionTable.iterator(); ei.hasNext();) {
+        ExceptionMemento em = (ExceptionMemento) ei.next();
+        if (!(em.isFullyResolved()))
+          throw new CodeException("Exception table entry refers to unresolved label");
+        bdos.writeShort(em.startHandled.getOffset());
+        bdos.writeShort(em.endHandled.getOffset());
+        bdos.writeShort(em.handler.getOffset());
+        if (em.eClass != null)
+          bdos.writeShort(cp.resolveClass(em.eClass));
+        else
+          bdos.writeShort(0); // For `finally'
+      }
+      bdos.writeShort(0); // Code has no sub-attributes
+
+      // Exceptions attribute
+      if (thrownExceptions.size() > 0) {
+        bdos.writeShort(cp.resolveUtf8("Exceptions"));  // attribute_name_index
+        bdos.writeInt(2 + thrownExceptions.size() * 2); // attribute_length
+        bdos.writeShort(thrownExceptions.size());       // number_of_exceptions
+        for (Iterator tei = thrownExceptions.iterator(); tei.hasNext();) {
+          CodeClass exClass = (CodeClass) tei.next();
+          bdos.writeShort(cp.resolveClass(exClass));    // exception class
+        }
+      }
+    }
+
+    // class-wide attributes
+    //
+    // currently, these are SourceFile and Deprecated only
+    int classAttributes = 0;
+
+    if(sourceFile != null) {
+      classAttributes++;
+    }
+    if(deprecated) {
+      classAttributes++;
+    }
+
+    bdos.writeShort(classAttributes);  // attributes_count
+
+    // write the source file attribute
+    if(sourceFile != null) {
+      bdos.writeShort(cp.resolveUtf8("SourceFile"));  // attribute_name_index
+      bdos.writeInt(2);                               // attribute_length
+      bdos.writeShort(cp.resolveUtf8(sourceFile));    // sourcefile_index
+    }
+
+    // write the deprecate attribute
+    if(isDeprecated()) {
+      bdos.writeShort(cp.resolveUtf8("Deprecated"));  // attribute_name_index
+      bdos.writeInt(0);                               // attribute_length
+    }
+
+    // All constants will now have been resolved, so we can finally write the cpool
+
+    dos.writeShort(cp.constantPoolSize());
+    cp.writeConstantPool(dos);
+
+    // Append the rest of the classfile to the stream
+
+    baos.writeTo(dos);
+  }
+
+  public boolean isPrimitive() {
+    return false;
+  }
+
+  public boolean isArray() {
+    return false;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/GeneratedCodeMethod.java b/src/org/biojava/utils/bytecode/GeneratedCodeMethod.java
new file mode 100755
index 0000000..539ffa0
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/GeneratedCodeMethod.java
@@ -0,0 +1,187 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+import java.util.*;
+
+/**
+ * A method that will be generated.
+ *
+ * <p>
+ * These are instantiated by factory methods on {@link GeneratedCodeClass}, and
+ * can not be instantiated directly.
+ * </p>
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+public final class GeneratedCodeMethod implements CodeMethod {
+  private final String name;
+  private List args;
+  private List localvars;
+  private LocalVariable thisV;
+  private int modifiers;
+  private CodeClass type;
+  private CodeClass container;
+  private Set thrownExceptions;
+  private Map nameToLocals;
+
+  GeneratedCodeMethod(
+    CodeClass container, 
+    String name, 
+    CodeClass type, 
+    CodeClass[] args, 
+    String[] names,
+    int modifiers
+  ) {
+    this.container = container;
+    this.name = name;
+    this.args = new ArrayList(Arrays.asList(args));
+    this.modifiers = modifiers;
+    this.type = type;
+    nameToLocals = new HashMap();
+    localvars = new ArrayList();
+    for(int i = 0; i < this.args.size(); ++i) {
+      if(i < names.length) {
+        LocalVariable arg = new LocalVariable(args[i], names[i]);
+        localvars.add(arg);
+        nameToLocals.put(names[i], arg);
+      } else {
+        localvars.add(new LocalVariable(args[i]));
+      }
+    }
+
+    if((modifiers & CodeUtils.ACC_STATIC) == 0) {
+      thisV = new LocalVariable(container, "this");
+      nameToLocals.put("this", thisV);
+    }
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public String getFullName() {
+    return container.getName() + "." + name;
+  }
+
+  public CodeClass getContainingClass() {
+    return container;
+  }
+
+  public String getDescriptor() {
+    StringBuffer sb = new StringBuffer();
+    sb.append('(');
+    for(Iterator i = args.iterator(); i.hasNext(); ) {
+      CodeClass cc = (CodeClass) i.next();
+      sb.append(cc.getDescriptor());
+    }
+    sb.append(')');
+    sb.append(type.getDescriptor());
+    return sb.toString();
+  }
+
+  public int getModifiers() {
+    return modifiers;
+  }
+
+  public CodeClass getReturnType() {
+    return type;
+  }
+
+  public int numParameters() {
+    return args.size();
+  }
+
+  public CodeClass getParameterType(int pos) {
+    return (CodeClass) args.get(pos);
+  }
+
+  /**
+   *  Gets the Variable attribute of the GeneratedCodeMethod object.
+   *
+   * <p>
+   * There is one local variable for each of the arguments of the method,
+   * indexed from 0.
+   * </p>
+   *
+   * @param  pos  the index of the local variable
+   * @return      the local variable
+   */
+  public LocalVariable getVariable(int pos) {
+    return (LocalVariable) localvars.get(pos);
+  }
+  
+  /**
+   * Gets the Variable attribute of the GenerateCodeMethod object by name.
+   *
+   * <P>
+   * All methods have a variable under the string "this". If it was constructed
+   * with a String [] naming the args, the locals for each local can be
+   * retrieved by name.
+   * </p>
+   *
+   * @param argName a String naming the local
+   * @return        the LocalVariable for that argName
+   * @throws        NoSuchElementException if there is no local with that name
+   */
+  public LocalVariable getVariable(String argName)
+  throws NoSuchElementException {
+    LocalVariable lv = (LocalVariable) nameToLocals.get(argName);
+    if(lv == null) {
+      throw new NoSuchElementException(
+        "Can't find local for argName " + argName
+      );
+    }
+    return lv;
+  }
+
+  /**
+   *  Gets the This attribute of the GeneratedCodeMethod object 
+   *
+   * @return    The This value 
+   */
+  public LocalVariable getThis() {
+    return thisV;
+  }
+
+  /**
+   *  Gets the ThrownExceptions attribute of the GeneratedCodeMethod object 
+   *
+   * @return    The ThrownExceptions value 
+   */
+  public Set getThrownExceptions() {
+    return Collections.unmodifiableSet(thrownExceptions);
+  }
+
+  /**
+   *  Adds a feature to the ThrownException attribute of the GeneratedCodeMethod object 
+   *
+   * @param  cc  The feature to be added to the ThrownException attribute 
+   */
+  public void addThrownException(CodeClass cc) {
+    thrownExceptions.add(cc);
+  }
+  
+  {
+    thrownExceptions = new HashSet();
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/IfExpression.java b/src/org/biojava/utils/bytecode/IfExpression.java
new file mode 100755
index 0000000..2ee97c1
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/IfExpression.java
@@ -0,0 +1,103 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+import java.util.*;
+
+/**
+ * A CodeGenerator that provides something semanticaly identical to if.
+ * <P>
+ * It generates code of the form:
+ * <P>
+ * conditional branch to trueLabel<br>
+ * ifFalse instructions here<br>
+ * branch to endLabel<br>
+ * trueLabel<br>
+ * ifTrue instructions here<br>
+ * endLabel
+ *
+ *
+ * @author Matthew Pocock
+ */
+
+public class IfExpression implements CodeGenerator {
+  private Instruction ifInstruction;
+  private CodeGenerator ifTrue;
+  private CodeGenerator ifFalse;
+  private Label trueLabel;
+  private Label endLabel;
+  private Instruction skipTrue;
+  
+  private InstructionVector instructions;
+  
+  public IfExpression(
+    byte ifInstruction, 
+    CodeGenerator ifTrue, 
+    CodeGenerator ifFalse
+  ) {
+    this.trueLabel = new Label();
+    this.endLabel = new Label();
+    this.skipTrue = ByteCode.make_goto(endLabel);
+
+    this.ifInstruction = ByteCode.make_if(ifInstruction, trueLabel);
+    this.ifTrue = ifTrue;
+    this.ifFalse = ifFalse;
+    
+    // lazyness - avoid work later
+    instructions = new InstructionVector();
+    instructions.add(this.ifInstruction);
+    instructions.add(this.ifFalse);
+    instructions.add(this.skipTrue);
+    instructions.add(ByteCode.make_markLabel(trueLabel));
+    instructions.add(this.ifTrue);
+    instructions.add(ByteCode.make_markLabel(endLabel));
+  }
+  
+  public Instruction getIfInstruction() {
+    return ifInstruction;
+  }
+  
+  public CodeGenerator getIfTrue() {
+    return ifTrue;
+  }
+  
+  public CodeGenerator getIfFalse() {
+    return ifFalse;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    instructions.writeCode(ctx);
+  }
+  
+  public int stackDepth() {
+    // custom handlers needed because of jumps
+    return
+      ifInstruction.stackDepth() +
+      Math.max(ifFalse.stackDepth(), ifTrue.stackDepth());
+  }
+  
+  public int stackDelta() {
+    // custom handler needed because of jumps
+    return
+      ifInstruction.stackDepth() +
+      Math.max(ifFalse.stackDepth(), ifTrue.stackDepth()); // these should agree
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/Instruction.java b/src/org/biojava/utils/bytecode/Instruction.java
new file mode 100755
index 0000000..e558b38
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/Instruction.java
@@ -0,0 +1,30 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Base class for java bytecode instructions.
+ *
+ * @author Thomas Down
+ */
+
+public interface Instruction extends CodeGenerator {
+}
diff --git a/src/org/biojava/utils/bytecode/InstructionVector.java b/src/org/biojava/utils/bytecode/InstructionVector.java
new file mode 100755
index 0000000..adce5f2
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/InstructionVector.java
@@ -0,0 +1,132 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+import java.util.*;
+
+/**
+ * A list of Instructions and/or other CodeGenerator objects.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+public class InstructionVector implements CodeGenerator {
+  private final List instructions;
+  private final Label startLabel;
+  private final Label endLabel;
+  
+  private StatsCache statsCache; // gets set to null on edits
+  
+  {
+    instructions = new ArrayList();
+    startLabel = new Label();
+    endLabel = new Label();
+    statsCache = null;
+  }
+  
+  public void add(CodeGenerator g) {
+    statsCache = null;
+    instructions.add(g);
+  }
+  
+  public int size() {
+    return instructions.size();
+  }
+  
+  public void add(int pos, CodeGenerator g) {
+    statsCache = null;
+    instructions.add(pos, g);
+  }
+  
+  public void remove(int pos) {
+    statsCache = null;
+    instructions.remove(pos);
+  }
+  
+  public CodeGenerator generatorAt(int pos) {
+    return (CodeGenerator) instructions.get(pos);
+  }
+  
+  public Label getStartLabel() {
+    return startLabel;
+  }
+  
+  public Label getEndLabel() {
+    return endLabel;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    CodeContext subctx = ctx.subContext();
+    subctx.open();
+    subctx.markLabel(startLabel);
+    for (Iterator i = instructions.iterator(); i.hasNext(); ) {
+      CodeGenerator cg = (CodeGenerator) i.next();
+      cg.writeCode(subctx);
+    }
+    subctx.markLabel(endLabel);
+    subctx.close(); // Wrap up the subcontt
+  }
+  
+  public int stackDepth() {
+    StatsCache statsCache = getStatsCache();
+    
+    return statsCache.depth;
+  }
+  
+  public int stackDelta() {
+    StatsCache statsCache = getStatsCache();
+    
+    return statsCache.delta;
+  }
+  
+  private StatsCache getStatsCache() {
+    if(statsCache == null) {
+      int depth = 0;
+      int delta = 0;
+      
+      for(Iterator i = instructions.iterator(); i.hasNext(); ) {
+        CodeGenerator cg = (CodeGenerator) i.next();
+        int dp = cg.stackDepth();
+        int dl = cg.stackDelta();
+        
+        dp += delta;
+        delta += dl;
+
+        depth = Math.max(depth, dp);
+      }
+      
+      statsCache = new StatsCache(depth, delta);
+    }
+    
+    return statsCache;
+  }
+  
+  private static class StatsCache {
+    public final int depth;
+    public final int delta;
+    
+    public StatsCache(int depth, int delta) {
+      this.depth = depth;
+      this.delta = delta;
+    }
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/IntConstantInstruction.java b/src/org/biojava/utils/bytecode/IntConstantInstruction.java
new file mode 100755
index 0000000..0a87f3c
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/IntConstantInstruction.java
@@ -0,0 +1,55 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Instructions which load int constants
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+class IntConstantInstruction implements Instruction {
+  private final int i;
+  
+  IntConstantInstruction(int i) {
+    this.i = i;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    int i_indx = ctx.getConstants().resolveInt(i);
+    if (i_indx < 256) {
+      ctx.writeByte(ByteCode.op_ldc);
+      ctx.writeByte((byte) i_indx);
+    } else {
+      ctx.writeByte(ByteCode.op_ldc_w);
+      ctx.writeShort(i_indx);
+    }
+  }
+  
+  public int stackDepth() {
+    return stackDelta();
+  }
+  
+  public int stackDelta() {
+    return 1;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/IntrospectedCodeClass.java b/src/org/biojava/utils/bytecode/IntrospectedCodeClass.java
new file mode 100755
index 0000000..cd53782
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/IntrospectedCodeClass.java
@@ -0,0 +1,341 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+import java.util.*;
+import java.lang.reflect.*;
+
+// fix for array types so that their descriptors are not prefixed with L
+
+/**
+ * CodeClass instances that represent normal Java Class objects.
+ *
+ * <p>
+ * Instances of IntrospectedCodeClass are generated using the static factory
+ * methods named forClass(). These methods ensure that the same
+ * IntrospectedCodeClass instance is returned for multiple invocations with
+ * the same argument.
+ * </p>
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+public class IntrospectedCodeClass implements CodeClass {
+  private static Map introspectedClasses;
+  private static Map primitiveDescriptors;
+
+  static {
+    introspectedClasses = new HashMap();
+
+    primitiveDescriptors = new HashMap();
+    primitiveDescriptors.put(Byte.TYPE, "B");
+    primitiveDescriptors.put(Character.TYPE, "C");
+    primitiveDescriptors.put(Double.TYPE, "D");
+    primitiveDescriptors.put(Float.TYPE, "F");
+    primitiveDescriptors.put(Integer.TYPE, "I");
+    primitiveDescriptors.put(Long.TYPE, "J");
+    primitiveDescriptors.put(Short.TYPE, "S");
+    primitiveDescriptors.put(Boolean.TYPE, "Z");
+    primitiveDescriptors.put(Void.TYPE, "V");
+
+  }
+
+  /**
+   * Get the CodeClass for a Java Class.
+   *
+   * @param c  the Java Class to reflect
+   * @return  a CodeClass representing the class
+   */
+  public static CodeClass forClass(Class c) {
+    CodeClass cc = (CodeClass) introspectedClasses.get(c);
+    if (cc == null) {
+      cc = new IntrospectedCodeClass(c);
+      introspectedClasses.put(c, cc);
+    }
+    return cc;
+  }
+
+  /**
+   * Get the CodeClass for a Java class name.
+   *
+   * @param name  the Java class name to reflect
+   * @return  a CodeClass representing the class
+   */
+  public static CodeClass forClass(String name) throws ClassNotFoundException {
+    Class c = ClassLoader.getSystemClassLoader().loadClass(name);
+
+    return forClass(c);
+  }
+
+  public static CodeMethod forMethod(Method method) {
+    return new IntrospectedCodeMethod(method);
+  }
+
+  //
+  // Instance
+  //
+
+  private Class clazz;
+
+  private IntrospectedCodeClass(Class c) {
+    this.clazz = c;
+  }
+
+  public String getName() {
+    return clazz.getName();
+  }
+
+  public String getJName() {
+    String name = getName();
+    StringBuffer sb = new StringBuffer();
+    for (int i = 0; i < name.length(); ++i) {
+      char c = name.charAt(i);
+      if (c == '.')
+        sb.append('/');
+      else
+        sb.append(c);
+    }
+
+    return sb.toString();
+  }
+
+  public String getDescriptor() {
+    if (clazz.isPrimitive()) {
+      String desc = (String) primitiveDescriptors.get(clazz);
+      if (desc == null) {
+        throw new RuntimeException("Unknown primitive type " + clazz.getName() + ", eeek!");
+      }
+      return desc;
+    }
+
+    if (clazz.isArray()) {
+      return "[" + IntrospectedCodeClass.forClass(clazz.getComponentType()).getDescriptor();
+    } else {
+      String name = getName();
+      StringBuffer sb = new StringBuffer();
+      sb.append('L');
+      for (int i = 0; i < name.length(); ++i) {
+        char c = name.charAt(i);
+        if (c == '.') {
+          sb.append('/');
+        } else {
+          sb.append(c);
+        }
+      }
+      sb.append(';');
+      return sb.toString();
+    }
+  }
+
+  public int getModifiers() {
+    return clazz.getModifiers();
+  }
+
+  public CodeClass getSuperClass() {
+    return IntrospectedCodeClass.forClass(clazz.getSuperclass());
+  }
+
+  public List getInterfaces() {
+    Class[] interfaces = clazz.getInterfaces();
+    return Arrays.asList(interfaces);
+  }
+
+  private Set _methods;
+  private Map _methsByNameSig;
+  private Map _methsByName;
+
+  public Set getMethods() {
+    initMethods();
+    return _methods;
+  }
+
+  private void initMethods() {
+    if (_methods == null) {
+      Map meths = new HashMap();
+      popMeths(this.clazz, meths);
+      popIMeths(this.clazz, meths);
+      _methods = new HashSet(meths.values());
+      _methsByNameSig = new HashMap();
+      _methsByName = new HashMap();
+      for(Iterator i = _methods.iterator(); i.hasNext(); ) {
+        CodeMethod m = (CodeMethod) i.next();
+        Set mbn = (Set) _methsByName.get(m.getName());
+        if(mbn == null) {
+          _methsByName.put(m.getName(), mbn = new HashSet());
+        }
+        mbn.add(m);
+        _methsByNameSig.put(makeNameSig(m), m);
+      }
+    }
+  }
+
+  private void popMeths(Class clazz, Map meths) {
+    Method[] methods = clazz.getDeclaredMethods();
+    for(int i = 0; i < methods.length; i++) {
+      Method m = methods[i];
+      ArrayList sigList = new ArrayList();
+      sigList.add(m.getName());
+      sigList.addAll(Arrays.asList(m.getParameterTypes()));
+      if(!meths.containsKey(sigList)) {
+        meths.put(sigList, new IntrospectedCodeMethod(m));
+      }
+    }
+
+    Class sup = clazz.getSuperclass();
+    if(sup != null) {
+      popMeths(sup, meths);
+    }
+  }
+
+  private void popIMeths(Class clazz, Map meths) {
+    if(clazz.isInterface()) {
+      Method[] methods = clazz.getDeclaredMethods();
+      for(int i = 0; i < methods.length; i++) {
+        Method m = methods[i];
+        ArrayList sigList = new ArrayList();
+        sigList.add(m.getName());
+        sigList.addAll(Arrays.asList(m.getParameterTypes()));
+        if(!meths.containsKey(sigList)) {
+          meths.put(sigList, new IntrospectedCodeMethod(m));
+        }
+      }
+      Class[] interfaces = clazz.getInterfaces();
+      for(int i = 0; i < interfaces.length; i++) {
+        popIMeths(interfaces[i], meths);
+      }
+    }
+
+    Class sup = clazz.getSuperclass();
+    if(sup != null) {
+      popIMeths(sup, meths);
+    }
+  }
+
+  private List makeNameSig(CodeMethod m) {
+    List res = new ArrayList();
+    res.add(m.getName());
+
+    for(int i = 0; i < m.numParameters(); i++) {
+      res.add(m.getParameterType(i));
+    }
+
+    return res;
+  }
+
+  public CodeField getFieldByName(String name)
+          throws NoSuchFieldException {
+    try {
+      Field f = clazz.getField(name);
+      return new CodeField(this,
+                           name,
+                           IntrospectedCodeClass.forClass(f.getType()),
+                           f.getModifiers());
+    } catch (NoSuchFieldException ex) {
+      throw (NoSuchFieldException) new NoSuchFieldException(
+              "Can't find field " + name +
+              " in class " + getName()
+      ).initCause(ex);
+    }
+  }
+
+  private Set _fields;
+
+  public Set getFields() {
+    if(_fields == null) {
+      _fields = new HashSet();
+      Field[] fields = clazz.getFields();
+      for(int fi = 0; fi < fields.length; fi++) {
+        Field f = fields[fi];
+        _fields.add(new CodeField(this,
+                                  f.getName(),
+                                  IntrospectedCodeClass.forClass(f.getType()),
+                                  f.getModifiers()));
+      }
+
+      _fields = Collections.unmodifiableSet(_fields);
+    }
+
+    return _fields;
+  }
+
+  public Set getMethodsByName(String name) {
+    initMethods();
+
+    Set hits = (Set) _methsByName.get(name);
+    if(hits == null) {
+      return Collections.EMPTY_SET;
+    } else {
+      return hits;
+    }
+  }
+
+  public CodeMethod getMethod(String name, CodeClass[] args)
+          throws NoSuchMethodException
+  {
+    initMethods();
+
+    List nameSig = new ArrayList();
+    nameSig.add(name);
+    for(int i = 0; i < args.length; i++) {
+      nameSig.add(args[i]);
+    }
+
+    CodeMethod cm = (CodeMethod) _methsByNameSig.get(nameSig);
+
+    if(cm == null) {
+      throw new NoSuchMethodException(
+              "Could not find method " + getName() +
+              "." + name +
+              "(" + CodeUtils.classListToString(args) + ")");
+    }
+
+    return cm;
+  }
+
+
+  public CodeMethod getConstructor(CodeClass[] args)
+          throws NoSuchMethodException {
+    try {
+      Class[] argsC = new Class[args.length];
+      for (int i = 0; i < args.length; i++) {
+        argsC[i] = ((IntrospectedCodeClass) args[i]).clazz;
+      }
+      return new IntrospectedCodeConstructor(clazz.getConstructor(argsC));
+    } catch (NoSuchMethodException nsme) {
+      throw (NoSuchMethodException) new NoSuchMethodException(
+              "Could not find constructor new " + getName() +
+              "(" + CodeUtils.classListToString(args) + ")"
+      ).initCause(nsme);
+    }
+  }
+
+  public boolean isPrimitive() {
+    return clazz.isPrimitive();
+  }
+
+  public boolean isArray() {
+    return clazz.isArray();
+  }
+
+  public String toString() {
+    return this.getClass().getName() + ": " + clazz.getName();
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/IntrospectedCodeConstructor.java b/src/org/biojava/utils/bytecode/IntrospectedCodeConstructor.java
new file mode 100755
index 0000000..bb6ae00
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/IntrospectedCodeConstructor.java
@@ -0,0 +1,77 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+import java.lang.reflect.*;
+
+/**
+ * Wrap up details about a constructor in a Java class file
+ *
+ * @author Matthew Pocock
+ */
+
+class IntrospectedCodeConstructor implements CodeMethod {
+    private final Constructor _constructor;
+
+    public IntrospectedCodeConstructor(Constructor m) {
+	_constructor = m;
+    }
+
+    public String getName() {
+	return "<init>"; // all constructors are called <init>
+    }
+
+    public String getFullName() {
+	return _constructor.getDeclaringClass().getName() + "." + getName();
+    }
+
+    public CodeClass getContainingClass() {
+	return IntrospectedCodeClass.forClass(_constructor.getDeclaringClass());
+    }
+
+    public String getDescriptor() {
+	StringBuffer sb = new StringBuffer();
+	sb.append('(');
+	for (int i = 0; i < numParameters(); ++i) {
+	    CodeClass cc = getParameterType(i);
+	    sb.append(cc.getDescriptor());
+	}
+	sb.append(')');
+	sb.append(getReturnType().getDescriptor());
+	return sb.toString();
+    }
+
+    public int getModifiers() {
+	return _constructor.getModifiers();
+    }
+
+    public CodeClass getReturnType() {
+	return CodeUtils.TYPE_VOID;
+    }
+
+    public int numParameters() {
+	return _constructor.getParameterTypes().length;
+    }
+
+    public CodeClass getParameterType(int pos) {
+	return IntrospectedCodeClass.forClass(_constructor.getParameterTypes()[pos]);
+    }
+}
diff --git a/src/org/biojava/utils/bytecode/IntrospectedCodeMethod.java b/src/org/biojava/utils/bytecode/IntrospectedCodeMethod.java
new file mode 100755
index 0000000..43bd314
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/IntrospectedCodeMethod.java
@@ -0,0 +1,81 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+import java.lang.reflect.*;
+
+/**
+ * Wrap up details about a method in a Java class file
+ *
+ * @author Thomas Down
+ */
+
+class IntrospectedCodeMethod implements CodeMethod {
+    private final Method _method;
+
+    public IntrospectedCodeMethod(Method m) {
+	_method = m;
+    }
+
+    public String getName() {
+	return _method.getName();
+    }
+
+    public String getFullName() {
+	return _method.getDeclaringClass().getName() + "." + getName();
+    }
+
+    public CodeClass getContainingClass() {
+	return IntrospectedCodeClass.forClass(_method.getDeclaringClass());
+    }
+
+    public String getDescriptor() {
+	StringBuffer sb = new StringBuffer();
+	sb.append('(');
+	for (int i = 0; i < numParameters(); ++i) {
+	    CodeClass cc = getParameterType(i);
+	    sb.append(cc.getDescriptor());
+	}
+	sb.append(')');
+	sb.append(getReturnType().getDescriptor());
+	return sb.toString();
+    }
+
+    public int getModifiers() {
+	return _method.getModifiers();
+    }
+
+    public CodeClass getReturnType() {
+	return IntrospectedCodeClass.forClass(_method.getReturnType());
+    }
+
+    public int numParameters() {
+	return _method.getParameterTypes().length;
+    }
+
+    public CodeClass getParameterType(int pos) {
+	return IntrospectedCodeClass.forClass(_method.getParameterTypes()[pos]);
+    }
+  
+  public String toString() {
+    return super.toString() + " " + getDescriptor();
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/Label.java b/src/org/biojava/utils/bytecode/Label.java
new file mode 100755
index 0000000..73716c8
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/Label.java
@@ -0,0 +1,64 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * A Label used to mark a position in byte code.
+ *
+ * <p>
+ * Labels are used as the targets for jumps, and for exception handlers. Labels
+ * can be named. They implement CodeGenerator, which allows them to be added
+ * to things like an InstructionVector. The writeCode method takes care of
+ * marking the label with the context.
+ * </p>
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+public class Label implements CodeGenerator {
+  public String name;
+  
+  public Label() {
+    name = null;
+  }
+  
+  public Label(String name) {
+    this.name = name;
+  }
+  
+  public String toString() {
+    if (name != null)
+      return name;
+    return super.toString();
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    ctx.markLabel(this);
+  }
+  
+  public int stackDepth() {
+    return 0;
+  }
+  
+  public int stackDelta() {
+    return 0;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/LabelInstruction.java b/src/org/biojava/utils/bytecode/LabelInstruction.java
new file mode 100755
index 0000000..3adc32f
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/LabelInstruction.java
@@ -0,0 +1,57 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Instructions which jump to a label.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+class LabelInstruction implements Instruction {
+  private final Label l;
+  private final byte opcode;
+  private final int delta;
+  
+  LabelInstruction(byte op, Label l, int delta) {
+    if(l == null) {
+      throw new NullPointerException("Label can not be null");
+    }
+    
+    this.opcode = op;
+    this.l = l;
+    this.delta = delta;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    ctx.writeByte(opcode);
+    ctx.writeLabel(l);
+  }
+  
+  public int stackDepth() {
+    return 0;
+  }
+  
+  public int stackDelta() {
+    return delta;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/LocalVariable.java b/src/org/biojava/utils/bytecode/LocalVariable.java
new file mode 100755
index 0000000..dabf720
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/LocalVariable.java
@@ -0,0 +1,98 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * A local variable.
+ *
+ * <p>
+ * Local variables are used as identifiers for things that can be stored and
+ * loaded from the local variable slots associated with each method. By using
+ * LocalVariable intances, you are removed from the taudry task of book-keeping
+ * these slots.
+ * </p>
+ *
+ * <p>
+ * To use a local variable, create an intance and then use it in a code
+ * generator. The method will keep track of which local variables are in scope,
+ * and will handle all the nastiness for you. You can re-use the same
+ * local variable instance in different contexts, and it will be sanely
+ * allocated different or the same slots.
+ * </p>
+ *
+ * <p>
+ * The JVM stores some things in single words, and others in pairs of words.
+ * To hide this detail from you, local variables take a class that indicates
+ * the type of thing they will store. Please populate this sensibly.
+ * </p>
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+public final class LocalVariable {
+  private final String name;
+  private final CodeClass clazz;
+
+  /**
+   * Create a new local variable that will store values of a given type.
+   *
+   * @param clazz  the type of the values stored in this variable
+   */
+  public LocalVariable(CodeClass clazz) {
+    this.clazz = clazz;
+    this.name = null;
+  }
+
+  /**
+   * Create a new local variable with a type and a name.
+   *
+   * <p>
+   * The name may appear in debug output from the generator, and possibly in
+   * stack-traces.
+   * </p>
+   *
+   * @param clazz  the type of the values stored in this variable
+   * @param name   the name of the variable
+   */
+  public LocalVariable(CodeClass clazz, String name) {
+    this.clazz = clazz;
+    this.name = name;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public int needSlots() {
+    return (clazz == CodeUtils.TYPE_LONG || clazz == CodeUtils.TYPE_DOUBLE) ? 2 : 1;
+  }
+
+  public CodeClass getType() {
+    return clazz;
+  }
+
+  public String toString() {
+    return
+            super.toString() +
+            "[slots: " + needSlots() + ", name: " + name +
+            ", class: " + clazz + "]";
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/LocalVariableInstruction.java b/src/org/biojava/utils/bytecode/LocalVariableInstruction.java
new file mode 100755
index 0000000..211b47a
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/LocalVariableInstruction.java
@@ -0,0 +1,66 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Instructions which load or store to a local variable.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+class LocalVariableInstruction implements Instruction {
+  private final LocalVariable var;
+  private final byte opcode;
+  private final byte specialOpCodeBase;
+  
+  LocalVariableInstruction(byte op, byte special, LocalVariable var) {
+    if(var == null) {
+      throw new NullPointerException("LocalVariable can not be null");
+    }
+    
+    this.opcode = op;
+    specialOpCodeBase = special;
+    this.var = var;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    int slot = ctx.resolveLocal(var);
+    if (slot <= 3) {
+      ctx.writeByte((byte) (specialOpCodeBase + slot));
+    } else if (slot < 256) {
+      ctx.writeByte(opcode);
+      ctx.writeByte((byte) slot);
+    } else {
+      ctx.writeByte(ByteCode.op_wide);
+      ctx.writeByte(opcode);
+      ctx.writeShort(slot);
+    }
+  }
+  
+  public int stackDepth() {
+    return stackDelta();
+  }
+  
+  public int stackDelta() {
+    return 1;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/LongConstantInstruction.java b/src/org/biojava/utils/bytecode/LongConstantInstruction.java
new file mode 100755
index 0000000..39dc8db
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/LongConstantInstruction.java
@@ -0,0 +1,49 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Instructions which retrieve a long from the constant pool.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock 
+ */
+
+class LongConstantInstruction implements Instruction {
+  private final long val;
+  
+  LongConstantInstruction(long val) {
+    this.val = val;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    ctx.writeByte(ByteCode.op_ldc2_w);
+    ctx.writeShort(ctx.getConstants().resolveLong(val));
+  }
+  
+  public int stackDepth() {
+    return stackDelta();
+  }
+  
+  public int stackDelta() {
+    return 1;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/MarkLabel.java b/src/org/biojava/utils/bytecode/MarkLabel.java
new file mode 100644
index 0000000..bde4c47
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/MarkLabel.java
@@ -0,0 +1,50 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+import java.util.*;
+
+/**
+ * A CodeGenerator that just marks a label that can be used for jumps.
+ *
+ * @author Matthew Pocock
+ */
+
+public class MarkLabel implements CodeGenerator {
+  private final Label label;
+  
+  public MarkLabel(Label label) {
+    this.label = label;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    ctx.markLabel(label);
+  }
+  
+  public int stackDepth() {
+    return 0;
+  }
+  
+  public int stackDelta() {
+    return 0;
+  }
+}
+
diff --git a/src/org/biojava/utils/bytecode/MethodInstruction.java b/src/org/biojava/utils/bytecode/MethodInstruction.java
new file mode 100755
index 0000000..7ebe8f8
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/MethodInstruction.java
@@ -0,0 +1,76 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Instructions which call a method.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+class MethodInstruction implements Instruction {
+  private final CodeMethod meth;
+  private final byte opcode;
+  
+  MethodInstruction(byte op, CodeMethod m) {
+    if(m == null) {
+      throw new NullPointerException("CodeMethod can not be null");
+    }
+    
+    this.opcode = op;
+    this.meth = m;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    ctx.writeByte(opcode);
+    if (opcode == ByteCode.op_invokeinterface) {
+      ctx.writeShort(ctx.getConstants().resolveInterfaceMethod(meth));
+      int count = 1;
+      for (int i = 0; i < meth.numParameters(); ++i) {
+        CodeClass ptype = meth.getParameterType(i);
+        count += CodeUtils.wordsForType(ptype);
+      }
+      ctx.writeByte((byte) count);
+      ctx.writeByte((byte) 0);
+    } else {
+      ctx.writeShort(ctx.getConstants().resolveMethod(meth));
+    }
+  }
+  
+  public int stackDepth() {
+    return 0;
+  }
+  
+  public int stackDelta() {
+    int popped = 0;
+    
+    if( (meth.getModifiers() & CodeUtils.ACC_STATIC) == 0) {
+      popped++;
+    }
+    
+    popped += meth.numParameters();
+    
+    int pushed = (meth.getReturnType() == CodeUtils.TYPE_VOID) ? 0 : 1;
+    
+    return pushed - popped;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/MethodRootContext.java b/src/org/biojava/utils/bytecode/MethodRootContext.java
new file mode 100755
index 0000000..657749b
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/MethodRootContext.java
@@ -0,0 +1,234 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+class MethodRootContext implements CodeContext, ParentContext {
+  private final CodeClass codeClass;
+  private final CodeMethod codeMethod;
+  private final ConstantPool cpool;
+  
+  private byte[] sink;
+  private int offset;
+  
+  private List outstandingRefs;
+  private Map markedLabels;
+  
+  private Map localVariables;
+  
+  private int usedLocals;
+  private int maxLocals;
+  private Map resolvedParametrics;
+
+  private List exceptionTable;
+  
+  {
+    outstandingRefs = new ArrayList();
+    markedLabels = new HashMap();
+    localVariables = new HashMap();
+    exceptionTable = new ArrayList();
+    resolvedParametrics = new HashMap();
+  }
+  
+  MethodRootContext(CodeClass cc, CodeMethod cm, ConstantPool cp) {
+    this.codeClass = cc;
+    this.codeMethod = cm;
+    this.cpool = cp;
+    
+    sink = new byte[65536];
+    offset = 0;
+    
+    // Should allocate local variables from method;
+    
+    usedLocals = maxLocals = 0;
+  }
+  
+  public CodeClass getCodeClass() {
+    return codeClass;
+  }
+  
+  public CodeMethod getCodeMethod() {
+    return codeMethod;
+  }
+  
+  public ConstantPool getConstants() {
+    return cpool;
+  }
+  
+  public void writeByte(byte b) {
+    sink[offset++] = b;
+  }
+  
+  public void writeShort(int i) {
+    sink[offset++] = (byte) ((i>>8) & 0xff);
+    sink[offset++] = (byte) ((i) & 0xff);
+  }
+  
+  public void writeShortAt(int pos, int i) {
+    sink[pos] = (byte) ((i>>8) & 0xff);
+    sink[pos+1] = (byte) ((i) & 0xff);
+  }
+  
+  public void writeLabel(Label l) {
+    outstandingRefs.add(new BranchFixup(l, getOffset(), this));
+    writeShort(0);
+  }
+  
+  public void markLabel(Label l) throws CodeException {
+    if (markedLabels.containsKey(l))
+      throw new CodeException("Attempt to duplicate marked label");
+    markedLabels.put(l, new Integer(getOffset()));
+  }
+  
+  public int resolveLocal(LocalVariable lv) {
+    // System.out.println("MethodRootContext.resolveLocal(" + lv + ")");
+    Integer slot = (Integer) localVariables.get(lv);
+    if (slot != null) {
+      // System.out.println("resolved to " + slot);
+      return slot.intValue();
+    }
+    int newLocal = usedLocals;
+    usedLocals += lv.needSlots();
+    setMaxLocals(usedLocals); 
+    localVariables.put(lv, new Integer(newLocal));
+    // System.out.println("created at" + newLocal);
+    return newLocal;
+  }
+  
+  public int resolveLocalNoCreate(LocalVariable lv) {
+    // System.out.println("MethodRootContext.resolveLocalNoCreate(" + lv + ")");
+    Integer slot = (Integer) localVariables.get(lv);
+    if (slot != null) {
+      // System.out.println("at " + slot);
+      return slot.intValue();
+    } else {
+      // System.out.println("not here");
+      return -1;
+    }
+  }
+  
+  public void registerParametricType(
+    ParametricType type,
+    CodeClass concreteType
+  ) throws CodeException {
+    if(resolvedParametrics.containsKey(type)) {
+      throw new CodeException("Failed to regiter parametric type " + type +
+        ". Attempted to register for " + concreteType +
+        " but it is already registered for " + resolvedParametrics.get(type) );
+    }
+    
+    if(!type.canAccept(concreteType)) {
+      throw new CodeException(
+        "Parametric type is not compattible with concrete type: " +
+        type + " : " + concreteType );
+    }
+
+    resolvedParametrics.put(type, concreteType);
+  }
+  
+  public CodeClass resolveParametricType(ParametricType type)
+  throws CodeException {
+    CodeClass cc = (CodeClass) resolvedParametrics.get(type);
+    
+    if(cc == null) {
+      throw new CodeException("Can not resolve type: " + type);
+    }
+    
+    return cc;
+  }
+  
+  public int getOffset() {
+    return offset;
+  }
+  
+  public void open() {
+  }
+  
+  public void close() throws CodeException {
+    for (ListIterator li = outstandingRefs.listIterator(); li.hasNext(); ) {
+      OutstandingReference or = (OutstandingReference) li.next();
+      Integer off = (Integer) markedLabels.get(or.getLabel());
+      if (off != null) {
+        or.resolve(off.intValue());
+      } else {
+        throw new CodeException("Reference to label " + or.getLabel() + " still outstanding at top level");
+      }
+    }
+  }
+  
+  public CodeContext subContext() {
+    return new ChildContext(this);
+  }
+  
+  public void promoteOutstandingReference(OutstandingReference or) {
+    outstandingRefs.add(or);
+  }
+  
+  public void writeTo(OutputStream os) throws IOException {
+    os.write(sink, 0, offset);
+  }
+  
+  public void setMaxLocals(int newMax) {
+    if (newMax > maxLocals) 
+      maxLocals = newMax;
+  }
+  
+  public int getMaxLocals() {
+    return maxLocals;
+  }
+  
+  public int getUsedLocals() {
+    return usedLocals;
+  }
+  
+  public void addExceptionTableEntry(
+    Label startHandled, 
+    Label endHandled,
+    CodeClass eClass, 
+    Label handler
+  ) {
+    SimpleReference rStartHandled = new SimpleReference(startHandled);
+    SimpleReference rEndHandled = new SimpleReference(endHandled);
+    SimpleReference rHandler = new SimpleReference(handler);
+    outstandingRefs.add(rStartHandled);
+    outstandingRefs.add(rEndHandled);
+    outstandingRefs.add(rHandler);
+    
+    addExceptionTableEntry(new ExceptionMemento(rStartHandled,
+    rEndHandled,
+    eClass,
+    rHandler));
+  }
+  
+  public void addExceptionTableEntry(ExceptionMemento em) {
+    exceptionTable.add(em);
+  }
+  
+  public List getExceptionTable() {
+    return Collections.unmodifiableList(exceptionTable);
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/NoOperandsInstruction.java b/src/org/biojava/utils/bytecode/NoOperandsInstruction.java
new file mode 100755
index 0000000..2fe37b1
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/NoOperandsInstruction.java
@@ -0,0 +1,50 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Instructions (like nop, dadd, etc.) which take no operands.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+class NoOperandsInstruction implements Instruction {
+  private final byte opcode;
+  private final int delta;
+  
+  public NoOperandsInstruction(byte b, int delta) {
+    this.opcode = b;
+    this.delta = delta;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    ctx.writeByte(opcode);
+  }
+  
+  public int stackDepth() {
+    return Math.max(delta, 0);
+  }
+  
+  public int stackDelta() {
+    return delta;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/OutstandingReference.java b/src/org/biojava/utils/bytecode/OutstandingReference.java
new file mode 100755
index 0000000..44e1ec3
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/OutstandingReference.java
@@ -0,0 +1,32 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Encapsulate a refererence to a Label which has not been resolved.
+ *
+ * @author Thomas Down
+ */
+
+interface OutstandingReference {
+    public Label getLabel();
+    public void resolve(int offset) throws CodeException;
+}
diff --git a/src/org/biojava/utils/bytecode/PParametricCodeGenerator.java b/src/org/biojava/utils/bytecode/PParametricCodeGenerator.java
new file mode 100644
index 0000000..9e48b53
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/PParametricCodeGenerator.java
@@ -0,0 +1,27 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+public interface PParametricCodeGenerator
+extends CodeGenerator {
+  public ParametricType getType1();
+  public ParametricType getType2();
+}
diff --git a/src/org/biojava/utils/bytecode/ParametricCodeGenerator.java b/src/org/biojava/utils/bytecode/ParametricCodeGenerator.java
new file mode 100644
index 0000000..efb5489
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/ParametricCodeGenerator.java
@@ -0,0 +1,26 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+public interface ParametricCodeGenerator
+extends CodeGenerator {
+  public ParametricType getType();
+}
diff --git a/src/org/biojava/utils/bytecode/ParametricType.java b/src/org/biojava/utils/bytecode/ParametricType.java
new file mode 100644
index 0000000..706d94f
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/ParametricType.java
@@ -0,0 +1,191 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * A template type.
+ *
+ * <p>Template types are resolved at code-generation type rather than at
+ * Instruction generation type. They let you bind the concrete type for opcodes
+ * at the last minute, so the same max conditional could be used for all
+ * primative types, with the type only being bound at the last moment.</p>
+ *
+ * <p>Two ParametricType instances are the same if they are the same object,
+ * regardless of their names.</p>
+ *
+ * @author Matthew Pocock
+ */
+
+public class ParametricType {
+  private static CodeClass[] OBJECT_CC;
+  
+  static {
+    OBJECT_CC = new CodeClass[] { IntrospectedCodeClass.forClass(Object.class) };
+  }
+  
+  /**
+   * Create a new ParametricType that claims nothing.
+   *
+   * @param name  the name given to this type
+   * @return a new ParametricType instance with that name
+   */
+  public static ParametricType createType(String name) {
+    return new ParametricType(name, false, false, false);
+  }
+  
+  /**
+   * Create a new ParametricType that claims to resolve to a primative type.
+   *
+   * @param name  the name given to this type
+   * @return a new ParametricType instance with that name
+   */
+  public static ParametricType createPrimitiveType(String name) {
+    return new ParametricType(name, true, false, false);
+  }
+  
+  /**
+   * Create a new ParametricType that claims to resolve to an object type.
+   *
+   * @param name  the name given to this type
+   * @return a new ParametricType instance with that name
+   */
+  public static ParametricType createObjectType(String name) {
+    return new ParametricType(name, false, true, false);
+  }
+  
+  /**
+   * Create a new ParametricType that claims to resolve to an array type. All
+   * array types are object types.
+   *
+   * @param name  the name given to this type
+   * @return a new ParametricType instance with that name
+   */
+  public static ParametricType createArrayType(String name) {
+    return new ParametricType(name, false, true, true);
+  }
+  
+  /**
+   * Create a new ParametricType that claims to be castable to all the classes
+   * in a list. Since neither Java nor bytecode support multiple inheritance,
+   * the classes must either be interfaces, or classes that fall into an
+   * inheritance path.
+   *
+   * @param name  the name given to this type
+   * @param classes an array of Class objects that any bound type must be
+   *   castable to
+   * @return a new ParametricType that can bind to classes with these properties
+   */
+  public static ParametricType createType(
+    String name,
+    CodeClass[] classes
+  ) {
+    return new ParametricType(name, classes);
+  }
+  
+  private final String name;
+  private final boolean isPrimitive;
+  private final boolean isObject;
+  private final boolean isArray;
+  private final CodeClass[] classes;
+  
+  private ParametricType(
+    String name,
+    boolean isPrimitive,
+    boolean isObject,
+    boolean isArray
+  ) {
+    this.name = name;
+    this.isPrimitive = isPrimitive;
+    this.isObject = isObject;
+    this.isArray = isArray;
+    if(isObject) {
+      this.classes = OBJECT_CC;
+    } else {
+      this.classes = CodeUtils.EMPTY_LIST;
+    }
+  }
+  
+  private ParametricType(
+    String name,
+    CodeClass[] classes
+  ) {
+    this.name = name;
+    this.classes = classes;
+    this.isObject = true;
+    this.isPrimitive = false;
+    this.isArray = false;
+  }
+  
+  /**
+   * Get the name of this type.
+   *
+   * Names are not unique.
+   *
+   * @return the name given to this type
+   */
+  public String getName() {
+    return name;
+  }
+  
+  /**
+   * Discover if this type must resolve to a primative.
+   *
+   * <p>It is an error for a parametric type to resolve to a non-primative if
+   * this flag is set.</p>
+   *
+   * @return true if this is guaranteed to resolve to a primative
+   */
+  public boolean isPrimitive() {
+    return isPrimitive;
+  }
+  
+  public boolean isObject() {
+    return isObject;
+  }
+  
+  public boolean isArray() {
+    return isArray;
+  }
+  
+  public boolean canAccept(CodeClass cc) {
+    if(cc.isArray() && this.isArray()) {
+      return true;
+    }
+    
+    if(!cc.isPrimitive() && this.isObject()) {
+      return true;
+    }
+    
+    if(cc.isPrimitive() && this.isPrimitive()) {
+      return true;
+    }
+    
+    return false;
+  }
+  
+  public CodeClass[] getClasses() {
+    return classes;
+  }
+  
+  public String toString() {
+    return "GenericType:" + name;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/ParentContext.java b/src/org/biojava/utils/bytecode/ParentContext.java
new file mode 100755
index 0000000..476d4bd
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/ParentContext.java
@@ -0,0 +1,33 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+interface ParentContext extends CodeContext {
+    public void promoteOutstandingReference(OutstandingReference ref);
+    public void writeShortAt(int pos, int i);
+    public int getOffset();
+
+    public int resolveLocalNoCreate(LocalVariable lv);
+    public void setMaxLocals(int m);
+    public int getUsedLocals();
+
+    public void addExceptionTableEntry(ExceptionMemento em);
+}
diff --git a/src/org/biojava/utils/bytecode/ShortInstruction.java b/src/org/biojava/utils/bytecode/ShortInstruction.java
new file mode 100755
index 0000000..9f6d872
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/ShortInstruction.java
@@ -0,0 +1,53 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Instructions which take a one-byte operand.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+class ShortInstruction implements Instruction {
+  private final byte opcode;
+  private final int val;
+  private final int delta;
+  
+  ShortInstruction(byte opcode, int val, int delta) {
+    this.opcode = opcode;
+    this.val = val;
+    this.delta = delta;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    ctx.writeByte(opcode);
+    ctx.writeShort(val);
+  }
+  
+  public int stackDepth() {
+    return Math.max(delta, 0);
+  }
+  
+  public int stackDelta() {
+    return delta;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/SimpleReference.java b/src/org/biojava/utils/bytecode/SimpleReference.java
new file mode 100755
index 0000000..ec97a41
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/SimpleReference.java
@@ -0,0 +1,46 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+class SimpleReference implements OutstandingReference {
+    private final Label label;
+    private int offset = -1;
+
+    public SimpleReference(Label l) {
+	this.label = l;
+    }
+
+    public Label getLabel() {
+	return label;
+    }
+
+    public void resolve(int offset) {
+	this.offset = offset;
+    }
+
+    public int getOffset() {
+	return offset;
+    }
+
+    public boolean isResolved() {
+	return (offset >= 0);
+    }
+}
diff --git a/src/org/biojava/utils/bytecode/StringConstantInstruction.java b/src/org/biojava/utils/bytecode/StringConstantInstruction.java
new file mode 100755
index 0000000..4ff016a
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/StringConstantInstruction.java
@@ -0,0 +1,58 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ */
+package org.biojava.utils.bytecode;
+
+/**
+ * Instructions which load or store to a local variable.
+ *
+ * @author Thomas Down
+ * @author Matthew Pocock
+ */
+
+class StringConstantInstruction implements Instruction {
+  private final String s;
+  
+  StringConstantInstruction(String s) {
+    if(s == null) {
+      throw new NullPointerException("Can't make a StringConstantInstruction for a null string");
+    }
+    this.s = s;
+  }
+  
+  public void writeCode(CodeContext ctx) throws CodeException {
+    int i_indx = ctx.getConstants().resolveString(s);
+    if (i_indx < 256) {
+      ctx.writeByte(ByteCode.op_ldc);
+      ctx.writeByte((byte) i_indx);
+    } else {
+      ctx.writeByte(ByteCode.op_ldc_w);
+      ctx.writeShort(i_indx);
+    }
+  }
+  
+  public int stackDepth() {
+    return stackDelta();
+  }
+  
+  public int stackDelta() {
+    return 1;
+  }
+}
diff --git a/src/org/biojava/utils/bytecode/package.html b/src/org/biojava/utils/bytecode/package.html
new file mode 100644
index 0000000..5f9df5e
--- /dev/null
+++ b/src/org/biojava/utils/bytecode/package.html
@@ -0,0 +1,199 @@
+<body>
+
+A Java object-model for a Java Bytecode Macro-Assembler.
+
+<h2>Description</h2>
+
+<p>
+The ByteCode package is able to generate Java Bytecode that can be used to
+define Java classes. It is not restricted to things that can be expressed as
+Java code (as in .java files), and is more flexible than basic Java bytecode.
+</p>
+
+<p>
+This package supports generating classes, interfaces, methods, fields, and the
+like. It follows the macro-assembler pattern, where users can effectively
+extend the bytecode instruction set with their own instructions that at
+compile time expand to real bytecode instructions. Many useful
+pseudo-instructions are provided, such as IfExpression. This package also
+supports some advanced functionality such as templating. Templating supports
+both object and primitive types and types can be resolved at the level of
+complete methods or single expressions.
+</p>
+
+<p>
+The ByteCode package has no support whatsoever for editing Java Bytecode. In
+particular, there is no support for search-and-replace or optimization.
+</p>
+
+<p>
+The main classes for generating bytecode are
+{@link org.biojava.utils.bytecode.CodeUtils},
+{@link org.biojava.utils.bytecode.ByteCode},
+{@link org.biojava.utils.bytecode.InstructionVector} and
+{@link org.biojava.utils.bytecode.GeneratedCodeClass}. You will probably also
+use {@link org.biojava.utils.bytecode.GeneratedClassLoader}, as it does the
+actual work of building and loading classes.
+</p>
+
+<p>
+It is probably a requirement of using this package effectively that you have
+memorised or have handy a copy of the Java VM specification. This is available
+from the Sun web site.
+</p>
+
+<h2>Class Reflection</h2>
+
+<p>
+The ByteCode package represents classes, methods and fields using its own APIs.
+These, for obvious reasons, closely resemble those provided by the core Java
+APIs. The three interfaces
+{@link org.biojava.utils.bytecode.CodeClass},
+{@link org.biojava.utils.bytecode.CodeMethod} and
+{@link org.biojava.utils.bytecode.CodeField}
+represent these basic concepts.
+</p>
+
+<p>
+Classes from the Java VM are reflected into this model using
+{@link org.biojava.utils.bytecode.IntrospectedCodeClass}.
+To get an instance, use the factory method
+{@link org.biojava.utils.bytecode.IntrospectedCodeClass#forClass(Class)} or
+{@link org.biojava.utils.bytecode.IntrospectedCodeClass#forClass(String)}.
+</p>
+
+<h2>Class Generation</h2>
+
+<p>
+Classes that you generate yourself will be represented by instances of
+{@link org.biojava.utils.bytecode.GeneratedCodeClass}.
+Methods are created by calling
+{@link org.biojava.utils.bytecode.GeneratedCodeClass#createMethod},
+which will return a
+{@link org.biojava.utils.bytecode.GeneratedCodeMethod}. The method can then be
+implemented by associating a
+{@link org.biojava.utils.bytecode.CodeGenerator}
+with the method on that particular class using
+{@link org.biojava.utils.bytecode.GeneratedCodeClass#setCodeGenerator}.
+</p>
+
+<p>
+Fields are generated by calling
+{@link org.biojava.utils.bytecode.GeneratedCodeClass#createField}.
+</p>
+
+<p>
+The classes themselves are instantiated into the VM using
+{@link org.biojava.utils.bytecode.GeneratedClassLoader}.
+This implements
+{@link java.lang.ClassLoader#defineClass} and
+over-rides the other necessary book-keeping methods. You may wish to sub-class
+or wrap this class in an application to generate the desired behavior.
+</p>
+
+<h2>An example</h2>
+
+<p>
+We are going to implement HelloWorld in bytecode. Here is the (annotated) code.
+</p>
+
+<p>
+Firstly, lets define our application structure...
+<code><pre>
+public class BCHelloWorld {
+  public static void main(String[] args)
+  throws Throwable {
+    createHelloWorld().run();
+  }
+
+  public static Runnable createHelloWorld() {
+    ...
+  }
+}
+</pre>
+</code>
+We will fill in the createHelloWorld method to actualy do the work of printing
+out hello world by implementing a Runnable with a run() method. Firstly, we
+need a load of types, methods and a field or two.
+<code>
+<pre>
+CodeClass cl_Object = IntrospectedCodeClass.forClass(Object.class);
+CodeClass cl_String = IntrospectedCodeClass.forClass(String.class);
+CodeClass cl_System = IntrospectedCodeClass.forClass(System.class);
+CodeClass cl_PrintStream = IntrospectedCodeClass.forClass(PrintStream.class);
+CodeClass cl_Void = IntrospectedCodeClass.forClass(Void.TYPE);
+CodeClass cl_Runnable = IntrospectedCodeClass.forClass(Runnable.class);
+
+CodeField f_System_out = cl_System.getFieldByName("out");
+
+CodeMethod m_PrintStream_printLn = cl_PrintStream.getMethod(
+    "printLn",
+    new CodeClass[] { cl_String } );
+CodeMethod m_Object_init = cl_Object.getConstructor(CodeUtils.EMPTY_LIST);
+</pre>
+</code>
+Now we are ready to create our code class. It will be called HelloWorldRunnable,
+inherit directly from Object, implement Runnable, and be a public class.
+<code>
+<pre>
+GeneratedCodeClass ourClass = new GeneratedCodeClass(
+    "HelloWorldRunnable",
+    cl_Object,
+    new CodeClass[] { cl_Runnable },
+    CodeUtils.ACC_PUBLIC | CodeUtils.ACC_SUPER);
+</pre>
+</code>
+This will need a constructor. Remember, constructors have the name >init&lt:,
+and you must be sure to call the super-constructor explicitly. Normaly the javac
+compiler does this for you.
+<code>
+<pre>
+GeneratedCodeMethod init = ourClass.createMethod(
+    "<init>",
+    cl_Void,
+    CodeUtils.EMPTY_LIST,
+    CodeUtils.ACC_PUBLIC);
+InstructionVector initIV = new InstructionVector();
+initIV.add(ByteCode.make_aload(init.getThis()));
+initIV.add(ByteCode.make_invokespecial(m_Object_init));
+initIV.add(ByteCode.make_return());
+ourClass.setCodeGenerator(init, initIV);
+</pre>
+</code>
+To be a Runnable implementation, we must also provide a run() method. This will
+take no arguments, return void and be publically accessible. Also, the body of
+this method will print out "Hello World" and then we can all feel pleased with
+ourselves.
+<code>
+<pre>
+GeneratedCodeMethod run = ourClass.createMethod(
+    "run",
+    cl_Void,
+    CodeUtils.EMPTY_LIST,
+    CodeUtils.ACC_PUBLIC);
+InstructionVector runIV = new InstructionVector();
+runIV.add(ByteCode.make_getstatic(f_System_out));
+runIV.add(ByteCode.make_sconst("Hello World");
+runIV.add(ByteCode.make_invokevirtual(m_PrintStream_printLn));
+runIV.add(ByteCode.make_return());
+ourClass.setCodeGenerator(run, runIV);
+</pre>
+</code>
+Now we want to load in a class with this deffinition and instantiate it.
+<code>
+<pre>
+GeneratedClassLoader gcl = new GeneratedClassLoader(class.getClassLoader());
+Class newClass = gcl.defineClass(ourClass);
+return (Runnable) newClass.newInstance();
+</pre>
+</code>
+And there you are. With any luck, if you type all of this in, and the fates
+smile on you, and biojava.jar is arround for linking against, you should have
+generated your very own unuque HelloWorld class.
+</p>
+
+<p>
+Good luck.
+</p>
+
+</body>
diff --git a/test/MakeHelloWorld.java b/test/MakeHelloWorld.java
new file mode 100755
index 0000000..7c9e3cb
--- /dev/null
+++ b/test/MakeHelloWorld.java
@@ -0,0 +1,83 @@
+package test;
+
+import org.biojava.utils.bytecode.*;
+
+import java.util.*;
+import java.io.*;
+
+public class MakeHelloWorld {
+    public static void main(String[] args) throws Exception {
+	CodeClass cl_Object = IntrospectedCodeClass.forClass("java.lang.Object");
+	CodeClass cl_String = IntrospectedCodeClass.forClass("java.lang.String");
+	CodeClass cl_System = IntrospectedCodeClass.forClass("java.lang.System");
+	CodeClass cl_PrintStream = IntrospectedCodeClass.forClass("java.io.PrintStream");
+	CodeClass cl_pVoid = IntrospectedCodeClass.forClass(Void.TYPE);
+	CodeClass i_Runnable = IntrospectedCodeClass.forClass(Runnable.class);
+        CodeClass[] aInterfaces = { i_Runnable };
+
+	CodeField f_System_out = cl_System.getFieldByName("out");
+	CodeMethod m_PrintStream_println_I = oneIntMethod(cl_PrintStream.getMethodsByName("println"));
+	CodeMethod m_Object_init = new SimpleCodeMethod("<init>", cl_Object, cl_pVoid,
+							 new ArrayList(), CodeUtils.ACC_PUBLIC);
+	
+        CodeClass[] aMethodArgs = {};
+	GeneratedCodeClass cc = new GeneratedCodeClass("MyTestClass",
+		       IntrospectedCodeClass.forClass("java.lang.Object"),
+		       aInterfaces,
+		       CodeUtils.ACC_PUBLIC | CodeUtils.ACC_SUPER);
+
+	GeneratedCodeMethod init = cc.createMethod("<init>",
+						   cl_pVoid,
+						   aMethodArgs,
+						   CodeUtils.ACC_PUBLIC);
+	InstructionVector iv = new InstructionVector();
+	iv.add(ByteCode.make_aload(init.getThis()));
+	iv.add(ByteCode.make_invokespecial(m_Object_init));
+	iv.add(ByteCode.make_return());
+	cc.setCodeGenerator(init, iv);
+
+	GeneratedCodeMethod run = cc.createMethod("run",
+						   cl_pVoid,
+						   aMethodArgs,
+						   CodeUtils.ACC_PUBLIC);
+	iv = new InstructionVector();
+	Label loopTest = new Label();
+	Label loopStart = new Label();
+	Label loopEnd = new Label();
+	iv.add(ByteCode.make_iconst(1));
+	iv.add(ByteCode.make_goto(loopStart));
+	iv.add(loopTest);
+        iv.add(ByteCode.make_dup());
+	iv.add(ByteCode.make_iconst(10));
+	iv.add(ByteCode.make_if_icmpgt(loopEnd));
+	iv.add(loopStart);
+	iv.add(ByteCode.make_dup());
+	iv.add(ByteCode.make_getstatic(f_System_out));
+	iv.add(ByteCode.make_swap());
+	iv.add(ByteCode.make_invokevirtual(m_PrintStream_println_I));
+	iv.add(ByteCode.make_iconst(1));
+	iv.add(ByteCode.make_iadd());
+	iv.add(ByteCode.make_goto(loopTest));
+	iv.add(loopEnd);
+	iv.add(ByteCode.make_return());
+
+	cc.setCodeGenerator(run, iv);
+
+	FileOutputStream fos = new FileOutputStream("MyTestClass.class");
+	cc.createCode(fos);
+	fos.close();
+    }
+
+    static CodeMethod oneIntMethod(Set methods) {
+	CodeClass cl_pInt = IntrospectedCodeClass.forClass(Integer.TYPE);
+	for (Iterator i = methods.iterator(); i.hasNext(); ) {
+	    CodeMethod cm = (CodeMethod) i.next();
+	    if (cm.numParameters() != 1)
+		continue;
+	    if (cm.getParameterType(0) == cl_pInt)
+		return cm;
+	}
+
+	return null;
+    }
+}
diff --git a/test/Runner.java b/test/Runner.java
new file mode 100755
index 0000000..52f587b
--- /dev/null
+++ b/test/Runner.java
@@ -0,0 +1,12 @@
+package test;
+
+public class Runner {
+    public static void main(String[] args) throws Exception {
+        if(args.length != 1) {
+	  throw new Exception("Use: test.Runner runnableClass");
+	}
+	Class cl = Class.forName(args[0]);
+	Runnable r = (Runnable) cl.newInstance();
+	r.run();
+    }
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/bytecode.git



More information about the pkg-java-commits mailing list