Skip to content

Commit 1c249f9

Browse files
committed
Errors bubble-up:1
1 parent 4322463 commit 1c249f9

File tree

11 files changed

+616
-32
lines changed

11 files changed

+616
-32
lines changed

meson.build

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ if pyprojectwheelbuild_enabled
5757
'src/example_fgen_basic/get_square_root_wrapper.f90',
5858
'src/example_fgen_basic/get_wavelength_wrapper.f90',
5959
'src/example_fgen_basic/result/result_dp_wrapper.f90',
60+
'src/example_fgen_basic/result/result_int_wrapper.f90',
6061
)
6162

6263
# Specify all the other source Fortran files (original files and managers)
@@ -72,11 +73,12 @@ if pyprojectwheelbuild_enabled
7273
'src/example_fgen_basic/get_wavelength.f90',
7374
'src/example_fgen_basic/kind_parameters.f90',
7475
'src/example_fgen_basic/result/result.f90',
76+
'src/example_fgen_basic/result/result_none.f90',
7577
'src/example_fgen_basic/result/result_dp.f90',
7678
'src/example_fgen_basic/result/result_dp_manager.f90',
7779
'src/example_fgen_basic/result/result_int.f90',
80+
'src/example_fgen_basic/result/result_int_manager.f90',
7881
'src/example_fgen_basic/result/result_int1D.f90',
79-
'src/example_fgen_basic/result/result_none.f90',
8082
)
8183

8284
# All Python files (wrappers and otherwise)
@@ -94,6 +96,7 @@ if pyprojectwheelbuild_enabled
9496
'src/example_fgen_basic/pyfgen_runtime/exceptions.py',
9597
'src/example_fgen_basic/result/__init__.py',
9698
'src/example_fgen_basic/result/result_dp.py',
99+
'src/example_fgen_basic/result/result_int.py',
97100
'src/example_fgen_basic/typing.py',
98101
)
99102

src/example_fgen_basic/meson.build

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,20 @@ srcs += files(
22
'error_v/creation.f90',
33
'error_v/error_v.f90',
44
'error_v/passing.f90',
5+
'error_v/creation_wrapper.f90',
6+
'error_v/error_v_manager.f90',
7+
'error_v/error_v_wrapper.f90',
8+
'error_v/passing_wrapper.f90',
59
'fpyfgen/base_finalisable.f90',
610
'get_wavelength.f90',
711
'kind_parameters.f90',
12+
'result/result_dp_manager.f90',
13+
'result/result_dp_wrapper.f90',
14+
'result/result_int1D.f90',
15+
'result/result_int_manager.f90',
16+
'result/result_int_wrapper.f90',
17+
'result/result_dp.f90',
18+
'result/result.f90',
19+
'result/result_int.f90',
20+
'result/result_none.f90',
821
)

src/example_fgen_basic/result/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
"""
44

55
from example_fgen_basic.result.result_dp import ResultDP
6+
from example_fgen_basic.result.result_int import ResultInt
67

7-
__all__ = ["ResultDP"]
8+
__all__ = ["ResultDP", "ResultInt"]

src/example_fgen_basic/result/result_dp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def from_instance_index(cls, instance_index: int) -> ResultDP:
5151
"""
5252
# Different wrapping strategies are needed
5353

54-
# Integer is very simple
54+
# Float is very simple
5555
if m_result_dp_w.data_v_is_set(instance_index):
5656
data_v: float | None = m_result_dp_w.get_data_v(instance_index)
5757
# data_v: np.Float64 = m_result_dp_w.get_data_v(instance_index)

src/example_fgen_basic/result/result_dp_manager.f90

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module m_result_dp_manager
44
use kind_parameters, only: dp
55
use m_error_v, only: ErrorV
66
use m_result_dp, only: ResultDP
7+
use m_result_int, only: ResultInt
78
use m_result_none, only: ResultNone
89

910
implicit none(type, external)
@@ -18,7 +19,7 @@ module m_result_dp_manager
1819

1920
contains
2021

21-
function build_instance(data_v_in, error_v_in) result(instance_index)
22+
function build_instance(data_v_in, error_v_in) result(res_available_instance_index)
2223
!! Build an instance
2324

2425
real(kind=dp), intent(in), optional :: data_v_in
@@ -27,14 +28,18 @@ function build_instance(data_v_in, error_v_in) result(instance_index)
2728
class(ErrorV), intent(in), optional :: error_v_in
2829
!! Error message
2930

30-
integer :: instance_index
31+
type(ResultInt) :: res_available_instance_index
3132
!! Index of the built instance
3233

3334
type(ResultNone) :: res_build
3435

