# loki.ir.pragma_utils

Functions

`attach_pragma_regions`(ir) | Create `PragmaRegion` node objects for all matching pairs of region pragmas.
`attach_pragmas`(ir, node_type[, ...]) | Find pragmas and merge them onto the given node type(s).
`detach_pragma_regions`(ir) | Remove any `PragmaRegion` node objects and replace each with a tuple of `(r.pragma, r.body, r.pragma_post)`, where `r` is the `PragmaRegion` node object.
`detach_pragmas`(ir, node_type[, ...]) | Revert the inlining of pragmas, e.g. as done by `attach_pragmas`.
`get_matching_region_pragmas`(pragmas) | Given a list of `Pragma` objects return a list of matching pairs that define a pragma region.
`get_pragma_command_and_parameters`(pragma[, ...]) | Parse a pragma in the form
`get_pragma_parameters`(pragma[, starts_with, ...]) | Parse the pragma content for parameters in the form `<command>[(<arg>)]` and return them as a map `{<command>: <arg> or None}`.
`is_loki_pragma`(pragma[, starts_with]) | Checks for a pragma annotation and, if it exists, for the `loki` keyword.
`pragma_regions_attached`(module_or_routine) | Create a context in which `PragmaRegion` node objects are inserted into the IR to define code regions marked by matching pairs of pragmas.
`pragmas_attached`(module_or_routine, node_type) | Create a context in which pragmas preceding nodes of given type(s) inside the module's or routine's IR are attached to these nodes.
`process_dimension_pragmas`(ir[, scope]) | Process any `!$loki dimension` pragmas to override deferred dimensions

Classes

`PragmaAttacher`(node_type[, attach_pragma_post]) | Utility visitor that finds pragmas preceding (or optionally also trailing) nodes of given types and attaches them to these nodes as `pragma` property.
`PragmaDetacher`(node_type[, detach_pragma_post]) | Utility visitor that detaches inlined pragmas from nodes of given types and inserts them before/after the nodes into the IR.
`PragmaParameters`() | Utility class to parse strings for parameters in the form `<command>[(<arg>)]` and return them as a map `{<command>: <arg> or None}`.
`PragmaRegionAttacher`([pragma_pairs]) | Utility transformer that inserts `PragmaRegion` objects to mark code section between matching `Pragma` pairs.
`PragmaRegionDetacher`([mapper, ...]) | Remove any `PragmaRegion` node objects and insert the tuple of `(r.pragma, r.body, r.pragma_post)` in the enclosing tuple.

is_loki_pragma(pragma, starts_with=None)

  Checks for a pragma annotation and, if it exists, for the `loki` keyword. Optionally, the pragma content is tested for a specific start.

  Parameters:

    - pragma (`Pragma` or list/tuple of `Pragma` or None) – the pragma or list of pragmas to check.

    - starts_with (str, optional) – the keyword the pragma content must start with.

get_pragma_parameters(pragma, starts_with=None, only_loki_pragmas=True)

  Parse the pragma content for parameters in the form `<command>[(<arg>)]` and return them as a map `{<command>: <arg> or None}`.

  Optionally, look only at the pragma with the given keyword at the beginning.

  Note that if multiple pragma are given as a tuple/list, arguments with the same name will overwrite previous definitions.

  Parameters:

    - pragma (`Pragma` or list/tuple of `Pragma` or None) – the pragma or list of pragmas to check.

    - starts_with (str, optional) – the keyword the pragma content should start with.

    - only_loki_pragmas (bool, optional) – restrict parameter extraction to `loki` pragmas only.

  Returns:

    Mapping of parameters `{<command>: <arg> or <None>}` with the values being a list when multiple entries have the same key

  Return type:

    dict

process_dimension_pragmas(ir, scope=None)

  Process any `!$loki dimension` pragmas to override deferred dimensions

  Note that this assumes `attach_pragmas` has been run on `ir` to attach any pragmas to the `VariableDeclaration` nodes.

  Parameters:

    ir (`Node`) – Root node of the (section of the) internal representation to process

