|
PyForTool
Python-fortran-tool
|

Public Member Functions | |
| isNodeInProcedure (self, node, procList) | |
| isNodeInCall (self, node) | |
| removeCall (self, callName, simplify=False) | |
| removePrints (self, simplify=False) | |
| removeArraySyntax (self, concurrent=False, useMnhExpand=True, everywhere=True, loopVar=None, reuseLoop=True, funcList=None, updateMemSet=False, updateCopy=False, addAccIndependentCollapse=True) | |
| inlineContainedSubroutines (self, simplify=False, loopVar=None) | |
| inline (self, subContained, callStmt, mainScope, simplify=False, loopVar=None) | |
| setFalseIfStmt (self, flags, simplify=False) | |
| evalFalseIfStmt (self, nodes, simplify=False) | |
| checkOpInCall (self, mustRaise=False) | |
| checkEmptyParensInCall (self, mustRaise=False) | |
| insertStatement (self, stmt, first) | |
| removeStmtNode (self, nodes, simplifyVar, simplifyStruct) | |
| removeConstructNode (self, node, simplifyVar, simplifyStruct) | |
| removeFromList (self, item, itemPar) | |
Static Public Member Functions | |
| createDoConstruct (loopVariables, indent=0, concurrent=False) | |
| insertInList (pos, item, parent) | |
Methods to act on statements
Definition at line 91 of file statements.py.
| pyfortool.statements.Statements.checkEmptyParensInCall | ( | self, | |
mustRaise = False |
|||
| ) |
:param mustRaise: True to raise Issue a logging.warning if some call arguments are arrays with empty parens Example: CALL FOO(A(:)) If mustRaise is True, issue a logging.error instead and raise an error
Definition at line 1383 of file statements.py.

| pyfortool.statements.Statements.checkOpInCall | ( | self, | |
mustRaise = False |
|||
| ) |
:param mustRaise: True to raise Issue a logging.warning if some call arguments are operations If mustRaise is True, issue a logging.error instead and raise an error
Definition at line 1366 of file statements.py.

|
static |
:param loopVariables: ordered dictionnary with loop variables as key and bounds as values.
Bounds are expressed with a 2-tuple.
Keys must be in the same order as the order used when addressing an
element: if loopVariables.keys is [JI, JK], arrays are
addressed with (JI, JK)
:param indent: current indentation
:param concurrent: if False, output is made of nested 'DO' loops
if True, output is made of a single 'DO CONCURRENT' loop
:return: (inner, outer, extraindent) with
- inner the inner do-construct where statements must be added
- outer the outer do-construct to be inserted somewhere
- extraindent the number of added indentation
(2 if concurrent else 2*len(loopVariables))
Definition at line 1649 of file statements.py.

| pyfortool.statements.Statements.evalFalseIfStmt | ( | self, | |
| nodes, | |||
simplify = False |
|||
| ) |
Evaluate if-stmt with multiple op-E and remove the nodes if only .FALSE. are present
:param nodes: list of nodes of type op-E to evaluate (containing .FALSE.)
:param simplify: try to simplify code (if if-block is removed, variables used in the
if condition are also checked)
Definition at line 1344 of file statements.py.

| pyfortool.statements.Statements.inline | ( | self, | |
| subContained, | |||
| callStmt, | |||
| mainScope, | |||
simplify = False, |
|||
loopVar = None |
|||
| ) |
Inline a single contained subroutine at its call site.
This method performs the actual inlining of a contained subroutine
into the calling scope. It handles:
- ELEMENTAL subroutines with array arguments
- Optional arguments (PRESENT intrinsic)
- Variable name conflicts
- USE statement merging
Parameters
----------
subContained : xml element
XML fragment corresponding to the contained subroutine scope.
callStmt : xml element
The call-stmt node to replace with inlined code.
mainScope : PYFTscope
Scope of the main (calling) subroutine.
simplify : bool, optional
If True, remove empty constructs and unused variables
after inlining. Default is False.
loopVar : callable or None, optional
Function to determine loop index variable name.
Used when inlining ELEMENTAL subroutines called on arrays.
Takes: (lowerDecl, upperDecl, lowerUsed, upperUsed, name, index)
Returns: str, True (auto-generate), or False (skip).
Notes
-----
- For ELEMENTAL subroutines on arrays: DO loops are introduced.
- Optional arguments: PRESENT(var) is replaced with .TRUE. or .FALSE.
- Missing optional arguments: code paths using them are removed.
- Name conflicts: local variables are renamed with _N suffixes.
Definition at line 810 of file statements.py.


