private pure subroutine error_wrap(self, code, message)
Wrap the current error with a higher-level context
Pushes the current error into the cause chain and sets a new
top-level code and message (Rust-style “caused by”)
Print order: outermost wrapper first, root cause last (like Rust).
Usage:
call parse_json(data, err)
if (err%has_error()) then
call err%wrap(ERROR_PARSE, “failed to load config file”)
return
end if
Produces:
ERROR_PARSE: failed to load config file
Caused by: ERROR_IO: could not read file “input.json”
Limits. The top-level message is deferred-length and never
truncated, but a message pushed into the cause chain has to fit a
fixed MAX_CAUSE_MSG_LEN slot; anything longer keeps its head and
ends with TRUNCATION_MARKER so the clipping is visible. Likewise
only MAX_CAUSE_DEPTH causes are stored: the root cause is always
kept and further wraps bump omitted_causes, which the traces
report as “N intermediate cause(s) omitted”, so a deep chain is
never silently presented as complete.
Nodes of different colours represent the following:
Solid arrows point from a procedure to one which it calls. Dashed
arrows point from an interface to procedures which implement that interface.
This could include the module procedures in a generic interface or the
implementation in a submodule of an interface in a parent module.
Where possible, edges connecting nodes are
given different colours to make them easier to distinguish in
large graphs.
Nodes of different colours represent the following:
Solid arrows point from a procedure to one which it calls. Dashed
arrows point from an interface to procedures which implement that interface.
This could include the module procedures in a generic interface or the
implementation in a submodule of an interface in a parent module.
Where possible, edges connecting nodes are
given different colours to make them easier to distinguish in
large graphs.
Source Code
pure subroutine error_wrap(self,code,message)!! Wrap the current error with a higher-level context!! Pushes the current error into the cause chain and sets a new!! top-level code and message (Rust-style "caused by")!!!! Print order: outermost wrapper first, root cause last (like Rust).!!!! Usage:!! call parse_json(data, err)!! if (err%has_error()) then!! call err%wrap(ERROR_PARSE, "failed to load config file")!! return!! end if!!!! Produces:!! ERROR_PARSE: failed to load config file!! Caused by: ERROR_IO: could not read file "input.json"!!!! Limits. The top-level `message` is deferred-length and never!! truncated, but a message pushed into the cause chain has to fit a!! fixed MAX_CAUSE_MSG_LEN slot; anything longer keeps its head and!! ends with TRUNCATION_MARKER so the clipping is visible. Likewise!! only MAX_CAUSE_DEPTH causes are stored: the root cause is always!! kept and further wraps bump `omitted_causes`, which the traces!! report as "N intermediate cause(s) omitted", so a deep chain is!! never silently presented as complete.class(error_t),intent(inout)::selfinteger(default_int),intent(in)::codecharacter(len=*),intent(in)::messageif(.not.self%has_error())return! Push current error into cause chainif(self%cause_depth<MAX_CAUSE_DEPTH)thenself%cause_depth=self%cause_depth+1self%cause_codes(self%cause_depth)=self%codeif(allocated(self%message))thenself%cause_messages(self%cause_depth)=clip_tail(self%message)elseself%cause_messages(self%cause_depth)="(no message)"end if else! Chain is full. The root cause matters most, so keep what is stored! and record that a middle layer was dropped.self%omitted_causes=self%omitted_causes+1end if! Set new top-level errorself%code=codeself%message=trim(message)end subroutine error_wrap