Fortiel (mixed Fortran and Cockatiel) is a Fortran preprocessor.
Fortiel can be install as the PyPI package:
pip3 install fortiel
Common directive syntax is:
#$directiveName directiveArguments
! or
#@directiveName directiveArguments
where directiveName
is one of the known preprocessor directives.
The #$
directive header is treated as a single token, so no whitespaces are allowed between #
and $
or @
.
directiveName
is case-insensitive
(Python expressions and file paths although are case-sensitive), so the following lines are equivalent:
#$use 'filename'
! and
#@uSe 'filename'
Fortran-style continuation lines &
are supported within the preprocessor directives:
#$ first_directive_part &
second_directive_part
! and
#$ first_directive_part &
& second_directive_part
is the same as include
, but it skips the non-directive lines:
#$use 'filePath'
! or
#$use "filePath"
! or
#$use <filePath>
declares a new named variable:
#$let var = expression
expression
should be a valid Python 3 expression, that may refer to the previously defined variables,
Fortiel builtins and Python 3 builtins.
Functions can be also declared using the let
directive:
#$ let fun([argument[, anotherArgument]*]) = expression
undefines the names, previously defined with the let
directive:
#$del var[, anotherVar]*
Builtin names like __FILE__
or __LINE__
cannot be undefined.
is a classic conditional directive:
#$if condition
! Fortran code.
#$else if condition
! Fortran code.
#$else
! Fortran code.
#$end if
Note that else if
, elseif
and elif
directives, end if
and endif
directives are respectively equivalent.
substitutes the source lines multiple times:
#$do var = first, last[, step]
! Fortran code.
#$end do
first
, last
and optional step
expressions should evaluate to integers.
Inside the loop body a special integer variable __INDEX__
is defined, which is equal to the current value of var
.
Note that end do
and enddo
directives are equivalent.
Consider the example:
#$let x = 'b'
a$x ! evaluates to ab;
${3*x}$a ! evaluates to bbba.
is a special substitution that becomes handy inside the #$do
loops:
@var[,]
! or
@:[,]
This substitution spawns the token after @
(an identifier or colon character), and an optional trailing comma,
the __INDEX__
amount of times.
Consider the example:
#$ do i = 0, 2
@a, b
#$ end do
! evaluates to
b
a, b
a, a, b
module Distances
implicit none
#$ let NUM_RANKS = 2
interface computeSquareDistance
#$ do rank = 0, NUM_RANKS
module procedure computeSquareDistance{rank}
#$ end do
end interface computeSquareDistance
contains
#$ do rank = 0, NUM_RANKS
function computeSquareDistance`rank`(n, u, v) result(d)
integer, intent(in) :: n
real, intent(in) :: u(@:,:), v(@:,:)
real :: d
integer :: i
d = 0.0
do i = 1, n
#$ if rank == 0
d = d + (u(i) - v(i))**2
#$ else
d = d + sum((u(@:,i) - v(@:,i))**2)
#$ end if
end do
end function computeSquareDistance`rank`
#$ end do
end module Distances
module Distances
implicit none
interface computeSquareDistance
module procedure computeSquareDistance0
module procedure computeSquareDistance1
module procedure computeSquareDistance2
end interface computeSquareDistance
contains
function computeSquareDistance0(n, u, v) result(d)
integer, intent(in) :: n
real, intent(in) :: u(:), v(:)
real :: d
integer :: i
d = 0.0
do i = 1, n
d = d + (u(i) - v(i))**2
end do
end function computeSquareDistance0
function computeSquareDistance1(n, u, v) result(d)
integer, intent(in) :: n
real, intent(in) :: u(:,:), v(:,:)
real :: d
integer :: i
d = 0.0
do i = 1, n
d = d + sum((u(:,i) - v(:,i))**2)
end do
end function computeSquareDistance1
function computeSquareDistance2(n, u, v) result(d)
integer, intent(in) :: n
real, intent(in) :: u(:,:,:), v(:,:,:)
real :: d
integer :: i
d = 0.0
do i = 1, n
d = d + sum((u(:,:,i) - v(:,:,i))**2)
end do
end function computeSquareDistance2
end module Distances
- Continuation lines in in-line substitutions.
- Long lines folding.
- CLI.
- GFortiel documentation.
- Builtin variables.