| pyfortool.statements.Statements.inlineContainedSubroutines | ( | self, | |
simplify = False, |
|||
loopVar = None |
|||
| ) |
Inline all contained subroutines into their parent.
Transforms contained subroutines (defined after CONTAINS) by:
1. Identifying contained subroutines
2. Finding all CALL statements to contained routines
3. Inlining the routine body where called
4. Removing the contained routine definitions
Parameters
----------
simplify : bool, optional
If True, simplify code by removing empty constructs
and unused variables after inlining. Default is False.
loopVar : callable or None, optional
Function to determine loop index variable name for ELEMENTAL
subroutine calls on arrays.
Takes: (lowerDecl, upperDecl, lowerUsed, upperUsed, name, index)
Returns: str, True (auto-generate), or False (skip).
Examples
--------
>>> pft = PYFT('input.F90')
>>> pft.inlineContainedSubroutines()
>>> pft.write()
Notes
-----
- ELEMENTAL subroutines called on arrays get wrapped in DO loops.
- Optional arguments are handled (PRESENT checks are added/removed).
- Variables in contained routines may be renamed to avoid conflicts.
- Empty CONTAINS sections are removed when simplify=True.
Definition at line 732 of file statements.py.


|
static |
:param pos: insertion position :param item: item to add to the list :param parent: the parent of item (the list)
Definition at line 1754 of file statements.py.

| pyfortool.statements.Statements.insertStatement | ( | self, | |
| stmt, | |||
| first | |||
| ) |
Insert a statement to be executed first (or last) :param stmt: statement to insert :param first: True to insert it in first position, False to insert it in last position :return: the index of the stmt inserted in scope
Definition at line 1404 of file statements.py.

| pyfortool.statements.Statements.isNodeInCall | ( | self, | |
| node | |||
| ) |
Check if a node is an argument of a CALL statement.
Parameters
----------
node : xml element
A named-E element to check.
Returns
-------
bool
True if the node is an argument in a CALL statement,
False otherwise.
Examples
--------
>>> node = pft.find('.//{*}named-E[{*}N/{*}n="X"]')
>>> is_arg = pft.isNodeInCall(node) # True if X is in CALL FOO(X)
Definition at line 142 of file statements.py.


| pyfortool.statements.Statements.isNodeInProcedure | ( | self, | |
| node, | |||
| procList | |||
| ) |
Check if a node is an argument of a specific intrinsic procedure.
Parameters
----------
node : xml element
A named-E element to check.
procList : list of str
List of intrinsic procedure names (e.g., ['ALLOCATED', 'PRESENT']).
Returns
-------
bool
True if the node is an argument of one of the specified procedures.
Examples
--------
>>> node = pft.find('.//{*}named-E')
>>> is_arg = pft.isNodeInProcedure(node, ['ALLOCATED', 'PRESENT'])
Definition at line 97 of file statements.py.


| pyfortool.statements.Statements.removeArraySyntax | ( | self, | |
concurrent = False, |
|||
useMnhExpand = True, |
|||
everywhere = True, |
|||
loopVar = None, |
|||
reuseLoop = True, |
|||
funcList = None, |
|||
updateMemSet = False, |
|||
updateCopy = False, |
|||
addAccIndependentCollapse = True |
|||
| ) |
Transform array syntax assignments into explicit DO loops.
Converts Fortran array syntax (e.g., A(:) = B(:)) into equivalent DO loop form.
Parameters
----------
concurrent : bool, optional
If True, use 'DO CONCURRENT' loops instead of simple 'DO' loops.
Default is False.
useMnhExpand : bool, optional
If True, respect mnh_expand directives to transform entire blocks
into a single loop. Default is True.
everywhere : bool, optional
If True, transform all array syntax in the code.
If False, only transform sections marked with !$mnh_expand directives.
Default is True.
loopVar : callable or None, optional
Function to determine loop index variable name.
Takes arguments: (lowerDecl, upperDecl, lowerUsed, upperUsed, name, index)
Returns: str (variable name), True (auto-generate name), or False (skip).
None (default) auto-generates variable names (J1, J2, etc.).
reuseLoop : bool, optional
If True, attempt to reuse loops when consecutive statements
have identical bounds. Default is True.
funcList : list of str, optional
Additional function names to recognize as array functions.
These functions will not be expanded. Default is None (empty list).
updateMemSet : bool, optional
If True, transform constant array initializations (e.g., A(:) = 0)
into DO loops. Default is False.
updateCopy : bool, optional
If True, transform array copy operations (e.g., A(:) = B(:))
into DO loops. Default is False.
addAccIndependentCollapse : bool, optional
If True, add !$acc loop independent collapse(N) directive
before DO constructs. Default is True.
Returns
-------
None
Transformation Examples
----------------------
Simple assignment:
Before:
A(:) = B(:) + C(:)
After (standard):
DO J1 = LBOUND(A, 1), UBOUND(A, 1)
A(J1) = B(J1) + C(J1)
END DO
After (concurrent):
DO CONCURRENT (J1=LBOUND(A, 1):UBOUND(A, 1))
A(J1) = B(J1) + C(J1)
END DO
WHERE construct:
Before:
WHERE (MASK(:)) X(:) = Y(:)
After:
DO J1 = 1, SIZE(X, 1)
IF (MASK(J1)) X(J1) = Y(J1)
END DO
Notes
-----
- Only transforms array syntax using explicit ':' notation.
- Intrinsic array functions (COUNT, ANY, SUM, etc.) are preserved.
- Does not transform:
- A=A(:) (no-op on left side)
- A(:)=A (single array without slice on right side)
- When useMnhExpand=True, requires specific directive format:
!$mnh_expand_array(INDEX=bounds)
... code to transform ...
!$mnh_end_expand_array(INDEX=bounds)
Definition at line 244 of file statements.py.


