Skip to content

Commit 3c57801

Browse files
committed
Add notes
1 parent 801c945 commit 3c57801

4 files changed

Lines changed: 124 additions & 3 deletions

File tree

meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ if pyprojectwheelbuild_enabled
6868
'src/example_fgen_basic/fpyfgen/derived_type_manager_helpers.f90',
6969
'src/example_fgen_basic/get_wavelength.f90',
7070
'src/example_fgen_basic/kind_parameters.f90',
71+
'src/example_fgen_basic/result/result.f90',
7172
)
7273

7374
# All Python files (wrappers and otherwise)

src/example_fgen_basic/error_v/error_v.f90

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
!>
66
!> Fortran doesn't have a null value.
77
!> As a result, we introduce this derived type
8-
!> with the convention that a code of 0 indicates no error.
8+
!> with the convention that a code of `NO_ERROR_CODE` (0)
9+
!> indicates no error (i.e. is our equivalent of a null value).
910
module m_error_v
1011

1112
implicit none

src/example_fgen_basic/error_v/error_v_manager.f90

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,16 @@ subroutine get_available_instance_index(available_instance_index)
6868

6969
instance_available(i) = .false.
7070
available_instance_index = i
71+
! TODO: switch to returning a Result type
72+
! res = ResultInt(data=i)
7173
return
7274

7375
end if
7476

7577
end do
7678

7779
! TODO: switch to returning a Result type with an error set
80+
! res = ResultInt(ErrorV(code=1, message="No available instances"))
7881
error stop 1
7982

8083
end subroutine get_available_instance_index
@@ -114,17 +117,37 @@ subroutine check_index_claimed(instance_index)
114117
!! Instance index to check
115118

116119
if (instance_available(instance_index)) then
117-
! TODO: switch to errors here - will require some thinking
120+
! TODO: Switch to using Result here
121+
! Use `ResultNone` which is a Result type
122+
! that doesn't have a `data` attribute
123+
! (i.e. if this succeeds, there is no data to check,
124+
! if it fails, the error_v attribute will be set).
125+
! So the code would be something like
126+
! res = ResultNone(ErrorV(code=1, message="Index ", instance_index, " has not been claimed"))
118127
print *, "Index ", instance_index, " has not been claimed"
119128
error stop 1
120129
end if
121130

122131
if (instance_index < 1) then
123-
! TODO: switch to errors here - will require some thinking
132+
! TODO: Switch to using Result here
133+
! Use `ResultNone` which is a Result type
134+
! that doesn't have a `data` attribute
135+
! (i.e. if this succeeds, there is no data to check,
136+
! if it fails, the error_v attribute will be set).
137+
! So the code would be something like
138+
! res = ResultNone(ErrorV(code=2, message="Requested index is ", instance_index, " which is less than 1"))
124139
print *, "Requested index is ", instance_index, " which is less than 1"
125140
error stop 1
126141
end if
127142

143+
! ! Here, result becomes
144+
! ! Now that I've thought about this, it's also clear
145+
! ! that we will only use functions
146+
! ! or subroutines with a result type that has `intent(out)`.
147+
! ! We will no longer have subroutines that return nothing
148+
! ! (like this one currently does).
149+
! res = ResultNone()
150+
128151
end subroutine check_index_claimed
129152

130153
subroutine ensure_instance_array_size_is_at_least(n)
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
!> Result value
2+
!>
3+
!> Inspired by the excellent, MIT licensed
4+
!> https://github.com/samharrison7/fortran-error-handler
5+
module m_result
6+
7+
implicit none
8+
private
9+
10+
type, abstract, public :: Result
11+
!! Result type
12+
!!
13+
!! Holds either the result or an error.
14+
15+
class(*), allocatable :: data(..)
16+
!! Data i.e. the result (if no error occurs)
17+
!!
18+
! Assumed rank array
19+
! (https://fortran-lang.discourse.group/t/assumed-rank-arrays/1049)
20+
! Technically a Fortran 2018 feature,
21+
! so maybe we need to update our file extensions.
22+
! If we can't use this, just comment this out
23+
! and leave each subclass of Result to set its data type
24+
! (e.g. ResultInteger will have `integer :: data`,
25+
! ResultDP1D will have `real(dp), dimension(:), allocatable :: data`)
26+
27+
class(ErrorV), allocatable :: error_v
28+
!! Error
29+
30+
contains
31+
32+
private
33+
34+
procedure, public:: build, finalise, is_error
35+
! TODO: Think about whether build should be on the abstract class
36+
! or just on each concrete implementation
37+
38+
end type Result
39+
40+
interface Result
41+
!! Constructor interface - see build (TODO: figure out cross-ref syntax) for details
42+
module procedure :: constructor
43+
end interface Result
44+
45+
contains
46+
47+
! See above about whether we include this here or not
48+
! Build should return a Result with an error if we try to set/allocate both
49+
! data and error
50+
! subroutine build(self, code, message)
51+
! !! Build instance
52+
!
53+
! class(ErrorV), intent(inout) :: self
54+
! ! Hopefully can leave without docstring (like Python)
55+
!
56+
! integer, intent(in) :: code
57+
! !! Error code
58+
! !!
59+
! !! Use [TODO: figure out xref] `NO_ERROR_CODE` if there is no error
60+
!
61+
! character(len=*), optional, intent(in) :: message
62+
! !! Error message
63+
!
64+
! self % code = code
65+
! if (present(message)) then
66+
! self % message = message
67+
! end if
68+
!
69+
! end subroutine build
70+
71+
subroutine finalise(self)
72+
!! Finalise the instance (i.e. free/deallocate)
73+
74+
class(Result), intent(inout) :: self
75+
! Hopefully can leave without docstring (like Python)
76+
77+
deallocate(self % data)
78+
deallocate(self % error)
79+
80+
end subroutine finalise
81+
82+
pure function is_error(self) result(is_err)
83+
!! Determine whether `self` contains an error or not
84+
85+
class(Result), intent(in) :: self
86+
! Hopefully can leave without docstring (like Python)
87+
88+
logical :: is_err
89+
! Whether `self` is an error or not
90+
91+
is_err = self % error_v % is_error()
92+
! TODO: implement is_error on `error_v`
93+
94+
end function is_error
95+
96+
end module m_result

0 commit comments

Comments
 (0)