Skip to content

Commit fbec11d

Browse files
committed
Improvements and bubbling up errors
1 parent 1c249f9 commit fbec11d

File tree

7 files changed

+58
-54
lines changed

7 files changed

+58
-54
lines changed

src/example_fgen_basic/result/result_dp.f90

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ function constructor(data_v, error_v) result(self)
5151

5252
type(ResultNone) :: build_res
5353

54-
build_res = self % build(data_v_in=data_v, error_v_in=error_v)
54+
call self % build(data_v_in=data_v, error_v_in=error_v, res=build_res)
5555

5656
if (build_res % is_error()) then
5757

@@ -68,7 +68,7 @@ function constructor(data_v, error_v) result(self)
6868

6969
end function constructor
7070

71-
function build(self, data_v_in, error_v_in) result(res)
71+
subroutine build(self, data_v_in, error_v_in, res)
7272
!! Build instance
7373

7474
class(ResultDP), intent(out) :: self
@@ -80,7 +80,7 @@ function build(self, data_v_in, error_v_in) result(res)
8080
class(ErrorV), intent(in), optional :: error_v_in
8181
!! Error message
8282

83-
type(ResultNone) :: res
83+
type(ResultNone), intent(out) :: res
8484
!! Result
8585

8686
if (present(data_v_in) .and. present(error_v_in)) then
@@ -99,7 +99,7 @@ function build(self, data_v_in, error_v_in) result(res)
9999

100100
end if
101101

102-
end function build
102+
end subroutine build
103103

104104
subroutine finalise(self)
105105
!! Finalise the instance (i.e. free/deallocate)

src/example_fgen_basic/result/result_dp_manager.f90

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
1-
!> Manager of `ResultDP` (TODO: xref) across the Fortran-Python interface
1+
!> manager of `resultdp` (todo: xref) across the fortran-python interface
22
module m_result_dp_manager
33

44
use kind_parameters, only: dp
5-
use m_error_v, only: ErrorV
6-
use m_result_dp, only: ResultDP
7-
use m_result_int, only: ResultInt
8-
use m_result_none, only: ResultNone
5+
use m_error_v, only: errorv
6+
use m_result_dp, only: resultdp
7+
use m_result_int, only: resultint
8+
use m_result_none, only: resultnone
99

1010
implicit none(type, external)
1111
private
1212

13-
type(ResultDP), dimension(:), allocatable :: instance_array
13+
type(resultdp), dimension(:), allocatable :: instance_array
1414
logical, dimension(:), allocatable :: instance_available
1515

16-
! TODO: think about ordering here, alphabetical probably easiest
16+
! todo: think about ordering here, alphabetical probably easiest
1717
public :: build_instance, finalise_instance, get_available_instance_index, get_instance, set_instance_index_to, &
1818
ensure_instance_array_size_is_at_least
1919

2020
contains
2121

22-
function build_instance(data_v_in, error_v_in) result(res_available_instance_index)
22+
subroutine build_instance(data_v_in, error_v_in, res_available_instance_index)
2323
!! Build an instance
2424

2525
real(kind=dp), intent(in), optional :: data_v_in
@@ -28,22 +28,28 @@ function build_instance(data_v_in, error_v_in) result(res_available_instance_ind
2828
class(ErrorV), intent(in), optional :: error_v_in
2929
!! Error message
3030

31-
type(ResultInt) :: res_available_instance_index
31+
type(ResultInt) , intent(out) :: res_available_instance_index
3232
!! Index of the built instance
3333

3434
type(ResultNone) :: res_build
3535

3636
call ensure_instance_array_size_is_at_least(1)
3737
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)
4338

44-
! TODO: check build has no error
39+
if (res_available_instance_index % is_error()) return
4540

46-
end function build_instance
41+
call instance_array(res_available_instance_index%data_v) % &
42+
build(data_v_in=data_v_in, error_v_in=error_v_in, res=res_build)
43+
44+
! Check if build failed
45+
if (res_build % is_error()) then
46+
! free slot again
47+
instance_available(res_available_instance_index%data_v) = .true.
48+
! bubble the error up as ResultInt
49+
res_available_instance_index = ResultInt(error_v=res_build%error_v)
50+
end if
51+
52+
end subroutine build_instance
4753

