: Class ExpressionImage

Overview | Package | Class | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

## gnu.jel
Class ExpressionImage

    java.lang.Object
      |
      +--gnu.jel.ExpressionImage

public class ExpressionImage
extends java.lang.Object

This class is responsible for generating valid Java class files based on a sequence of calls to it's methods (asm_XXXX family of methods). This assembler tries to do more things than other java assemblers do. It keeps track of types in Java stack and automatically chooses which java bytecodes should be generated to perform a given operation on types in stack.

Anyway, it is not general purpose Java assembler, it is specifically JEL oriented. Currently this assembler does not provide direct access to Java control transfer instructions.

This class is designed to be the part of a bigger package. This means it will silently generate wrong bytecodes. ;) BUT, if You compile it with debugging ON (see `boolean gnu.jel.debug.Debug.enabled`) it should warn You about all possible wrong things it does. If there are more assertions to be made, please submit Your patches to `metlov@fzu.cz`.

Author:
  Konstantin L. Metlov (metlov@fzu.cz)
See Also:
  `Debug.enabled`

Field Summary
`static int` | `BI_AN` Denotes the AND binary operation.
`static int` | `BI_DI` Denotes the DIVIDE binary operation.
`static int` | `BI_EQ` Denotes binary comparizon for equality
`static int` | `BI_GE` Denotes binary comparizon for "greater or equal"
`static int` | `BI_GT` Denotes binary comparizon for "greater"
`static int` | `BI_LE` Denotes binary comparizon for "less or equal"
`static int` | `BI_LS` Denotes binary left shift
`static int` | `BI_LT` Denotes binary comparizon for "less"
`static int` | `BI_MI` Denotes the MINUS binary operation.
`static int` | `BI_MU` Denotes the MULTIPLY binary operation.
`static int` | `BI_NE` Denotes binary comparizon for inequality
`static int` | `BI_OR` Denotes the OR binary operation.
`static int` | `BI_PL` Denotes the PLUS binary operation.
`static int` | `BI_RE` Denotes the REMAINDER binary operation.
`static int` | `BI_RSS` Denotes binary right signed shift
`static int` | `BI_RUS` Denotes binary right unsigned shift
`static int` | `BI_XO` Denotes the XOR binary operation.
`static java.lang.String[]` | `binaryNames` Names of binary operations by ID in the readable form.
`static java.lang.String[]` | `binarySymbols` Symbols of binary operations by ID in the readable form.
`static int` | `LOG_AN` Denotes logical conjunction operator
`static int` | `LOG_NO` Denotes logical complement operator
`static int` | `LOG_OR` Denotes logical disjunction operator
`static java.lang.String[]` | `logicalNames` Names of logical operations by ID in the readable form.
`static java.lang.String[]` | `logicalSymbols` Symbols of logical operations by ID in the readable form.
`static java.lang.String[]` | `primitiveTypeNames` Names of the primitive types by ID in readable form.
`static java.lang.Class[]` | `primitiveTypes` Classes of the primitive types by ID
`static int` | `UN_NE` Denotes the unary NEGATION operation.
`static int` | `UN_NO` Denotes the unary bitwise complement operation.
`static java.lang.String[]` | `unaryNames` Names of unary operations by ID in the readable form.
`static java.lang.String[]` | `unarySymbols` Symbols of unary operations by ID in the readable form.

Constructor Summary
`ExpressionImage()` Constructs and initializes empty expression image.

