Thanks for all the comments, the interest is really encouraging.
@everythingfunctional The idea of simplifying the error catching by passing an error handler routine to catch()
is magnificent. Although, it is not applicable under all circumstances (e.g. if you wanted to return from the subroutine during the error handling), it can shorten the error handling considerably. I’ve extended my implementation accordingly. Now one can do
subroutine main()
type(fatal_error), allocatable :: error
call routine_with_possible_error(..., error)
call catch(error, error_handler)
:
contains
subroutine error_handler(error)
type(fatal_error), intent(in) :: error
! Do whatever is needed to resolve the error
print "(a,a,a,i0,a)", "Fatal error found: '", error%message, "' (code: ", error%code, ")"
end subroutine error_handler
end subroutine main
The error handler routine only contains the error handling code, no deactivation/deallocation boilerplate. And in case of an exception class hierarchy, it even makes the clumsy select type
construct superfluous:
subroutine main()
class(fatal_error), allocatable :: error
call routine_throwing_error(..., error)
call catch_io_error_class(error, handle_io_error)
call catch_linalg_error_class(error, handle_linalg_error)
contains
! Handler for io error
subroutine handle_io_error(error)
class(io_error), intent(in) :: error
print "(2a)", "IO Error found: ", error%message
end subroutine handle_io_error
! Handler for linalg error
subroutine handle_linalg_error(error)
class(linalg_error), intent(in) :: error
print "(2a)", "Linear algebra error found: ", error%message
end subroutine handle_linalg_error
As for chaining the errors, I think, that would add significant complexity. Also, I don’t see at the moment, how you would catch/deactivate the chained errors. Would a catch deactivate all of them? If not, how do you select, which ones get deactivated. And what happens, if different exception classes are added?
I think, it is easier and more robust to extend the base type and provide in the extended type a container for all the data, you want to extract (e.g. a parser_error
containing all the locations, where the parser had problems to understand the content of a file).