| pyfortool.statements.Statements.removeCall | ( | self, | |
| callName, | |||
simplify = False |
|||
| ) |
Remove all CALL statements to a specified subprogram.
Parameters
----------
callName : str
Name of the subprogram to remove calls to.
simplify : bool, optional
If True, also remove variables that become unused after the deletion.
For example, if "CALL FOO(X)" is removed and X is not used elsewhere,
X will also be removed.
Returns
-------
int
Number of CALL statements removed.
Examples
--------
>>> pft = PYFT('input.F90')
>>> n = pft.removeCall('FOO') # Remove all CALL FOO statements
>>> print(f"Removed {n} calls")
Remove calls and simplify (remove unused variables):
>>> pft.removeCall('BAR', simplify=True)
Notes
-----
- When simplify=True, may cascade to remove:
- Empty IF constructs (if call was the only statement)
- Variables only used in removed calls
- Type declarations that become empty
Definition at line 179 of file statements.py.


| pyfortool.statements.Statements.removeConstructNode | ( | self, | |
| node, | |||
| simplifyVar, | |||
| simplifyStruct | |||
| ) |
This function removes a construct node and:
- suppress variable that became useless (if simplifyVar is True)
- suppress outer loop/if if useless (if simplifyStruct is True)
:param node: node representing the statement to remove
:param simplifyVar: try to simplify code (if we delete "CALL FOO(X)" and if X not used
else where, we also delete it; or if the call was alone inside a
if-then-endif construct, with simplifyStruct=True, the construct is also
removed, and variables used in the if condition are also checked...)
:param simplifyStruct: try to simplify code (if we delete "CALL FOO(X)" and if the call was
alone inside a if-then-endif construct, the construct is also
removed, and variables used in the if condition
(with simplifyVar=True) are also checked...)
If a statement is passed, it is suppressed by removeStmtNode
Definition at line 1598 of file statements.py.


| pyfortool.statements.Statements.removeFromList | ( | self, | |
| item, | |||
| itemPar | |||
| ) |
:param item: item to remove from list :param itemPar: the parent of item (the list)
Definition at line 1773 of file statements.py.


| pyfortool.statements.Statements.removePrints | ( | self, | |
simplify = False |
|||
| ) |
Remove all PRINT statements from the code.
Parameters
----------
simplify : bool, optional
If True, also remove variables that become unused after the deletion.
Examples
--------
>>> pft = PYFT('input.F90')
>>> pft.removePrints() # Remove all PRINT statements
>>> pft.removePrints(simplify=True) # Also remove unused variables
Notes
-----
- When simplify=True, may cascade to remove:
- Empty IF constructs (if print was the only statement)
- Variables only used in removed prints
Definition at line 220 of file statements.py.

| pyfortool.statements.Statements.removeStmtNode | ( | self, | |
| nodes, | |||
| simplifyVar, | |||
| simplifyStruct | |||
| ) |
Remove statement nodes with optional code simplification.
Parameters
----------
nodes : xml element or list of xml elements
Node(s) to remove from the code tree.
simplifyVar : bool
If True, also remove variables that become unused after
the deletion of the nodes.
simplifyStruct : bool
If True, also remove empty enclosing constructs
(IF blocks, loops) that become empty after node removal.
Examples
--------
>>> pft = PYFT('input.F90')
>>> nodes = pft.findall('.//{*}call-stmt')
>>> pft.removeStmtNode(nodes, simplifyVar=True, simplifyStruct=True)
Notes
-----
- Handles nested structures (removes inner statements first).
- When simplifyStruct=True:
- Empty IF blocks are removed
- Empty loops are removed
- WHERE constructs are handled
- When simplifyVar=True:
- Unused local variables are removed
- Empty type declarations are cleaned up
Definition at line 1449 of file statements.py.


| pyfortool.statements.Statements.setFalseIfStmt | ( | self, | |
| flags, | |||
simplify = False |
|||
| ) |
Set conditional flags to .FALSE. in IF conditions.
Replaces specified flag variables in IF conditions with .FALSE.,
effectively disabling code paths controlled by those flags.
Parameters
----------
flags : str or list of str
Flag variable name(s) to set to .FALSE.
Can be a single string or a list of strings.
simplify : bool, optional
If True, remove resulting dead code:
- IF blocks that always evaluate to .FALSE. are removed
- Unused variables are cleaned up. Default is False.
Examples
--------
>>> pft = PYFT('input.F90')
>>> pft.setFalseIfStmt('LFLAG') # IF (LFLAG) -> .FALSE.
>>> pft.setFalseIfStmt(['LFLAG1', 'LFLAG2'], simplify=True)
Before:
IF (LDEBUG) THEN
PRINT*, "Debug info"
END IF
After (LDEBUG set to .FALSE.):
! Block removed when simplify=True
Notes
-----
- Multiple flags in a single condition (e.g., LFLAG1 .AND. LFLAG2)
result in removal of the entire condition.
- Works on both IF statements and IF constructs.
Definition at line 1272 of file statements.py.