Method Summary
`void` | `asm_binary_param(int opc)` Denotes that the first parameter for the given binary OP is now in stack.
`void` | `asm_binary(int o)` Generates code to perform given binary operation.
`void` | `asm_branch_end()` Finishes generation of code for conditional.
`void` | `asm_branch_start_false()` Continues generation of code for conditional.
`void` | `asm_branch_start_true()` Starts generation of code for conditional.
`boolean` | `asm_convert(java.lang.Class type)` Converts current top of the java stack to the given class type.
`void` | `asm_func_call()` Finishes generation of call to a function.
`void` | `asm_func_param()` Denotes that the next parameter for the current function is now in stack.
`void` | `asm_func_start(java.lang.reflect.Method f, int id)` Starts generation of code for the method call.
`void` | `asm_load_object(java.lang.Object o)` Generates code to load given object constant into Java stack.
`void` | `asm_load_primitive(java.lang.Object o)` Generates code to load given constant of a primitive type.
`void` | `asm_logical_binary_param(int opc)` Denotes the first parameter for the given logical binary OP is now in stack.
`void` | `asm_logical_binary(int opc)` Generates code to perform given logical binary operation.
`void` | `asm_logical_block()` This function starts a group of logical subexpressions.
`void` | `asm_logical_unblock_not()` This function finishes a group of logical subexpressions with inversion.
`void` | `asm_return()` Finishes construction of expression by generating code to return a value.
`void` | `asm_throw_return()` Finishes construction of expression by generating code to throw exception.
`void` | `asm_unary(int o)` Generates code to perform given unary operation on the value in stack.
`static boolean` | `canConvert(java.lang.Class t1, java.lang.Class t2)` Tests is this assembler can generate code to convert from from one type to another even with possible loss of the information.
`static boolean` | `canConvertByWidening(java.lang.Class t1, java.lang.Class t2)` Tests is this assembler can generate code to convert from from one type to another without loss of the information.
`static boolean` | `canGenerateBinary(int op, java.lang.Class t1, java.lang.Class t2)` Used to test if this assembler can generate given binary operation.
`static boolean` | `canGenerateUnary(int op, java.lang.Class type)` Used to test if this assembler can generate given unary operation.
`static java.lang.Class` | `getBinaryPromoted(java.lang.Class c1, java.lang.Class c2)` Performs binary numeric promotion of types.
`ExpressionBits` | `getBits()` Returns compiled expression represented by ExpressionBits object.
`CompiledExpression` | `getExpression()` Constructs a new instance of this expression.
`byte[]` | `getImage()` Used to get the binary image of the class.
`static java.lang.String` | `getSignature(java.lang.Class cls)` Computes the signature of the given class.
`static java.lang.String` | `getSignature(java.lang.reflect.Constructor c)` Computes signature of the given constructor.
`static java.lang.String` | `getSignature(java.lang.reflect.Method m)` Computes signature of the given method.
`static java.lang.Class` | `getUnaryPromoted(java.lang.Class c)` Performs unary numeric promotion of types.
`static boolean` | `isPromotionBinary(int binary_op)` Checks if the binary numeric promotion is required for the operation.
`static void` | `main(java.lang.String[] args)` Performs unitary test of the code generator.
`static void` | `test(Tester t)` Performs unitary test of the code generator.

