I'be been looking at some of the proposals (here) for error-handling in Fortran, and even though they're good, none of them seem to take advantage of existing Fortran idioms, but rather borrow heavily from other language(s).
One of the things I like in Fortran 2023 is the enumeration type ---which would be perfect, had it included the option for a formatted type-bound write.
Using that enumeration type as a guideline, an exception could be declared as:
module my_exceptions
implicit none
private
exceptions type, public :: io_ex
exception :: open_error, read_error
exception :: write_error
contains
write(formatted) :: write_io_ex !<-- there is no need for generic here
end exceptions type
exceptions type, public :: print_only
exception :: to_error_unit
exception :: to_log
end exceptions type
contains
subroutine write_io_ex(dtv, unit, iotype, v_list, iostat, iomsg)
...
select case (dtv)
case (open_error)
write (unit, '(...)') 'error opening unit...'
end select
end subroutine
end module my_exceptions
With that, I think subroutines (and only a subroutines i.m.o.) could declare and "throw" exceptions like this:
module my_io
use my_exceptions
implicit none
contains
subroutine sub(arg) failing with(io_ex, print_only) !<-- annotate expected failures
...
open (NEWUNIT = unit, IOSTAT = ios, ...)
if (ios /= 0) fail with (open_error) !<-- throw exception here
...
close (unit, IOSTAT = ios)
if (ios /= 0) fail with (to_error_unit) !<-- thrown at the end, so failure could be ignored
end subroutine
end module my_io
And another program unit calling the subroutine could do this:
program test
use my_io
use iso_fortran_env
implicit none
exception :: handle_ex !<-- define the variable "catching" the exception
call sub(arg) with (handle_ex) !<-- without the "with (handle_ex)", the failure would propagate up the stack
! handling alternative one: handle by exception
select case (handle_ex)
case (open_error)
print *, handle_ex
case (to_error_unit)
write (ERROR_UNIT, *) handle_ex !<-- error, no formatted type-bound write
case default
...
end select
! alternative 2: handle by type
select type (handle_ex)
type is (io_ex)
...
type is (print_only)
...
class default
...
end select
end program test
With that, the exception handling facilities could be defined by leveraging existing features, avoiding reliance on inheritance, and not having to deal with explicit error codes.
There might be some pending details though, like
If going the subroutines-only route for the failing with(...) annotation, disallowing it in subroutines contained within functions,
Whether to allow an extra message in the fail with statement (e.g., fail with (open_error, "/etc/config not found")), and how to retrieve it from the formatted type-bound write,
...
And although I think a try-catch block would be unnecessary with the above, for syntactic-sugar purposes it could be something like
exception :: catcher
...
failing [ with (catcher) ] !<-- the "with (catcher)" is optional
call sub(arg)
recover from (open_error, print_only)
select case (catcher) !<-- only possible if catcher is explicit for the failing block
...
end select
select type (catcher) !<-- only possible if catcher is explicit for the failing block
...
end select
recover from (write_error)
...
recover all
...
end failing
I'be been looking at some of the proposals (here) for error-handling in Fortran, and even though they're good, none of them seem to take advantage of existing Fortran idioms, but rather borrow heavily from other language(s).
One of the things I like in Fortran 2023 is the
enumeration type
---which would be perfect, had it included the option for a formatted type-bound write.Using that
enumeration type
as a guideline, an exception could be declared as:With that, I think subroutines (and only a subroutines i.m.o.) could declare and "throw" exceptions like this:
And another program unit calling the subroutine could do this:
With that, the exception handling facilities could be defined by leveraging existing features, avoiding reliance on inheritance, and not having to deal with explicit error codes.
There might be some pending details though, like
failing with(...)
annotation, disallowing it in subroutines contained within functions,fail with
statement (e.g.,fail with (open_error, "/etc/config not found")
), and how to retrieve it from the formatted type-bound write,And although I think a try-catch block would be unnecessary with the above, for syntactic-sugar purposes it could be something like
So, any thoughts on the above?