From 768f7ce9a77db599950288b0d1027b561657c319 Mon Sep 17 00:00:00 2001 From: "J.J. Tolton" Date: Thu, 6 Nov 2025 19:02:30 -0500 Subject: [PATCH] -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 --- src/toplevel.pl | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/toplevel.pl b/src/toplevel.pl index 0727aee0..18f5c799 100644 --- a/src/toplevel.pl +++ b/src/toplevel.pl @@ -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: '), -- 2.54.0