Skip to content

Commit e2145a0

Browse files
committed
Get fortran compiling
1 parent 02b5392 commit e2145a0

9 files changed

Lines changed: 316 additions & 170 deletions

File tree

meson.build

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,9 @@ if pyprojectwheelbuild_enabled
6969
'src/example_fgen_basic/get_wavelength.f90',
7070
'src/example_fgen_basic/kind_parameters.f90',
7171
'src/example_fgen_basic/result/result.f90',
72-
'src/example_fgen_basic/result/result0D_int.f90',
7372
'src/example_fgen_basic/result/result_int.f90',
73+
'src/example_fgen_basic/result/result_int1D.f90',
74+
'src/example_fgen_basic/result/result_none.f90',
7475
)
7576

7677
# All Python files (wrappers and otherwise)

src/example_fgen_basic/error_v/error_v.f90

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ module m_error_v
3737

3838
procedure, public :: build
3939
procedure, public :: finalise
40-
final :: clean_up
40+
final :: finalise_auto
4141
! get_res sort of not needed (?)
4242
! get_err sort of not needed (?)
4343

@@ -95,14 +95,17 @@ subroutine finalise(self)
9595

9696
end subroutine finalise
9797

98-
subroutine clean_up(self)
98+
subroutine finalise_auto(self)
9999
!! Finalise the instance (i.e. free/deallocate)
100+
!!
101+
!! This method is expected to be called automatically
102+
!! by clever clean up, which is why it differs from [TODO x-ref] `finalise`
100103

101104
type(ErrorV), intent(inout) :: self
102105
! Hopefully can leave without docstring (like Python)
103106

104-
call self%finalise()
107+
call self % finalise()
105108

106-
end subroutine clean_up
109+
end subroutine finalise_auto
107110

108111
end module m_error_v

src/example_fgen_basic/pyfgen_runtime/exceptions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ def __init__(self, compiled_extension_name: str):
1818
super().__init__(error_msg)
1919

2020

