Menu

Expressions

Donald Strong

[Home]


Language features

Expressions

Literals

Literals are numbers, strings and boolean values. They are created in ClassMaker using the Literal method.

The following table displays the way they are created and their equivalent in Java.

Java codeClassMaker code
        234.56789D
        223.345F
        2000000L
        200
        (short)32000
        (byte)200
        'Z'
        true
        "Hello World"
        Literal(234.56789D)
        Literal(123.456F)
        Literal(2000000L)
        Literal(200)
        Literal((short)32000)
        Literal((byte)200)
        Literal('Z')
        Literal(true)
        Literal("Hello World")

The Literal(int) method deserves special mention. Even though it takes an
int as a parameter, the Type returned may correspond to a
byte or short depending upon the actual value used.
This is so that int literals can be assigned to byte and short variables without
casting. If the literal is assigned to anything else it will be automatically promoted.

Reference keywords

There are three keywords in java that deal with references.
These are null, this and super.
Each has its own method in ClassMaker.

Java codeClassMaker code
        null
        this
        super
        Null()
        This()
        Super()

Simple Arithmatic

Simple arithmetic involves unary and binary operations on numbers.
Each operator has a separate method in ClassMaker, but the method may be applied to any numeric type.

The following table displays example expressions in ClassMaker and their equivalent in Java.

