Skip to content

Commit 572ff14

Browse files
committed
Add Fortran back-end
1 parent baaf7b7 commit 572ff14

4 files changed

Lines changed: 191 additions & 0 deletions

File tree

meson.build

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ if pyprojectwheelbuild_enabled
5454
# Specify all the other source Fortran files (original files and managers)
5555
# Injected with `script/inject-srcs-into-meson-build.py`
5656
srcs_ancillary_lib = files(
57+
'src/example_fgen_basic/error_v/creation.f90',
58+
'src/example_fgen_basic/error_v/error_v.f90',
59+
'src/example_fgen_basic/fpyfgen/base_finalisable.f90',
5760
'src/example_fgen_basic/get_wavelength.f90',
5861
'src/example_fgen_basic/kind_parameters.f90',
5962
)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
!> Error creation
2+
!>
3+
!> A very basic demo to get the idea.
4+
!
5+
! TODO: discuss - we should probably have some convention for module names.
6+
! The hard part is avoiding them becoming too long...
7+
module m_error_v_creation
8+
9+
use m_error_v, only: ErrorV, NO_ERROR_CODE
10+
11+
implicit none
12+
private
13+
14+
public :: create_error
15+
16+
contains
17+
18+
function create_error(inv) result(err)
19+
!! Create an error
20+
!!
21+
!! If an odd number is supplied, the error code is no error (TODO: cross-ref).
22+
!! If an even number is supplied, the error code is 1.
23+
!! If a negative number is supplied, the error code is 2.
24+
25+
integer, intent(in) :: inv
26+
!! Value to use to create the error
27+
28+
type(ErrorV) :: err
29+
!! Created error
30+
31+
if (inv < 0) then
32+
err = ErrorV(code=2, message="Negative number supplied")
33+
return
34+
end if
35+
36+
if (mod(inv, 2) .eq. 0) then
37+
err = ErrorV(code=1, message="Even number supplied")
38+
else
39+
err = ErrorV(code=0)
40+
end if
41+
42+
end function create_error
43+
44+
end module m_error_v_creation
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
!> Error value
2+
!>
3+
!> Inspired by the excellent, MIT licensed
4+
!> https://github.com/samharrison7/fortran-error-handler
5+
!>
6+
!> Fortran doesn't have a null value.
7+
!> As a result, we introduce this derived type
8+
!> with the convention that a code of 0 indicates no error.
9+
module m_error_v
10+
11+
! TODO: switch `m_` prefix to project name prefix
12+
! (e.g. fpyfgen, "Fortran-code for Python-Fortran wrapper Generator")
13+
! (same idea as `tomlf_` prefix)
14+
! TODO: move this to standalone repo (eventually)
15+
use fpyfgen_base_finalisable, only: BaseFinalisable
16+
17+
implicit none
18+
private
19+
20+
integer, parameter, public :: NO_ERROR_CODE = 0
21+
!! Code that indicates no error
22+
23+
type, extends(BaseFinalisable), public :: ErrorV
24+
!! Error value
25+
26+
integer :: code = 1
27+
!! Error code
28+
29+
character(len=128) :: message = ""
30+
! TODO: think about making the message allocatable to handle long messages
31+
32+
! TODO: think about adding idea of critical
33+
! (means you can stop but also unwind errors and traceback along the way)
34+
35+
! TODO: think about adding trace (might be simpler than compiling with traceback)
36+
37+
contains
38+
39+
private
40+
41+
procedure, public:: build, finalise
42+
! get_res sort of not needed (?)
43+
! get_err sort of not needed (?)
44+
45+
end type ErrorV
46+
47+
interface ErrorV
48+
!! Constructor interface - see build (TODO: figure out cross-ref syntax) for details
49+
! This is what allows us to do ErrorV(...) when using this class
50+
module procedure :: constructor
51+
end interface ErrorV
52+
53+
contains
54+
55+
function constructor(code, message) result(self)
56+
!! Constructor - see build (TODO: figure out cross-ref syntax) for details
57+
58+
integer, intent(in) :: code
59+
character(len=*), optional, intent(in) :: message
60+
61+
type(ErrorV) :: self
62+
63+
call self % build(code, message)
64+
65+
end function constructor
66+
67+
subroutine build(self, code, message)
68+
!! Build instance
69+
70+
class(ErrorV), intent(inout) :: self
71+
! Hopefully can leave without docstring (like Python)
72+
73+
integer, intent(in) :: code
74+
!! Error code
75+
!!
76+
!! Use [TODO: figure out xref] `NO_ERROR_CODE` if there is no error
77+
78+
character(len=*), optional, intent(in) :: message
79+
!! Error message
80+
81+
self % code = code
82+
if (present(message)) then
83+
self % message = message
84+
end if
85+
86+
end subroutine build
87+
88+
subroutine finalise(self)
89+
!! Finalise the instance (i.e. free/deallocate)
90+
91+
class(ErrorV), intent(inout) :: self
92+
! Hopefully can leave without docstring (like Python)
93+
94+
! If we make message allocatable, deallocate here
95+
96+
end subroutine finalise
97+
98+
end module m_error_v
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
!> Base class for classes that can be wrapped with pyfgen.
2+
!>
3+
!> Such classes must always be finalisable, to help with memory management
4+
!> across the Python-Fortran interface.
5+
module fpyfgen_base_finalisable
6+
7+
implicit none
8+
private
9+
10+
integer, parameter, public :: INVALID_INSTANCE_INDEX = -1
11+
!! Value that denotes an invalid model index
12+
13+
public :: BaseFinalisable
14+
15+
type, abstract :: BaseFinalisable
16+
17+
integer :: instance_index = INVALID_INSTANCE_INDEX
18+
!! Unique identifier for the instance.
19+
!!
20+
!! Set to a value > 0 when the instance is in use,
21+
!! set to `INVALID_INSTANCE_INDEX` (TODO xref) otherwise.
22+
!! The value is linked to the position in a manager array stored elsewhere.
23+
!! This value shouldn't be modified from outside the manager
24+
!! unless you really know what you're doing.
25+
26+
contains
27+
28+
private
29+
30+
procedure(derived_type_finalise), public, deferred :: finalise
31+
32+
end type BaseFinalisable
33+
34+
interface
35+
36+
subroutine derived_type_finalise(self)
37+
!! Finalise the instance (i.e. free/deallocate)
38+
39+
import :: BaseFinalisable
40+
class(BaseFinalisable), intent(inout) :: self
41+
42+
end subroutine derived_type_finalise
43+
44+
end interface
45+
46+
end module fpyfgen_base_finalisable

0 commit comments

Comments
 (0)