[[painless-operators-array]] === Operators: Array [[array-initialization-operator]] ==== Array Initialization Use the `array initialization operator '[] {}'` to allocate a single-dimensional <> instance to the heap with a set of pre-defined elements. Each value used to initialize an element in the array type instance is cast to the specified element type value upon insertion. The order of specified values is maintained. *Errors* * If a value is not castable to the specified type value. *Grammar* [source,ANTLR4] ---- array_initialization: 'new' TYPE '[' ']' '{' expression_list '}' | 'new' TYPE '[' ']' '{' '}'; expression_list: expression (',' expression); ---- *Example:* * Array initialization with static values. + [source,Painless] ---- <1> int[] x = new int[] {1, 2, 3}; ---- + <1> declare `int[] x`; allocate `1-d int array` instance with `length [3]` -> `1-d int array reference`; store `int 1` to `index [0]` of `1-d int array reference`; store `int 2` to `index [1]` of `1-d int array reference`; store `int 3` to `index [2]` of `1-d int array reference`; store `1-d int array reference` to `x`; + * Array initialization with non-static values. + [source,Painless] ---- <1> int i = 1; <2> long l = 2L; <3> float f = 3.0F; <4> double d = 4.0; <5> String s = "5"; <6> def array = new def[] {i, l, f*d, s}; ---- + <1> declare `int i`; store `int 1` to `i` <2> declare `long l`; store `long 2` to `l` <3> declare `float f`; store `float 3.0` to `f` <4> declare `double d`; store `double 4.0` to `d` <5> declare `String s`; store `String "5"` to `s` <6> declare `def array`; allocate `1-d def array` instance with `length [4]` -> `1-d def array reference`; load from `i` -> `int 1`; implicit cast `int 1` to `def` -> `def`; store `def` to `index [0]` of `1-d def array reference`; load from `l` -> `long 2`; implicit cast `long 2` to `def` -> `def`; store `def` to `index [1]` of `1-d def array reference`; load from `f` -> `float 3.0`; load from `d` -> `double 4.0`; promote `float 3.0` and `double 4.0`: result `double`; implicit cast `float 3.0` to `double 3.0` -> `double 3.0`; multiply `double 3.0` and `double 4.0` -> `double 12.0`; implicit cast `double 12.0` to `def` -> `def`; store `def` to `index [2]` of `1-d def array reference`; load from `s` -> `String "5"`; implicit cast `String "5"` to `def` -> `def`; store `def` to `index [3]` of `1-d def array reference`; implicit cast `1-d int array reference` to `def` -> `def`; store `def` to `array` [[array-access-operator]] ==== Array Access Use the `array access operator '[]'` to store a value to or load a value from an <> value. Each element of an array type value is accessed with an `int` type value to specify the index to store/load. The range of elements within an array that are accessible is `[0, size)` where size is the number of elements specified at the time of allocation. Use a negative `int` type value as an index to access an element in reverse from the end of an array type value within a range of `[-size, -1]`. *Errors* * If a value other than an `int` type value or a value that is castable to an `int` type value is provided as an index. * If an element is accessed outside of the valid ranges. *Grammar* [source,ANTLR4] ---- brace_access: '[' expression ']' ---- *Examples* * Array access with a single-dimensional array. + [source,Painless] ---- <1> int[] x = new int[2]; <2> x[0] = 2; <3> x[1] = 5; <4> int y = x[0] + x[1]; <5> int z = 1; <6> int i = x[z]; ---- + <1> declare `int[] x`; allocate `1-d int array` instance with `length [2]` -> `1-d int array reference`; store `1-d int array reference` to `x` <2> load from `x` -> `1-d int array reference`; store `int 2` to `index [0]` of `1-d int array reference`; <3> load from `x` -> `1-d int array reference`; store `int 5` to `index [1]` of `1-d int array reference`; <4> declare `int y`; load from `x` -> `1-d int array reference`; load from `index [0]` of `1-d int array reference` -> `int 2`; load from `x` -> `1-d int array reference`; load from `index [1]` of `1-d int array reference` -> `int 5`; add `int 2` and `int 5` -> `int 7`; store `int 7` to `y` <5> declare `int z`; store `int 1` to `z`; <6> declare `int i`; load from `x` -> `1-d int array reference`; load from `z` -> `int 1`; load from `index [1]` of `1-d int array reference` -> `int 5`; store `int 5` to `i`; + * Array access with the `def` type. + [source,Painless] ---- <1> def d = new int[2]; <2> d[0] = 2; <3> d[1] = 5; <4> def x = d[0] + d[1]; <5> def y = 1; <6> def z = d[y]; ---- + <1> declare `def d`; allocate `1-d int array` instance with `length [2]` -> `1-d int array reference`; implicit cast `1-d int array reference` to `def` -> `def`; store `def` to `d` <2> load from `d` -> `def` implicit cast `def` to `1-d int array reference` -> `1-d int array reference`; store `int 2` to `index [0]` of `1-d int array reference`; <3> load from `d` -> `def` implicit cast `def` to `1-d int array reference` -> `1-d int array reference`; store `int 5` to `index [1]` of `1-d int array reference`; <4> declare `int x`; load from `d` -> `def` implicit cast `def` to `1-d int array reference` -> `1-d int array reference`; load from `index [0]` of `1-d int array reference` -> `int 2`; load from `d` -> `def` implicit cast `def` to `1-d int array reference` -> `1-d int array reference`; load from `index [1]` of `1-d int array reference` -> `int 5`; add `int 2` and `int 5` -> `int 7`; implicit cast `int 7` to `def` -> `def`; store `def` to `x` <5> declare `def y`; implicit cast `int 1` to `def` -> `def`; store `def` to `y`; <6> declare `int i`; load from `d` -> `def` implicit cast `def` to `1-d int array reference` -> `1-d int array reference`; load from `y` -> `def`; implicit cast `def` to `int 1` -> `int 1`; load from `index [1]` of `1-d int array reference` -> `int 5`; implicit cast `int 5` to `def`; store `def` to `z`; + * Array access with a multi-dimensional array. + [source,Painless] ---- <1> int[][][] ia3 = new int[2][3][4]; <2> ia3[1][2][3] = 99; <3> int i = ia3[1][2][3]; ---- + <1> declare `int[][][] ia`; allocate `3-d int array` instance with length `[2, 3, 4]` -> `3-d int array reference`; store `3-d int array reference` to `ia3` <2> load from `ia3` -> `3-d int array reference`; store `int 99` to `index [1, 2, 3]` of `3-d int array reference` <3> declare `int i`; load from `ia3` -> `3-d int array reference`; load from `index [1, 2, 3]` of `3-d int array reference` -> `int 99`; store `int 99` to `i` [[array-length-operator]] ==== Array Length An array type value contains a read-only member field named `length`. The `length` field stores the size of the array as an `int` type value where size is the number of elements specified at the time of allocation. Use the <> to load the field `length` from an array type value. *Examples* * Access the `length` field. + [source,Painless] ---- <1> int[] x = new int[10]; <2> int l = x.length; ---- <1> declare `int[] x`; allocate `1-d int array` instance with `length [2]` -> `1-d int array reference`; store `1-d int array reference` to `x` <2> declare `int l`; load `x` -> `1-d int array reference`; load `length` from `1-d int array reference` -> `int 10`; store `int 10` to `l`; [[new-array-operator]] ==== New Array Use the `new array operator 'new []'` to allocate an array type instance to the heap. Specify the element type following the `new` token. Specify each dimension with the `[` and `]` tokens following the element type name. The size of each dimension is specified by an `int` type value in between each set of `[` and `]` tokens. *Errors* * If a value other than an `int` type value or a value that is castable to an `int` type value is specified for a dimension's size. *Grammar* [source,ANTLR4] ---- new_array: 'new' TYPE ('[' expression ']')+; ---- *Examples* * Allocation of different array types. + [source,Painless] ---- <1> int[] x = new int[5]; <2> x = new int[10]; <3> int y = 2; <4> def z = new def[y][y*2]; ---- + <1> declare `int[] x`; allocate `1-d int array` instance with `length [5]` -> `1-d int array reference`; store `1-d int array reference` to `x` <2> allocate `1-d int array` instance with `length [10]` -> `1-d int array reference`; store `1-d int array reference` to `x` <3> declare `int y`; store `int 2` to `y`; <4> declare `def z`; load from `y` -> `int 2 @0`; load from `y` -> `int 2 @1`; multiply `int 2 @1` by `int 2 @2` -> `int 4`; allocate `2-d int array` instance with length `[2, 4]` -> `2-d int array reference`; implicit cast `2-d int array reference` to `def` -> `def`; store `def` to `z`;