Arrays

Arrays in Pollen can be declared with elements of primitive type, class type, and function reference type.

Here are several arrays of primitive type, showing explicit as well as default initialization.

uint8 arr1[3]             // array of 3 uint8, by default each element initialized to 0.

uint8 arr2[3] = {7}       // array of 3 uint8, each element initialized to 7.

The above arrays are target arrays. They will be initialized at load time. They must be initialized to constants, not variable values or function returns.

A host array as the attribute host. Here is a host array. It will be initialized during the host phase:

host uint8[3] arr3 = {5,5,7}   // host array of 3 uint8, initialized to 5,5,7.

Host arrays have the ability to be initialized to host variable values or host functions.

host uint8[3] arr4 = { myHostVar, hostFcnInit(), hostFcnInit() }   // host array init to host values

For all arrays the type of the array is on the left and is followed by the array name. The specification of the size can follow either the type or the name.

    host Led ledArr[2] = { new Led(7) }

This is a host array of two Leds. The new Led() call will invoke the host constructor so the array is allocated and initialized to two Led elements statically. Target arrays are supported; they differ by the abscence of the host attribute.

    Led leds[3] = { null }        // initialized to 3 nulls

This target array is allocated and initialized to three null elements at load time. Constructors cannot be called in target array initialization.

Arrays can have an element type which is a function reference. The element type can be a module function reference.

  Mod.on(uint8)  onf                         // A function reference to Mod.on()
  host Mod.on on_functions[3] = { onf }      // Array of references to Mod.on()

The element type can also be a protocol function reference. This is useful in supporting generic code as the protocol function can be implemented by multiple functions with the same signature. Iterating over the array provides a generic way of calling these multiple functions. OnP is a protocol which contains the function declaration on(uint8).

  OnP.on on_functions[3] = { onf1, onf2, onf3 }

The function references in the initializer has been initialized to functions in modules which implement OnP.

An example of generic code using arrays of function references is here. More information on function references is here.

Arrays can be declared with no dimension at all. That is, there is no dimension and also no initializer. Such arrays are not allocated as arrays. Instead they are pegged (using the pegging operator @=) to other arrays at runtime. Only arrays declared without dimension can be pegged. A pegged array overlays in memory the array to which it was pegged.

    byte arrNoDim[]    // no initializer!

Here is an array of characters:

    byte arrStr[] = { 'h', 'e', 'l', 'l', 'o' , ' ', 'm', 'a', 'r', 'y'}

The first array can be pegged to the second array and then accessed through it:

    arrNoDim @= arrStr       // array pegging
    string str = arrNoDim[6]
    print str                // prints 'mary'

A uint32 array can be pegged to a uint8 (or bool, int16, etc.) array and vice versa. This is useful for flexible memory access and it can also be used to obtain some of the functionality of a type cast as shown below.

   uint8 _src_u8[4] = {0,1,2,3}
   uint32 arr_u32[] 
   bool   arr_b[] 

   arr_u32 @= _src_u8   // access the source as an unsigned 32 bit
   arr_b   @= _src_u8   // access the source as a boolean

An array without dimension can also be pegged to a class reference, allowing access to the object as if it were overlaid by an array.

Arrays can have dimensions specified by a host variable, as below:

host uint8 numLeds = 1        // a host array dimension variable
Led leds[numLeds] = {null}

The value of variable numLeds is computed during the host phase. Thus its value at load time will be known. This supports static allocation and initialization for arrays of computed size. Such an array can adjust to changing requirements without changing source code. Also static allocation avoids all the problems associated with dynamic memory management.

More information on host array initialization is here.

Array access uses the [] operator.

  myVar = myArray[idx]   // idx can be any unary expression

Assigning an array element is an ordinary assignment with the array element expression on the right hand side.

  myArray[idx] = newValue  

The type of the array element must be compatible with the type of the expression on the other side of the assignment operator.

The for and while statements can be used to iterate over an array. strlen(), the function shown below, can be found in the pollen.text package in the bundle pollen.core.

  public uint16 strlen(string s) {
    byte b [] @= s
    uint16 i = 0
    while (b[i] != '\0') {   // look for the string terminator character
      i++
    }
    return i
  }

In the example below, numLeds is a host variable computed at host time. Its value will default to 1 if no host initialization assignment occurs.

host uint8 numLeds = 1        // a host array dimension variable
Led leds[numLeds] = {null}    

for (uint8 i = 0; i < numLeds; i++) {
     // process leds element
}