../_images/logo.png

http://www.bardolph.org

Arrays

An array is set up with the declare keyword. After it has been declared, the elements can be accessed with numerical subscripts. The language specification allows for arrays to have an arbitrary number of dimensions. The size and dimension of an array are static and set when the array is declared. For example, to declare a one-dimensional array:

declare vector[5]

In this example, the array named vector has 5 elements and can be accessed with subscripts from 0 to 4.

Once an array is declared, it can be written with assign and read wherever any other variable is allowed.

declare hues[10]
assign hues[5] 120

hue hues[5]

Accessing an array with a subscript that is negative or outside the bounds of its size will cause an error to be logged, but in most cases, the virtual machine will make an attempt to provide a reasonable default. If the subscript is a floating-point value, the fraction will be truncated to yield an integer.

To declare a multi-dimensional array, use a series of square brackets, each with a size. For example:

declare colors[8][4][9]
assign colors[1][3][8] 100

Within the declaration, the size of the array can be calculated at run-tme. However, after an arrary has been declared, its size may not be changed. As with other features of the language, numerical expressions need to be in curly braces.

declare hue_segment[{hue / 10}]

assign array_size {24 * 60}
declare day[array_size]

Assigning an array to a variable creates an alias and does not make a copy:

declare mat[3]
assign mat[0] 100
assign mat2 mat
assign mat2[0] 200

# This will print 200
print mat[0]

When an array is partially subscripted, the result is itself an array with a reduced dimension.

Iterating Over an Array

To iterate over a specific range, use the repeat with construct:

declare vector[5]

repeat with i from 1 to 3
    assign vector[i] {i * 2}

To iterate over all of the elements in an array, use a repaeat in as clause:

declare hues[3]
repeat in hues as i begin
    assign hues[i] {i * 120}
end

A similar construct can be used for multi-dimensional arrays:

declare colors[5][4]

repeat in colors as color_num
    repeat in colors[color_num] as setting_num
        assign colors[color_num][setting_num] 100


repeat in colors[0] as setting_num
    assign colors[0][setting_num] 200


declare matrix[6][5][3]
repeat in matrix as i
    repeat in matrix[i] as j
        repeat in matrix[i][j] as k
            assign matrix[i][j][k] 500

Arrays as Parameters

When an array is passed into a routine, it needs to be declared as such in the routine’s definition. This is done with a pair of square brackets for each dimension. For example:

