ArrayItem¶
One element of an array.
Declaration¶
Syntax¶
ArrayItem(expr v, array_index* args, ttype type,
arraystorage storage_format, expr? value, bool in_bounds)
Arguments¶
Argument |
Описание |
|---|---|
|
the array. |
|
one array_index per dimension, each with only |
|
the type of the element. |
|
the element order of the array; see arraystorage. |
|
the compile time value of the expression, when the frontend could fold it; |
|
|
Return values¶
The value of the expression.
Описание¶
a(i, j). The result is a scalar of the element type, which is what
distinguishes it from ArraySection: a section keeps the
array type.
Subscripts are as written, so an array declared a(2:5) is indexed from two.
A backend subtracts the lower bound itself, using the dims of the array
type.
With runtime bounds checking, a backend checks every subscript of an element
reference against the bounds of v. A pass that creates the reference can
set in_bounds when the subscript cannot be out of bounds, and the check is
then omitted. The frontend sets it when every subscript is a compile-time
constant and the array, neither allocatable nor a pointer, has compile-time
constant bounds in every dimension, as for a(2, 3) with a(8, 4); a
constant subscript outside such bounds is a compile-time error. A reference
into an assumed-shape, assumed-size, allocatable or pointer array, or with a
subscript that is not a constant, is still checked. The array_op pass sets it in
the loops it creates for an array assignment: for the operand whose bounds
the loops run over, and for every operand whose shape a preceding
DebugCheckArrayBounds compares
with the target, or whose extents are compile-time constants equal to those
of the target (the check is then omitted). With a runtime check the claim
holds only because that check stops the program on a mismatch, so a backend
that honors in_bounds must also implement DebugCheckArrayBounds.
A section target such as a(:, i) is assigned through its base array, with
the loops running over its subscript triplets. Its element references are
marked when the end of every triplet is known to lie within the bounds of
a, for example a bound of a itself, and the subscripts of the first
element, the starts of the triplets and the scalar subscripts, are known to
as well. With bounds checking, array_op checks the latter once instead,
by referencing that element before the loops if the section is not empty.
Examples¶
(ArrayItem
:v (Var
:v (SymbolRef 1 "a")
)
:args [
(array_index
:left nil
:right (IntegerConstant
:n 2
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:step nil
)
]
:type (Integer
:kind 4
)
:storage_format :ColMajor
:value nil
:in_bounds false
)
It comes from this complete ASR text document:
(TranslationUnit
:symtab (SymbolTable
:id 0
:symbols {
"main" (Program
:symtab (SymbolTable
:id 1
:symbols {
"a" (Variable
:parent_symtab 1
:name "a"
:dependencies []
:intent :Local
:symbolic_value nil
:value nil
:storage :Default
:type (Array
:type (Integer
:kind 4
)
:dims [
(dimension
:start (IntegerConstant
:n 1
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:length (IntegerConstant
:n 3
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
)
]
:physical_type :FixedSizeArray
:memory_space :Global
)
:type_declaration nil
:abi :Source
:access :Public
:presence :Required
:value_attr false
:target_attr false
:contiguous_attr false
:bindc_name nil
:is_volatile false
:is_protected false
:pass_attr :NotMethod
:self_argument nil
:codims []
:common_block nil
)
"b" (Variable
:parent_symtab 1
:name "b"
:dependencies []
:intent :Local
:symbolic_value nil
:value nil
:storage :Default
:type (Array
:type (Integer
:kind 4
)
:dims [
(dimension
:start (IntegerConstant
:n 1
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:length (IntegerConstant
:n 3
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
)
]
:physical_type :FixedSizeArray
:memory_space :Global
)
:type_declaration nil
:abi :Source
:access :Public
:presence :Required
:value_attr false
:target_attr false
:contiguous_attr false
:bindc_name nil
:is_volatile false
:is_protected false
:pass_attr :NotMethod
:self_argument nil
:codims []
:common_block nil
)
"i" (Variable
:parent_symtab 1
:name "i"
:dependencies []
:intent :Local
:symbolic_value nil
:value nil
:storage :Default
:type (Integer
:kind 4
)
:type_declaration nil
:abi :Source
:access :Public
:presence :Required
:value_attr false
:target_attr false
:contiguous_attr false
:bindc_name nil
:is_volatile false
:is_protected false
:pass_attr :NotMethod
:self_argument nil
:codims []
:common_block nil
)
"l" (Variable
:parent_symtab 1
:name "l"
:dependencies []
:intent :Local
:symbolic_value nil
:value nil
:storage :Default
:type (Logical
:kind 4
)
:type_declaration nil
:abi :Source
:access :Public
:presence :Required
:value_attr false
:target_attr false
:contiguous_attr false
:bindc_name nil
:is_volatile false
:is_protected false
:pass_attr :NotMethod
:self_argument nil
:codims []
:common_block nil
)
}
)
:name "main"
:dependencies []
:body [
(Assignment
:target (Var
:v (SymbolRef 1 "a")
)
:value (ArrayConstant
:n_data 12
:data #asr/bytes "010000000200000003000000"
:type (Array
:type (Integer
:kind 4
)
:dims [
(dimension
:start (IntegerConstant
:n 1
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:length (IntegerConstant
:n 3
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
)
]
:physical_type :FixedSizeArray
:memory_space :Global
)
:storage_format :ColMajor
)
:overloaded nil
:realloc_lhs false
:move_allocation false
)
(Assignment
:target (Var
:v (SymbolRef 1 "i")
)
:value (ArrayItem
:v (Var
:v (SymbolRef 1 "a")
)
:args [
(array_index
:left nil
:right (IntegerConstant
:n 2
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:step nil
)
]
:type (Integer
:kind 4
)
:storage_format :ColMajor
:value nil
:in_bounds false
)
:overloaded nil
:realloc_lhs false
:move_allocation false
)
(Assignment
:target (Var
:v (SymbolRef 1 "b")
)
:value (ArraySection
:v (Var
:v (SymbolRef 1 "a")
)
:args [
(array_index
:left (IntegerConstant
:n 1
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:right (IntegerConstant
:n 3
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:step (IntegerConstant
:n 1
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
)
]
:type (Array
:type (Integer
:kind 4
)
:dims [
(dimension
:start (IntegerConstant
:n 1
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:length (IntegerConstant
:n 3
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
)
]
:physical_type :DescriptorArray
:memory_space :Global
)
:value nil
)
:overloaded nil
:realloc_lhs false
:move_allocation false
)
(Assignment
:target (Var
:v (SymbolRef 1 "i")
)
:value (ArraySize
:v (Var
:v (SymbolRef 1 "a")
)
:dim (IntegerConstant
:n 1
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:type (Integer
:kind 4
)
:value nil
)
:overloaded nil
:realloc_lhs false
:move_allocation false
)
(Assignment
:target (Var
:v (SymbolRef 1 "i")
)
:value (ArrayRank
:v (Var
:v (SymbolRef 1 "a")
)
:type (Integer
:kind 4
)
:value nil
)
:overloaded nil
:realloc_lhs false
:move_allocation false
)
(Assignment
:target (Var
:v (SymbolRef 1 "i")
)
:value (ArrayBound
:v (Var
:v (SymbolRef 1 "a")
)
:dim (IntegerConstant
:n 1
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:type (Integer
:kind 4
)
:bound :UBound
:value nil
)
:overloaded nil
:realloc_lhs false
:move_allocation false
)
(Assignment
:target (Var
:v (SymbolRef 1 "l")
)
:value (ArrayIsContiguous
:array (Var
:v (SymbolRef 1 "a")
)
:type (Logical
:kind 4
)
:value nil
)
:overloaded nil
:realloc_lhs false
:move_allocation false
)
]
:global_init nil
)
}
)
:items []
:global_init nil
)