4854
subroutine finalise_instance(instance_index)
4955
!! Finalise an instance
@@ -89,8 +95,9 @@ subroutine get_available_instance_index(res_available_instance_index)
8995
end do
9096

9197
! TODO: switch to returning a Result type with an error set
92-
res_available_instance_index = ResultInt(error_v=ErrorV(code=1, message="No available instances"))
9398
! error stop 1
99+
res_available_instance_index = ResultInt(error_v=ErrorV(code=1, message="No available instances"))
100+
94101
end subroutine get_available_instance_index
95102

96103
! Change to pure function when we update check_index_claimed to be pure
@@ -135,6 +142,8 @@ function check_index_claimed(instance_index) result(res_check_index_claimed)
135142
!! Instance index to check
136143
type(ResultNone) :: res_check_index_claimed
137144
character(len=:), allocatable :: msg
145+
! msg initialisation to avoid compiler warning
146+
msg = ""
138147

139148
if (instance_available(instance_index)) then
140149
! TODO: Switch to using Result here
@@ -146,8 +155,6 @@ function check_index_claimed(instance_index) result(res_check_index_claimed)
146155
! res = ResultNone(ResultDP(code=1, message="Index ", instance_index, " has not been claimed"))
147156
! print *, "Index ", instance_index, " has not been claimed"
148157
! error stop 1
149-
! MZ Weird thing allocatable message
150-
msg = ""
151158
write(msg,fmt="(A, I0, A)") "Index ", instance_index," has not been claimed"
152159
res_check_index_claimed = ResultNone(error_v=ErrorV(code=1, message=msg))
153160
end if

src/example_fgen_basic/result/result_dp_wrapper.f90

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
!> Wrapper for interfacing `m_result_dp` with Python
22
module m_result_dp_w
33

4-
use m_error_v, only: ErrorV
4+
use m_error_v, only: ErrorV, NO_ERROR_CODE
55
use m_result_dp, only: ResultDP
66
use m_result_int, only: ResultInt
7+
use m_result_none, only: ResultNone
78

89
! The manager module, which makes this all work
910
use m_error_v_manager, only: &
@@ -25,22 +26,21 @@ module m_result_dp_w
2526
ensure_at_least_n_instances_can_be_passed_simultaneously, &
2627
data_v_is_set, get_data_v, error_v_is_set, get_error_v
2728

29+
! Annoying that this has to be injected everywhere,
30+
! but ok it can be automated.
31+
integer, parameter :: dp = selected_real_kind(15, 307)
32+
2833
contains
2934

3035
subroutine build_instance(data_v, error_v_instance_index, res_available_instance_index)
3136
!! Build an instance
3237

33-
! Annoying that this has to be injected everywhere,
34-
! but ok it can be automated.
35-
integer, parameter :: dp = selected_real_kind(15, 307)
36-
3738
real(kind=dp), intent(in), optional :: data_v
3839
!! Data
3940

4041
integer, intent(in), optional :: error_v_instance_index
4142
!! Error
4243

