fgen.fortran_parsing#

Support for parsing Fortran type declarations

We just want to make this as helpful as possible when auto-generating our wrappers while keeping the implemenation here as minimal as possible because duplicating the Fortran implementation logic is not the point of this module. The fortran compiler will catch any odd type declarations at compile-time.

To understand what is going on, we start with the syntax for declaring fortran types as defined in Section 5.1 of the Fortran 2003 standard. It looks like the below:

R501 type-declaration-stmt  is declaration-type-spec [ [ , attr-spec ] ... :: ] entity-decl-list
R502 declaration-type-spec  is intrinsic-type-spec
                            or TYPE ( derived-type-spec )
                            or CLASS ( derived-type-spec )
                            or CLASS ( * )

In short, a type declaration statement is composed of a declaration type specification, a collection of one or more attribute specifications and then an entity declaration list. The declaration type specification can be either an intrinsic type that has been defined by the language, or a derived type which has been declared using a type block elsewhere.

We focus on the combination of the declaration type specification (which we typically shorten to type specification) and the attribute specifications i.e. we largely ignore the entity declarations. In the absence of a defined term in the Fortran standard, we call this combination the type attribute declaration throughout.

To illustrate, consider the following example

real(8), dimension(3), pointer :: heat_uptake

Here is how we would refer to the parts of this example:

  • type declaration statement: real(8), dimension(3), pointer :: heat_uptake

  • declaration type specification (or simply type specification): real(8)

  • attribute specifications: dimension(3), pointer

  • type attribute declaration: real(8), dimension(3), pointer

  • entity declaration (largely ignored by this module, we treat the double colon :: as part of the entity declaration): :: heat_uptake

One other example using a derived type

type(my_calculator) :: heat_uptake_calculator

Here is how we would refer to the parts of this example:

  • type declaration statement: type(my_calculator) :: heat_uptake_calculator

  • declaration type specification (or simply type specification): type(my_calculator)

  • attribute specifications: none

  • type attribute declaration (same as type specification in this case): type(my_calculator)

  • entity declaration (largely ignored by this module, we treat the double colon :: as part of the entity declaration): :: heat_uptake_calculator

Notes

Fortran type declaration statements (and Fortran in general) are case-insensitive

This module relies heavily on regular expressions. If needed, use an online tool like regex101.com to help you understand them.

SUPPORTED_TYPE_SPECIFICATIONS#

SUPPORTED_TYPE_SPECIFICATIONS: tuple[str, ...] = ('^INTEGER(\\(.*\\)|)$', '^REAL(\\(.*\\)|)$', '^COMPLEX(\\(.*\\)|)$', '^CHARACTER(\\(.*\\)|)$', '^LOGICAL(\\(.*\\)|)$', 'type\\(\\s?(?P<derived_type_name>[a-z0-9]+)\\s?\\)', 'integer\\(\\s?kind\\s?\\(\\s?(?P<enum_name>[a-z0-9]+)\\s?\\)\\s?\\)')#

The collection of valid type specifications that are supported

This covers both intrinsic type specifications and derived type specifications.

SUPPORTED_ATTRIBUTE_SPECIFICATIONS#

SUPPORTED_ATTRIBUTE_SPECIFICATIONS: tuple[Union[str, re.Pattern[str]], ...] = ('ALLOCATABLE', 'DIMENSION\\((?P<dimension>(\\*|:|[a-z0-9]+)(,\\s*(\\*|:|[a-z0-9]+))*)\\)', 'POINTER', 'TARGET')#

The collection of valid attribute specifications that are supported

In the type declaration, “type(my_calculator), pointer”, the attribute specification is “pointer” (the other part, “type(my_calculator)”, is simply the type specification (or declaration type specification if you’re being very precise))

Note that only a subset of valid attributes can be specified. The more esoteric attributes have been excluded until the use case for these attributes is better understood.

DimensionAttributeSpecification#

class DimensionAttributeSpecification(dimensions)[source]#

Bases: object

Dimension attribute specification

Defines the shape of a data type. See Section 5.1.2.5 of the Fortran 2003 standard for a description of the dimension attribute specification.

Currently, we only support explicit dimensions where the size of the dimension is explicitly declared at compile-time with an integer or execution-time using a variable provided to a procedure (e.g. using “n” which is a variable that is also provided to a procedure). The later form is an automatic explicit dimension and will rely upon the Fortran compiler to validate the attribute declaration since additional context is required about where the attribute is used.

Assumed-sized dimensions (“*”) are not currently supported.

dimensions: tuple[typing.Union[str, int], ...]#

Collection of dimensions of the attribute specification

Can include explicit dimensions (e.g. 5) or automatic explicit dimensions (e.g. “n”). Deferred dimensions (e.g. “:”) are allowed.

