From 8f39bee463eeaf64c04213e99606b75b9a3c8b52 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Sat, 28 Feb 2026 14:23:44 +0100 Subject: [PATCH 1/3] ISO: Implement the include/1 directive Quoting from the standard: 7.4.2.7 include/1 If F is an implementation defined ground term designating a Prolog text unit, then Prolog text P1 which contains a directive include(F) is identical to a Prolog text P2 obtained by replacing the directive include(F) in P1 by the Prolog text denoted by F. Example: :- include("hello.pl"). This addresses #583 and #634. --- src/toplevel.pl | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/toplevel.pl b/src/toplevel.pl index ce0190c7..9c0ad643 100644 --- a/src/toplevel.pl +++ b/src/toplevel.pl @@ -220,6 +220,46 @@ expand_op_list([Op | OtherOps], Pri, Spec, [(:- op(Pri, Spec, Op)) | OtherResult expand_op_list(OtherOps, Pri, Spec, OtherResults). +% Implement the include/1 directive via term expansion. + +user:term_expansion((:- include(File0)), Clauses) :- + ( si:atom_si(File0) -> + atom_chars(File0, File), + format("% Warning: include/1: atom arguments are deprecated. Use chars for file paths:~n", []), + format("% :- include(\"~s\").~n", [File]) + ; error:must_be(chars, File0), + File = File0 + ), + '$toplevel':gather_clauses_from_file(File, Clauses). + + +gather_clauses_from_file(File, Clauses) :- + ( file_exists(File) -> + setup_call_cleanup(open(File, read, Stream), + gather_clauses_(Stream, File, Clauses), + close(Stream)) + ; format("include/1: ~s does not exist.", [File]), + Clauses = [] + ). + + +gather_clauses_(Stream, _, []) :- at_end_of_stream(Stream), !. +gather_clauses_(Stream, File, Clauses) :- + catch((read(Stream, Clause), + Continue = true), + Error, + ( Error = error(syntax_error(incomplete_reduction),_), + at_end_of_stream(Stream) -> + true + ; format("~s: ~q", [File,Error]) + )), + ( Continue == true -> + Clauses = [Clause|Rest], + gather_clauses_(Stream, File, Rest) + ; Clauses = [] + ). + + read_and_match :- '$read_query_term'(_, Term, _, _, VarList), instruction_match(Term, VarList). From b41563e976eda4e555c8b0fb3924a174d8143517 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Sat, 7 Mar 2026 09:37:30 +0100 Subject: [PATCH 2/3] ENHANCED: support quads in included files Suggested by @dcnorris, many thanks! https://github.com/mthom/scryer-prolog/issues/634#issuecomment-4003451420 --- src/toplevel.pl | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/toplevel.pl b/src/toplevel.pl index 9c0ad643..465c37c0 100644 --- a/src/toplevel.pl +++ b/src/toplevel.pl @@ -251,11 +251,40 @@ gather_clauses_(Stream, File, Clauses) :- ( Error = error(syntax_error(incomplete_reduction),_), at_end_of_stream(Stream) -> true - ; format("~s: ~q", [File,Error]) + ; format("~s: ~q~n", [File,Error]) )), ( Continue == true -> - Clauses = [Clause|Rest], - gather_clauses_(Stream, File, Rest) + ( var(Clause) -> + format("~s: variable clause is ignored.~n", [File]), + gather_clauses_(Stream, File, Clauses) + ; Clause = (?- _Query) -> + devour_answer_descriptions(Stream, File, Clauses) + ; Clauses = [Clause|Rest], + gather_clauses_(Stream, File, Rest) + ) + ; Clauses = [] + ). + + +devour_answer_descriptions(Stream, File, Clauses) :- + catch((read(Stream, Clause), + Continue = true), + Error, + ( Error = error(syntax_error(incomplete_reduction),_), + at_end_of_stream(Stream) -> + true + ; format("~s: ~q~n", [File,Error]) + )), + ( Continue == true -> + ( var(Clause) -> + format("~s: variable clause is ignored.~n", [File]) + ; Clause = (?- _Query) -> + devour_answer_descriptions(Stream, File, Clauses) + ; loader:answer_description(Clause) -> + devour_answer_descriptions(Stream, File, Clauses) + ; Clauses = [Clause|Rest], + gather_clauses_(Stream, File, Rest) + ) ; Clauses = [] ). From 1c9fd1501af60bb5ec38c461aaddf117d00bb8cf Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Mon, 16 Mar 2026 07:36:55 +0100 Subject: [PATCH 3/3] retain error context (load/1) when using :- D. --- src/toplevel.pl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/toplevel.pl b/src/toplevel.pl index 465c37c0..2a1b5034 100644 --- a/src/toplevel.pl +++ b/src/toplevel.pl @@ -222,7 +222,9 @@ expand_op_list([Op | OtherOps], Pri, Spec, [(:- op(Pri, Spec, Op)) | OtherResult % Implement the include/1 directive via term expansion. -user:term_expansion((:- include(File0)), Clauses) :- +user:term_expansion((:- Include), Clauses) :- + nonvar(Include), + Include = include(File0), ( si:atom_si(File0) -> atom_chars(File0, File), format("% Warning: include/1: atom arguments are deprecated. Use chars for file paths:~n", []),