4.1 Translating CDL to Java

The description of a cellular automaton in CDL, cellang, or caxl can be translated fairly directly into Java, since most language constructs of CDL have direct equivalents in Java. These are: arithmetic and logical operators, assignment, if-statement, blocks, and case-statements. Most primitive data types can also be translated into Java primitive types, but Java does not have primitive enumeration types or range types. The range types can be translated into suitable primitive integer types. The enumeration types can be translated into integers as well, or into a type-safe system of sub-classes, which however is less memory-efficient. As an example, the following translation is shown:

** CDL:**

cellular automaton T4 ; type celltype = record a: boolean; b: 0..3; end; rule begin *[0].a := ( *[-1].a AND *[0].a ) XOR *[1].a; if *[0].a AND *[-1].a AND *[1].a then *[0].b := ((*[1].b ) + (*[0].b DIV 2) ) MOD 4 else *[0].b := *[0].b; end;

public class T4 extends State { protected celltype mystate; protected class celltype implements Serializable { boolean a; /*0..3*/ int b; } public T4(){ mystate = new celltype(); }Then, the state transition method:

public void transition(Cell cell){ final State [] neighbors = cell.getNeighbors(); { mystate.a = (((T4)neighbors[1]).mystate.a && ((T4)neighbors[0]).mystate.a) ^ ((T4)neighbors[2]).mystate.a; if (( (T4)neighbors[0]).mystate.a && ((T4)neighbors[1]).mystate.a && ((T4)neighbors[2]).mystate.a ){ mystate.b = ((((T4)neighbors[2]).mystate.b) + (((T4)neighbors[0]).mystate.b / 2)) % 4; }else{ mystate.b = ((T4)neighbors[0]).mystate.b; }; } }More Java code (not shown here) is generated for initialization and display.

`for`

, `one`

, `all`

,
`num`

, `sum`

). There are two
possible ways to translate this feature of CDL into Java. One
way is to translate it
into vectors and iterators. The second possibility exploits the fact that the
group is (in our language definition) fixed, i.e., all elements are known, and thus the action of
iterators can be expanded explicitly into a sequence of statements (`for`

) or
expressions. Both possibilities are used in CASim: The first is used for groups
with the name ```neighbors`

'', which makes it possible for CDL to be written
independently of the dimension and neighborhood of the lattice (selection of the
neighborhood is done in the simulation environment). The second possibility is
used for all other cases, since it is more efficient for small groups.
As an example, the following CDL-code is translated into Java using the two different options.

** CDL:**

cellular automaton TestGroup; type celltype = 0 .. 2; group neighbors = {*[0],*[-1],*[1]}; var n : celltype; rule begin for n in neighbors do if n > 0 then ..... end

public void transition(Cell cell){ int n; final State [] neighbors = cell.getNeighbors(); for (int i=0; i<neighbors.length; i++){ n = ((TestGroup)neighbors[i]).mystate; if (n > 0){ ..... } } }

public void transition(Cell cell){ final State [] neighbors = cell.getNeighbors(); { if (((TestGroup)neighbors[0]).mystate > 0){ ..... }; if (((TestGroup)neighbors[1]).mystate > 0){ ..... }; if (((TestGroup)neighbors[2]).mystate > 0){ ..... }; } }

`one`

, `num`

, `all`

, `sum`

. The Java code uses
statements, but the CDL expressions can occur inside complicated expressions,
and Java does not allow statements to occur inside expressions. One possible
solution is to use anonymous inner classes, but it is more efficient to generate
temporary variables which are assigned a value directly before the expression
in which they are used. Example:
** CDL: **

r := (1+num( n in neighbors: n = 1)) mod 3;

r = (1 + ( (((TestGroup)neighbors[0]).mystate == 1?1:0) +(((TestGroup)neighbors[1]).mystate == 1?1:0) +(((TestGroup)neighbors[2]).mystate == 1?1:0) )) % 3;

int temp1_=0; for (int i=0; i<neighbors.length; i++){ n = ((TestGroup)neighbors[i]).mystate; temp1_+= ( n == 1)?1:0; } r = (1 + temp1_) % 3;Note that the translation system must have detailed type information to determine the type of the temporary variable (boolean, integer, or float).

`State`

-object. These operations involve a certain amount of
overhead. Another possibility is to collect all neighboring states into an array
once, and access them using this array. In CASim this array is actually
preserved between time steps, since the neighborhood does not change between
time steps. This option is called ``cache neighborhood'' in the CASim system and
can be turned on or off, since caching the neighborhood involves a cost in
memory but improves performance (if enough memory is available).