Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace polymorphism with fypp code-gen #10

Merged
merged 2 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,13 @@ jobs:
nf-config --all
- uses: actions/checkout@v3

- name: Set up Python "3.x"
uses: actions/setup-python@v4
with:
python-version: "3.x"

- name: Install fypp
run: pip install fypp

- name: Build neasy-f
run: ./scripts/ci_build_and_run.sh
15 changes: 5 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,18 @@ target_include_directories(neasyf PUBLIC
)

if (NEASYF_GENERATE_SOURCE)
find_package(Python3)
if (NOT Python3_FOUND)
message(FATAL_ERROR "Python not found. Unable to generate source file. If you just want to build \
find_program(FYPP
NAMES fypp)
if (NOT FYPP)
message(FATAL_ERROR "fypp not found. Unable to generate source file. If you just want to build \
neasy-f, then disable source generation with NEASYF_GENERATE_SOURCE=off.")
endif()

set(neasy_f_source_file "${CMAKE_CURRENT_SOURCE_DIR}/src/neasyf.f90")
add_custom_command(OUTPUT ${neasy_f_source_file}
COMMAND ${Python3_EXECUTABLE} generate_source.py --write-to ${neasy_f_source_file}
COMMAND ${FYPP} "${CMAKE_CURRENT_SOURCE_DIR}/src/neasyf.in.f90" ${neasy_f_source_file}
DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/generate_source.py"
"${CMAKE_CURRENT_SOURCE_DIR}/src/neasyf.in.f90"
"${CMAKE_CURRENT_SOURCE_DIR}/src/neasyf.type.in.f90"
"${CMAKE_CURRENT_SOURCE_DIR}/src/neasyf.get_var.in.f90"
"${CMAKE_CURRENT_SOURCE_DIR}/src/neasyf.put_var.in.f90"
"${CMAKE_CURRENT_SOURCE_DIR}/src/neasyf.read.in.f90"
"${CMAKE_CURRENT_SOURCE_DIR}/src/neasyf.write.in.f90"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src
COMMENT "Generating source code"
)
Expand Down
31 changes: 14 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ netCDF4 files, and so requires netCDF to have been built with HDF5.

Tested with gfortran 11 and netCDF-Fortran 4.5.3.

For developers,
[fypp](https://fypp.readthedocs.io/en/stable/index.html) is also required.

Known Issues
------------

Expand Down Expand Up @@ -145,27 +148,21 @@ target_link_libraries(<your target> PRIVATE neasyf::neasyf)
Implementation
--------------

To simplify a lot of the code, neasy-f uses unlimited polymorphism (`class(*)`)
for a few dummy/input variables. This means that instead of needing to write
separate implementations for `integer, real, character`, and their different
`kind`s, _as well as_ handling scalar and array arguments, we only need to
overload on the array rank. This possibly has a slight runtime overhead, as
we've shifted from compile-time dispatch to runtime, but this is should be small
compared to reading from/writing to disk.

NetCDF supports up to 7 dimensions. Most of neasy-f's implementation is agnostic
to the dimension, with some slight differences between the scalar and
n-dimensional overloads. The result is that there is a _lot_ of repeated code in
neasy-f. To handle this, there is a short Python script to generate the 1-7D
overloads of the neasy-f functions.
to the type, kind, and dimension, with some slight differences between the
scalar and n-dimensional overloads. The result is that there is a _lot_ of
repeated code in neasy-f. To handle this, we use the fypp preprocessor to
generate the (6 types/kinds times 8 rank) overloads of the neasy-f functions.

The various `*.in.f90` files hold the "real" implementations, and
`src/generate_source.py` generates the code and spits it out. To update the main
code, run:
The compiled `neasyf.f90` file is generated from `neasyf.in.f90` by running:

```
$ ./generate_source.py --write-to neasyf.f90
fypp src/neasy.in.f90 src/neasyf.f90
```

If you develop neasy-f and make changes to any of the `*.in.f90` files, don't
If you're developing neasy-f, you might find it useful to add the `-n` flag,
which adds line directives, making it easier to track down compiler warnings and
errors.

If you develop neasy-f and make changes to the `neasyf.in.f90` files, don't
forget to re-generate the main `neasyf.f90` file and commit it.
80 changes: 0 additions & 80 deletions src/generate_source.py

This file was deleted.

Loading
Loading