43-
! integer, intent(out) :: instance_index
4444
type(ResultInt), intent(out) :: res_available_instance_index
4545
!! Instance index of the built instance
4646
!
@@ -51,9 +51,15 @@ subroutine build_instance(data_v, error_v_instance_index, res_available_instance
5151
! We use the manager layer to initialise the attributes before passing on.
5252
type(ErrorV) :: error_v
5353

54-
error_v = error_v_manager_get_instance(error_v_instance_index)
54+
if (present(error_v_instance_index)) then
55+
error_v = error_v_manager_get_instance(error_v_instance_index)
56+
else
57+
! No error provided: initialize empty error
58+
error_v%code = NO_ERROR_CODE
59+
error_v%message = ""
60+
end if
5561

56-
res_available_instance_index = result_dp_manager_build_instance(data_v, error_v)
62+
call result_dp_manager_build_instance(data_v, error_v, res_available_instance_index)
5763

5864
end subroutine build_instance
5965

@@ -130,10 +136,6 @@ subroutine get_data_v( &
130136
data_v &
131137
)
132138

133-
! Annoying that this has to be injected everywhere,
134-
! but ok it can be automated.
135-
integer, parameter :: dp = selected_real_kind(15, 307)
136-
137139
integer, intent(in) :: instance_index
138140

139141
real(kind=dp), intent(out) :: data_v

src/example_fgen_basic/result/result_int.f90

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ function constructor(data_v, error_v) result(self)
5151

5252
type(ResultNone) :: build_res
5353

54-
build_res = self % build(data_v_in=data_v, error_v_in=error_v)
54+
call self % build(data_v_in=data_v, error_v_in=error_v, res= build_res)
5555

5656
if (build_res % is_error()) then
5757

@@ -68,19 +68,19 @@ function constructor(data_v, error_v) result(self)
6868

6969
end function constructor
7070

71-
function build(self, data_v_in, error_v_in) result(res)
71+
subroutine build(self, data_v_in, error_v_in, res)
7272
!! Build instance
7373

74-
class(ResultInt), intent(out) :: self
75-
! Hopefully can leave without docstring (like Python)
76-
7774
integer(kind=i8), intent(in), optional :: data_v_in
7875
!! Data
7976

8077
class(ErrorV), intent(in), optional :: error_v_in
8178
!! Error message
8279

83-
type(ResultNone) :: res
80+
class(ResultInt), intent(inout) :: self
81+
! Hopefully can leave without docstring (like Python)
82+
83+
type(ResultNone), intent(inout) :: res
8484
!! Result
8585

8686
if (present(data_v_in) .and. present(error_v_in)) then
@@ -99,7 +99,7 @@ function build(self, data_v_in, error_v_in) result(res)
9999

100100
end if
101101

102-
end function build
102+
end subroutine build
103103

104104
subroutine finalise(self)
105105
!! Finalise the instance (i.e. free/deallocate)

src/example_fgen_basic/result/result_int.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
@define
2323
class ResultInt:
2424
"""
25-
Result type that can hold double precision real values
25+
Result type that can hold (8 bit) integer values
2626
"""
2727

2828
# TODO: add validation that one of data_v and error_v is provided but not both

src/example_fgen_basic/result/result_int_manager.f90

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ function build_instance(data_v_in, error_v_in) result(instance_index)
3434

3535
call ensure_instance_array_size_is_at_least(1)
3636
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)
38-
! MZ: Is the line above correct??
37+
call instance_array(instance_index) % build(data_v_in=data_v_in, error_v_in=error_v_in, res=res_build)
3938
! TODO: check build has no error
4039

4140
end function build_instance

src/example_fgen_basic/result/result_int_wrapper.f90

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,23 @@ module m_result_int_w
1616
result_int_manager_finalise_instance => finalise_instance, &
1717
result_int_manager_get_instance => get_instance, &
1818
result_int_manager_ensure_instance_array_size_is_at_least => ensure_instance_array_size_is_at_least
19-
!MZ: Set instance?
19+
2020
implicit none(type, external)
2121
private
2222

2323
public :: build_instance, finalise_instance, finalise_instances, &
2424
ensure_at_least_n_instances_can_be_passed_simultaneously, &
2525
data_v_is_set, get_data_v, error_v_is_set, get_error_v
2626

27+
! Annoying that this has to be injected everywhere,
28+
! but ok it can be automated.
29+
integer, parameter :: i8 = selected_int_kind(18)
30+
2731
contains
2832

2933
subroutine build_instance(data_v, error_v_instance_index, instance_index)
3034
!! Build an instance
3135

32-
! Annoying that this has to be injected everywhere,
33-
! but ok it can be automated.
34-
integer, parameter :: i8 = selected_int_kind(18)
35-
3636
integer(kind=i8), intent(in), optional :: data_v
3737
!! Data
3838

@@ -128,10 +128,6 @@ subroutine get_data_v( &
128128
data_v &
129129
)
130130

131-
! Annoying that this has to be injected everywhere,
132-
! but ok it can be automated.
133-
integer, parameter :: i8 = selected_int_kind(18)
134-
135131
integer, intent(in) :: instance_index
136132

137133
integer(kind=i8), intent(out) :: data_v

0 commit comments

Comments
 (0)