Add g_caused_exception/2 for custom toplevel error handling

When a goal throws an exception during initialization (-g flag), the
system now asserts g_caused_exception(Goal, Exception) in the user
module. This allows custom toplevels (-t flag) to check if an error
occurred and handle it appropriately.

Example usage:
  scryer-prolog -g "throw(error)" -t check_error

Where check_error can be:
  :- dynamic(g_caused_exception/2).

  check_error :-
      (   g_caused_exception(_, E) ->
          write('Error: '), write(E), nl, halt(1)
      ;   halt(0)
      ).

This enables scripts to use custom toplevels for sophisticated error
handling and exit code logic.

Addresses: https://github.com/mthom/scryer-prolog/pull/3147#issuecomment-3503875719

Co-Authored-By: J.J.'s Robot <jjtolton@gmail.com>
This commit is contained in:
J.J. Tolton
2025-11-08 12:43:46 -05:00
parent 31247545c3
commit 617a551a56

View File

@@ -58,7 +58,12 @@ start_repl :-
start_toplevel :- start_toplevel :-
( custom_toplevel(Goal) -> ( custom_toplevel(Goal) ->
user:call(Goal) catch(user:call(Goal),
Exception,
( print_exception(Exception),
halt(1)
)
)
; repl ; repl
). ).
@@ -174,7 +179,8 @@ run_goals([g(Gs0)|Goals]) :- !,
Exception, Exception,
( write_term(Goal, [variable_names(VNs),double_quotes(DQ)]), ( write_term(Goal, [variable_names(VNs),double_quotes(DQ)]),
write(' causes: '), write(' causes: '),
write_term(Exception, [double_quotes(DQ)]), nl write_term(Exception, [double_quotes(DQ)]), nl,
asserta(user:g_caused_exception(Goal, Exception))
) )
) -> true ) -> true
; write('% Warning: initialization failed for: '), ; write('% Warning: initialization failed for: '),