do_loop_head¶
The control of a counted loop.
Declaration¶
Syntax¶
do_loop_head = (expr? v, expr? start, expr? end, expr? increment)
Arguments¶
Argument |
Description |
|---|---|
|
the loop variable. |
|
its first value. |
|
its last value. |
|
the step. |
Return values¶
None.
Description¶
Shared by DoLoop, DoConcurrentLoop and ForAllSingle, so that one form of loop control serves all three.
The trip count is computed from start, end and increment before the
first iteration. A head whose members are all nil is an infinite loop.
Normalized form¶
Every head is in a normalized form, so that passes and backends lower it as given, without supplying a default step or converting types themselves. The verifier checks that each head of a DoLoop, DoConcurrentLoop and ForAllSingle is either
a counted head:
vis a scalar variable, andstart,endandincrementare all present and scalar, each of exactly the type and kind ofv. A step of one is written out as a constant1of that type; where the source mixes kinds, such asdo i = 1_8, nwith aninteger(4) :: i, the expression is wrapped in an explicit Cast to the type ofv; orthe head of an infinite loop,
do ... end do, with all four membersnil. Only a DoLoop may have it.
v is usually an integer, but has to agree only with the other three, so the
deleted feature of a real DO variable, which the frontend still accepts,
gives a head of that real type.
Code that creates a loop builds the head with
ASRUtils::make_DoLoop_t_util, ASRUtils::make_DoConcurrentLoop_t_util,
ASRUtils::make_ForAllSingle_t_util or ASRBuilder::DoLoop, which normalize
it (ASRUtils::normalize_do_loop_head), rather than with the generated
ASR::make_*_t constructors. ASR written as text has to spell out the
normalized form, including the increment.
Examples¶
(do_loop_head
:v (Var
:v (SymbolRef 1 "i")
)
:start (IntegerConstant
:n 1
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:end (IntegerConstant
:n 10
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:increment (IntegerConstant
:n 1
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
)
It comes from this complete ASR text document:
(TranslationUnit
:symtab (SymbolTable
:id 0
:symbols {
"main" (Program
:symtab (SymbolTable
:id 1
:symbols {
"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_asynchronous false
:is_protected false
:pass_attr :NotMethod
:self_argument nil
:codims []
:common_block nil
)
"j" (Variable
:parent_symtab 1
:name "j"
: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_asynchronous false
:is_protected false
:pass_attr :NotMethod
:self_argument nil
:codims []
:common_block nil
)
"p" (Variable
:parent_symtab 1
:name "p"
: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_asynchronous false
:is_protected false
:pass_attr :NotMethod
:self_argument nil
:codims []
:common_block nil
)
}
)
:name "main"
:dependencies []
:body [
(DoLoop
:name "loop"
:head (do_loop_head
:v (Var
:v (SymbolRef 1 "i")
)
:start (IntegerConstant
:n 1
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:end (IntegerConstant
:n 10
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:increment (IntegerConstant
:n 1
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
)
:body [
(If
:name nil
:test (IntegerCompare
:left (Var
:v (SymbolRef 1 "i")
)
:op :Eq
:right (IntegerConstant
:n 5
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:type (Logical
:kind 4
)
:value nil
)
:body [
(Cycle
:stmt_name "loop"
)
]
:orelse []
)
(If
:name nil
:test (Var
:v (SymbolRef 1 "p")
)
:body [
(Exit
:stmt_name "loop"
)
]
:orelse [
(Assignment
:target (Var
:v (SymbolRef 1 "j")
)
:value (Var
:v (SymbolRef 1 "i")
)
:overloaded nil
:realloc_lhs false
:move_allocation false
:new_target false
:new_allocation false
)
]
)
]
:orelse []
)
(WhileLoop
:name nil
:test (IntegerCompare
:left (Var
:v (SymbolRef 1 "j")
)
:op :Lt
:right (IntegerConstant
:n 100
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:type (Logical
:kind 4
)
:value nil
)
:body [
(Assignment
:target (Var
:v (SymbolRef 1 "j")
)
:value (IntegerBinOp
:left (Var
:v (SymbolRef 1 "j")
)
:op :Add
:right (IntegerConstant
:n 1
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:type (Integer
:kind 4
)
:value nil
)
:overloaded nil
:realloc_lhs false
:move_allocation false
:new_target false
:new_allocation false
)
]
:orelse []
)
(Assert
:test (IntegerCompare
:left (Var
:v (SymbolRef 1 "j")
)
:op :GtE
:right (IntegerConstant
:n 0
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:type (Logical
:kind 4
)
:value nil
)
:msg (StringConstant
:s "j is not negative"
:type (String
:kind 1
:len (IntegerConstant
:n 17
:type (Integer
:kind 4
)
:intboz_type :Decimal
)
:len_kind :ExpressionLength
:physical_type :DescriptorString
)
)
)
]
:global_init nil
)
}
)
:items []
:global_init nil
)