    All Packages  Class Hierarchy  This Package  Previous  Next  Index

# Class gnu.jel.ExpressionImage

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

public class ExpressionImage
extends Object

A class which is repsonsible for generating valid class files for compiler.

It is not general purpose Java assembler, it is specifically JEL oriented.

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 debuging 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`.

##

BI_AN
  Denotes the AND binary operation.
BI_DI
  Denotes the DIVIDE binary operation.
BI_MI
  Denotes the MINUS binary operation.
BI_MU
  Denotes the MULTIPLY binary operation.
BI_OR
  Denotes the OR binary operation.
BI_PL
  Denotes the PLUS binary operation.
BI_RE
  Denotes the REMAINDER binary operation.
BI_XO
  Denotes the XOR binary operation.
binaryNames
UN_NE
  Denotes the unary NEGATION operation.
unaryNames

##

ExpressionImage()
  Constructs and initializes empty expression image.

##

asm_binary(int)
  Generates code to perform given binary operation.
asm_convert(Class)
  Converts current top of the java stack to the given class type.
asm_func_call()
  Generates the actual call to the current function.
asm_func_param()
  Converts the current top of Java stack to the next formal parameter type.
asm_func_start(Method, int)
  Prepare stack for the method call.
asm_load_object(Object)
  Loads a constant into the Java stack.
asm_load_primitive(Object)
asm_return()
  Finishes construction of the expression normally.
asm_ThrowReturn()
  Finishes construction if the method abnormally.
asm_unary(int)
  Generates code to perform given unary operation.
canConvert(Class, Class)
  Tests is this codegen can generate code to convert from from one type to another even with possible loss of the information.
canConvertByWidening(Class, Class)
  Tests is this codegen can generate code to convert from from one type to another without loss of the information.
canGenerateBinary(int, Class)
  Used to test if this codegen.
canGenerateBinary(int, Class, Class)
  Used to test if this codegen.
canGenerateUnary(int, Class)
  Used to test if this codegen.
getExpression()
  Constructs a new instance of the CompiledExpression with this image.
getMostGeneralType(Class, Class)
  Used to get the most general type of the two given.
getSignature(Class)
  Computes the signature of the given class.
getSignature(Method)
  Computes signature of the given method.
main(String[])
  Performs unitary test of the code generator.
test(Tester)
  Performs unitary test of the code generator.

##

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.

binaryNames

     public static final String binaryNames[]

unaryNames

     public static final String unaryNames[]

UN_NE

     public static final int UN_NE

  Denotes the unary NEGATION operation.

##

ExpressionImage

     public ExpressionImage()

  Constructs and initializes empty expression image.

  The class name of the expression is generated automatically by appending successive integer numbers (incremented for each instantiated ExpressionImage) to the "gnu.jel.generated.E_". This should ensure the names of expressions are unique. The number is represented by long integer allowing to instantiate close to 10^19 expressions during the program lifetime. This means program, instantiating a new expression each second, will fail with numeric overflow in about 300000000000 years, which is big enough for most applications.

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

       asm_load_primitive(...)
       asm_Sum(..)
       ...

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

       asm_return();
       asm_ThrowReturn();

  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 Object type other than java.lang.String there. This assembler overcomes this limitation by allowing to use other _NON-MUTABLE_ objects as constants. More information is provided in the description of `asm_load_object` method.

##

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.

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 utilizing `java.lang.Class.getName()`, however that Java method do not always follow Java VM spec.... To be on the safe (controllable) side I dicided to implement this method myself.

  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.

getExpression

     public CompiledExpression getExpression()

  Constructs a new instance of the CompiledExpression with this image.

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

asm_load_object

     public void asm_load_object(Object o)

  Loads a constant into the Java stack.

  Currently only java.lang.Long and java.lang.Double can be loaded as primitive types. Other classes will load as `reference`s.

  Internally, this code generator supports operations with all Java primitive types. Now, there is only single way how these other primitive types can come into the stack, namely as function return values. This will be extended in the subsequent versions allowing to load them directly using this method.

  Parameters:
    o - is the object to load.

asm_load_primitive

     public void asm_load_primitive(Object o)

canConvert

     public static boolean canConvert(Class t1,
                                      Class t2)

  Tests is this codegen 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(Class t1,
                                                Class t2)

  Tests is this codegen 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(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.

getMostGeneralType

     public static Class getMostGeneralType(Class c1,
                                            Class c2)

  Used to get the most general type of the two given.

  Both operands for the binary OP type should be converted to the most general of them, returned by this function.

  Both parameters should be Java primitive types.

  Parameters:
    c1 - first operand of the binary OP
    c2 - second operand of the binary OP
  Returns:
    Class, representing the most general primitive type of two.

canGenerateUnary

     public static boolean canGenerateUnary(int op,
                                            Class type)

  Used to test if this codegen. can generate requested 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 boolean asm_unary(int o)

  Generates code to perform given unary operation.

  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
  Returns:
    true if the code was successfully generated.

canGenerateBinary

     public static boolean canGenerateBinary(int op,
                                             Class type)

  Used to test if this codegen. can generate requested binary operation.

  Parameters:
    is - the code of operation (BI_PL,BI_MI,BI_MU ...).
    type - is the type of both operands.
  Returns:
    if the code for such operation can be generated.

canGenerateBinary

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

  Used to test if this codegen. can generate requested 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 boolean asm_binary(int o)

  Generates code to perform given binary operation.

  Binary operations can be performed on the primitive Java types only. The two numbers in Java stack have to have the same type, in order for binary operation to succeed.

  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 PL,MI,MU,DI,AN,OR,XO
  Returns:
    true if the code was successfully generated.

asm_func_start

     public void asm_func_start(Method f,
                                int id)

  Prepare stack for the method call.

  Method can be static or virtual.

  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 actual code for the call is generated by calling asm_func_call() method.

  Function calls can be nested.

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

  Parameters:
    f - is the method to call.
    id - is the number of the function in the array of the instance of the object, implementing the function (for virtual methods only).

asm_func_param

     public boolean asm_func_param()

  Converts the current top of Java stack to the next formal parameter type.

  The type of the quantity on top of the Java stack should be convertible to the function required input.

  Use can convert function to test for convertibility.

  Returns:
    false if types are incompatible.

asm_func_call

     public boolean asm_func_call()

  Generates the actual call to the current function.

  The stack structure should be already prepared by `asm_func_start(...)` and `asm_func_param` methods.

  Returns:
    false if the number of formal parameters is mismatched.

asm_return

     public void asm_return()

  Finishes construction of the expression normally.

  Number on top of the Java stack converted is returned. If it is of the primitive type it is converted to the Reflection object (i.e. `double` to `java.lang.Double`. Currently such conversion is supported for doubles and longs only.

asm_ThrowReturn

     public void asm_ThrowReturn()

  Finishes construction if the method abnormally.

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

main

     public static void main(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.

    All Packages  Class Hierarchy  This Package  Previous  Next  Index