Function

A function or a subroutine, with or without a body.

Declaration

Syntax

Function(symbol_table symtab, identifier name,
    ttype function_signature, identifier* dependencies, expr* args,
    stmt* body, expr? return_var, access access, bool deterministic,
    bool side_effect_free, string? module_file, location start_name,
    location end_name)

Arguments

Argument

Description

symtab

the symbol table of the procedure: its dummy arguments, its result variable and its local variables.

name

the name of the procedure.

function_signature

a FunctionType giving the argument types, the result type (nil for a subroutine), the ABI and the attributes (elemental, pure, module, …).

dependencies

the names of the symbols the body refers to.

args

the dummy arguments, as Var expressions pointing into symtab. The order is the calling order.

body

the statements of the procedure. Empty for an interface (deftype=Interface) and for an external procedure.

return_var

the result variable of a function, as a Var; nil for a subroutine.

access

Public or Private, from the module’s access specification.

deterministic

true when the procedure returns the same result for the same arguments. Reserved for optimizations that need to duplicate or eliminate calls.

side_effect_free

true when a call has no effect other than its result. Reserved for the same optimizations.

module_file

the module file the procedure was loaded from, when it was; nil otherwise.

start_name

the source span of the name in the function or subroutine statement.

end_name

the source span of the name in the matching end statement.

Return values

None.

Description

One constructor represents both Fortran functions and Fortran subroutines. A subroutine is a Function whose return_var is nil and whose function_signature has no return_var_type; it is called by SubroutineCall rather than by FunctionCall.

The dummy arguments appear twice: in symtab, which owns the Variable symbols, and in args, which fixes their order. The result variable of a function is likewise owned by symtab, with intent=ReturnVar, and referenced by return_var.

deterministic and side_effect_free are declarations about the procedure, not consequences of its body. A frontend that cannot prove them must leave them false.

Examples

An ASR text document that uses it:

(TranslationUnit
  :symtab (SymbolTable
    :id 0
    :symbols {
      "m" (Module
        :symtab (SymbolTable
          :id 1
          :symbols {
            "add" (Function
              :symtab (SymbolTable
                :id 2
                :symbols {
                  "a" (Variable
                    :parent_symtab 2
                    :name "a"
                    :dependencies []
                    :intent :In
                    :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 []
                  )
                  "b" (Variable
                    :parent_symtab 2
                    :name "b"
                    :dependencies []
                    :intent :In
                    :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 []
                  )
                  "c" (Variable
                    :parent_symtab 2
                    :name "c"
                    :dependencies []
                    :intent :ReturnVar
                    :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 []
                  )
                }
              )
              :name "add"
              :function_signature (FunctionType
                :arg_types [
                  (Integer
                    :kind 4
                  )
                  (Integer
                    :kind 4
                  )
                ]
                :return_var_type (Integer
                  :kind 4
                )
                :abi :Source
                :deftype :Implementation
                :bindc_name nil
                :elemental false
                :pure false
                :module false
                :inline false
                :static false
                :restrictions []
                :is_restriction false
              )
              :dependencies []
              :args [
                (Var
                  :v (SymbolRef 2 "a")
                )
                (Var
                  :v (SymbolRef 2 "b")
                )
              ]
              :body [
                (Assignment
                  :target (Var
                    :v (SymbolRef 2 "c")
                  )
                  :value (IntegerBinOp
                    :left (Var
                      :v (SymbolRef 2 "a")
                    )
                    :op :Add
                    :right (Var
                      :v (SymbolRef 2 "b")
                    )
                    :type (Integer
                      :kind 4
                    )
                    :value nil
                  )
                  :overloaded nil
                  :realloc_lhs false
                  :move_allocation false
                )
              ]
              :return_var (Var
                :v (SymbolRef 2 "c")
              )
              :access :Public
              :deterministic false
              :side_effect_free false
              :module_file nil
            )
          }
        )
        :name "m"
        :parent_module nil
        :dependencies []
        :loaded_from_mod false
        :intrinsic false
        :has_submodules false
      )
      "main" (Program
        :symtab (SymbolTable
          :id 3
          :symbols {}
        )
        :name "main"
        :dependencies []
        :body []
      )
    }
  )
  :items []
)

See Also

Module, Variable, FunctionCall, SubroutineCall, FunctionType