Scoped Code Blocks
ClassMaker provides the following methods to create scoped code blocks.
public Labelled Begin() throws ClassMakerException
public void End() throws ClassMakerException
A Begin and End pair create a code block that limits the scope of variables
declared within the code block. Other statements may include a code block of multiple statements
but they do not limit variable scope.
In the following code the variable a is declared twice in different scoped code blocks.
Consequently, the variable can be declared as an integer in one code block and a character in the other.
| Java code | ClassMaker code |
if (n > 0)
{
int a;
a = n++;
}
else
{
char a;
a = '0';
n = a - n;
}
|
If(GT(Get("n"), Literal(0)));
Begin();
Declare("a", int.class, 0);
Set("a", Inc("n"));
End();
Else();
Begin();
Declare("a", char.class, 0);
Set("a", Literal('0'));
Set("n", Subt(Get("a"), Get("n")));
End();
EndIf();
|
Begin and End are also used to define the code block for a method, as described in the section
about [Methods].
If Statement
ClassMaker provides the following methods to create if statements.
public Labelled If(Type condition) throws ClassMakerException;
public void Else() throws ClassMakerException;
public void EndIf() throws ClassMakerException;
There may be any number of statements between the If, Else and EndIf method calls.
Unlike java, there is an implicit code block between each clause.
An exception will be thrown if the clauses do not balance, for example, if an Else method is
called when not preceded by an If call and followed by an EndIf call.
| Java code | ClassMaker code |
if (a<0) {
a = 0;
}
|
If(LT(Get("a"), Literal(0)));
Set("a", Literal(0));
EndIf();
|
if (a<0) {
a = 0;
} else {
a = 1;
}
|
If(LT(Get("a"), Literal(0)));
Set("a", Literal(0));
Else();
Set("a", Literal(1));
EndIf();
|
While loop
A while loop can be created using the following methods from ClassMaker.
public Labelled Loop() throws ClassMakerException
public void While(Type condition) throws ClassMakerException
public void EndLoop() throws ClassMakerException
The While clause can appear at the start or end of the loop, either after the Loop
clause or just before the EndLoop clause. In actual fact it could appear anywhere in the loop
as ClassMaker places no restrictions on the placement of the While clause, but the traditional
place is at the start of the loop or occasionally at the end.
| Java code | ClassMaker code |
x = 1;
while (n>0)
{
x = x * n;
--n;
}
|
Eval(Set("x", Literal(1)));
Loop();
While(GT(Get("n"), Literal(0)));
Eval(Set("x", Mult(Get("x"), Get("n"))));
Eval(Dec("n"));
EndLoop();
|
For loop
The methods for generating a for loop in ClassMaker look like this.
public ForWhile For(Type declare) throws ClassMakerException;
interface ForWhile
{
ForStep While(Type condition) throws ClassMakerException;
}
interface ForStep
{
Labelled Step(Type step) throws ClassMakerException;
}
public void EndFor() throws ClassMakerException
While this looks daunting it actually comes down to this simple sequence.
For( <assignment> ).While( <condition> ).Step( <increment> ); </increment></condition></assignment>
The For method expects an expression which is usually an assignment, although this is not enforced.
The While method expects a boolean expression and will complain if it doesn't get one.
The Step method expects another expression which usually increments a value, although again, this is not enforced.
Any or all of the expressions may be omitted by providing null.
The call to EndFor terminates the loop.
The following code calculates factorial for a given n.
| Java code | ClassMaker code |
for (x=1; n>0; --n)
{
x = x * n;
}
|
For(Set("x", Literal(1))).While(GT(Get("n"), Literal(0))).Step(Dec("n"));
Eval(Set("x", Mult(Get("x"), Get("n"))));
EndFor();
|
Break & Continue
The usual way to shortcut evaluation in the middle of a loop in java is to use a break
or continue statement. The equivalents in ClassMaker are named similarly.
public void Break() throws ClassMakerException
public void Continue() throws ClassMakerException
The While clause in a loop is optional; a break can be used instead. The following
code sums values up to n, the second version excludes multiples of 2.
| Java code | ClassMaker code |
// Sum all values up to n.
x = 0;
while (true) {
if (n<=0) {
break;
}
x = x + n;
--n;
}
|
Eval(Set("x", Literal(0)));
Loop();
If(LE(Get("n"), Literal(0)));
Break();
EndIf();
Eval(Set("x", Add(Get("x"), Get("n"))));
Eval(Dec("n"));
EndLoop();
|
// Sum all values up to n, except multiples of 2
x = 0;
while (true) {
y = n--;
if (y<=0) {
break;
}
if ((y % 2) == 0) {
continue;
}
x = x + y;
}
|
Eval(Set("x", Literal(0)));
Loop();
Eval(Set("y", PostDec("n")));
If(LE(Get("y"), Literal(0)));
Break();
EndIf();
If(EQ(Rem(Get("y"), Literal(2)), Literal(0)));
Continue();
EndIf();
Eval(Set("x", Add(Get("x"), Get("y"))));
EndLoop();
|
Switch
ClassMaker provides the following methods to support the switch statement.
public Labelled Switch(Type switchType) throws ClassMakerException;
public void Case(int key) throws ClassMakerException;
public void Break() throws ClassMakerException
public void Break(String label) throws ClassMakerException
public void Default() throws ClassMakerException;
public void EndSwitch() throws ClassMakerException;
The Case(int key) method will accept an int, char, short or byte type.
ClassMaker will generate different byte-code for the switch depending upon whether the keys
are contiguous or non-contiguous. It will generate a table-switch in the former situation or a
lookup-switch in the latter.
| Java code | ClassMaker code |
y = 0;
switch (x)
{
case 0:
y = 1;
break;
case 4:
y = 2;
break;
case 2:
y = 3;
break;
case 6:
y = 4;
break;
default:
y = 0;
break;
}
|
Set("y", Literal(0));
Switch(Get("x"));
{
Case(0);
Set("y", Literal(1));
Break();
Case(4);
Set("y", Literal(3));
Break();
Case(2);
Set("y", Literal(2));
Break();
Case(6);
Set("y", Literal(4));
Break();
Default();
Set("y", Literal(0));
Break();
}
EndSwitch();
|
Try catch finally
ClassMaker provides the following methods to perform exception handling.
public Labelled Try();
public void Catch(Class javaClass, String name) throws ClassMakerException;
public void Catch(String exceptionName, String name)
public void Finally() throws ClassMakerException;
public void EndTry() throws ClassMakerException;
There are two versions of the Catch method. You will use the version that
takes a reflection Class most of the time. The version that takes a
!String is necessary when you are catching an exception class
that you are generating at runtime.
The generated code in the Finally clause is always executed, as you would expect.
The code is put in a subroutine and the subroutine is invoked:
Try block completes normallyCatch clause processes an exceptionBreak, Continue or Return methods are called| Java code | ClassMaker code |
try
{
x = func.unary(x);
}
catch (FileNotFoundException ex1)
{
x = 10000;
}
catch (IllegalArgumentException ex1)
{
x = 20000;
}
finally
{
x = x + 100;
}
|
Try();
{
Eval(Set("x", Call(Get("func"), "unary", Push(Get("x")))));
}
Catch(FileNotFoundException.class, "ex1");
{
Eval(Set("x", Literal(10000)));
}
Catch(IllegalArgumentException.class, "ex2");
{
Eval(Set("x", Literal(20000)));
}
Finally()
{
Eval(Set("x", Add(Get("x"), Literal(100))));
}
EndTry();
|
Labelled Break & Continue
ClassMaker provides the following interface and methods to support labelled Break and Continue.
public interface Labelled
{
void setLabel(String label);
String getLabel();
}
public void Break(String label) throws ClassMakerException
public void Continue(String label) throws ClassMakerException
The Labelled interface is returned by all !ClassMaker statements to allow
them to be labelled. It is then possible to Break to the labelled
statement. Labelled loops can also be the target of a Continue method.
Statements may be labelled as follows.
Begin().setLabel("HERE");
If(<cond>).setLabel("THERE");
Loop().setLabel("LOOP");
For(<expr>).While(<cond>).Step(<expr>).setLabel("FORLOOP");
Switch().setLabel("EXIT");
Try().setLabel("TRYING");
</expr></cond></expr></cond>
The following example demonstrates several of these uses.
| Java code | ClassMaker code |
outer: {
loop: for (j=1; j<=3; j++)
{
switch (i) {
case 1:
break;
case 2:
continue;
case 3:
break loop;
case 4:
continue loop;
case 5:
break outer;
}
n++;
}
}
|
Begin().setLabel("outer");
For(Set("j", Literal(1))).While(LE(Get("j"), Literal(3))).Step(Inc("j")).setLabel("loop");
Switch(Get("i"));
Case(1);
Break();
Case(2);
Continue();
Case(3);
Break("loop");
Case(4);
Continue("loop");
Case(5);
Break("outer");
EndSwitch();
Eval(Inc("n"));
EndFor();
End();
|