Error handlng

This commit is contained in:
Vitor Santos Costa 2018-05-27 00:47:03 +01:00
parent eeb8f7c6a1
commit b59af58616
16 changed files with 59 additions and 404 deletions

View File

@ -50,11 +50,11 @@ static xarg *failed__(yap_error_number e, Term t, xarg *a USES_REGS) {
xarg *Yap_ArgListToVector(Term listl, const param_t *def, int n) {
CACHE_REGS
listl = Deref(listl);
if (IsVarTerm(listl)) {
Yap_ThrowError(INSTANTIATION_ERROR, listl, "while opening a list of options");
}
xarg *a = calloc(n, sizeof(xarg));
if (IsVarTerm(listl)) {
return failed(INSTANTIATION_ERROR, listl, a);
}
if (IsApplTerm(listl) && FunctorOfTerm(listl) == FunctorModule)
listl = ArgOfTerm(2, listl);
if (!IsPairTerm(listl) && listl != TermNil) {
@ -144,7 +144,11 @@ static xarg *matchKey2(Atom key, xarg *e0, int n, const param2_t *def) {
/// scope
xarg *Yap_ArgList2ToVector(Term listl, const param2_t *def, int n) {
CACHE_REGS
xarg *a = calloc(n, sizeof(xarg));
listl = Deref(listl);
if (IsVarTerm(listl)) {
Yap_ThrowError(INSTANTIATION_ERROR, listl, "while opening a list of options");
}
xarg *a = calloc(n, sizeof(xarg));
if (!IsPairTerm(listl) && listl != TermNil) {
if (IsVarTerm(listl)) {
return failed(INSTANTIATION_ERROR, listl, a);

View File

@ -1725,8 +1725,6 @@ X_API bool YAP_EnterGoal(YAP_PredEntryPtr ape, CELL *ptr, YAP_dogoalinfo *dgi) {
BACKUP_MACHINE_REGS();
LOCAL_ActiveError->errorNo = YAP_NO_ERROR;
LOCAL_PrologMode = UserMode;
if( LOCAL_CommittedError)
LOCAL_CommittedError->errorNo = YAP_NO_ERROR;
dgi->p = P;
dgi->cp = CP;
dgi->CurSlot = LOCAL_CurSlot;
@ -1845,8 +1843,8 @@ X_API bool YAP_LeaveGoal(bool successful, YAP_dogoalinfo *dgi) {
P = dgi->p;
LOCAL_CurSlot = dgi->CurSlot;
RECOVER_MACHINE_REGS();
fprintf(stderr,"LeftGoal success=%d: H=%d ENV=%p B=%d TR=%d P=%p CP=%p Slots=%d\n",
successful,HR-H0,LCL0-ENV,LCL0-(CELL*)B,(CELL*)TR-LCL0, P, CP, LOCAL_CurSlot);
// fprintf(stderr,"LeftGoal success=%d: H=%d ENV=%p B=%d TR=%d P=%p CP=%p Slots=%d\n",
// successful,HR-H0,LCL0-ENV,LCL0-(CELL*)B,(CELL*)TR-LCL0, P, CP, LOCAL_CurSlot);
return TRUE;
}

View File

@ -865,7 +865,11 @@ yamop *Yap_Error__(bool throw, const char *file, const char *function,
}
static Int close_error(USES_REGS1) {
LOCAL_Error_TYPE = YAP_NO_ERROR;
if (!LOCAL_CommittedError)
return true;
LOCAL_CommittedError->errorNo = YAP_NO_ERROR;
free(LOCAL_CommittedError);
LOCAL_CommittedError = NULL;
return true;
}
@ -955,7 +959,8 @@ yap_error_descriptor_t *Yap_GetException(yap_error_descriptor_t *i ) {
void Yap_PrintException(void) { printErr(LOCAL_ActiveError); }
bool Yap_RaiseException(void) {
if (LOCAL_ActiveError->errorNo == YAP_NO_ERROR)
if (LOCAL_CommittedError == NULL ||
LOCAL_CommittedError->errorNo == YAP_NO_ERROR)
return false;
return Yap_JumpToEnv();
}
@ -970,7 +975,9 @@ bool Yap_ResetException(yap_error_descriptor_t *i) {
return true;
}
static Int reset_exception(USES_REGS1) { return Yap_ResetException(worker_id); }
static Int reset_exception(USES_REGS1) {
return Yap_ResetException(worker_id); }
Term MkErrorTerm(yap_error_descriptor_t *t) {
if (t->errorClass == EVENT)
@ -1020,18 +1027,12 @@ static Int new_exception(USES_REGS1) {
return Yap_unify(ARG1, t);
}
static Int committed_exception(USES_REGS1) {
Term t = MkSysError(LOCAL_CommittedError);
return Yap_unify(ARG1, t);
}
static Int get_exception( USES_REGS1) {
yap_error_descriptor_t *i;
Term t;
i = LOCAL_ActiveError;
if (i && i->errorNo != YAP_NO_ERROR) {
i = Yap_GetException(LOCAL_CommittedError);
if (LOCAL_ActiveError->errorNo != YAP_NO_ERROR) {
i = Yap_GetException(LOCAL_ActiveError);
Yap_ResetException(LOCAL_ActiveError);
LOCAL_PrologMode = UserMode;
if (i->errorRawTerm &&
@ -1216,7 +1217,6 @@ void Yap_InitErrorPreds(void) {
Yap_InitCPred("$get_exception", 1, get_exception, 0);
Yap_InitCPred("$read_exception", 2, read_exception, 0);
Yap_InitCPred("$query_exception", 3, query_exception, 0);
Yap_InitCPred("$committed_exception", 1, committed_exception, 0);
Yap_InitCPred("$drop_exception", 1, drop_exception, 0);
Yap_InitCPred("$close_error", 0, close_error, HiddenPredFlag);
Yap_InitCPred("is_boolean", 2, is_boolean, TestPredFlag);

View File

@ -205,7 +205,7 @@ static void consult(const char *b_file USES_REGS) {
}
yap_error_descriptor_t *errd;
if ((errd =
Yap_GetException(LOCAL_CommittedError))) {
Yap_GetException(LOCAL_ActiveError))) {
fprintf(stderr, "%s:%ld:0: Error %s %s Found\n", errd->errorFile, (long int) errd->errorLine, errd->classAsText,
errd->errorAsText);
}

View File

@ -35,7 +35,7 @@ X_API bool do_init_python(void);
static void YAPCatchError()
{
if (false && LOCAL_CommittedError != nullptr &&
if (LOCAL_CommittedError != nullptr &&
LOCAL_CommittedError->errorNo != YAP_NO_ERROR ) {
// Yap_PopTermFromDB(info->errorTerm);
// throw throw YAPError( );
@ -555,10 +555,9 @@ bool YAPEngine::mgoal(Term t, Term tmod, bool release) {
// PyEval_RestoreThread(_save);
RECOVER_MACHINE_REGS();
return result;
} catch (...) {
} catch (...) {
YAPCatchError();
// free(LOCAL_CommittedError);
return false;
}
}
@ -1050,12 +1049,17 @@ void YAPEngine::reSet() {
P = FAILCODE;
Yap_exec_absmi(true, YAP_EXEC_ABSMI);
/* recover stack space */
LOCAL_ActiveError->errorNo = YAP_NO_ERROR;
if (H0+q.h < HR)
HR = H0+q.h;
if (LCL0+q.tr < (CELL*)TR)
TR = (tr_fr_ptr)(LCL0+q.tr);
Yap_CloseHandles( q.CurSlot );
LOCAL_ActiveError->errorNo = YAP_NO_ERROR;
if (LOCAL_CommittedError) {
LOCAL_CommittedError->errorNo = YAP_NO_ERROR;
free(LOCAL_CommittedError );
LOCAL_CommittedError = NULL;
}
RECOVER_MACHINE_REGS();
}

View File

@ -195,7 +195,7 @@ LOCAL(ADDR, TrailTop);
/* error handling info, designed to be easy to pass to the foreign world */
LOCAL_INIT(yap_error_descriptor_t *, ActiveError, calloc(sizeof(yap_error_descriptor_t), 1));
LOCAL_INIT(yap_error_descriptor_t *, CommittedError, calloc(sizeof(yap_error_descriptor_t), 1));
LOCAL_INIT(yap_error_descriptor_t *, CommittedError, NULL);
LOCAL_INIT(bool, delay, false);
/// pointer to an exception term, from throw
LOCAL(jmp_buf, IOBotch);

View File

@ -75,6 +75,7 @@ E(DOMAIN_ERROR_SOURCE_SINK, DOMAIN_ERROR, "source_sink")
E(DOMAIN_ERROR_SOLUTIONS, DOMAIN_ERROR, "solutions")
E(DOMAIN_ERROR_STREAM, DOMAIN_ERROR, "stream")
E(DOMAIN_ERROR_STREAM_ENCODING, DOMAIN_ERROR, "stream_encoding")
E(DOMAIN_ERROR_STREAM_OPTION, DOMAIN_ERROR, "stream_option")
E(DOMAIN_ERROR_STREAM_OR_ALIAS, DOMAIN_ERROR, "stream_or_alias")
E(DOMAIN_ERROR_STREAM_POSITION, DOMAIN_ERROR, "stream_position")
E(DOMAIN_ERROR_STREAM_PROPERTY_OPTION, DOMAIN_ERROR, "stream_property_option")

View File

@ -151,6 +151,7 @@ int Yap_open_buf_read_stream(const char *buf, size_t nchars, encoding_t *encp,
encoding = LOCAL_encoding;
// like any file stream.
f = st->file = fmemopen((void *)buf, nchars, "r");
st->vfs = NULL;
flags = Input_Stream_f | InMemory_Stream_f | Seekable_Stream_f;
Yap_initStream(sno, f, "memStream", "r", TermNone, encoding, flags, NULL);
// like any file stream.
@ -172,7 +173,7 @@ open_mem_read_stream(USES_REGS1) /* $open_mem_read_stream(+List,-Stream) */
if (!buf) {
return false;
}
buf = pop_output_text_stack(l, buf);
buf = pop_output_text_stack(l, buf);
sno = Yap_open_buf_read_stream(buf, strlen(buf) + 1, &LOCAL_encoding,
MEM_BUF_MALLOC);
t = Yap_MkStream(sno);

View File

@ -1237,7 +1237,10 @@ static Int do_open(Term file_name, Term t2, Term tlist USES_REGS) {
encoding_t encoding;
Term tenc;
char io_mode[8];
file_name = Deref( file_name);
if (IsVarTerm(file_name)) {
Yap_ThrowError(INSTANTIATION_ERROR, file_name, "while opening a list of options");
}
// open mode
if (IsVarTerm(t2)) {
Yap_Error(INSTANTIATION_ERROR, t2, "open/3");
@ -1321,7 +1324,7 @@ static Int do_open(Term file_name, Term t2, Term tlist USES_REGS) {
#endif
/* note that this matters for UNICODE style conversions */
} else {
Yap_Error(DOMAIN_ERROR_STREAM, tlist,
Yap_Error(DOMAIN_ERROR_STREAM_OPTION, t,
"type is ~a, must be one of binary or text", t);
}
}
@ -1584,15 +1587,16 @@ int Yap_OpenStream(Term tin, const char *io_mode, Term user_name,
} else {
st->file = fopen(fname, io_mode);
if (st->file == NULL) {
UNLOCK(st->streamlock);
if (errno == ENOENT && !strchr(io_mode, 'r')) {
PlIOError(EXISTENCE_ERROR_SOURCE_SINK, tin, "%s: %s", fname,
strerror(errno));
} else {
PlIOError(PERMISSION_ERROR_OPEN_SOURCE_SINK, tin, "%s: %s", fname,
UNLOCK(st->streamlock);
if (errno == ENOENT && !strchr(io_mode, 'r')) {
PlIOError(EXISTENCE_ERROR_SOURCE_SINK, tin, "%s: %s", fname,
strerror(errno));
} else {
PlIOError(PERMISSION_ERROR_OPEN_SOURCE_SINK, tin, "%s: %s", fname,
strerror(errno));
}
}
}
st->vfs = NULL;
}
if (!st->file && !st->vfs) {
PlIOError(EXISTENCE_ERROR_SOURCE_SINK, tin, "%s", fname);
@ -1636,6 +1640,8 @@ int Yap_OpenStream(Term tin, const char *io_mode, Term user_name,
user_name = tin;
flags |= Popen_Stream_f;
pop_text_stack(i);
} else {
Yap_ThrowError(DOMAIN_ERROR_SOURCE_SINK, tin, "open");
}
}
if (!strchr(io_mode, 'b') && binary_file(fname)) {

View File

@ -9,6 +9,7 @@
show_answer/3,
yap_query/4,
python_query/2,
python_query/3,
yapi_query/2
]).

View File

@ -1,258 +0,0 @@
/**
* @file jupyter.yap
*
* @brief allow interaction between Jupyter and YAP.
*
* @long The code in here:
* - establishes communication between Prolog and Python Streams
* - inputs Prolog code and queries
* - supports completion of Prolog programs.
* -
*/
%% :- module( jupyter,
%% [jupyter_query/3,
%% errors/2,
%% ready/2,
%% completion/2,
%% ]
%% ).
:- reexport(library(yapi)).
:- use_module(library(lists)).
:- use_module(library(maplist)).
:- use_module(library(python)).
:- python_import(sys).
jupyter_query(Self, Cell, Line ) :-
setup_call_cleanup(
enter_cell(Self),
jupyter_cell(Self, Cell, Line),
exit_cell(Self)
).
jupyter_cell(_Self, Cell, _) :-
jupyter_consult(Cell),
fail.
jupyter_cell( _Self, _, Line ) :-
blank( Line ),
!.
jupyter_cell( _Self, _, [] ) :- !.
jupyter_cell( Self, _, Line ) :-
python_query( Self, Line ).
jupyter_consult(Text) :-
blank( Text ),
!.
jupyter_consult(Cell) :-
open_mem_read_stream( Cell, Stream),
load_files(user:'jupyter cell',[stream(Stream)]).
%should load_files close?
blank(Text) :-
atom_codes(Text, L),
maplist( blankc, L).
blankc(' ').
blankc('\n').
blankc('\t').
enter_cell(_Self) :-
%open('//python/input', read, _Input, []),
open('//python/sys.stdout', append, _Output, []),
open('//python/sys.stdout', append, _Error, []),
%set_prolog_flag(user_input, _Input),
set_prolog_flag(user_output, _Output),
set_prolog_flag(user_error, _Error).
exit_cell(_Self) :-
%close( user_input),
close( user_output),
close( user_error).
completions(S, Self) :-
open_mem_read_stream(S, St),
scan_to_list(St, Tokens),
close(St),
reverse(Tokens, RTokens),
strip_final_tokens(RTokens, MyTokens),
setof( Completion, complete(MyTokens, Completion), Cs),
Self.matches := Cs.
strip_final_tokens(['EOT'|Ts], Ts) :- !.
strip_final_tokens( Ts, Ts ).
complete([E,l,C,l,A|More],
isconsult(A),
%B = l,
library(C,Lib),
%D=l,
E=atom(Prefix),
\+ arg( Rest ),
check_library( Prefix, Lib, C).
complete([E,l,C,l,-,'['|More],
isconsult(A),
%B = l,
library(C,Lib),
%D=l,
E=atom(Prefix),
\+ arg( Rest ),
check_library( Prefix, Lib, C).
complete([C,l,A|More],
isconsult(A),
%B = l,
C=atom(Prefix),
\+ arg( Rest ),
file_or_library( Prefix, C).
complete([C,l,-,'['|More],
isconsult(A),
%B = l,
C=atom(Prefix),
\+ arg( Rest ),
file_or_library( Prefix, C).
complete( [atom(F)|Rest], C) :-
\+ arg( Rest ),
predicate( F, Pred, Arity ),
cont( Arity, F, Pred, C).
isconsult( atom(use_module) ).
isconsult( atom(ensure_loaded) ).
isconsult( atom(compile) ).
isconsult( atom(consult) ).
isconsult( atom(reconsult) ).
isconsult( atom(load_files) ).
isconsult( '[' ).
arg([']'|_]).
arg([l|_]).
file_or_library(F,C) :-
libsym(C0),
atom_cooncat(F,C,C0).
file_or_library(F,C) :-
check_file(F,C).
check_file(F0,C) :-
atom_concat('\'',F,F0),
!,
absolute_file_name( F, FF, [access(none)] ),
atom_concat( FF, '*' , Pat),
absolute_file_name( Pat, C0, [glob(true)] ),
atom_concat(Pat,C00,C0),
atom_conct(C00,'\'',C).
check_file(F0,C) :-
atom_concat( F0, '*' , Pat),
absolute_file_name( Pat, C0, [glob(true)] ),
atom_concat(Pat,C,C0).
check_library( Lib, F, C) :-
atom_concat( F, '*' , Pat),
LibF =.. [Lib(Pat)],
absolute_file_name( LibF, Lib, [glob(true)] ),
file_directory_name( Lib, Name),
( atom_concat(C, '.yap', Name) -> true ;
atom_concat(C, '.ypp', Name) -> true ;
atom_concat(C, '.prolog', Name) -> true
).
predicate(N,P,A) :-
system_predicate(P0/A),
atom_concat(N,P,P0).
predicate(N,P,A) :-
current_predicate(P0/A),
atom_concat(N,P,P0).
cont(0, F, P, P0) :-
atom_concat( F, P, P0 ).
cont( _, F, P, PB ):-
atom_concat( [F, P, '('], PB ).
ready(_Self, Line ) :-
blank( Line ),
!.
ready(Self, Line ) :-
errors( Self, Line ),
\+ syntax_error(_,_).
errors( Self, Text ) :-
setup_call_cleanup(
open_events( Self, Text, Stream),
clauses(Self, Stream),
close_events( Self )
).
clauses(Self, Stream) :-
repeat,
read_clause(Stream, Cl, [term_position(_Pos), syntax_errors(fail)] ),
command( Self, Cl ),
Cl == end_of_file,
!.
command(_, end_of_file) :- !.
command( _Self, ( :- op(Prio,Assoc,Name) ) ) :-
addop(Prio,Assoc,Name).
command( _Self, ( :- module(Name, Exports) )) :-
retract( active_module( M0 ) ),
atom_concat( '__m0_', Name, M ),
assert( active_module(M) ),
assert( undo( active_module(M0) ) ),
maplist( addop2(M), Exports).
addop(Prio,Assoc,Name) :-
(
current_op(OPrio, SimilarAssoc, Name),
op(Prio, Assoc, Name),
matched_op(Assoc, SimilarAssoc)
->
assertz( undo(op( OPrio, Assoc, Name ) ) )
;
assertz( undo(op( 0, Assoc, Name ) ) )
).
addop2(M, op(Prio, Assoc, Name)) :-
addop( Prio, Assoc, M:Name ).
matched_op(A, B) :-
optype( A, T),
optype( B, T).
optype(fx,pre).
optype(fy,pre).
optype(xfx,in).
optype(xfy,in).
optype(yfx,in).
optype(yfy,in).
optype(xf,pos).
optype(yf,pos).
:- dynamic user:portray_message/2.
:- multifile user:portray_message/2.
:- dynamic syntax_error/4, undo/1.
open_events(Self, Text, Stream) :-
Self.errors := [],
open_mem_read_stream( Text, Stream ),
assert((user:portray_message(_Severity, error(syntax_error(Cause),info(between(_,LN,_), _FileName, CharPos, Details))) :-
assert( syntax_error(Cause,LN,CharPos,Details) )
)).
close_events( _Self ) :-
retract( undo(G) ),
call(G),
fail.
close_events( Self ) :-
retract( syntax_error( C, L, N, A )),
Self.errors := [t(C,L,N,A)] + Self.errors,
fail.
close_events( _ ).

View File

@ -21,6 +21,7 @@
%% ).
:- [library(hacks)].
:- reexport(library(yapi)).
:- reexport(completer).
:- use_module(library(lists)).
:- use_module(library(maplist)).
:- use_module(library(python)).
@ -39,7 +40,7 @@ jupyter_cell( _Caller, _, Line ) :-
jupyter_cell( _Caller, _, [] ) :- !.
jupyter_cell( Caller, _, Line ) :-
Self := Caller.query,
python_query( Self, Line ).
python_query( Self, Line, box_input ).
jupyter_consult(Text) :-
blank( Text ),
@ -77,105 +78,6 @@ streams(true) :-
set_prolog_flag(user_error,_Error).
completions(S, Self) :-
open_mem_read_stream(S, St),
scan_to_list(St, Tokens),
close(St),
reverse(Tokens, RTokens),
strip_final_tokens(RTokens, MyTokens),
setof( Completion, complete(MyTokens, Completion), Cs),
Self.matches := Cs.
strip_final_tokens(['EOT'|Ts], Ts) :- !.
strip_final_tokens( Ts, Ts ).
complete([E,l,C,l,A|More],
isconsult(A),
%B = l,
library(C,Lib),
%D=l,
E=atom(Prefix),
\+ arg( Rest ),
check_library( Prefix, Lib, C).
complete([E,l,C,l,-,'['|More],
isconsult(A),
%B = l,
library(C,Lib),
%D=l,
E=atom(Prefix),
\+ arg( Rest ),
check_library( Prefix, Lib, C).
complete([C,l,A|More],
isconsult(A),
%B = l,
C=atom(Prefix),
\+ arg( Rest ),
file_or_library( Prefix, C).
complete([C,l,-,'['|More],
isconsult(A),
%B = l,
C=atom(Prefix),
\+ arg( Rest ),
file_or_library( Prefix, C).
complete( [atom(F)|Rest], C) :-
\+ arg( Rest ),
predicate( F, Pred, Arity ),
cont( Arity, F, Pred, C).
isconsult( atom(use_module) ).
isconsult( atom(ensure_loaded) ).
isconsult( atom(compile) ).
isconsult( atom(consult) ).
isconsult( atom(reconsult) ).
isconsult( atom(load_files) ).
isconsult( '[' ).
arg([']'|_]).
arg([l|_]).
file_or_library(F,C) :-
libsym(C0),
atom_cooncat(F,C,C0).
file_or_library(F,C) :-
check_file(F,C).
check_file(F0,C) :-
atom_concat('\'',F,F0),
!,
absolute_file_name( F, FF, [access(none)] ),
atom_concat( FF, '*' , Pat),
absolute_file_name( Pat, C0, [glob(true)] ),
atom_concat(Pat,C00,C0),
atom_conct(C00,'\'',C).
check_file(F0,C) :-
atom_concat( F0, '*' , Pat),
absolute_file_name( Pat, C0, [glob(true)] ),
atom_concat(Pat,C,C0).
check_library( Lib, F, C) :-
atom_concat( F, '*' , Pat),
LibF =.. [Lib(Pat)],
absolute_file_name( LibF, Lib, [glob(true)] ),
file_directory_name( Lib, Name),
( atom_concat(C, '.yap', Name) -> true ;
atom_concat(C, '.ypp', Name) -> true ;
atom_concat(C, '.prolog', Name) -> true
).
predicate(N,P,A) :-
system_predicate(P0/A),
atom_concat(N,P,P0).
predicate(N,P,A) :-
current_predicate(P0/A),
atom_concat(N,P,P0).
cont(0, F, P, P0) :-
atom_concat( F, P, P0 ).
cont( _, F, P, PB ):-
atom_concat( [F, P, '( )'], PB ).
ready(_Self, Line ) :-
blank( Line ),
!.

View File

@ -25,7 +25,7 @@
*/
:- system_module( attributes, [delayed_goals/4,
:- module( attributes, [delayed_goals/4,
all_attvars/1,
bind_attvar/1,
del_all_atts/1,
@ -36,7 +36,7 @@ all_attvars/1,
put_att_term/2,
put_module_atts/2,
unbind_attvar/1,
woken_att_do/4], []).
woken_att_do/4] .
:- use_system_module( '$_boot', ['$undefp'/1]).

View File

@ -217,7 +217,6 @@ print_message(L,E) :-
'$command'(C,VL,Pos,Con) :-
( (Con = top ; var(C) ; C = [_|_]) ->
'$yap_strip_module'(C, EM, EG),
writeln(EM),
'$execute_command'(EG,EM,VL,Pos,Con,C) ;
% do term expansion
'$expand_term'(C, Con, EC),

View File

@ -89,9 +89,9 @@ system_error(Type,Goal) :-
%%
% error_handler(+Error,+ Level)
%
% process a````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````n error term.
% process an error term.
%
errorv_handler(Error, Level) :-
error_handler(Error, Level) :-
'$LoopError'(Error, Level).
'$LoopError'(_, _) :-

View File

@ -1009,11 +1009,8 @@ prolog:print_message(Severity, Term) :-
prolog:print_message_lines(user_error, Prefix, Lines)
),
!.
prolog:print_message(Severity, _Term) :-
format('No handler for ~a message ~q,~n',[Severity, _Term]).
'$error_descriptor'(_Info, Desc) :-
'$committed_exception'( Desc ).
'$error_descriptor'( Info, Info ).
/**
@}
*/