All Packages  Class Hierarchy  This Package  Previous  Next  Index

Class gnu.jel.ExpressionImage

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

public class ExpressionImage
extends 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:
enabled

Variable Index

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

Constructor Index

 o ExpressionImage()
Constructs and initializes empty expression image.

Method Index

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

Variables

 o BI_PL
 public static final int BI_PL
Denotes the PLUS binary operation.

 o BI_MI
 public static final int BI_MI
Denotes the MINUS binary operation.

 o BI_MU
 public static final int BI_MU
Denotes the MULTIPLY binary operation.

 o BI_DI
 public static final int BI_DI
Denotes the DIVIDE binary operation.

 o BI_RE
 public static final int BI_RE
Denotes the REMAINDER binary operation.

 o BI_AN
 public static final int BI_AN
Denotes the AND binary operation.

 o BI_OR
 public static final int BI_OR
Denotes the OR binary operation.

 o BI_XO
 public static final int BI_XO
Denotes the XOR binary operation.

 o BI_EQ
 public static final int BI_EQ
Denotes binary comparizon for equality

 o BI_NE
 public static final int BI_NE
Denotes binary comparizon for inequality

 o BI_LT
 public static final int BI_LT
Denotes binary comparizon for "less"

 o BI_GE
 public static final int BI_GE
Denotes binary comparizon for "greater or equal"

 o BI_GT
 public static final int BI_GT
Denotes binary comparizon for "greater"

 o BI_LE
 public static final int BI_LE
Denotes binary comparizon for "less or equal"

 o BI_LS
 public static final int BI_LS
Denotes binary left shift

 o BI_RSS
 public static final int BI_RSS
Denotes binary right signed shift

 o BI_RUS
 public static final int BI_RUS
Denotes binary right unsigned shift

 o binaryNames
 public static final String binaryNames[]
Names of binary operations by ID in the readable form.

 o binarySymbols
 public static final String binarySymbols[]
Symbols of binary operations by ID in the readable form.

 o LOG_AN
 public static final int LOG_AN
Denotes logical conjunction operator

 o LOG_OR
 public static final int LOG_OR
Denotes logical disjunction operator

 o LOG_NO
 public static final int LOG_NO
Denotes logical complement operator

 o logicalNames
 public static final String logicalNames[]
Names of logical operations by ID in the readable form.

 o logicalSymbols
 public static final String logicalSymbols[]
Symbols of logical operations by ID in the readable form.

 o UN_NE
 public static final int UN_NE
Denotes the unary NEGATION operation.

 o UN_NO
 public static final int UN_NO
Denotes the unary bitwise complement operation.

 o unaryNames
 public static final String unaryNames[]
Names of unary operations by ID in the readable form.

 o unarySymbols
 public static final String unarySymbols[]
Symbols of unary operations by ID in the readable form.

 o primitiveTypes
 public static final Class primitiveTypes[]
Classes of the primitive types by ID

 o primitiveTypeNames
 public static final String primitiveTypeNames[]
Names of the primitive types by ID in readable form.

Constructors

 o 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, asm_load_primitive, asm_binary, asm_convert, asm_func_call, asm_logical_binary, asm_logical_unblock_not, asm_unary, asm_return, asm_throw_return

Methods

 o 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.
 o getSignature
 public static String getSignature(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.
 o getSignature
 public static String getSignature(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
 o getSignature
 public static String getSignature(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.
 o 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.
 o 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.
 o 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.
 o asm_load_object
 public void asm_load_object(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
 o asm_load_primitive
 public void asm_load_primitive(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.
 o canConvert
 public static boolean canConvert(Class t1,
                                  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.
 o canConvertByWidening
 public static boolean canConvertByWidening(Class t1,
                                            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.
 o asm_convert
 public boolean asm_convert(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.
 o getBinaryPromoted
 public static Class getBinaryPromoted(Class c1,
                                       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.
 o getUnaryPromoted
 public static Class getUnaryPromoted(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.
 o canGenerateUnary
 public static boolean canGenerateUnary(int op,
                                        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.
 o 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
 o canGenerateBinary
 public static boolean canGenerateBinary(int op,
                                         Class t1,
                                         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.
 o 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, asm_binary_param
 o asm_func_start
 public void asm_func_start(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
 o 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
 o 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
 o 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.

 o asm_branch_start_false
 public void asm_branch_start_false()
Continues generation of code for conditional.

See Also:
asm_branch_start_true
 o asm_branch_end
 public void asm_branch_end()
Finishes generation of code for conditional.

See Also:
asm_branch_start_true
 o 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
 o 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
 o 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)
 o asm_logical_block
 public void asm_logical_block()
This function starts a group of logical subexpressions.

See Also:
asm_logical_unblock_not
 o 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.

 o 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.

 o 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.

 o main
 public static void main(String args[])
Performs unitary test of the code generator.

Parameters:
args - ignored.
 o 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.

All Packages  Class Hierarchy  This Package  Previous  Next  Index