-t custom toplevel option

- Add -t FLAG to specify custom toplevel (arity 0 predicate)
- Default toplevel is 'repl' if -t is not specified
- Using `-t halt` achieves original goal of guaranteed termination
- Custom toplevels enable flexible exit strategies (e.g., server mode)
- Update help text to document -t flag

Examples:
  scryer-prolog -t halt program.pl    # Exits after execution
  scryer-prolog -t my_repl program.pl # Custom REPL
  scryer-prolog program.pl            # Default REPL

Co-Authored-By: J.J.'s Robot <noreply@example.com>
This commit is contained in:
J.J. Tolton
2025-11-06 19:02:30 -05:00
parent 2b85a307ae
commit 768f7ce9a7

View File

@@ -16,6 +16,7 @@
:- dynamic(disabled_init_file/0).
:- dynamic(started/0).
:- dynamic(custom_toplevel/1).
load_scryerrc :-
( '$home_directory'(HomeDir) ->
@@ -53,7 +54,13 @@ start_repl :-
; true
),
(\+ disabled_init_file -> load_scryerrc ; true),
repl.
start_toplevel.
start_toplevel :-
( custom_toplevel(Goal) ->
user:call(Goal)
; repl
).
args_consults_goals([], [], []).
args_consults_goals([Arg|Args], Consults, Goals) :-
@@ -71,12 +78,13 @@ delegate_task([], Goals0) :-
args_consults_goals(Goals1, Consults, Goals),
run_goals(Consults),
run_goals(Goals),
repl.
start_toplevel.
delegate_task([Arg0|Args], Goals0) :-
( ( member(Arg0, ["-h", "--help"]) -> print_help
; member(Arg0, ["-v", "--version"]) -> print_version
; member(Arg0, ["-g", "--goal"]) -> gather_goal(g, Args, Goals0)
; member(Arg0, ["-t"]) -> gather_toplevel(Args, Goals0)
; member(Arg0, ["-f"]) -> disable_init_file
; member(Arg0, ["--no-add-history"]) -> ignore_machine_arg
),
@@ -96,6 +104,8 @@ print_help :-
write('Print version information and exit'), nl,
write(' -g, --goal GOAL '),
write('Run the query GOAL'), nl,
write(' -t GOAL '),
write('Use GOAL as custom toplevel (arity 0 predicate)'), nl,
write(' -f '),
write('Fast startup. Do not load initialization file (~/.scryerrc)'), nl,
write(' --no-add-history '),
@@ -117,6 +127,17 @@ gather_goal(Type, Args0, Goals) :-
Gs =.. [Type, Gs1],
delegate_task(Args, [Gs|Goals]).
gather_toplevel(Args0, Goals0) :-
length(Args0, N),
( N < 1 -> print_help, halt
; true
),
[TopLevel|Args] = Args0,
atom_chars(Goal, TopLevel),
retractall(custom_toplevel(_)),
asserta(custom_toplevel(Goal)),
delegate_task(Args, Goals0).
disable_init_file :-
asserta('disabled_init_file').
@@ -154,7 +175,7 @@ run_goals([g(Gs0)|Goals]) :- !,
Exception,
( write_term(Goal, [variable_names(VNs),double_quotes(DQ)]),
write(' causes: '),
write_term(Exception, [double_quotes(DQ)]), nl % halt?
write_term(Exception, [double_quotes(DQ)]), nl
)
) -> true
; write('% Warning: initialization failed for: '),