define sum_array with arr[][] begin
    assign sum 0

    repeat with i from 0 to 4 begin
        repeat with j from 0 to 9 begin
            assign sum {sum + arr[i][j]
        end
    end
end

declare matrix[5][10]

# ...some code here fills the "matrix" array with data.

println [sum_array matrix]

The code using the array can also be written without explicitly giving the lengths of each dimension:

define sum_array with arr[][] begin
    assign sum 0

    repeat in arr as i begin
        repeat in arr[i] as j begin
            assign sum {sum + arr[i][j]}
        end
    end
end

Design Overview

Support for arrays is accomplished with a couple of new instructions and new handling of certain types of parameters passed into to move-related instructions.

New VM Instructions

OpCode.ARRAY, name, size

Declares an array with the given name and size.

For example, this script:

declare a[5]

can be accomplished with:

OpCode.ARRAY, "a", 5

If the array already exists, its dimensionality is increased accoringly. So, to have v[3][4]:

OpCode.ARRAY, "v", 3
OpCode.ARRAY, "v", 4

OpCode.DEREF, name

Resets the indexing of the named array and positions it at the value provided in the second parameter:

OpCode.DEREF, "v", 1

OpCode.INDEX, name, index

Positions the named array at the given index, typically:

OpCode.DEREF "a", 1
OpCode.INDEX, "a", 2

Instructions With New Parameter Types

When an array is part of move instruction, it utilizes whatever address it got in the last INDEX or DEREF instruction. For example:

assign a[3] 5

would yield:

OpCode.DEREF, "a", 3
OpCode.MOVEQ 5, "a"

Conversely, referencing an array element:

assign x a[2]

can be done with:

OpCode.DEREF, "a", 2
OpCode.MOV, "a", "x"

Multi-dimensional arrays are handled with a DEREF, followed by multiple INDEX instructions:

assign x v[2][3]

can be done with:

OpCode.DEREF, "a", 2
OpCode.INDEX, "a", 3
OpCode.MOVEQ, "a", "x"

Use Case: 1D Assignment

Script:

declare v[5]
assign v[3] 20

VM code:

OpCode.ARRAY, "v", 5
OpCode.DEREF, "v", 2
OpCode.MOVEQ, 10, "v"

Use Case: 1D Read

Script:

declare v[5]
assign v[2] 10

...

hue v[2]

VM code:

OpCode.ARRAY, "v", 5
OpCode.DEREF, "v", 2
OpCode.MOVEQ, 10, "v"

...

Opcode.DEREF, "v", 2
OpCode.MOVE, "v", Register.HUE

Use Case: 2D Assignment

This use case also covers arrays with dimensions of 3 and above.

Script:

declare a[10][5]
assign a[3][4] 200

VM code:

OpCode.ARRAY, "a", 10
OpCode.ARRAY, "a", 5
OpCode.DEREF, "a", 3
OpCode.INDEX, "a", 4
OpCode.MOVEQ, 200, "a"

Use Case: 2D Read

This use case also covers arrays with dimensions of 3 and above.

Script:

declare a[10][5]
assign a[5][2] 100

...

hue a[5][2]

VM code:

OpCode.ARRAY, "a", 10
OpCode.ARRAY, "a", 5
OpCode.DEREF, "a", 5
OpCode.INDEX, "a", 2
OpCode.MOVEQ, 100, "a"

...

OpCode.DEREF, "a", 5
OpCode.INDEX, "a", 2
OpCode.MOVE, "a", Register.HUE

Use Case: Assign Array to Variable

Script:

declare v[10]
assign v[5] 100

assign v_ref v

hue v_ref[5]
assign 10 v_ref[6]

VM code:

OpCode.ARRAY, "v", 10
OpCode.DEREF, "v", 5
OpCode.MOVEQ, 100, "v"

OpCode.DEREF, "v", None
OpCode.MOVE, "v", "v_ref"

OpCode.DEREF, "v_ref", 5
OpCode.MOVE, "v_ref", Register.HUE

OpCode.DEREF, "v_ref", 6
OpCode.MOVEQ, 10 "v_ref"

Use Case: Assign Partially-Dereferenced Array to Variable

Script:

declare a[5][7]
assign a[2][5] 100
...
assign a_ref a[2]
...
hue a_ref[5]

VM code:

OpCode.ARRAY, "a", 5
OpCode.ARRAY, "a", 7
OpCode.DEREF, "a", 2
OpCode.INDEX, "a", 5
OpCode.MOVEQ, 100, "a"
...
OpCode.DEREF, "a", 2
OpCode.MOVE, "a", "a_ref"
...
OpCode.DEREF, "a_ref", 5
OpCode.MOVE, "a_ref", Register.HUE

Problem: Assign Partially-Dereferenced Array to Variable

Script:

declare a[5][7]
assign a[2][5] 100
...
assign a_ref a[2]
...
hue a[3][3]
hue a_ref[5]

VM code:

OpCode.ARRAY, "a", 5
OpCode.ARRAY, "a", 7
OpCode.DEREF, "a", 2
OpCode.INDEX, "a", 5
OpCode.MOVEQ, 100, "a"
...
OpCode.DEREF, "a", 2
OpCode.MOVE, "a", "a_ref"
...
OpCode.DEREF, "a", 3
OpCode.INDEX, "a", 3
OpCode.MOVE, "a", Register.HUE
OpCode.DEREF, "a_ref", 5
OpCode.MOVE, "a_ref", Register.HUE

Use Case: Array as Parameter

Script:

define fn with v[] begin
    assign v[7] 9
    return v[5]
end

declare arr[10]
assign arr[5] 250

hue [fn arr]

VM code:

OpCode.ROUTINE, "fn"
OpCode.DEREF, "v", 7
OpCode.MOVEQ, 9, "v"
OpCode.DEREF, "v", 5
OpCode.MOVE, "v", Register.RESULT
OpCode.RETURN

OpCode.ARRAY, "arr", 10
OpCode.DEREF, "arr", 5
Opcode.MOVEQ, 250, "arr"

OpCode.CTX
OpCode.DEREF, "arr", None
OpCode.PARAM, "v", "arr"
OpCode.JSR, "fn"
OpCode.END_CTX

Use Case: Partially-Dereferenced Array as a Parameter

Script:

define fn with v[] begin
    assign v[6] 7
    return v[5]
end

declare arr[5][7]
assign arr[2][5] 100

hue [fn arr[5]]

VM code:

OpCode.ROUTINE, "fn"
OpCode.DEREF, "v", 6
OpCode.MOVE, 7, "v"
OpCode.DEREF, "v", 5
OpCode.MOVE, "v", Register.RESULT
OpCode.RETURN

OpCode.ARRAY, "arr", 5
OpCode.ARRAY, "arr", 7
OpCode.DEREF, "arr", 2
OpCode.INDEX, "arr", 5
OpCode.MOVEQ, 100, "arr"

OpCode.CTX
OpCode.DEREF, "arr", 5
OpCode.PARAM, "v", "arr"
OpCode.JSR, "fn"
OpCode.END_CTX
OpCode.MOVE, Register.RESULT, Register.HUE

Use Case: Nesting

Script:

declare a[5]
assign a[2] 3
assign a[a[2]] 4

VM code:

OpCode.ARRAY, "a", 5
OpCode.DEREF, "a", 2
OpCode.MOVEQ, 3, "a"

OpCode.DEREF, "a", 2
OpCode.MOVE, "a", Register.RESULT   # rvalue
OpCode.DEREF, "a", Register.RESULT
OpCode.MOVEQ, "4", "a"

Use Case: Loop over 1D Array

Script:

declare v[10]
repeat in v as i
    hue v[i]

Use Case: Loop over 2D Array

Script:

declare m[5][10]

repeat in m as i
    repeat in m[i] as j
        assign m[i][j] 0

repeat in m as i
    repeat in m[i] as j
        hue m[i][j]