LARA

Translating If Expressions

int activityLevel
boolean action(int signals, boolean objects, int smart, int pretty) {
  if ((signals > 5 || !objects) && smart + 2*pretty > 10) {
    activityLevel++;
    return true;
  } else {
    activityLevel--;
    return false;
  }
}

can be abstracted as:

[| if (condition) {...} else {...} |]

Using the branch(c, l1, l2) instruction this will translate into

	branch( condition, cYes, cNo)
cYes:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

Translating Complex Boolean Conditions

The boolean condition is again complex and it can be represented as a conjunction of two simpler conditions.

	branch( condition1 && condition2, cYes, cNo)
cYes:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

Using the rule for translating conjunctions, this becomes:

	branch( condition1, c1Yes, cNo) 
c1Yes:	branch( condition2, cYes, cNo) 
cYes:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

The boolean condition condition1 is a disjunction of two conditions:

	branch( condition11 || condition12, c1Yes, cNo) 
c1Yes:	branch( condition2, cYes, cNo) 
cYes:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

Using the rule for translating disjunctions, this becomes:

	branch( condition11, c1Yes, c11No) 
c11No:	branch( condition12, c1Yes, cNo) 
c1Yes:	branch( condition2, cYes, cNo) 
cYes:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

Using the real boolean conditions from the program we obtain:

	branch( signals > 5, c1Yes, c11No) 
c11No:	branch( !objects, c1Yes, cNo) 
c1Yes:	branch( smart + 2*pretty > 10, cYes, cNo) 
cYes:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

Negation is eliminated by reversing the labels:

	branch( signals > 5, c1Yes, c11No) 
c11No:	branch( objects, cNo, c1Yes) 
c1Yes:	branch( smart + 2*pretty > 10, cYes, cNo) 
cYes:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

Translation of Relations in Boolean Conditions

Translating a boolean condition involving > operator is done using a bytecode comparison instruction:

	[| signals |]
	[| 5 |]
	if_icmpgt c1Yes
	goto c1No
c11No:	branch( objects, cNo, c1Yes) 
c1Yes:	branch( smart + 2*pretty > 10, cYes, cNo) 
cYes:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

Finally, we derive a beginning of the bytecode program:

0:	iload_1
1:	iconst_5
2:	if_icmpgt c1Yes
3:	goto c1No
c11No:	branch( objects, cNo, c1Yes) 
c1Yes:	branch( smart + 2*pretty > 10, cYes, cNo) 
cYes:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

We apply the same procedure on the piece of code labeled with c1Yes:

0:	iload_1
1:	iconst_5
2:	if_icmpgt c1Yes
3:	goto c1No
c11No:	branch( objects, cNo, c1Yes) 
c1Yes:	[| smart + 2*pretty |]
	[| 10 |]
	if_icmple cNo
	goto cYes
cYes:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

Note that label c11No is not needed, so the code can be optimized:

0:	iload_1
1:	iconst_5
2:	if_icmpgt c1Yes
3:	branch( objects, cNo, c1Yes) 
c1Yes:	[| smart + 2*pretty |]
	[| 10 |]
	if_icmple cNo
	goto cYes
cYes:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

Translating of Boolean Variables

The next unprocessed branch instruction ckecks the value of a boolean variable objects:

0:	iload_1
1:	iconst_5
2:	if_icmpgt c1Yes
3:	iload_2
4:	ifne cNo
5:	goto c1Yes
c1Yes:	[| smart + 2*pretty |]
	[| 10 |]
	if_icmple cNo
	goto cYes
cYes:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

Note that we can further optimize the code since the command currently labeled with 5 is not needed. This way, the label c1Yes gets the value 5.

0:	iload_1
1:	iconst_5
2:	if_icmpgt 5
3:	iload_2
4:	ifne cNo
5:	[| smart + 2*pretty |]
	[| 10 |]
	if_icmple cNo
	goto cYes
cYes:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