3536
call ensure_instance_array_size_is_at_least(1)
36-
call get_available_instance_index(instance_index)
37-
res_build = instance_array(instance_index) % build(data_v_in=data_v_in, error_v_in=error_v_in)
37+
call get_available_instance_index(res_available_instance_index)
38+
! MZ check for errors ?
39+
! MZ function with side effect: good idea??
40+
! MZ why res_build is ResultNone??
41+
res_build = instance_array(res_available_instance_index%data_v) % &
42+
build(data_v_in=data_v_in, error_v_in=error_v_in)
3843

3944
! TODO: check build has no error
4045

@@ -46,44 +51,46 @@ subroutine finalise_instance(instance_index)
4651
integer, intent(in) :: instance_index
4752
!! Index of the instance to finalise
4853

49-
call check_index_claimed(instance_index)
54+
type(ResultNone) :: res_check_index_claimed
55+
56+
res_check_index_claimed = check_index_claimed(instance_index)
57+
if(res_check_index_claimed%is_error()) return
5058

5159
call instance_array(instance_index) % finalise()
5260
instance_available(instance_index) = .true.
5361

5462
end subroutine finalise_instance
5563

56-
subroutine get_available_instance_index(available_instance_index)
64+
subroutine get_available_instance_index(res_available_instance_index)
5765
!! Get a free instance index
5866

5967
! TODO: think through whether race conditions are possible
6068
! e.g. while returning a free index number to one Python call
6169
! a different one can be looking up a free instance index at the same time
6270
! and something goes wrong (maybe we need a lock)
6371

64-
integer, intent(out) :: available_instance_index
72+
type(ResultInt), intent(out) :: res_available_instance_index
73+
! integer, intent(out) :: available_instance_index
6574
!! Available instance index
66-
6775
integer :: i
6876

6977
do i = 1, size(instance_array)
7078

7179
if (instance_available(i)) then
7280

7381
instance_available(i) = .false.
74-
available_instance_index = i
82+
! available_instance_index = i
7583
! TODO: switch to returning a Result type
76-
! res = ResultInt(data=i)
84+
res_available_instance_index = ResultInt(data_v=i)
7785
return
7886

7987
end if
8088

8189
end do
8290

8391
! TODO: switch to returning a Result type with an error set
84-
! res = ResultInt(ResultDP(code=1, message="No available instances"))
85-
error stop 1
86-
92+
res_available_instance_index = ResultInt(error_v=ErrorV(code=1, message="No available instances"))
93+
! error stop 1
8794
end subroutine get_available_instance_index
8895

8996
! Change to pure function when we update check_index_claimed to be pure
@@ -95,8 +102,14 @@ function get_instance(instance_index) result(inst)
95102
type(ResultDP) :: inst
96103
!! Instance at `instance_array(instance_index)`
97104

98-
call check_index_claimed(instance_index)
99-
inst = instance_array(instance_index)
105+
type(ResultNone) :: res_check_index_claimed
106+
107+
res_check_index_claimed = check_index_claimed(instance_index)
108+
if(res_check_index_claimed%is_error()) then
109+
inst = ResultDP(error_v=res_check_index_claimed%error_v)
110+
else
111+
inst = instance_array(instance_index)
112+
end if
100113

101114
end function get_instance
102115

@@ -106,19 +119,22 @@ subroutine set_instance_index_to(instance_index, val)
106119
!! Index in `instance_array` of which to set the value equal to `val`
107120

108121
type(ResultDP), intent(in) :: val
122+
type(ResultNone) :: res_check_index_claimed
109123

110-
call check_index_claimed(instance_index)
111-
instance_array(instance_index) = val
124+
res_check_index_claimed = check_index_claimed(instance_index)
125+
if(res_check_index_claimed%is_error()) instance_array(instance_index) = val
112126

113127
end subroutine set_instance_index_to
114128

115-
subroutine check_index_claimed(instance_index)
129+
function check_index_claimed(instance_index) result(res_check_index_claimed)
116130
!! Check that an index has already been claimed
117131
!!
118132
!! Stops execution if the index has not been claimed.
119133

120134
integer, intent(in) :: instance_index
121135
!! Instance index to check
136+
type(ResultNone) :: res_check_index_claimed
137+
character(len=:), allocatable :: msg
122138

123139
if (instance_available(instance_index)) then
124140
! TODO: Switch to using Result here
@@ -128,8 +144,12 @@ subroutine check_index_claimed(instance_index)
128144
! if it fails, the result_dp attribute will be set).
129145
! So the code would be something like
130146
! res = ResultNone(ResultDP(code=1, message="Index ", instance_index, " has not been claimed"))
131-
print *, "Index ", instance_index, " has not been claimed"
132-
error stop 1
147+
! print *, "Index ", instance_index, " has not been claimed"
148+
! error stop 1
149+
! MZ Weird thing allocatable message
150+
msg = ""
151+
write(msg,fmt="(A, I0, A)") "Index ", instance_index," has not been claimed"
152+
res_check_index_claimed = ResultNone(error_v=ErrorV(code=1, message=msg))
133153
end if
134154