classmethod from_dimension_info(dimension_info)[source]#

Create a DimensionAttributeSpecification from the dimension information

The dimension information describes the shape and dimensionality of a variable.

Parameters:

dimension_info (str) –

The dimension information is the content between the () for a dimension attribute. For example, for an attribute “dimension(8, n)” the dimension_info would be “8, n”.

Static dimensions are converted to integers before initialising.

Returns:

fgen.fortran_parsing.DimensionAttributeSpecification – New DimensionAttributeSpecification

property ndim: int#

Number of dimensions of the attribute

FortranDataType#

class FortranDataType(type_specification, attribute_specifications)[source]#

Bases: object

A fortran data type including its attributes

See the docstring of fgen.fortran_parsing for further details on Fortran type declaration statements and how we handle and describe them.

We are only interested in the type attribute declaration so anything including and after a “::” should be stripped before initialising this class.

attribute_specifications: tuple[typing.Union[str, fgen.fortran_parsing.DimensionAttributeSpecification], ...]#

List of attribute specifications that apply to the Fortran data type

These are our internal representation of attribute specifications e.g. “pointer”, “target”, “dimension(3, 3)”

property base_python_type: str#

Determine the “base” Python type that represents the Fortran type declaration

This focuses on the base type (float, int, DerivedType etc.) and ignores the modification of this type from attributes such as “dimension” (which mean the ‘full’ python type is some sort of array or iterable). Such dimension handling is done in equivalent_python_type.

Returns:

  • The string representation of the python type

  • that is equivalent to the base type

  • (i.e. ignoring any array or other container) of self

property dimension_attribute_specification: Optional[DimensionAttributeSpecification]#

Get the dimension attribute of the type if it exists

Returns:

The dimension attribute if it is present otherwise None

property equivalent_python_type: str#

Python type-hint for the data type

The “base” type of the equivalent Python type will be:

If the Fortran type has a “dimension” attribute specification, this modifies the “base” type to a tuple that respects the intended shape of the value. n-dimensional variables are supported. TODO: remove this behaviour, doesn’t scale well to long arrays and doesn’t help with deferred shape arrays.

property fortran_type_attribute_declaration: str#

Fortran type attribute declaration, including attribute specifications.

Attribute specifications are only included if they are applicable.

See the docstring of fgen.fortran_parsing for further details.

classmethod from_str(fortran_type_attribute_declaration)[source]#

Create FortranDataType from type declaration statement

Parses and validates a type declaration statement

Parameters:

fortran_type_attribute_declaration (str) –

Fortran type declaration statement

For example, “real(8), dimension(2) :: heat_uptake_sensitivity”

The entity declaration component (including and after “::”) is ignored hence is optional.

See the docstring of fgen.fortran_parsing for further details.

Raises:

ValueError – The type declaration statement is invalid

Return type:

fgen.fortran_parsing.FortranDataType

property has_deferred_size: bool#

Whether this instance represents a type with a deferred size or not.

Returns:

  • True if self represents a type with a deferred size,

  • False otherwise.

property is_array: bool#

Whether this instance represents an array or not.

Returns:

True if self represents an array, False otherwise.

property is_array_of_derived_type: bool#

Whether this instance represents an array of a derived type or not.

Returns:

True if self represents an array of a derived type, False otherwise.

property is_array_of_float_double: bool#

Whether this instance represents an array of floating double-point type.

Returns:

  • True if self represents a type

  • which is an of floating double-point type,

  • False otherwise.

property is_character: bool#

Whether this instance represents a character type

Returns:

True if self represents a character type, False otherwise.

property is_deferred_array: bool#

Whether this instance represents a deferred size array

Returns:

  • True if self represents a type which is a deferred size array

  • False otherwise.

property is_deferred_array_of_derived_type: bool#

Whether this instance represents a deferred size array of a derived type

Returns:

  • True if self represents a type

  • which is a deferred size array of a derived type,

  • False otherwise.

property is_derived_type: bool#

Whether this instance represents a type which is a derived type

Returns:

  • True if self represents a type which is a derived type

  • False otherwise.

  • True if a type is a derived type, False if it is an intrinsic type

property is_enum: bool#

Whether this instance represents a type which is an enum.

Returns:

  • True if self represents a type which is an enum.

  • False otherwise.

property is_logical: bool#

Whether this instance represents a logical type

Returns:

True if self represents a logical type, False otherwise.

property is_pointer: bool#

Whether this instance represents a type which is a pointer

Returns:

  • True if self represents a type which is a pointer

  • False otherwise.

property python_equivalent_type_annotation: str#

Type annotation for the python-equivalent of this Fortran type

type_specification: str#

This can be either an intrinsic type, or a derived type.

For example, “real(8)”, “logical”, “type(my_calculator)”