From 9548da3c43fe3c24b289c528e9ce05c11bfe4928 Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Sat, 19 Jul 2025 12:34:04 -0400 Subject: [PATCH 1/6] doc(README): desc use in pure procs, ref Julienne other minor edits --- README.md | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0ee77c7..386e0e1 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ When the `ASSERTIONS` preprocessor macro is not defined to any value, the default is that assertions are *disabled* and will not check the condition. To enable assertion enforcement (e.g., for a debug build), define the -preprocessor ASSERTIONS to non-zero, eg: +preprocessor ASSERTIONS to non-zero, e.g., ``` fpm build --flag "-DASSERTIONS" ``` @@ -45,10 +45,27 @@ Use Cases --------- Two common use cases include -1. [Enforcing programming contracts] throughout a project via runtime checks. -2. Producing output in `pure` procedures for debugging purposes. +1. [Producing output in pure procedures] for debugging purposes. +2. [Enforcing programming contracts] throughout a project via runtime checks. -### Enforcing programming contracts +### Producing output in pure procedures +Writing pure procedures communicates useful information to a compiler or a developer. +Specifically, the pure attribute conveys compliance with several constraints that clarify data dependencies and preclude side effects. +For a compiler, these constraints support optimizations, including automatic parallelization on a central processing unit (CPU) or offloading to a graphics processing unit (GPU). +For a developer, the constraints support refactoring tasks such as code movement. + +A developer seeking output inside a procedure presumably has an expectation regarding what ranges of output values represent correct program execution. +A developer can state such expectations in an assertion such as `call_assert(i>0 .and. j<0)`. +Enforce the assertion by defining the `ASSERTIONS` macro when compiling. +If the expectation is not met, the program error terminates and prints a stop code showing the assertion's file and line location and a description. +By default, the description is the literal text of what was asserted: `i>0 .and. j<0` in the aforementioned example. +Alternatively, the user can provide a custom description. + +For richer diagnostic messages from failed assertions, please see the [Julienne] correctness-checking framework. +Julienne wraps Assert and defines idioms that automatically generate diagnostic messages containing program data. +Julienne also offers string-handling utilities to assist users with customizing diagnostic messages by, for example, converting an array of numeric type into string representing comma-separated values as text. + +## Enforcing programming contracts Programming can be thought of as requirements for correct execution of a procedure and assurances for the result of correct execution. The requirements and assurances might be constraints of three kinds: @@ -193,17 +210,17 @@ limit. This can result in compile-time errors like the following from gfortran: Error: Line truncated at (1) [-Werror=line-truncation] ``` -Some compilers offer a command-line argument that can be used to workaround this legacy limit, eg: +Some compilers offer a command-line argument that can be used to workaround this legacy limit, e.g., -* `gfortran -ffree-line-length-0` aka `gfortran -ffree-line-length-none` +* `gfortran -ffree-line-length-0` or equivalently `gfortran -ffree-line-length-none` -When using `fpm`, one can pass such a flag to the compiler using the `fpm --flag` option, eg: +When using `fpm`, one can pass such a flag to the compiler using the `fpm --flag` option, e.g., ```shell $ fpm test --profile release --flag -ffree-line-length-0 ``` -Thankfully Fortran 2023 raised this obscolecent line limit to 10,000 +Thankfully, Fortran 2023 raised this obsolescent line limit to 10,000 characters, so by using newer compilers you might never encounter this problem. In the case of gfortran, this appears to have been resolved by default starting in release 14.1.0. @@ -283,7 +300,8 @@ See the [LICENSE](LICENSE) file for copyright and licensing information. [Single-image execution]: #single-image-execution [example/README.md]: ./example/README.md [tests]: ./tests -[src]: ./src [Fortran Package Manager]: https://github.com/fortran-lang/fpm [OCL]: https://en.wikipedia.org/wiki/Object_Constraint_Language [example/invoke-via-macro.F90]: ./example/invoke-via-macro.F90 +[Producing output in pure procedures]: #producing-output-in-pure-procedures +[Julienne]: https://go.lbl.gov/julienne From 3e74af3d0fb362ccc56815cf35ed8037f45c648e Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Mon, 21 Jul 2025 00:53:25 -0400 Subject: [PATCH 2/6] doc(README.md): fix mistaken header promotion Co-authored-by: Dan Bonachea --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 386e0e1..23f1adc 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ For richer diagnostic messages from failed assertions, please see the [Julienne] Julienne wraps Assert and defines idioms that automatically generate diagnostic messages containing program data. Julienne also offers string-handling utilities to assist users with customizing diagnostic messages by, for example, converting an array of numeric type into string representing comma-separated values as text. -## Enforcing programming contracts +### Enforcing programming contracts Programming can be thought of as requirements for correct execution of a procedure and assurances for the result of correct execution. The requirements and assurances might be constraints of three kinds: From aedbf4b75b9d790b5e25efe3e4fae69395735ece Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Mon, 21 Jul 2025 01:01:39 -0400 Subject: [PATCH 3/6] doc: clarify that pure prevents most side effects --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 23f1adc..41df8e9 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Two common use cases include ### Producing output in pure procedures Writing pure procedures communicates useful information to a compiler or a developer. -Specifically, the pure attribute conveys compliance with several constraints that clarify data dependencies and preclude side effects. +Specifically, the pure attribute conveys compliance with several constraints that clarify data dependencies and preclude most side effects. For a compiler, these constraints support optimizations, including automatic parallelization on a central processing unit (CPU) or offloading to a graphics processing unit (GPU). For a developer, the constraints support refactoring tasks such as code movement. From 574e9cad08b8e38cde80a0ec457e3fe7909d312b Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Wed, 30 Jul 2025 10:38:41 -0700 Subject: [PATCH 4/6] add sentence about prohibition against I/O in pure procedures --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 41df8e9..96731bb 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ Specifically, the pure attribute conveys compliance with several constraints tha For a compiler, these constraints support optimizations, including automatic parallelization on a central processing unit (CPU) or offloading to a graphics processing unit (GPU). For a developer, the constraints support refactoring tasks such as code movement. +The Fortran standard prohibits input or output in pure procedures, which precludes a common debugging mechanism. A developer seeking output inside a procedure presumably has an expectation regarding what ranges of output values represent correct program execution. A developer can state such expectations in an assertion such as `call_assert(i>0 .and. j<0)`. Enforce the assertion by defining the `ASSERTIONS` macro when compiling. From 453a745b6b6d01eb0c6a6dac336daf5b00e1ab6d Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Wed, 30 Jul 2025 10:48:43 -0700 Subject: [PATCH 5/6] doc(README): list client packages --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 96731bb..d0db68c 100644 --- a/README.md +++ b/README.md @@ -62,10 +62,6 @@ If the expectation is not met, the program error terminates and prints a stop co By default, the description is the literal text of what was asserted: `i>0 .and. j<0` in the aforementioned example. Alternatively, the user can provide a custom description. -For richer diagnostic messages from failed assertions, please see the [Julienne] correctness-checking framework. -Julienne wraps Assert and defines idioms that automatically generate diagnostic messages containing program data. -Julienne also offers string-handling utilities to assist users with customizing diagnostic messages by, for example, converting an array of numeric type into string representing comma-separated values as text. - ### Enforcing programming contracts Programming can be thought of as requirements for correct execution of a procedure and assurances for the result of correct execution. The requirements and assurances might be constraints of three kinds: @@ -291,6 +287,16 @@ call_assert_describe( computed_checksum == expected_checksum, \ ) ! TODO: write a better message above ``` +Clients of Assert +----------------- + +A few packages that use Assert include + +* The [Julienne](https://go.lbl.gov/julienne) correctness-checking framework wraps Assert and defines idioms that automatically generate diagnostic messages containing program data. +* The [Caffeine](https://go.lbl.gov/caffeine) multi-image Fortran compiler runtime library uses Assert for internal sanity checks and interface validation. +* The [Fiats](https://go.lbl.gov/fiats) deep learning library uses Assert and Julienne. +* The [Matcha](https://go.lbl.gov/matcha) T-cell motility simulator also uses Assert and Julienne. + Legal Information ----------------- See the [LICENSE](LICENSE) file for copyright and licensing information. From 12e6fce76a7da2112e90b7f229c29e46cea9a06f Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Wed, 30 Jul 2025 10:52:00 -0700 Subject: [PATCH 6/6] Apply suggestions from code review Co-authored-by: Katherine Rasmussen --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d0db68c..9410b93 100644 --- a/README.md +++ b/README.md @@ -45,10 +45,10 @@ Use Cases --------- Two common use cases include -1. [Producing output in pure procedures] for debugging purposes. +1. [Supporting output in pure procedures] for debugging purposes. 2. [Enforcing programming contracts] throughout a project via runtime checks. -### Producing output in pure procedures +### Supporting output in pure procedures Writing pure procedures communicates useful information to a compiler or a developer. Specifically, the pure attribute conveys compliance with several constraints that clarify data dependencies and preclude most side effects. For a compiler, these constraints support optimizations, including automatic parallelization on a central processing unit (CPU) or offloading to a graphics processing unit (GPU).