001    /*
002     *                    BioJava development code
003     *
004     * This code may be freely distributed and modified under the
005     * terms of the GNU Lesser General Public Licence.  This should
006     * be distributed with the code.  If you do not have a copy,
007     * see:
008     *
009     *      http://www.gnu.org/copyleft/lesser.html
010     *
011     * Copyright for this code is held jointly by the individual
012     * authors.  These should be listed in @author doc comments.
013     *
014     * For more information on the BioJava project and its aims,
015     * or to join the biojava-l mailing list, visit the home page
016     * at:
017     *
018     *      http://www.biojava.org/
019     *
020     */
021    package org.biojava.utils.bytecode;
022    
023    /**
024     * Interface which encapsulates the stream to which Java bytecode can
025     * be written.
026     *
027     * <p>
028     * The context takes care of all the book-keeping tasks associated with emitting
029     * well-formed byte code. For example, the context manages jumps and local
030     * variables.
031     * </p>
032     *
033     * <p>
034     * Most of the funcionality here is very low level. You will almost certainly
035     * want to use CodeGenerator instances to manipulate a CodeContext, rather than
036     * writing to it yourself.
037     * </p>
038     *
039     * @author Thomas Down
040     * @author Matthew Pocock
041     */
042    
043    public interface CodeContext {
044      /**
045       * Get the class for which a method is being generated.
046       *
047       * @return the current class
048       */
049      public CodeClass getCodeClass();
050    
051      /**
052       * Get the method which is being generated.
053       *
054       * @return the current method
055       */
056      public CodeMethod getCodeMethod();
057    
058      /**
059       * Get the constants pool for this context.
060       *
061       * @return the contant pool
062       */
063      public ConstantPool getConstants();
064    
065      // Write methods.
066    
067      /**
068       * Write a single byte to the context.
069       *
070       * <p>
071       * This can be used both to write opcodes and to write byte data to the
072       * context.
073       * </p>
074       *
075       * @param  b the byte to write
076       */
077      public void writeByte(byte b) throws CodeException;
078    
079      /**
080       * Write a short (2 bytes) to the context.
081       *
082       * @param i  the short to write
083       */
084      public void writeShort(int i) throws CodeException;
085    
086      /**
087       * Write the offset of a Label to the context.
088       *
089       * <p>This can be called before or after markLabel is invoked for the
090       * corresponding label. The context will ensure that the offset is
091       * correctly written before the method is fully emitted.</p>
092       *
093       * @param lab  the Label to write
094       */
095      public void writeLabel(Label lab) throws CodeException;
096    
097      /**
098       * Resolve a local variable to the local variable slot assigned to it.
099       *
100       * <p>The context will ensure that local variables are stored in their
101       * own bits of the local variable area. It may chose to re-use portions
102       * of this area as local variables go out of scope.</p>
103       *
104       * @param lv  the LocalVariable to resolve
105       * @return the index of the local variable slot
106       */
107      public int resolveLocal(LocalVariable lv) throws CodeException;
108    
109      /**
110       * Mark a label at the current point in the stream.
111       *
112       * <p>This can be used as the target for branching instructions, such as
113       * GOTO and IF.</p>
114       *
115       * @param lab the Label to mark
116       * @throws CodeException if the label has previously been marked
117       */
118      public void markLabel(Label lab) throws CodeException;
119    
120      /**
121       * Register a concrete type for a parametric type.
122       *
123       * <p>This is the mechanism where-by real CodeClass types are associated
124       * with the virtual ParametricType types. If type pubishes that it
125       * is a primative, an object or an array, then the concreteType must be
126       * compattible. It's an error to bind the VOID type.</p>
127       *
128       * @for.developer
129       *  You should probably call
130       * <code>ParametricType.canAccept(concreteType)</code> to make sure of this.
131       * This implementation will shield you from any modifications to the exact
132       * semantics of ParametricType.
133       *
134       * @param type  ParametricType the parametric type to register
135       * @param concreteType  the CodeClass that it resolves to
136       * @throws CodeException if the type has already been registered or if the
137       *   guarantees about type made in the parametric type are violated
138       */
139      public void registerParametricType(ParametricType type, CodeClass concreteType)
140              throws CodeException;
141    
142      /**
143       * Resolve a parametric type to a concrete class.
144       *
145       * <p>The type will be resolved by first searching through all those
146       * registered with this context. If it found there, this value is returned.
147       * If it is not, then the emediate parent context is searched. This parent
148       * is responsible for searching its parent and so on. If a context has no
149       * parent and the type is not registered with this context, it should raise
150       * a CodeException.</p>
151       *
152       * @param type  the ParametricType to resolve
153       * @return the  ColdeClass associated with that parametric type
154       * @throws CodeException if the type has not been registered
155       */
156      public CodeClass resolveParametricType(ParametricType type)
157              throws CodeException;
158    
159      /**
160       * Open a sub context.
161       *
162       * <p>The sub context should inherit all the state of the parent context.
163       * Modifications to the state of the child (for example, local variable
164       * management or registered labels) should not be propogated to the parent.
165       * Modifications to the parent should not be propogated to the child.
166       * However, contexts should be used serialy, and only one context should be
167       * accessible to a code generator at a time, so in practice, there should be
168       * no way for a code generator using a child context to alter the state of
169       * or discover the state of the parent context.</p>
170       */
171      public CodeContext subContext();
172    
173      /**
174       * Open the context for writing.
175       *
176       * <p>This must be called before any code writing methods are called. It
177       * can not be called more than once.</p>
178       */
179      public void open() throws CodeException;
180    
181      /**
182       * Close the context for writing. It is at this point that any process
183       * necisary for comitting the bytecode will be executed.
184       *
185       * <p>This must be called after all code writing methods have been called.
186       * It can not be called more than once.</p>
187       */
188      public void close() throws CodeException;
189    
190      // Exception tables
191    
192      /**
193       * Add an exception table entry.
194       *
195       * @param startHandled    the beginning of the try block
196       * @param endHandled      the end of the try block
197       * @param eClass          the exception class
198       * @param handler         the beginning of the exception handler
199       * @throws CodeException
200       */ 
201      public void addExceptionTableEntry(Label startHandled,
202                                         Label endHandled,
203                                         CodeClass eClass,
204                                         Label handler)
205              throws CodeException;
206    
207    }