135155
if (instance_index < 1) then
@@ -140,8 +160,10 @@ subroutine check_index_claimed(instance_index)
140160
! if it fails, the result_dp attribute will be set).
141161
! So the code would be something like
142162
! res = ResultNone(ResultDP(code=2, message="Requested index is ", instance_index, " which is less than 1"))
143-
print *, "Requested index is ", instance_index, " which is less than 1"
144-
error stop 1
163+
! print *, "Requested index is ", instance_index, " which is less than 1"
164+
! error stop 1
165+
write(msg,fmt="(A, I0, A)") "Requested index is ", instance_index, " which is less than 1"
166+
res_check_index_claimed = ResultNone(error_v=ErrorV(code=2, message=msg))
145167
end if
146168

147169
! ! Here, result becomes
@@ -151,8 +173,9 @@ subroutine check_index_claimed(instance_index)
151173
! ! We will no longer have subroutines that return nothing
152174
! ! (like this one currently does).
153175
! res = ResultNone()
176+
res_check_index_claimed = ResultNone()
154177

155-
end subroutine check_index_claimed
178+
end function check_index_claimed
156179

157180
subroutine ensure_instance_array_size_is_at_least(n)
158181
!! Ensure that `instance_array` and `instance_available` have at least `n` slots

src/example_fgen_basic/result/result_dp_wrapper.f90

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module m_result_dp_w
33

44
use m_error_v, only: ErrorV
55
use m_result_dp, only: ResultDP
6+
use m_result_int, only: ResultInt
67

78
! The manager module, which makes this all work
89
use m_error_v_manager, only: &
@@ -26,7 +27,7 @@ module m_result_dp_w
2627

2728
contains
2829

29-
subroutine build_instance(data_v, error_v_instance_index, instance_index)
30+
subroutine build_instance(data_v, error_v_instance_index, res_available_instance_index)
3031
!! Build an instance
3132

3233
! Annoying that this has to be injected everywhere,
@@ -39,7 +40,8 @@ subroutine build_instance(data_v, error_v_instance_index, instance_index)
3940
integer, intent(in), optional :: error_v_instance_index
4041
!! Error
4142

42-
integer, intent(out) :: instance_index
43+
! integer, intent(out) :: instance_index
44+
type(ResultInt), intent(out) :: res_available_instance_index
4345
!! Instance index of the built instance
4446
!
4547
! This is the major trick for wrapping.
@@ -51,7 +53,7 @@ subroutine build_instance(data_v, error_v_instance_index, instance_index)
5153

5254
error_v = error_v_manager_get_instance(error_v_instance_index)
5355

54-
instance_index = result_dp_manager_build_instance(data_v, error_v)
56+
res_available_instance_index = result_dp_manager_build_instance(data_v, error_v)
5557

5658
end subroutine build_instance
5759

src/example_fgen_basic/result/result_int.f90

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
!> https://github.com/samharrison7/fortran-error-handler
55
module m_result_int
66

7+
use kind_parameters, only: i8
78
use m_error_v, only: ErrorV
89
use m_result, only: ResultBase
910
use m_result_none, only: ResultNone
@@ -14,7 +15,7 @@ module m_result_int
1415
type, extends(ResultBase), public :: ResultInt
1516
!! Result type that holds integer values
1617

17-
integer, allocatable :: data_v
18+
integer(kind=i8), allocatable :: data_v
1819
!! Data i.e. the result (if no error occurs)
1920

2021
! Note: the error_v attribute comes from ResultBase
@@ -42,7 +43,7 @@ function constructor(data_v, error_v) result(self)
4243
type(ResultInt) :: self
4344
! Hopefully can leave without docstring (like Python)
4445

45-
integer, intent(in), optional :: data_v
46+
integer(kind=i8), intent(in), optional :: data_v
4647
!! Data
4748

4849
class(ErrorV), intent(in), optional :: error_v
@@ -73,7 +74,7 @@ function build(self, data_v_in, error_v_in) result(res)
7374
class(ResultInt), intent(out) :: self
7475
! Hopefully can leave without docstring (like Python)
7576

76-
integer, intent(in), optional :: data_v_in
77+
integer(kind=i8), intent(in), optional :: data_v_in
7778
!! Data
7879

7980
class(ErrorV), intent(in), optional :: error_v_in

0 commit comments

Comments
 (0)