A Quick Introduction to Virgil - Arrays

This is part of a basic introduction to programming in Virgil and gives an overview of the language, its syntax, and its structures. This page focuses on declaring and using Virgil arrays, including allocation and access.

Overview

Virgil has arrays built into the base language. An array is a collection that maps an integer index to an element, a location that can store a value. Arrays represent a contiguous region of memory cells and come with the implicit guarantee that an access of an element is a constant time operation. Virgil arrays are statically typed, so that every array has a type which is written elem[] where elem is the type of the elements of the array. Every Virgil array also has a length that is fixed when the array is allocated; valid indices to an array a are the interval [0, a.length - 1] (i.e. all indices between zero and the length of the array, inclusive). Every access of an array is dynamically checked against the valid indices for the array and will generate a BoundsCheckException if the index is not valid for the array.

Allocating Arrays

local x: int[] = { 0, 1, 2, 3 };
local y: int[] = new int[89];

Arrays can be allocated one of two ways in Virgil. The first way is to declare an array literal, which is a list of expressions enclosed in curly braces { ... }. Array literals can only be used in the initialization expression for a local variable or field. When the statement that contains the array literal is executed, a new array is allocated of the corresponding length and its elements are initialized to the result of evaluating each expression in the literal. The second way is to explicitly allocate a new array using the new operator. The type of the array is given, and an expression that is evaluated and used as the length of the array. All of the elements of the array are initialized to the default value for the element type (e.g. 0 for integers, null for reference types).

Accessing Arrays

local x: int = array[expr];
array[expr] = x;
local y: int = array.length;

Arrays can be accessed using the [] array subscript operator. The expression representing the array is given, followed by the index in square brackets [ ... ]. The index expression must be of type of int. Array index expressions can be used as the target of an assignment statement, in which case, the value of the right hand side is assigned to the specified element. The length of an array can be accessed as if it were a field by applying the .length suffix to the array reference.

Arrays are References

local x: int[] = new int[1];
local y: int[] = x;
y[0] = 100;
local z: int = x[0]; // z == 100

Virgil arrays are always passed by reference. This means that assigning a variable to an array expression, or passing an array across a method call does not copy the contents of the array, but instead just passes a reference to the array's contents. Thus, updates to the array's elements after a reference has been passed are visible to the new holder of the reference.

Exceptions

local x: int[] = null;
local y: int = x[0]; // NullCheckException
local z: int[] = new int[2];
local w: int = z[3]; // BoundsCheckException

Array accesses can generate two kinds of exceptions. Like any other reference in Virgil, including object references and delegates, array references may be null, which indicates the reference does not point to any valid array. An array length access or array element access will generate a NullCheckException if the array reference is null. If the reference is not null then the index value is checked against the valid bounds for the array. If the index is out of the bounds of the array (i.e. it is less than zero or is greater than or equal to the length of the array), a BoundsCheckException will be generated.

Multi-dimension Arrays

local x: int[][] = { {0, 1}, {0, 4} };
local y: int[][] = new int[3][4];
local w: int[] = x[0];
local z: int = x[0][0];

Arrays can have multiple dimensions in Virgil. Such multi-dimensional arrays are represented as arrays of arrays. Array literal expressions allow nesting of multiple array literals; new expressions allow multiple dimensions to be specified. Accesses to multiple dimensional arrays are then straightforward; the left part of the expression represents the selection of which of the nested arrays to acccess, and the rightmost part specifies the element of that array to access.

Strings as Arrays of Characters

local x: char[] = "str";
local y: char[] = { 's', 't', 'r' };

Strings are represented as character arrays of fixed length in Virgil. The syntax for declaring string literals is in fact just a shorthand for writing out a character array literal.

Go back to the tutorial.