attach_pragmas(ir, node_type, attach_pragma_post=True)

  Find pragmas and merge them onto the given node type(s).

  This can be done for all IR nodes that have a `pragma` property (`VariableDeclaration`, `Loop`, `WhileLoop`, `CallStatement`). Optionally, attaching pragmas after nodes as `pragma_post` can be disabled by setting `attach_pragma_post` to False (relevant only for `Loop` and `WhileLoop`).

  Note

  Pragmas are not discovered by `FindNodes` while attached to IR nodes.

  This is implemented using `PragmaAttacher`. Therefore, the IR is not rebuilt but updated and existing references should remain valid.

  Parameters:

    - ir (`Node`) – the root of (a section of the) intermediate representation in which pragmas are to be attached.

    - node_type (list) – the (list of) `Node` types pragmas should be attached to.

    - attach_pragma_post (bool, optional) – process `pragma_post` attachments.

detach_pragmas(ir, node_type, detach_pragma_post=True)

  Revert the inlining of pragmas, e.g. as done by `attach_pragmas`.

  This can be done for all IR nodes that have a `pragma` property (:class:`Declaration`, :class:`Loop`, :class:`WhileLoop`, :class:``CallStatement`). Optionally, detaching of pragmas after nodes (for nodes with a `pragma_post` property) can be disabled by setting `detach_pragma_post` to False (relevant only for `Loop` and `WhileLoop`).

  This is implemented using `PragmaDetacher`. Therefore, the IR is not rebuilt but updated and existing references should remain valid.

  Parameters:

    - ir (`Node`) – the root node of the (section of the) intermediate representation in which pragmas are to be detached.

    - node_type – the (list of) `Node` types that pragmas should be detached from.

    - detach_pragma_post (bool, optional) – process `pragma_post` attachments.

pragmas_attached(module_or_routine, node_type, attach_pragma_post=True)

  Create a context in which pragmas preceding nodes of given type(s) inside the module’s or routine’s IR are attached to these nodes.

  This can be done for all IR nodes that have a `pragma` property (`VariableDeclaration`, `ProcedureDeclaration`, `Loop`, `WhileLoop`, `CallStatement`). Inside the created context, attached pragmas are no longer standalone IR nodes but accessible via the corresponding node’s `pragma` property.

  Pragmas after nodes are attached as `pragma_post`, which can be disabled by setting `attach_pragma_post` to False (for `Loop` and `WhileLoop`).

  Note

  Pragmas are not discovered by `FindNodes` while attached to IR nodes.

  When leaving the context all pragmas for nodes of the given type are detached, irrespective of whether they had already been attached or not when entering the context.

  Note

  Pragma attachment is only done for the object itself (i.e. its spec and body), not for any contained subroutines.

  This is implemented using `PragmaAttacher` and `PragmaDetacher`, respectively. Therefore, the IR is not rebuilt but updated and existing references should remain valid when entering the context and stay valid beyond exiting the context.

  Example:

      loop_of_interest = None
      with pragmas_attached(routine, Loop):
          for loop in FindNodes(Loop).visit(routine.body):
              if is_loki_pragma(loop.pragma, starts_with='foobar'):
                  loop_of_interest = loop
                  break
      # Do something with that loop
      loop_body = loop_of_interest.body
      # Note that loop_body.pragma == None!

  Parameters:

    - module_or_routine (`Module` or `Subroutine`) – the program unit in which pragmas are to be inlined.

    - node_type – the (list of) `Node` types, that pragmas should be attached to.

    - attach_pragma_post (bool, optional) – process `pragma_post` attachments.

attach_pragma_regions(ir)

  Create `PragmaRegion` node objects for all matching pairs of region pragmas.

  Matching pragma pairs are assumed to be of the form `!$<keyword> <marker>` and `!$<keyword> end <marker>`.

  The defining `Pragma` nodes are accessible via the `pragma` and `pragma_post` attributes of the region object. Insertion is performed in-place, without rebuilding any IR nodes.

detach_pragma_regions(ir)

  Remove any `PragmaRegion` node objects and replace each with a tuple of `(r.pragma, r.body, r.pragma_post)`, where `r` is the `PragmaRegion` node object.

  All replacements are performed in-place, without rebuilding any IR nodes.

pragma_regions_attached(module_or_routine)

  Create a context in which `PragmaRegion` node objects are inserted into the IR to define code regions marked by matching pairs of pragmas.

  Matching pragma pairs are assumed to be of the form `!$<keyword> <marker>` and `!$<keyword> end <marker>`.

  In the resulting context `FindNodes(PragmaRegion).visit(ir)` can be used to select code regions marked by pragma pairs as node objects.

  The defining `Pragma` nodes are accessible via the `pragma` and `pragma_post` attributes of the region object. Importantly, Pragmas are not discovered by `FindNodes` while attached to IR nodes.

  When leaving the context all `PragmaRegion` objects are replaced with a tuple of `(r.pragma, r.body, r.pragma_post)`, where `r` is the `PragmaRegion` node object.

  Throughout the setup and teardown of the context IR nodes are only updated, never rebuild, meaning node mappings from inside the context are valid outside of it.

  Example:

      with pragma_regions_attached(routine):
          for region in FindNodes(PragmaRegion).visit(routine.body):
              if is_loki_pragma(region.pragma, starts_with='foobar'):
                  <transform code in region.body>

  Parameters:

    module_or_routine (`Module` or `Subroutine` in) – which `PragmaRegion` objects are to be inserted.

class PragmaAttacher(node_type, attach_pragma_post=True)

  Bases: `Visitor`

  Utility visitor that finds pragmas preceding (or optionally also trailing) nodes of given types and attaches them to these nodes as `pragma` property.

  Note that this operates by updating (instead of rebuilding) the relevant nodes, thus only nodes to which pragmas are attached get modified and the tree as a whole is not modified if no pragmas are found. This means existing node references should remain valid.

  Note

  When using `attach_pragma_post` and two nodes qualifying according to `node_type` are separated only by `Pragma` nodes inbetween, it is not possible to decide to which node these pragmas belong. In such cases, they are attached to the second node as `pragma` property takes precedence. Such situations can only be resolved by full knowledge about the pragma language specification (_way_ out of scope) or modifying the original source, e.g. by inserting a comment between the relevant pragmas.

  Parameters:

    - node_type – the IR node type (or a list of them) to attach pragmas to.

    - attach_pragma_post (bool, optional) – look for pragmas after the node, too, and attach as `pragma_post` if applicable.

  visit_tuple(o, **kwargs)

    Visit all elements in a tuple and return the results as a tuple.

  visit_list(o, **kwargs)

    Visit all elements in a tuple and return the results as a tuple.

  visit_Node(o, **kwargs)

    Visit all children of a `Node`.

  visit_object(o, **kwargs)

    Fallback method for objects that do not match any handler.

    Parameters:

      - o – The object to visit.

      - **kwargs – Optional keyword arguments passed to the visit methods.

    Returns:

      The default return value.

    Return type:

      `GenericVisitor.default_retval()`

class PragmaDetacher(node_type, detach_pragma_post=False)

  Bases: `Visitor`

  Utility visitor that detaches inlined pragmas from nodes of given types and inserts them before/after the nodes into the IR.

  Note that this operates by updating (instead of rebuilding) the relevant nodes, thus only nodes to which pragmas are attached get modified and the tree as a whole is not modified if no pragmas are found. This means existing node references should remain valid.

  Parameters:

    - node_type – the IR node type (or a list of them) to detach pragmas from.

    - detach_pragma_post (bool, optional) – detach `pragma_post` properties, if applicable.

  visit_tuple(o, **kwargs)

    Visit all elements in a tuple and return the results as a tuple.

  visit_list(o, **kwargs)

    Visit all elements in a tuple and return the results as a tuple.

  visit_Node(o, **kwargs)

    Visit all children of a `Node`.

  visit_object(o, **kwargs)

    Fallback method for objects that do not match any handler.

    Parameters:

      - o – The object to visit.

      - **kwargs – Optional keyword arguments passed to the visit methods.

    Returns:

      The default return value.

    Return type:

      `GenericVisitor.default_retval()`

get_pragma_command_and_parameters(pragma, only_loki_pragmas=True)

  Parse a pragma in the form

  `!$loki [end] command [param] [param_with_val(val)]`

  and return `command, {param: None, param_with_val: val}`

  Parameters:

    pragma (`Pragma`) – the pragma to parse and return parameters

  Returns:

    tuple being (command, parameters as dictionary)

  Return type:

    tuple(str, dict)