Methods inherited from class java.lang.Object
`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

Field Detail

### BI_PL

    public static final int BI_PL

  Denotes the PLUS binary operation.

### BI_MI

    public static final int BI_MI

  Denotes the MINUS binary operation.

### BI_MU

    public static final int BI_MU

  Denotes the MULTIPLY binary operation.

### BI_DI

    public static final int BI_DI

  Denotes the DIVIDE binary operation.

### BI_RE

    public static final int BI_RE

  Denotes the REMAINDER binary operation.

### BI_AN

    public static final int BI_AN

  Denotes the AND binary operation.

### BI_OR

    public static final int BI_OR

  Denotes the OR binary operation.

### BI_XO

    public static final int BI_XO

  Denotes the XOR binary operation.

### BI_EQ

    public static final int BI_EQ

  Denotes binary comparizon for equality

### BI_NE

    public static final int BI_NE

  Denotes binary comparizon for inequality

### BI_LT

    public static final int BI_LT

  Denotes binary comparizon for "less"

### BI_GE

    public static final int BI_GE

  Denotes binary comparizon for "greater or equal"

### BI_GT

    public static final int BI_GT

  Denotes binary comparizon for "greater"

### BI_LE

    public static final int BI_LE

  Denotes binary comparizon for "less or equal"

### BI_LS

    public static final int BI_LS

  Denotes binary left shift

### BI_RSS

    public static final int BI_RSS

  Denotes binary right signed shift

### BI_RUS

    public static final int BI_RUS

  Denotes binary right unsigned shift

### binaryNames

    public static final java.lang.String[] binaryNames

  Names of binary operations by ID in the readable form.

### binarySymbols

    public static final java.lang.String[] binarySymbols

  Symbols of binary operations by ID in the readable form.

### LOG_AN

    public static final int LOG_AN

  Denotes logical conjunction operator

### LOG_OR

    public static final int LOG_OR

  Denotes logical disjunction operator

### LOG_NO

    public static final int LOG_NO

  Denotes logical complement operator

### logicalNames

    public static final java.lang.String[] logicalNames

  Names of logical operations by ID in the readable form.

### logicalSymbols

    public static final java.lang.String[] logicalSymbols

  Symbols of logical operations by ID in the readable form.

### UN_NE

    public static final int UN_NE

  Denotes the unary NEGATION operation.

### UN_NO

    public static final int UN_NO

  Denotes the unary bitwise complement operation.

### unaryNames

    public static final java.lang.String[] unaryNames

  Names of unary operations by ID in the readable form.

### unarySymbols

    public static final java.lang.String[] unarySymbols

  Symbols of unary operations by ID in the readable form.

### primitiveTypes

    public static final java.lang.Class[] primitiveTypes

  Classes of the primitive types by ID

### primitiveTypeNames

    public static final java.lang.String[] primitiveTypeNames

  Names of the primitive types by ID in readable form.

Constructor Detail

### ExpressionImage

    public ExpressionImage()

  Constructs and initializes empty expression image.

  Immediately after the construction of the expression a number of code generating methods can be issued:

       asm_load_primitive(...)
       asm_binary_param(..)
       ...

  The code generation should be finished by one of the return methods:

       asm_return();
       asm_throw_return();

  Before any return method is called, the code generation is assumed to be in progress and methods, attempting to get class representation (getImage) or instantiate the class (getExpression) will fail assertion.

  After the code generation is finished and one of return methods is called methods, attempting to modify the class (i.e. `asm_load_primitive(...)`...) will fail. This is done to ensure integrity of generated classes.

  Constants of the type object are allowed in the generated expressions. (If You don't know in java the constants are residing in the constant pool and it is impossible to store constants of general Object type other than java.lang.String there. This assembler overcomes this limitation and allows to use other _NON-MUTABLE_ objects as constants. More information is provided in the description of `asm_load_object` method.

  See Also:
    `asm_load_object(java.lang.Object)`, `asm_load_primitive(java.lang.Object)`, `asm_binary(int)`, `asm_convert(java.lang.Class)`, `asm_func_call()`, `asm_logical_binary(int)`, `asm_logical_unblock_not()`, `asm_unary(int)`, `asm_return()`, `asm_throw_return()`

Method Detail

### isPromotionBinary

    public static final boolean isPromotionBinary(int binary_op)

  Checks if the binary numeric promotion is required for the operation.

  Used to check whether given binary operation requires binary or unary numeric promotion (see JLS 5.6.1) of it's operands.

  Parameters:
    `binary_op` - is one of BI_XXX constants.
  Returns:
    true if binary numeric promotion is required false if unary numeric promotion is required.

### getSignature

    public static java.lang.String getSignature(java.lang.reflect.Method m)

  Computes signature of the given method.

  The signature of the method(Method descriptor) is the string and it's format is described in the paragraph 4.3.3 of the Java VM specification (ISBN 0-201-63451-1).

  This utility method can be used outside of the JEL package it does not involve any JEL specific assumptions and should follow JVM Specification precisely.

  Parameters:
    `m` - is the method to compute the sugnature of.
  Returns:
    the method sugnature.

### getSignature

    public static java.lang.String getSignature(java.lang.reflect.Constructor c)

  Computes signature of the given constructor.
  Parameters:
    `m` - is the method to compute the sugnature of.
  Returns:
    the method sugnature.
  See Also:
    `getSignature(java.lang.reflect.Method)`

### getSignature

    public static java.lang.String getSignature(java.lang.Class cls)

  Computes the signature of the given class.

  The signature of the class (Field descriptor) is the string and it's format is described in the paragraph 4.3.2 of the Java VM specification (ISBN 0-201-63451-1).

  The same can be done using `java.lang.Class.getName()` by converting it's result into the "historical form".

  This utility method can be used outside of the JEL package it does not involve any JEL specific assumptions and should follow JVM Specification precisely.

  Parameters:
    `cls` - is the class to compute the sgnature of. Can be primitive or array type.
  Returns:
    the class signature.

### getBits

    public ExpressionBits getBits()

  Returns compiled expression represented by ExpressionBits object.

  This function should be called after the code generation had finished.

  The only case You'll want to get `gnu.jel.ExpressionBits` class instead of instantiated and ready to run `gnu.jel.CompiledExpression` subclass is when You intend to write expression to a persistent storage and run it in other JVM session.

  Returns:
    ready to be serialized ExpressionBits object.

### getImage

    public byte[] getImage()

  Used to get the binary image of the class.

  This function returns bytecode of generated expression in a Java classfile format. It is for debugging purposes only. Use ExpressionBits if You want to store expression into a stream (file).

  Returns:
    a binary class representation.

### getExpression

    public CompiledExpression getExpression()

  Constructs a new instance of this expression.

  This function returns ready to run instance of `gnu.jel.CompiledExpression` subclass.

  Returns:
    a CompiledExpression instance or null if there was a error.

### asm_load_object

    public void asm_load_object(java.lang.Object o)

  Generates code to load given object constant into Java stack.

  Constants of type object, other than instances of `java.lang.String` are not directly supported by Java Virtual Machine. This means there is no way to reinstantiate those object based on the information in the Java class file alone.

  To overcome this limitation an array of such objects is created and only integer index into this "object constants" array is compiled into a class file. The drawback is that the generated class file can not be run without proper object constants array supplied. This means bytecode alone does not represent compiled program anymore.

  To simplify storage of expressions an ExpressionBits class is introduced which holds both bytecode and object constants, allowing to easily store them together in a stream.

  CONCLUSION : if Your class uses this function for objects other than Strings You _must_ use ExpressionBits to store compiled bytecode.

  Parameters:
    `o` - is the object to load.
  See Also:
    `ExpressionBits`

### asm_load_primitive

    public void asm_load_primitive(java.lang.Object o)

  Generates code to load given constant of a primitive type.

  For example, to load `double` constant `1.0D` into the Java stack one has to call :
  `asm_load_primitive(new Double(1.0))`.

  Parameters:
    `o` - is the value of a constant of primitive type, wrapped into corresponding reflection object.

### canConvert

    public static boolean canConvert(java.lang.Class t1,
                                     java.lang.Class t2)

  Tests is this assembler can generate code to convert from from one type to another even with possible loss of the information.

  Both widening and narrowing conversions are supported by the assembler, this function reports all supported conversions.

  There are thoughts about support wrapping/unwrapping conversions (i.e. double <--> java.lang.Double) as described in the Java Reflection Specification. Currently these are not supported.

  Parameters:
    `t1` - is the type You want to convert from.
    `t2` - is the type You want to convert to.
  Returns:
    true is the corresponding conversion is supported.

### canConvertByWidening

    public static boolean canConvertByWidening(java.lang.Class t1,
                                               java.lang.Class t2)

  Tests is this assembler can generate code to convert from from one type to another without loss of the information.

  Both widening and narrowing conversions are supported by the assembler itself, this function reports widening conversions only.

  Parameters:
    `t1` - is the type You want to convert from.
    `t2` - is the type You want to convert to.
  Returns:
    true is the corresponding widening conversion is supported.

### asm_convert

    public boolean asm_convert(java.lang.Class type)

  Converts current top of the java stack to the given class type.
  Parameters:
    `type` - is the type to convert to, can be primitive.
  Returns:
    true if conversion was made, false if types incompatible.

### getBinaryPromoted

    public static java.lang.Class getBinaryPromoted(java.lang.Class c1,
                                                    java.lang.Class c2)

  Performs binary numeric promotion of types.

  Promotion is done according to the Java Language Specification (paragraph 5.6.2). Both parameters should be Java primitive types.

  Parameters:
    `c1` - first type
    `c2` - second type
  Returns:
    Class (primitive type reflection), representing the binary promoted type, null if can't promote.

### getUnaryPromoted

    public static java.lang.Class getUnaryPromoted(java.lang.Class c)

  Performs unary numeric promotion of types.

  Promotion is done according to the Java Language Specification (paragraph 5.6.1). Both parameters should be Java primitive numeric types.

  Parameters:
    `c` - the type to promote
  Returns:
    Class (primitive type reflection), representing unary promoted type, null if can't promote.

### canGenerateUnary

    public static boolean canGenerateUnary(int op,
                                           java.lang.Class type)

  Used to test if this assembler can generate given unary operation.
  Parameters:
    `is` - the code of operation (UN_NE).
    `type` - is the type of the operand.
  Returns:
    if the code for such operation can be generated.

### asm_unary

    public void asm_unary(int o)

  Generates code to perform given unary operation on the value in stack.

  Unary operations can be performed on the primitive Java types only.

  If operation can not be supported for the given type this method returns false and generates nothing.

  Parameters:
    `o` - type of operation to perform, one of NE

### canGenerateBinary

    public static boolean canGenerateBinary(int op,
                                            java.lang.Class t1,
                                            java.lang.Class t2)

  Used to test if this assembler can generate given binary operation.
  Parameters:
    `is` - the code of operation (BI_PL,BI_MI,BI_MU ...).
    `t1` - is the type of the first operand.
    `t2` - is the type of the second operand.
  Returns:
    if the code for such operation can be generated.

### asm_binary

    public void asm_binary(int o)

  Generates code to perform given binary operation.

  Method canGenerateBinary(..) should be used to determine if the binary operation can be generated for particular types of data.

  The pattern to generate binary operations with this code generator is following :

       1. Calculate the first operand.
       2. asm_binary_param( BI_XXX )
       3. Calculate the second operand.
       4. asm_binary( BI_XXX )

  If operation can not be supported due to incompatible types of operands this method returns false and generates nothing.

  Parameters:
    `o` - type of operation to perform, one of BI_XXX
  See Also:
    `canGenerateBinary(int, java.lang.Class, java.lang.Class)`, `asm_binary_param(int)`

### asm_func_start

    public void asm_func_start(java.lang.reflect.Method f,
                               int id)

  Starts generation of code for the method call.

  Method can be static or virtual. See the descrition of `asm_func_call` for more details.

  Parameters:
    `f` - is the method to call.
    `id` - is the number of the function in the array of the instances of objects implementing the function (for virtual methods only).
  See Also:
    `asm_func_call()`

### asm_func_param

    public void asm_func_param()

  Denotes that the next parameter for the current function is now in stack.

  Actually, this method generates code to convert the value currently on top of Java stack to the next formal parameter type of a current function.

  Returns:
    false if types are incompatible.
  See Also:
    `asm_func_start(java.lang.reflect.Method, int)`

### asm_func_call

    public void asm_func_call()

  Finishes generation of call to a function.

  Call to this method should be followed zero or more asm_func_param() calls which would transform parameters on top of the stack to be compatible with the function input (each additioal call will process the next formal parameter).

  The pattern to generate the function call is the following

       1. asm_func_start(...);
       2. Calculate the first parameter.
       3. asm_func_param();
       4. Calculate the second parameter.
       5. asm_func_param();
         .... so on ...
       6  Calculate the last parameter.
       7. asm_func_param();
       8. asm_func_call();

  Correctness of `id` parameter can not be checked by the code generator !!! Be careful, runtime error will be generated if it's incorrect.

  See Also:
    `asm_func_param()`, `asm_func_start(java.lang.reflect.Method, int)`

### asm_branch_start_true

    public void asm_branch_start_true()

  Starts generation of code for conditional.

  Starts the branch, corresponding to the case when previous logical was "true". expression.

  The pattern to generate an "if" operator or ?: conditional is the following :

       1. Calculate condition
       2. asm_branch_start_true()
       3. Generate code for the "true" branch
       4. asm_branch_start_false()
       5. Generate code for the "false" branch
       6. asm_branch_end()

  Note that the code for "true" branch should be generated BEFORE the code for the current branch. This limitation may be removed in a future.

### asm_branch_start_false

    public void asm_branch_start_false()

  Continues generation of code for conditional.
  See Also:
    `asm_branch_start_true()`

### asm_branch_end

    public void asm_branch_end()

  Finishes generation of code for conditional.
  See Also:
    `asm_branch_start_true()`

### asm_binary_param

    public void asm_binary_param(int opc)

  Denotes that the first parameter for the given binary OP is now in stack.
  Parameters:
    `op` - type of operation to perform, one of BI_XXX
  See Also:
    `asm_binary(int)`

### asm_logical_binary_param

    public void asm_logical_binary_param(int opc)

  Denotes the first parameter for the given logical binary OP is now in stack.
  Parameters:
    `opc` - is the code of the logical binary operation (LOG_AN,LOG_OR)
  See Also:
    `asm_logical_binary(int)`

### asm_logical_binary

    public void asm_logical_binary(int opc)

  Generates code to perform given logical binary operation.

  The logical binary operations are either logical and (LOG_AN) or logical or (LOG_OR).

  The following pattern should be followed in order to evaluate logical expressions :

       1. Calculate the first operand (should be boolean).
       2. asm_logical_binary_param(  |  )
       3. Calculate the second operand (should be boolean).
       4. asm_logical_binary(  |  )

  Parameters:
    `opc` - is the code of the logical binary operation (LOG_AN,LOG_OR)

### asm_logical_block

    public void asm_logical_block()

  This function starts a group of logical subexpressions.
  See Also:
    `asm_logical_unblock_not()`

### asm_logical_unblock_not

    public void asm_logical_unblock_not()

  This function finishes a group of logical subexpressions with inversion.

  For example, to calculate "!(..something..)" it is needed to call :

       asm_logical_block()
       ....
       calculate something manipulating with other methods of this code generator
       ....
       asm_logical_unblock_not();

  After the above block the state of this codegenerator will correspond to the boolean result of the logical not operator on something.

### asm_return

    public void asm_return()

  Finishes construction of expression by generating code to return a value.

  Code to return to a caller a quantity on top of the Java stack is generated.

### asm_throw_return

    public void asm_throw_return()

  Finishes construction of expression by generating code to throw exception.

  Object on top of the Java stack (which should be instance of `java.lang.Throwable`) is thrown.

### main

    public static void main(java.lang.String[] args)

  Performs unitary test of the code generator.
  Parameters:
    `args` - ignored.

### test

    public static void test(Tester t)

  Performs unitary test of the code generator.

  Used if all package is being tested and not just codegen.

  Parameters:
    `t` - Tester to report test results.

Overview | Package | Class | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD