Skip to content

Commit 56ff714

Browse files
authored
Merge pull request #61 from rouson/lfortran-and-simpler-assert
Support LFortran and simplify assertions
2 parents c096843 + 4c1b2df commit 56ff714

21 files changed

+208
-1132
lines changed

.github/workflows/deploy-docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
2525
- name: Build Developer Documentation
2626
run: |
27-
ford -I include doc-generator.md > ford_output.txt
27+
ford -I include ford.md > ford_output.txt
2828
# Turn warnings into errors
2929
cat ford_output.txt; if grep -q -i Warning ford_output.txt; then exit 1; fi
3030
cp ./README.md ./doc/html

README.md

Lines changed: 70 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ This assertion utility contains four public entities:
1919

2020
The `assert` subroutine
2121
* Error-terminates with a variable stop code when a caller-provided logical assertion fails,
22-
* Includes user-supplied diagnostic data in the output if provided by the calling procedure,
2322
* Is callable inside `pure` procedures, and
2423
* Can be eliminated at compile-time, as controlled by the `ASSERTIONS` preprocessor define.
2524

@@ -42,10 +41,6 @@ If instead `fpm install` is used, then either the user must copy `include/assert
4241
the user must invoke `assert` directly (via `call assert(...)`).
4342
In the latter approach when the assertions are disabled, the `assert` procedure will start and end with `if (.false.) then ... end if`, which might facilitate automatic removal of `assert` during the dead-code removal phase of optimizing compilers.
4443

45-
The `characterizable_t` type defines an `as_character()` deferred binding that produces `character` strings for use as diagnostic output from a user-defined derived type that extends `characterizable_t` and implements the deferred binding.
46-
47-
The `intrinsic_array_t` type that extends `characterizable_t` provides a convenient mechanism for producing diagnostic output from arrays of intrinsic type `complex`, `integer`, `logical`, or `real`.
48-
4944
Use Cases
5045
---------
5146
Two common use cases include
@@ -63,27 +58,49 @@ The requirements and assurances might be constraints of three kinds:
6358

6459
The [example/README.md] file shows examples of writing constraints in notes on class diagrams using the formal syntax of the Object Constraint Language ([OCL]).
6560

66-
Downloading, Building, and Running Examples
67-
-------------------------------------------
61+
Running the Examples
62+
--------------------
63+
See the [./example](./example) subdirectory.
64+
65+
Building and Testing
66+
--------------------
67+
68+
- [Cray Compiler Environment (CCE) `ftn`](#cray-compiler-environment-cce-ftn)
69+
- [GNU Compiler Collection (GCC) `gfortran`](#gnu-compiler-collection-gcc-gfortran))
70+
- [Intel `ifx`](#intel-ifx))
71+
- [LFortran `lfortran`](#lfortran-lfortran)
72+
- [LLVM `flang-new`](#llvm-flang-new)
73+
- [Numerical Algorithms Group (NAG) `nagfor`](#numerical-algorithms-group-nag-nagfor)
74+
75+
### Cray Compiler Environment (CCE) `ftn`
76+
Because `fpm` uses the compiler name to determine the compiler identity and because
77+
CCE provides one compiler wrapper, `ftn`, for invoking all compilers, you will
78+
need to invoke `ftn` in a shell script named to identify CCE compiler. For example,
79+
place a script named `crayftn.sh` in your path with the following contents and with
80+
executable privileges set appropriately:
81+
```
82+
#!/bin/bash
6883
69-
### Downloading Assert
84+
ftn $@
7085
```
71-
git clone git@github.com:berkeleylab/assert
72-
cd assert
86+
Then build and test Assert with the command
87+
```
88+
fpm test --compiler crayftn.sh --profile release
7389
```
7490

75-
### Building and testing with `gfortran`
91+
### GNU Compiler Collection (GCC) `gfortran`
92+
7693
#### Single-image (serial) execution
77-
The command below builds Assert and runs the full test suite in a single image.
78-
For `gfortran` 14 or later, use
94+
With `gfortran` 14 or later, use
7995
```
8096
fpm test --profile release
8197
```
82-
For `gfortran` 13 or earlier, use
98+
With `gfortran` 13 or earlier, use
8399
```
84100
fpm test --profile release --flag "-ffree-line-length-0"
85101
```
86102
The above commands build the Assert library (with the default of assertion enforcement disabled) and runs the test suite.
103+
87104
#### Multi-image (parallel) execution
88105
With `gfortran` 14 or later versions and OpenCoarrays installed, use
89106
```
@@ -93,60 +110,56 @@ With `gfortran` 13 or earlier versions and OpenCoarrays installed,
93110
```
94111
fpm test --compiler caf --profile release --runner "cafrun -n 2" --flag "-ffree-line-length-0"
95112
```
96-
To build and test with the Numerical Algorithms Group (NAG) Fortran compiler version
97-
7.1 or later, use
98-
```
99-
fpm test --compiler=nagfor --profile release --flag "-coarray=cosmp -fpp -f2018"
100-
```
101113

102-
### Building and testing with the Intel `ifx` compiler
114+
### Intel `ifx`
115+
103116
#### Single-image (serial) execution
104117
```
105118
fpm test --compiler ifx --profile release
106119
```
120+
107121
#### Multi-image (parallel) execution
108122
With Intel Fortran and Intel MPI installed,
109123
```
110124
fpm test --compiler ifx --profile release --flag "-coarray -DASSERT_MULTI_IMAGE"
111125
```
112126

113-
### Building and testing with the LLVM `flang-new` compiler
114-
#### LLVM version 19
127+
### LLVM `flang-new`
128+
129+
#### Single-image (serial) execution
130+
With `flang-new` version 19, use
115131
```
116132
fpm test --compiler flang-new --flag "-mmlir -allow-assumed-rank -O3"
117133
```
118-
#### LLVM version 20 or later
134+
With `flang-new` version 20 or later, use
119135
```
120136
fpm test --compiler flang-new --flag "-O3"
121137
```
122138

123-
### Building and testing with the Numerical Algorithms Group (NAG) compiler
139+
### LFortran `lfortran`
140+
141+
#### Single-image (serial) execution
124142
```
125-
fpm test --compiler nagfor --profile release --flag "-fpp -coarray=cosmp"
143+
fpm test --compiler lfortran --profile release --flag --cpp
126144
```
127145

128-
### Building and testing with the Cray Compiler Environment (CCE)
129-
Because `fpm` uses the compiler name to determine the compiler identity and because
130-
CCE provides one compiler wrapper, `ftn`, for invoking all compilers, you will
131-
need to invoke `ftn` in a shell script named to identify CCE compiler. For example,
132-
place a script named `crayftn.sh` in your path with the following contents and with
133-
executable privileges set appropriately:
146+
### Numerical Algorithms Group (NAG) `nagfor`
147+
148+
#### Single-image (serial) execution
149+
With `nagfor` version 7.1 or later, use
150+
```
151+
fpm test --compiler nagfor --flag -fpp
134152
```
135-
#!/bin/bash
136153

137-
ftn $@
154+
#### Multi-image execution
155+
With `nagfor` 7.1, use
138156
```
139-
Then build and test Assert with the command
157+
fpm test --compiler nagfor --profile release --flag "-fpp -coarray=cosmp -f2018"
140158
```
141-
fpm test --compiler crayftn.sh --profile release
159+
With `nagfor` 7.2 or later, use
160+
```
161+
fpm test --compiler nagfor --flag -fpp
142162
```
143-
144-
145-
### Building and testing with other compilers
146-
To use Assert with other compilers, please submit an issue or pull request.
147-
148-
### Running the examples
149-
See the [./example](./example) subdirectory.
150163

151164
Documentation
152165
-------------
@@ -208,19 +221,19 @@ character for line-breaks in a macro invocation:
208221

209222
```fortran
210223
! OK for flang-new and gfortran
211-
call_assert_diagnose( computed_checksum == expected_checksum, \
212-
"Checksum mismatch failure!", \
213-
expected_checksum )
224+
call_assert_describe( computed_checksum == expected_checksum, \
225+
"Checksum mismatch failure!" \
226+
)
214227
```
215228

216229
Whereas Cray Fortran wants `&` line continuation characters, even inside
217230
a macro invocation:
218231

219232
```fortran
220233
! OK for Cray Fortran
221-
call_assert_diagnose( computed_checksum == expected_checksum, &
222-
"Checksum mismatch failure!", &
223-
expected_checksum )
234+
call_assert_describe( computed_checksum == expected_checksum, &
235+
"Checksum mismatch failure!" &
236+
)
224237
```
225238

226239
There appears to be no syntax acceptable to all compilers, so when writing
@@ -237,29 +250,29 @@ after macro expansion (on gfortran and flang-new):
237250

238251
```fortran
239252
! INCORRECT: cannot use Fortran comments inside macro invocation
240-
call_assert_diagnose( computed_checksum == expected_checksum, ! ensured since version 3.14
241-
"Checksum mismatch failure!", ! TODO: write a better message here
242-
computed_checksum )
253+
call_assert_describe( computed_checksum == expected_checksum, ! ensured since version 3.14
254+
"Checksum mismatch failure!" ! TODO: write a better message here
255+
)
243256
```
244257

245258
Depending on your compiler it *might* be possible to use a C-style block
246259
comment (because they are often removed by the preprocessor), for example with
247260
gfortran one can instead write the following:
248261

249262
```fortran
250-
call_assert_diagnose( computed_checksum == expected_checksum, /* ensured since version 3.14 */ \
251-
"Checksum mismatch failure!", /* TODO: write a better message here */ \
252-
computed_checksum )
263+
call_assert_describe( computed_checksum == expected_checksum, /* ensured since version 3.14 */ \
264+
"Checksum mismatch failure!" /* TODO: write a better message here */ \
265+
)
253266
```
254267

255268
However that capability might not be portable to other Fortran compilers.
256269
When in doubt, one can always move the comment outside the macro invocation:
257270

258271
```fortran
259272
! assert a property ensured since version 3.14
260-
call_assert_diagnose( computed_checksum == expected_checksum, \
261-
"Checksum mismatch failure!", \
262-
computed_checksum ) ! TODO: write a better message above
273+
call_assert_describe( computed_checksum == expected_checksum, \
274+
"Checksum mismatch failure!" \
275+
) ! TODO: write a better message above
263276
```
264277

265278
Legal Information

doc/assert_class_diagram.puml

Lines changed: 0 additions & 21 deletions
This file was deleted.

doc/example_class_diagram.puml

Lines changed: 0 additions & 29 deletions
This file was deleted.

example/README.md

Lines changed: 3 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -10,82 +10,34 @@ The [simple_assertions.f90] example demonstrates a precondition and a
1010
postcondition, each with an assertion that checks the truth of a logical
1111
expression based on scalar, real values.
1212

13-
Derived type diagnostic data
14-
----------------------------
15-
16-
See [derived_type_diagnostic.f90]. For reasons related to runtime performance,
17-
it is desirable to ensure that any computation required to extract diagnostic
18-
data from an object only take place if the assertion fails. This is one of the
19-
main motivations for allowing objects to be passed to the `diagnostic_data`
20-
argument of `assert`. The generic programming facilities planned for
21-
"Fortran 202y" (two standards after Fortran 2018) will ultimately provide the
22-
best way to facilitate the extraction of diagnostic data from objects by
23-
empowering developers to express requirements on types such as that the types
24-
must support a specific procedure binding that can be used to extract output
25-
in character form, the form that `assert` uses for its error stop code. For
26-
now, we impose such a requirement through an `as_character` deferred binding
27-
on the provided `characterizable_t` abstract type.
28-
29-
Because it might prove problematic to require that a user type to extend the
30-
`characterizable_t` abstract type, the [derived_type_diagnostic.f90] example
31-
shows a workaround based on the class hierarchy described in the figure below.
32-
The figure shows a Unified Modeling Language ([UML]) class diagram with the
33-
`characterizable_t` abstract class, an example user's `stuff_t` class, and a
34-
`characterizable_stuff_t` class. The pattern expressed in the workaround
35-
aggregates the example user type, `stuff_t`, as a component inside the
36-
encapsulating `characterizable_stuff_t` type defined to extend `characterizable_t`
37-
for purposes of implementing `characterizable_t` parent type's deferred
38-
`as_character()` binding.
39-
40-
The figure below also shows two constraints written in UML's Object Constraint
41-
Language ([OCL]). The constraints describe the precondition and postcondition
42-
checked in [derived_type_diagnostic.f90] and the context for those constraints.
43-
44-
The UML diagram below was generated in the [Atom] editor [PlantUML] package
45-
from the PlantUML script in this repository's [doc] folder.
46-
47-
![Classes involved in Derived-Type Diagnostic Example](https://user-images.githubusercontent.com/13108868/130385757-6b79e5f1-5dec-440c-98f5-0f659c538754.png)
48-
4913
Running the examples
5014
--------------------
5115

5216
### Single-image execution
5317
```
5418
fpm run --example simple_assertions
55-
fpm run --example derived_type_diagnostic
5619
```
5720
where `fpm run` automatically invokes `fpm build` if necessary, .e.g., if the package's source code
58-
has changed since the most recent build. If `assert` is working correctly, the first `fpm run` above
59-
will error-terminate with the character stop code
60-
```
61-
Assertion "reciprocal: abs(error) < tolerance" failed on image 1 with diagnostic data "-1.00000000"
21+
has changed since the most recent build. If `assert` is working correctly, the `fpm run` above
22+
will error-terminate with the character stop code similar to the following
6223
```
63-
and the second `fpm run` above will error-terminate with the character stop code
64-
```
65-
Assertion "stuff_t%z(): self%defined()" failed on image 1 with diagnostic data "(none provided)"
24+
Assertion failure on image 1: reciprocal: abs(error) < tolerance
6625
```
6726

6827
### Multi-image execution with `gfortran` and OpenCoarrays
6928
```
7029
git clone git@github.com/sourceryinstitute/assert
7130
cd assert
7231
fpm run --compiler caf --runner "cafrun -n 2" --example simple_assertions
73-
fpm run --compiler caf --runner "cafrun -n 2" --example derived_type_diagnostic
7432
```
7533
Replace either instance of `2` above with the desired number of images to run for parallel execution.
7634
If `assert` is working correctly, both of the latter `fpm run` commands will error-terminate with one
7735
or more images providing stop codes analogous to those quoted in the [Single-image execution] section.
7836

79-
## Derived-type diagnostic data output
80-
To demonstrate the derived-type diagnostic data output capability, try replacing the
81-
`i%defined()` assertion in the [derived_type_diagnostic.f90](./derived_type_diagnostic.f90)
82-
with `.false.`.
83-
8437
[Hyperlinks]:#
8538
[OpenCoarrays]: https://github.com/sourceryinstitute/opencoarrays
8639
[Enforcing programming contracts]: #enforcing-programming-contracts
8740
[Single-image execution]: #single-image-execution
88-
[derived_type_diagnostic.f90]: ./derived_type_diagnostic.f90
8941
[simple_assertions.f90]: ./simple_assertions.f90
9042
[UML]: https://en.wikipedia.org/wiki/Unified_Modeling_Language
9143
[OCL]: https://en.wikipedia.org/wiki/Object_Constraint_Language

0 commit comments

Comments
 (0)