21+
class FortranError(Exception):
22+
"""
23+
Base class for errors that originated on the Fortran side
24+
"""
25+
26+
2127
class MissingOptionalDependencyError(ImportError):
2228
"""
2329
Raised when an optional dependency is missing

src/example_fgen_basic/result/result.f90

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,15 @@ module m_result
99
implicit none (type, external)
1010
private
1111

12-
type, abstract, public :: Result
12+
type, abstract, public :: ResultBase
1313
!! Result type
1414
!!
1515
!! Holds either the result or an error.
1616

1717
! class(*), allocatable :: data_v(..)
18-
! MZ: assumed rank can only be dummy argument NOT type/class argument
19-
! Data i.e. the result (if no error occurs)
20-
!
21-
! Assumed rank array
22-
! (https://fortran-lang.discourse.group/t/assumed-rank-arrays/1049)
23-
! Technically a Fortran 2018 feature,
24-
! so maybe we need to update our file extensions.
25-
! If we can't use this, just comment this out
26-
! and leave each subclass of Result to set its data type
27-
! (e.g. ResultInteger will have `integer :: data`,
28-
! ResultDP1D will have `real(dp), dimension(:), allocatable :: data`)
18+
! assumed rank can only be dummy argument NOT type/class argument
19+
! hence leave this undefined
20+
! Sub-classes have to define what kind of data value they support
2921

3022
class(ErrorV), allocatable :: error_v
3123
!! Error
@@ -34,35 +26,27 @@ module m_result
3426

3527
private
3628

29+
! Expect sub-classes to implement
3730
! procedure, public:: build
38-
! TODO: Think about whether build should be on the abstract class
39-
! or just on each concrete implementation
4031
procedure, public :: is_error
41-
procedure, public :: clean_up
32+
! Expect sub-classes to implement
33+
! procedure, public :: finalise
34+
! final :: finalise_auto
4235

43-
end type Result
36+
end type ResultBase
4437

45-
! interface Result
46-
!! Constructor interface - see build (TODO: figure out cross-ref syntax) for details
38+
! Expect sub-classes to implement
39+
! interface ResultSubClass
40+
!! Constructor interface - see build [cross-ref goes here] for details
4741
! module procedure :: constructor
48-
! end interface Result
42+
! end interface ResultSubClass
4943

5044
contains
5145

52-
subroutine clean_up(self)
53-
!! Finalise the instance (i.e. free/deallocate)
54-
55-
class(Result), intent(inout) :: self
56-
! Hopefully can leave without docstring (like Python)
57-
58-
deallocate (self % error_v)
59-
60-
end subroutine clean_up
61-
6246
pure function is_error(self) result(is_err)
6347
!! Determine whether `self` contains an error or not
6448

65-
class(Result), intent(in) :: self
49+
class(ResultBase), intent(in) :: self
6650
! Hopefully can leave without docstring (like Python)
6751

6852
logical :: is_err

src/example_fgen_basic/result/result0D_int.f90

Lines changed: 0 additions & 98 deletions
This file was deleted.
Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,127 @@
1-
!> Result value for integers
1+
!> Result type for integers
22
!>
33
!> Inspired by the excellent, MIT licensed
44
!> https://github.com/samharrison7/fortran-error-handler
55
module m_result_int
66

77
use m_error_v, only: ErrorV
8-
use m_result, only: Result
8+
use m_result, only: ResultBase
9+
use m_result_none, only: ResultNone
910

1011
implicit none (type, external)
1112
private
1213

13-
type, extends(Result), public :: ResultInteger1D
14+
type, extends(ResultBase), public :: ResultInt
1415
!! Result type that holds integer values
15-
!!
16-
!! Holds either an integer value or an error.
1716

18-
integer, allocatable :: data_v(:)
17+
integer, allocatable :: data_v
1918
!! Data i.e. the result (if no error occurs)
2019

21-
! class(ErrorV), allocatable :: error_v
22-
!! Error
20+
! Note: the error_v attribute comes from ResultBase
2321

2422
contains
2523

2624
private
2725

2826
procedure, public :: build
29-
! `finalise` and `is_error` come from abstract base class
30-
final :: finalise
27+
procedure, public :: finalise
28+
final :: finalise_auto
3129

32-
end type ResultInteger1D
30+
end type ResultInt
3331

34-
interface ResultInteger1D
35-
!! Constructor interface - see build (TODO: figure out cross-ref syntax) for details
32+
interface ResultInt
33+
!! Constructor interface - see build [TODO: x-ref] for details
3634
module procedure :: constructor
37-
end interface ResultInteger1D
35+
end interface ResultInt
3836

3937
contains
4038

4139
function constructor(data_v, error_v) result(self)
4240
!! Build instance
4341

44-
type(ResultInteger1D) :: self
42+
type(ResultInt) :: self
4543
! Hopefully can leave without docstring (like Python)
4644

47-
class(ErrorV), intent(inout), optional :: error_v
48-
!! Error message
49-
50-
integer, allocatable, intent(in), optional :: data_v(:)
45+
integer, intent(in), optional :: data_v
5146
!! Data
5247

53-
call self % build(data_v_in=data_v, error_v_in=error_v)
48+
class(ErrorV), intent(in), optional :: error_v
49+
!! Error
50+
51+
type(ResultNone) :: build_res
52+
53+
build_res = self % build(data_v_in=data_v, error_v_in=error_v)
54+
55+
if (build_res % is_error()) then
56+
57+
! This interface has to return the initialised object,
58+
! it cannot return a Result type,
59+
! so we have no choice but to raise a fatal error here.
60+
print *, build_res % error_v % message
61+
error stop build_res % error_v % code
62+
63+
! else
64+
! Assume no error occurred and initialisation was fine
65+
66+
end if
5467

5568
end function constructor
5669

57-
subroutine build(self, data_v_in, error_v_in)
70+
function build(self, data_v_in, error_v_in) result(res)
5871
!! Build instance
5972

60-
class(ResultInteger1D), intent(inout) :: self
73+
class(ResultInt), intent(out) :: self
6174
! Hopefully can leave without docstring (like Python)
6275

63-
integer, intent(in), optional :: data_v_in(:)
76+
integer, intent(in), optional :: data_v_in
6477
!! Data
6578

66-
class(ErrorV), intent(inout), optional :: error_v_in
79+
class(ErrorV), intent(in), optional :: error_v_in
6780
!! Error message
6881

82+
type(ResultNone) :: res
83+
!! Result
84+
6985
if (present(data_v_in) .and. present(error_v_in)) then
70-
error_v_in % message = "Both data and error were provided"
86+
res % error_v % message = "Both data and error were provided"
87+
7188
else if (present(data_v_in)) then
7289
allocate (self % data_v, source=data_v_in)
7390
! No error - no need to call res % build
91+
7492
else if (present(error_v_in)) then
7593
allocate (self % error_v, source=error_v_in)
7694
! No error - no need to call res % build
95+
7796
else
78-
error_v_in % message = "Neither data nor error were provided"
97+
res % error_v % message = "Neither data nor error were provided"
98+
7999
end if
80100

81-
end subroutine build
101+
end function build
82102

83103
subroutine finalise(self)
84-
!! Finalise instance
104+
!! Finalise the instance (i.e. free/deallocate)
85105

86-
type(ResultInteger1D), intent(inout) :: self
106+
class(ResultInt), intent(inout) :: self
87107
! Hopefully can leave without docstring (like Python)
88108

89109
if (allocated(self % data_v)) deallocate (self % data_v)
90-
if (allocated(self % error_v)) call self % clean_up()
110+
if (allocated(self % error_v)) deallocate(self % error_v)
91111

92112
end subroutine finalise
93113

114+
subroutine finalise_auto(self)
115+
!! Finalise the instance (i.e. free/deallocate)
116+
!!
117+
!! This method is expected to be called automatically
118+
!! by clever clean up, which is why it differs from [TODO x-ref] `finalise`
119+
120+
type(ResultInt), intent(inout) :: self
121+
! Hopefully can leave without docstring (like Python)
122+
123+
call self % finalise()
124+
125+
end subroutine finalise_auto
126+
94127
end module m_result_int

0 commit comments

Comments
 (0)