Translating Arithmetical Expressions

Arithemtical expressions are translated using standard postfix notation:

0:	iload_1
1:	iconst_5
2:	if_icmpgt 5
3:	iload_2
4:	ifne cNo
5:	[| smart |] :: [| 2 |] :: [| pretty |] :: * :: + 
	[| 10 |]
	if_icmple cNo
	goto cYes
cYes:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

At the end this piece of code translates to:

0:	iload_1
1:	iconst_5
2:	if_icmpgt 5
3:	iload_2
4:	ifne cNo
5:	iload_3
6:	iconst_2
7:	iload_4
8:	imul
9:	iadd
10:	bipush 10
11:	if_icmple cNo
12:	goto cYes
cYes:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

Note that we can again optimize the code since the command currently labeled with 12 is not needed. This way, the label cYes gets the value 12.

0:	iload_1
1:	iconst_5
2:	if_icmpgt 5
3:	iload_2
4:	ifne cNo
5:	iload_3
6:	iconst_2
7:	iload_4
8:	imul
9:	iadd
10:	bipush 10
11:	if_icmple cNo
12:	[|activityLevel++; return true;|]
	goto lAfter
cNo:	[|activityLevel--;return false;	|]
lAfter:

Manipulating an Object Reference

We continue to translate block statements:

0:	iload_1
1:	iconst_5
2:	if_icmpgt 5
3:	iload_2
4:	ifne cNo
5:	iload_3
6:	iconst_2
7:	iload_4
8:	imul
9:	iadd
10:	bipush 10
11:	if_icmple cNo
12:	[|activityLevel++|] 
	iconst_1
	ireturn
	goto lAfter
cNo:	[|activityLevel--|]
	iconst_0
	ireturn
lAfter:

There is no need for goto command after ireturn and we do not have any code after if_then_else command, so we can delete lAfter label:

0:	iload_1
1:	iconst_5
2:	if_icmpgt 5
3:	iload_2
4:	ifne cNo
5:	iload_3
6:	iconst_2
7:	iload_4
8:	imul
9:	iadd
10:	bipush 10
11:	if_icmple cNo
12:	[|activityLevel++|] 
	iconst_1
	ireturn
cNo:	[|activityLevel--|]
	iconst_0
	ireturn

In the tutorial we increased (and decreased) the variable activityLevel using the following command: iinc 0, 1 (iinc 0, -1). This was not completely correct as activityLevel is a field of a class so the correct version is by using aload, getfield and putfield.

This way the command

activityLevel++

is translated as:

aload_0
dup
getfield        #2; //Field activityLevel:I
iconst_1
iadd
putfield        #2; //Field activityLevel:I

The command for decrement of activityLevel is translated similarly. If we intagrate that into the bytecode program we obtain:

0:	iload_1
1:	iconst_5
2:	if_icmpgt 5
3:	iload_2
4:	ifne cNo
5:	iload_3
6:	iconst_2
7:	iload_4
8:	imul
9:	iadd
10:	bipush 10
11:	if_icmple cNo
12:	aload_0
13:	dup
14:	getfield
15:	iconst_1
16:	iadd
17:	putfield
18:	iconst_1
19:	ireturn
cNo:	[|activityLevel--|]
	iconst_0
	ireturn

At the end we see that the label cNo has value 20 and finally, the complete translated program looks as follows:

0:	iload_1
1:	iconst_5
2:	if_icmpgt 5
3:	iload_2
4:	ifne 20
5:	iload_3
6:	iconst_2
7:	iload_4
8:	imul
9:	iadd
10:	bipush 10
11:	if_icmple 20
12:	aload_0
13:	dup
14:	getfield
15:	iconst_1
16:	iadd
17:	putfield
18:	iconst_1
19:	ireturn
20:	aload_0
21:	dup
22:	getfield
23:	iconst_1
24:	isub
25:	putfield
26:	iconst_0
27:	ireturn