Java codeClassMaker code
        x + 5
        x - 7
        4 * 2
        6 / 2
        7 % 3
        -a
        a ^ 3
        a & 3
        a | 3
        ~ a
        a << 3
        a >> 3
        a >>> 3
        Add(Get("x"), Literal(5))
        Subt(Get("x"), Literal(7))
        Mult(Literal(4), Literal(2))
        Div((Literal(6), Literal(2))
        Rem((Literal(7), Literal(3))
        Neg(Get("a"))
        Xor(Get("a"), Literal(3))
        And(Get("a"), Literal(3))
        Or(Get("a"), Literal(3))
        Inv(Get("a"))
        SHL(Get("a"), Literal(3))
        SHR(Get("a"), Literal(3))
        USHR(Get("a"), Literal(3))

The Literal(int) method deserves special mention. Even though it takes an
int as a parameter, the Type returned may correspond to a
byte or short depending upon the actual value used.
This is so that integer literals can be assigned to byte and short variables without
casting. If the literal is assigned to anything else it will be automatically promoted.

In many cases an operand will be automatically promoted. Numeric promotion in ClassMaker
follows almost the same rules as numeric promotion in Java. See the section on Numeric promotion
for a detailed description.

Access & Assignment

ClassMaker uses Get to access variables and Set to
assign variables.

The methods are overloaded to handle local variables, member variables and static variables.

Java codeClassMaker code
   a     = 2
   b     = a
   obj.i = a
   b     = obj.i
   MyClass.s = a
   b = MyClass.s
   Set("a", Literal(2))
   Set("b", Get("a"))
   Set(Get("obj"), "i", Get("a"))
   Set("b", Get(Get("obj"), "i"))
   Set("MyClass", "s", Get("a"))
   Set("b", Get("MyClass", "s"))

Increment and decrement

The increment and decrement operators have side effects. When the side effect takes place
in java is determined by whether the operator appears before or after the operand. In
ClassMaker a separate method call is used.

Inc and PostInc are overloaded to handle local
variables, member variables and static variables.

Java codeClassMaker code
     ++i
     i++
     ++obj.i
     obj.i++
     ++MyClass.i
     MyClass.i++
     Inc("i")
     PostInc("i")
     Inc(Get("obj"), "i")
     PostInc(Get("obj"), "i")
     Inc("MyClass", "i")
     PostInc("MyClass", "i")

Comparisons

Comparison arithmetic involves unary and binary operations that return boolean.
Each operator has a separate method in ClassMaker, but the method may be applied to any numeric type.

The following table displays example comparisons in ClassMaker and their equivalent in Java.


Java codeClassMaker code
     a == b
     a != b
     a < b
     a > b
     a <= b
     a >= b
     !a
    EQ(Get("a"), Get("b"))
    NE(Get("a"), Get("b"))
    LT(Get("a"), Get("b"))
    GT(Get("a"), Get("b"))
    LE(Get("a"), Get("b"))
    GE(Get("a"), Get("b"))
    Not(Get("a"))

Logic expressions

Logic expressions in Java use the && and || operators. These
operators are difficult to implement in bytecode because they involve shortcut evaluation.

The equivalent operators in ClassMaker are implemented using the
Logic, AndThen and OrElse methods.

Logic expressions are used in If statements, While statements
and For statements. The conditions for these statements all require a
boolean expression.


Java codeClassMaker code
     a && b
     a || b
     a && b && c
     a || b || c
     (a && b) || c
     (a || b) && c
     (a && b) || (c && d)
     (a || b) && (c || d)
     Logic(AndThen(Get("a")), Get("b"))
     Logic(OrElse(Get("a")), Get("b"))
     Logic(AndThen(AndThen(Get("a")), Get("b")), Get("c"))
     Logic(OrElse(OrElse(Get("a")), Get("b")), Get("c"))
     Logic(OrElse(AndThen(Get("a")), Get("b")), Get("c"))
     Logic(AndThen(OrElse(Get("a")), Get("b")), Get("c"))
     Logic(OrElse(AndThen(Get("a")), Get("b")), Logic(AndThen(Get("c")), Get("d")))
     Logic(AndThen(OrElse(Get("a")), Get("b")), Logic(OrElse(Get("c")), Get("d")))

Generating the byte-code for shortcut evaluation of || and && is not straight forward.
The byte-code must be generated sequentially so a separate method must be called when a boolean
value is tested and at the end of the expression to be shortcut.

The following example shows how this is done. The ClassMaker equivalent of
(a && b) is expanded out to show the order in which the methods are called.
Variables a and b are assumed to hold boolean (1 or 0) values.
On the right of the example is the pseudo byte code that would be generated.

ClassMaker codeGenerated byte code
            Logic(AndThen(Get("a")), Get("b"))
     1.                   Get("a")
     2.           AndThen(  ...   ),
 
 
     3.                              Get("b")
     4.     Logic(     ...         ,   ...   )
 
     1.     LOAD a                 // Push a local variable (a) onto the stack
     2.     DUP                    // Duplicate the value so it still exists after the jump
            IF_Zero GOTO L1        // Jump to L1 if the value is false
            POP                    // Otherwise, discard the duplicate value
     3.     LOAD b                 // Push another local variable (b) onto the stack
     4. L1: NOP                    // Mark the label L1.
                                   // The value on the stack is the result of (a && b).

The following example expands out a more complex example of (a && b) || (c && d).


Java codeClassMaker code
  (a && b) || (c && d)    
 
 
 
 
 
 
 
 
 
 
  Logic(OrElse(AndThen(Get("a")), Get("b")), Logic(AndThen(Get("c")), Get("d")))
 
                       Get("a")
               AndThen(  ...   )
                                  Get("b")
        OrElse(        ...      ,   ...   )
                                                           Get("c")
                                                   AndThen(        )
                                                                     Get("d")
                                             Logic(         ...     ,   ...   )
  Logic(               ...                 ,                ...                )    

Arrays

Java codeClassMaker code
      a = b[0]
      a = b[c]
      a = b[0][c]
      x = ++this.values[0]
      x = this.values[0]--
      b[1] = a
      b[c] = a
      b[0][c] = a
      this.values[0] = ++x
      this.values[0] = x--
      Set("a", GetAt(Get("b"), Literal(0))
      Set("a", GetAt(Get("b"), Get("c"))
      Set("a", GetAt(GetAt(Get("b"), Literal(0), Get("c"))
      Set("a", IncAt(Get(This(), "values"), Literal(0))
      Set("a", PostDecAt(Get(This(), "values"), Literal(0))
      SetAt(Get("b"), Literal(1), Get("a"))
      SetAt(Get("b"), Get("c"), Get("a"))
      SetAt(GetAt(Get("b"), Literal(0)), Get("c"), Get("a"))    
      SetAt(Get(This(), "values"), Literal(0), Inc("x"))
      SetAt(Get(This(), "values"), Literal(0), PostDec("x"))

Strings

ClassMaker supports the concatenation of strings with the add + operator.

If either operand is of type String the other operand will be converted to a String
and the result will be a StringBuffer. These automatically created StringBuffers are
converted back to a String when the result is assigned to a variable or passed as an actual
parameter to a method call. An Object is converted to a String by calling its toString
method.

Java codeClassMaker codeResult
     "Hello" + " World"
     "Total = " + total
     360 + " degrees"
     12 + 3 + " widgets"
     "widgets " + 12 + 3
     Add(Literal("Hello"), Literal(" World"))
     Add(Literal("Total = "), Get("total"))
     Add(Literal(360), Literal(" degrees"))
     Add(Add(Literal(12), Literal(3)), Literal(" widgets"))    
     Add(Add(Literal("widgets "), Literal(12)), Literal(3))
     Hello World    
     Total = 256
     360 degrees
     15 widgets
     widgets 123

Eval

Most expressions leave a result on the stack. If the expression is a statement then the result
must be popped off the stack before the next statement begins. If this is not done consistently
the class verifier may throw a verification exception when the class is loaded. This would
typically happen when a loop or branch creates multiple paths to the end of a method and
the stack size differs depending upon which path is taken.

ClassMaker provides the Eval method to dispose of the result of an expression.
An Eval call should surround all expression statements generated by ClassMaker,
including calls to methods that return void. Eval will figure out
whether or not there is a value to be discarded.

Eval should not be called around compound statements like if statements and loops
as they cannot leave a result on the stack.

Java codeClassMaker code
     --a;
     obj.i++;
     obj.b = 12345;
     Eval(Dec("a"));
     Eval(PostInc(Get("obj"), "i"));
     Eval(Set(Get("obj"), "b"), Literal(12345));

[Home]


Related

Wiki: Home

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.