[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<:,
+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