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

v

the loop variable.

start

its first value.

end

its last value.

increment

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: v is a scalar variable, and start, end and increment are all present and scalar, each of exactly the type and kind of v. A step of one is written out as a constant 1 of that type; where the source mixes kinds, such as do i = 1_8, n with an integer(4) :: i, the expression is wrapped in an explicit Cast to the type of v; or

  • the head of an infinite loop, do ... end do, with all four members nil. 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
)

See Also

DoLoop, DoConcurrentLoop, ForAllSingle