1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 1985-2022, University of Amsterdam 7 VU University Amsterdam 8 CWI, Amsterdam 9 SWI-Prolog Solutions b.v. 10 All rights reserved. 11 12 Redistribution and use in source and binary forms, with or without 13 modification, are permitted provided that the following conditions 14 are met: 15 16 1. Redistributions of source code must retain the above copyright 17 notice, this list of conditions and the following disclaimer. 18 19 2. Redistributions in binary form must reproduce the above copyright 20 notice, this list of conditions and the following disclaimer in 21 the documentation and/or other materials provided with the 22 distribution. 23 24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 34 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 POSSIBILITY OF SUCH DAMAGE. 36*/ 37 38/* 39Consult, derivates and basic things. This module is loaded by the 40C-written bootstrap compiler. 41 42The $:- directive is executed by the bootstrap compiler, but not 43inserted in the intermediate code file. Used to print diagnostic 44messages and start the Prolog defined compiler for the remaining boot 45modules. 46 47If you want to debug this module, put a '$:-'(trace). directive 48somewhere. The tracer will work properly under boot compilation as it 49will use the C defined write predicate to print goals and does not 50attempt to call the Prolog defined trace interceptor. 51*/ 52 53 /******************************** 54 * LOAD INTO MODULE SYSTEM * 55 ********************************/ 56 57:- '$set_source_module'(system). 58 59'$boot_message'(_Format, _Args) :- 60 current_prolog_flag(verbose, silent), 61 !. 62'$boot_message'(Format, Args) :- 63 format(Format, Args), 64 !. 65 66'$:-'('$boot_message'('Loading boot file ...~n', [])).
once(member(E,List))
. Implemented in C.
If List is partial though we need to do the work in Prolog to get
the proper constraint behavior. Needs to be defined early as the
boot code uses it.76memberchk(E, List) :- 77 '$memberchk'(E, List, Tail), 78 ( nonvar(Tail) 79 -> true 80 ; Tail = [_|_], 81 memberchk(E, Tail) 82 ). 83 84 /******************************** 85 * DIRECTIVES * 86 *********************************/ 87 88:- meta_predicate 89 dynamic( ), 90 multifile( ), 91 public( ), 92 module_transparent( ), 93 discontiguous( ), 94 volatile( ), 95 thread_local( ), 96 noprofile( ), 97 non_terminal( ), 98 det( ), 99 '$clausable'( ), 100 '$iso'( ), 101 '$hide'( ).
public
also plays this role. in SWI,
public
means that the predicate can be called, even if we cannot
find a reference to it.133dynamic(Spec) :- '$set_pattr'(Spec, pred, dynamic(true)). 134multifile(Spec) :- '$set_pattr'(Spec, pred, multifile(true)). 135module_transparent(Spec) :- '$set_pattr'(Spec, pred, transparent(true)). 136discontiguous(Spec) :- '$set_pattr'(Spec, pred, discontiguous(true)). 137volatile(Spec) :- '$set_pattr'(Spec, pred, volatile(true)). 138thread_local(Spec) :- '$set_pattr'(Spec, pred, thread_local(true)). 139noprofile(Spec) :- '$set_pattr'(Spec, pred, noprofile(true)). 140public(Spec) :- '$set_pattr'(Spec, pred, public(true)). 141non_terminal(Spec) :- '$set_pattr'(Spec, pred, non_terminal(true)). 142det(Spec) :- '$set_pattr'(Spec, pred, det(true)). 143'$iso'(Spec) :- '$set_pattr'(Spec, pred, iso(true)). 144'$clausable'(Spec) :- '$set_pattr'(Spec, pred, clausable(true)). 145'$hide'(Spec) :- '$set_pattr'(Spec, pred, trace(false)). 146 147'$set_pattr'(M:Pred, How, Attr) :- 148 '$set_pattr'(Pred, M, How, Attr).
pred
or directive
.154'$set_pattr'(X, _, _, _) :- 155 var(X), 156 '$uninstantiation_error'(X). 157'$set_pattr'(as(Spec,Options), M, How, Attr0) :- 158 !, 159 '$attr_options'(Options, Attr0, Attr), 160 '$set_pattr'(Spec, M, How, Attr). 161'$set_pattr'([], _, _, _) :- !. 162'$set_pattr'([H|T], M, How, Attr) :- % ISO 163 !, 164 '$set_pattr'(H, M, How, Attr), 165 '$set_pattr'(T, M, How, Attr). 166'$set_pattr'((A,B), M, How, Attr) :- % ISO and traditional 167 !, 168 '$set_pattr'(A, M, How, Attr), 169 '$set_pattr'(B, M, How, Attr). 170'$set_pattr'(M:T, _, How, Attr) :- 171 !, 172 '$set_pattr'(T, M, How, Attr). 173'$set_pattr'(PI, M, _, []) :- 174 !, 175 '$pi_head'(M:PI, Pred), 176 '$set_table_wrappers'(Pred). 177'$set_pattr'(A, M, How, [O|OT]) :- 178 !, 179 '$set_pattr'(A, M, How, O), 180 '$set_pattr'(A, M, How, OT). 181'$set_pattr'(A, M, pred, Attr) :- 182 !, 183 Attr =.. [Name,Val], 184 '$set_pi_attr'(M:A, Name, Val). 185'$set_pattr'(A, M, directive, Attr) :- 186 !, 187 Attr =.. [Name,Val], 188 catch('$set_pi_attr'(M:A, Name, Val), 189 error(E, _), 190 print_message(error, error(E, context((Name)/1,_)))). 191 192'$set_pi_attr'(PI, Name, Val) :- 193 '$pi_head'(PI, Head), 194 '$set_predicate_attribute'(Head, Name, Val). 195 196'$attr_options'(Var, _, _) :- 197 var(Var), 198 !, 199 '$uninstantiation_error'(Var). 200'$attr_options'((A,B), Attr0, Attr) :- 201 !, 202 '$attr_options'(A, Attr0, Attr1), 203 '$attr_options'(B, Attr1, Attr). 204'$attr_options'(Opt, Attr0, Attrs) :- 205 '$must_be'(ground, Opt), 206 ( '$attr_option'(Opt, AttrX) 207 -> ( is_list(Attr0) 208 -> '$join_attrs'(AttrX, Attr0, Attrs) 209 ; '$join_attrs'(AttrX, [Attr0], Attrs) 210 ) 211 ; '$domain_error'(predicate_option, Opt) 212 ). 213 214'$join_attrs'([], Attrs, Attrs) :- 215 !. 216'$join_attrs'([H|T], Attrs0, Attrs) :- 217 !, 218 '$join_attrs'(H, Attrs0, Attrs1), 219 '$join_attrs'(T, Attrs1, Attrs). 220'$join_attrs'(Attr, Attrs, Attrs) :- 221 memberchk(Attr, Attrs), 222 !. 223'$join_attrs'(Attr, Attrs, Attrs) :- 224 Attr =.. [Name,Value], 225 Gen =.. [Name,Existing], 226 memberchk(Gen, Attrs), 227 !, 228 throw(error(conflict_error(Name, Value, Existing), _)). 229'$join_attrs'(Attr, Attrs0, Attrs) :- 230 '$append'(Attrs0, [Attr], Attrs). 231 232'$attr_option'(incremental, [incremental(true),opaque(false)]). 233'$attr_option'(monotonic, monotonic(true)). 234'$attr_option'(lazy, lazy(true)). 235'$attr_option'(opaque, [incremental(false),opaque(true)]). 236'$attr_option'(abstract(Level0), abstract(Level)) :- 237 '$table_option'(Level0, Level). 238'$attr_option'(subgoal_abstract(Level0), subgoal_abstract(Level)) :- 239 '$table_option'(Level0, Level). 240'$attr_option'(answer_abstract(Level0), answer_abstract(Level)) :- 241 '$table_option'(Level0, Level). 242'$attr_option'(max_answers(Level0), max_answers(Level)) :- 243 '$table_option'(Level0, Level). 244'$attr_option'(volatile, volatile(true)). 245'$attr_option'(multifile, multifile(true)). 246'$attr_option'(discontiguous, discontiguous(true)). 247'$attr_option'(shared, thread_local(false)). 248'$attr_option'(local, thread_local(true)). 249'$attr_option'(private, thread_local(true)). 250 251'$table_option'(Value0, _Value) :- 252 var(Value0), 253 !, 254 '$instantiation_error'(Value0). 255'$table_option'(Value0, Value) :- 256 integer(Value0), 257 Value0 >= 0, 258 !, 259 Value = Value0. 260'$table_option'(off, -1) :- 261 !. 262'$table_option'(false, -1) :- 263 !. 264'$table_option'(infinite, -1) :- 265 !. 266'$table_option'(Value, _) :- 267 '$domain_error'(nonneg_or_false, Value).
277'$pattr_directive'(dynamic(Spec), M) :- 278 '$set_pattr'(Spec, M, directive, dynamic(true)). 279'$pattr_directive'(multifile(Spec), M) :- 280 '$set_pattr'(Spec, M, directive, multifile(true)). 281'$pattr_directive'(module_transparent(Spec), M) :- 282 '$set_pattr'(Spec, M, directive, transparent(true)). 283'$pattr_directive'(discontiguous(Spec), M) :- 284 '$set_pattr'(Spec, M, directive, discontiguous(true)). 285'$pattr_directive'(volatile(Spec), M) :- 286 '$set_pattr'(Spec, M, directive, volatile(true)). 287'$pattr_directive'(thread_local(Spec), M) :- 288 '$set_pattr'(Spec, M, directive, thread_local(true)). 289'$pattr_directive'(noprofile(Spec), M) :- 290 '$set_pattr'(Spec, M, directive, noprofile(true)). 291'$pattr_directive'(public(Spec), M) :- 292 '$set_pattr'(Spec, M, directive, public(true)). 293'$pattr_directive'(det(Spec), M) :- 294 '$set_pattr'(Spec, M, directive, det(true)).
298'$pi_head'(PI, Head) :- 299 var(PI), 300 var(Head), 301 '$instantiation_error'([PI,Head]). 302'$pi_head'(M:PI, M:Head) :- 303 !, 304 '$pi_head'(PI, Head). 305'$pi_head'(Name/Arity, Head) :- 306 !, 307 '$head_name_arity'(Head, Name, Arity). 308'$pi_head'(Name//DCGArity, Head) :- 309 !, 310 ( nonvar(DCGArity) 311 -> Arity is DCGArity+2, 312 '$head_name_arity'(Head, Name, Arity) 313 ; '$head_name_arity'(Head, Name, Arity), 314 DCGArity is Arity - 2 315 ). 316'$pi_head'(PI, _) :- 317 '$type_error'(predicate_indicator, PI).
322'$head_name_arity'(Goal, Name, Arity) :- 323 ( atom(Goal) 324 -> Name = Goal, Arity = 0 325 ; compound(Goal) 326 -> compound_name_arity(Goal, Name, Arity) 327 ; var(Goal) 328 -> ( Arity == 0 329 -> ( atom(Name) 330 -> Goal = Name 331 ; Name == [] 332 -> Goal = Name 333 ; blob(Name, closure) 334 -> Goal = Name 335 ; '$type_error'(atom, Name) 336 ) 337 ; compound_name_arity(Goal, Name, Arity) 338 ) 339 ; '$type_error'(callable, Goal) 340 ). 341 342:- '$iso'(((dynamic)/1, (multifile)/1, (discontiguous)/1)). 343 344 345 /******************************** 346 * CALLING, CONTROL * 347 *********************************/ 348 349:- noprofile((call/1, 350 catch/3, 351 once/1, 352 ignore/1, 353 call_cleanup/2, 354 setup_call_cleanup/3, 355 setup_call_catcher_cleanup/4, 356 notrace/1)). 357 358:- meta_predicate 359 ';'( , ), 360 ','( , ), 361 @( , ), 362 call( ), 363 call( , ), 364 call( , , ), 365 call( , , , ), 366 call( , , , , ), 367 call( , , , , , ), 368 call( , , , , , , ), 369 call( , , , , , , , ), 370 not( ), 371 \+( ), 372 $( ), 373 '->'( , ), 374 '*->'( , ), 375 once( ), 376 ignore( ), 377 catch( , , ), 378 reset( , , ), 379 setup_call_cleanup( , , ), 380 setup_call_catcher_cleanup( , , , ), 381 call_cleanup( , ), 382 catch_with_backtrace( , , ), 383 notrace( ), 384 '$meta_call'( ). 385 386:- '$iso'((call/1, (\+)/1, once/1, (;)/2, (',')/2, (->)/2, catch/3)). 387 388% The control structures are always compiled, both if they appear in a 389% clause body and if they are handed to call/1. The only way to call 390% these predicates is by means of call/2.. In that case, we call the 391% hole control structure again to get it compiled by call/1 and properly 392% deal with !, etc. Another reason for having these things as 393% predicates is to be able to define properties for them, helping code 394% analyzers. 395 396(M0:If ; M0:Then) :- !, call(M0:(If ; Then)). 397(M1:If ; M2:Then) :- call(M1:(If ; M2:Then)). 398(G1 , G2) :- call((G1 , G2)). 399(If -> Then) :- call((If -> Then)). 400(If *-> Then) :- call((If *-> Then)). 401@(Goal,Module) :- @(Goal,Module).
This implementation is used by reset/3 because the continuation cannot be captured if it contains a such a compiled temporary clause.
415'$meta_call'(M:G) :- 416 prolog_current_choice(Ch), 417 '$meta_call'(G, M, Ch). 418 419'$meta_call'(Var, _, _) :- 420 var(Var), 421 !, 422 '$instantiation_error'(Var). 423'$meta_call'((A,B), M, Ch) :- 424 !, 425 '$meta_call'(A, M, Ch), 426 '$meta_call'(B, M, Ch). 427'$meta_call'((I->T;E), M, Ch) :- 428 !, 429 ( prolog_current_choice(Ch2), 430 '$meta_call'(I, M, Ch2) 431 -> '$meta_call'(T, M, Ch) 432 ; '$meta_call'(E, M, Ch) 433 ). 434'$meta_call'((I*->T;E), M, Ch) :- 435 !, 436 ( prolog_current_choice(Ch2), 437 '$meta_call'(I, M, Ch2) 438 *-> '$meta_call'(T, M, Ch) 439 ; '$meta_call'(E, M, Ch) 440 ). 441'$meta_call'((I->T), M, Ch) :- 442 !, 443 ( prolog_current_choice(Ch2), 444 '$meta_call'(I, M, Ch2) 445 -> '$meta_call'(T, M, Ch) 446 ). 447'$meta_call'((I*->T), M, Ch) :- 448 !, 449 prolog_current_choice(Ch2), 450 '$meta_call'(I, M, Ch2), 451 '$meta_call'(T, M, Ch). 452'$meta_call'((A;B), M, Ch) :- 453 !, 454 ( '$meta_call'(A, M, Ch) 455 ; '$meta_call'(B, M, Ch) 456 ). 457'$meta_call'(\+(G), M, _) :- 458 !, 459 prolog_current_choice(Ch), 460 \+ '$meta_call'(G, M, Ch). 461'$meta_call'($(G), M, _) :- 462 !, 463 prolog_current_choice(Ch), 464 $('$meta_call'(G, M, Ch)). 465'$meta_call'(call(G), M, _) :- 466 !, 467 prolog_current_choice(Ch), 468 '$meta_call'(G, M, Ch). 469'$meta_call'(M:G, _, Ch) :- 470 !, 471 '$meta_call'(G, M, Ch). 472'$meta_call'(!, _, Ch) :- 473 prolog_cut_to(Ch). 474'$meta_call'(G, M, _Ch) :- 475 call(M:G).
491:- '$iso'((call/2, 492 call/3, 493 call/4, 494 call/5, 495 call/6, 496 call/7, 497 call/8)). 498 499call(Goal) :- % make these available as predicates 500 . 501call(Goal, A) :- 502 call(Goal, A). 503call(Goal, A, B) :- 504 call(Goal, A, B). 505call(Goal, A, B, C) :- 506 call(Goal, A, B, C). 507call(Goal, A, B, C, D) :- 508 call(Goal, A, B, C, D). 509call(Goal, A, B, C, D, E) :- 510 call(Goal, A, B, C, D, E). 511call(Goal, A, B, C, D, E, F) :- 512 call(Goal, A, B, C, D, E, F). 513call(Goal, A, B, C, D, E, F, G) :- 514 call(Goal, A, B, C, D, E, F, G).
521not(Goal) :-
522 \+ .
528\+ Goal :-
529 \+ .
call((Goal, !))
.
535once(Goal) :-
536 ,
537 !.
544ignore(Goal) :- 545 , 546 !. 547ignore(_Goal). 548 549:- '$iso'((false/0)).
555false :-
556 fail.
562catch(_Goal, _Catcher, _Recover) :- 563 '$catch'. % Maps to I_CATCH, I_EXITCATCH
569prolog_cut_to(_Choice) :- 570 '$cut'. % Maps to I_CUTCHP
576'$' :- '$'.
582$(Goal) :- $(Goal).
588:- '$hide'(notrace/1). 589 590notrace(Goal) :- 591 setup_call_cleanup( 592 '$notrace'(Flags, SkipLevel), 593 once(Goal), 594 '$restore_trace'(Flags, SkipLevel)).
601reset(_Goal, _Ball, _Cont) :-
602 '$reset'.
611shift(Ball) :- 612 '$shift'(Ball). 613 614shift_for_copy(Ball) :- 615 '$shift_for_copy'(Ball).
Note that we can technically also push the entire continuation onto the environment and call it. Doing it incrementally as below exploits last-call optimization and therefore possible quadratic expansion of the continuation.
629call_continuation([]). 630call_continuation([TB|Rest]) :- 631 ( Rest == [] 632 -> '$call_continuation'(TB) 633 ; '$call_continuation'(TB), 634 call_continuation(Rest) 635 ).
642catch_with_backtrace(Goal, Ball, Recover) :- 643 catch(Goal, Ball, Recover), 644 '$no_lco'. 645 646'$no_lco'.
656:- public '$recover_and_rethrow'/2. 657 658'$recover_and_rethrow'(Goal, Exception) :- 659 call_cleanup(Goal, throw(Exception)), 660 !.
I_CALLCLEANUP
, I_EXITCLEANUP
. These
instructions rely on the exact stack layout left by these
predicates, where the variant is determined by the arity. See also
callCleanupHandler()
in pl-wam.c
.674setup_call_catcher_cleanup(Setup, _Goal, _Catcher, _Cleanup) :- 675 sig_atomic(Setup), 676 '$call_cleanup'. 677 678setup_call_cleanup(Setup, _Goal, _Cleanup) :- 679 sig_atomic(Setup), 680 '$call_cleanup'. 681 682call_cleanup(_Goal, _Cleanup) :- 683 '$call_cleanup'. 684 685 686 /******************************* 687 * INITIALIZATION * 688 *******************************/ 689 690:- meta_predicate 691 initialization( , ). 692 693:- multifile '$init_goal'/3. 694:- dynamic '$init_goal'/3.
-g goal
goals.Note that all goals are executed when a program is restored.
720initialization(Goal, When) :- 721 '$must_be'(oneof(atom, initialization_type, 722 [ now, 723 after_load, 724 restore, 725 restore_state, 726 prepare_state, 727 program, 728 main 729 ]), When), 730 '$initialization_context'(Source, Ctx), 731 '$initialization'(When, Goal, Source, Ctx). 732 733'$initialization'(now, Goal, _Source, Ctx) :- 734 '$run_init_goal'(Goal, Ctx), 735 '$compile_init_goal'(-, Goal, Ctx). 736'$initialization'(after_load, Goal, Source, Ctx) :- 737 ( Source \== (-) 738 -> '$compile_init_goal'(Source, Goal, Ctx) 739 ; throw(error(context_error(nodirective, 740 initialization(Goal, after_load)), 741 _)) 742 ). 743'$initialization'(restore, Goal, Source, Ctx) :- % deprecated 744 '$initialization'(restore_state, Goal, Source, Ctx). 745'$initialization'(restore_state, Goal, _Source, Ctx) :- 746 ( \+ current_prolog_flag(sandboxed_load, true) 747 -> '$compile_init_goal'(-, Goal, Ctx) 748 ; '$permission_error'(register, initialization(restore), Goal) 749 ). 750'$initialization'(prepare_state, Goal, _Source, Ctx) :- 751 ( \+ current_prolog_flag(sandboxed_load, true) 752 -> '$compile_init_goal'(when(prepare_state), Goal, Ctx) 753 ; '$permission_error'(register, initialization(restore), Goal) 754 ). 755'$initialization'(program, Goal, _Source, Ctx) :- 756 ( \+ current_prolog_flag(sandboxed_load, true) 757 -> '$compile_init_goal'(when(program), Goal, Ctx) 758 ; '$permission_error'(register, initialization(restore), Goal) 759 ). 760'$initialization'(main, Goal, _Source, Ctx) :- 761 ( \+ current_prolog_flag(sandboxed_load, true) 762 -> '$compile_init_goal'(when(main), Goal, Ctx) 763 ; '$permission_error'(register, initialization(restore), Goal) 764 ). 765 766 767'$compile_init_goal'(Source, Goal, Ctx) :- 768 atom(Source), 769 Source \== (-), 770 !, 771 '$store_admin_clause'(system:'$init_goal'(Source, Goal, Ctx), 772 _Layout, Source, Ctx). 773'$compile_init_goal'(Source, Goal, Ctx) :- 774 assertz('$init_goal'(Source, Goal, Ctx)).
runInitialization()
in pl-wic.c for .qlf files. The
'$run_initialization'/3 is called with Action set to loaded
when called for a QLF file.786'$run_initialization'(_, loaded, _) :- !. 787'$run_initialization'(File, _Action, Options) :- 788 '$run_initialization'(File, Options). 789 790'$run_initialization'(File, Options) :- 791 setup_call_cleanup( 792 '$start_run_initialization'(Options, Restore), 793 '$run_initialization_2'(File), 794 '$end_run_initialization'(Restore)). 795 796'$start_run_initialization'(Options, OldSandBoxed) :- 797 '$push_input_context'(initialization), 798 '$set_sandboxed_load'(Options, OldSandBoxed). 799'$end_run_initialization'(OldSandBoxed) :- 800 set_prolog_flag(sandboxed_load, OldSandBoxed), 801 '$pop_input_context'. 802 803'$run_initialization_2'(File) :- 804 ( '$init_goal'(File, Goal, Ctx), 805 File \= when(_), 806 '$run_init_goal'(Goal, Ctx), 807 fail 808 ; true 809 ). 810 811'$run_init_goal'(Goal, Ctx) :- 812 ( catch_with_backtrace('$run_init_goal'(Goal), E, 813 '$initialization_error'(E, Goal, Ctx)) 814 -> true 815 ; '$initialization_failure'(Goal, Ctx) 816 ). 817 818:- multifile prolog:sandbox_allowed_goal/1. 819 820'$run_init_goal'(Goal) :- 821 current_prolog_flag(sandboxed_load, false), 822 !, 823 call(Goal). 824'$run_init_goal'(Goal) :- 825 prolog:sandbox_allowed_goal(Goal), 826 call(Goal). 827 828'$initialization_context'(Source, Ctx) :- 829 ( source_location(File, Line) 830 -> Ctx = File:Line, 831 '$input_context'(Context), 832 '$top_file'(Context, File, Source) 833 ; Ctx = (-), 834 File = (-) 835 ). 836 837'$top_file'([input(include, F1, _, _)|T], _, F) :- 838 !, 839 '$top_file'(T, F1, F). 840'$top_file'(_, F, F). 841 842 843'$initialization_error'(E, Goal, Ctx) :- 844 print_message(error, initialization_error(Goal, E, Ctx)). 845 846'$initialization_failure'(Goal, Ctx) :- 847 print_message(warning, initialization_failure(Goal, Ctx)).
855:- public '$clear_source_admin'/1. 856 857'$clear_source_admin'(File) :- 858 retractall('$init_goal'(_, _, File:_)), 859 retractall('$load_context_module'(File, _, _)), 860 retractall('$resolved_source_path_db'(_, _, File)). 861 862 863 /******************************* 864 * STREAM * 865 *******************************/ 866 867:- '$iso'(stream_property/2). 868stream_property(Stream, Property) :- 869 nonvar(Stream), 870 nonvar(Property), 871 !, 872 '$stream_property'(Stream, Property). 873stream_property(Stream, Property) :- 874 nonvar(Stream), 875 !, 876 '$stream_properties'(Stream, Properties), 877 '$member'(Property, Properties). 878stream_property(Stream, Property) :- 879 nonvar(Property), 880 !, 881 ( Property = alias(Alias), 882 atom(Alias) 883 -> '$alias_stream'(Alias, Stream) 884 ; '$streams_properties'(Property, Pairs), 885 '$member'(Stream-Property, Pairs) 886 ). 887stream_property(Stream, Property) :- 888 '$streams_properties'(Property, Pairs), 889 '$member'(Stream-Properties, Pairs), 890 '$member'(Property, Properties). 891 892 893 /******************************** 894 * MODULES * 895 *********************************/ 896 897% '$prefix_module'(+Module, +Context, +Term, -Prefixed) 898% Tags `Term' with `Module:' if `Module' is not the context module. 899 900'$prefix_module'(Module, Module, Head, Head) :- !. 901'$prefix_module'(Module, _, Head, Module:Head).
907default_module(Me, Super) :- 908 ( atom(Me) 909 -> ( var(Super) 910 -> '$default_module'(Me, Super) 911 ; '$default_module'(Me, Super), ! 912 ) 913 ; '$type_error'(module, Me) 914 ). 915 916'$default_module'(Me, Me). 917'$default_module'(Me, Super) :- 918 import_module(Me, S), 919 '$default_module'(S, Super). 920 921 922 /******************************** 923 * TRACE AND EXCEPTIONS * 924 *********************************/ 925 926:- dynamic user:exception/3. 927:- multifile user:exception/3. 928:- '$hide'(user:exception/3).
937:- public 938 '$undefined_procedure'/4. 939 940'$undefined_procedure'(Module, Name, Arity, Action) :- 941 '$prefix_module'(Module, user, Name/Arity, Pred), 942 user:exception(undefined_predicate, Pred, Action0), 943 !, 944 Action = Action0. 945'$undefined_procedure'(Module, Name, Arity, Action) :- 946 \+ current_prolog_flag(autoload, false), 947 '$autoload'(Module:Name/Arity), 948 !, 949 Action = retry. 950'$undefined_procedure'(_, _, _, error).
962'$loading'(Library) :- 963 current_prolog_flag(threads, true), 964 ( '$loading_file'(Library, _Queue, _LoadThread) 965 -> true 966 ; '$loading_file'(FullFile, _Queue, _LoadThread), 967 file_name_extension(Library, _, FullFile) 968 -> true 969 ). 970 971% handle debugger 'w', 'p' and <N> depth options. 972 973'$set_debugger_write_options'(write) :- 974 !, 975 create_prolog_flag(debugger_write_options, 976 [ quoted(true), 977 attributes(dots), 978 spacing(next_argument) 979 ], []). 980'$set_debugger_write_options'(print) :- 981 !, 982 create_prolog_flag(debugger_write_options, 983 [ quoted(true), 984 portray(true), 985 max_depth(10), 986 attributes(portray), 987 spacing(next_argument) 988 ], []). 989'$set_debugger_write_options'(Depth) :- 990 current_prolog_flag(debugger_write_options, Options0), 991 ( '$select'(max_depth(_), Options0, Options) 992 -> true 993 ; Options = Options0 994 ), 995 create_prolog_flag(debugger_write_options, 996 [max_depth(Depth)|Options], []). 997 998 999 /******************************** 1000 * SYSTEM MESSAGES * 1001 *********************************/
query
channel. This
predicate may be hooked using confirm/2, which must return
a boolean.1010:- multifile 1011 prolog:confirm/2. 1012 1013'$confirm'(Spec) :- 1014 prolog:confirm(Spec, Result), 1015 !, 1016 Result == true. 1017'$confirm'(Spec) :- 1018 print_message(query, Spec), 1019 between(0, 5, _), 1020 get_single_char(Answer), 1021 ( '$in_reply'(Answer, 'yYjJ \n') 1022 -> !, 1023 print_message(query, if_tty([yes-[]])) 1024 ; '$in_reply'(Answer, 'nN') 1025 -> !, 1026 print_message(query, if_tty([no-[]])), 1027 fail 1028 ; print_message(help, query(confirm)), 1029 fail 1030 ). 1031 1032'$in_reply'(Code, Atom) :- 1033 char_code(Char, Code), 1034 sub_atom(Atom, _, _, _, Char), 1035 !. 1036 1037:- dynamic 1038 user:portray/1. 1039:- multifile 1040 user:portray/1. 1041 1042 1043 /******************************* 1044 * FILE_SEARCH_PATH * 1045 *******************************/ 1046 1047:- dynamic 1048 user:file_search_path/2, 1049 user:library_directory/1. 1050:- multifile 1051 user:file_search_path/2, 1052 user:library_directory/1. 1053 1054user(file_search_path(library, Dir) :- 1055 library_directory(Dir)). 1056user:file_search_path(swi, Home) :- 1057 current_prolog_flag(home, Home). 1058user:file_search_path(swi, Home) :- 1059 current_prolog_flag(shared_home, Home). 1060user:file_search_path(library, app_config(lib)). 1061user:file_search_path(library, swi(library)). 1062user:file_search_path(library, swi(library/clp)). 1063user:file_search_path(foreign, swi(ArchLib)) :- 1064 current_prolog_flag(apple_universal_binary, true), 1065 ArchLib = 'lib/fat-darwin'. 1066user:file_search_path(foreign, swi(ArchLib)) :- 1067 \+ current_prolog_flag(windows, true), 1068 current_prolog_flag(arch, Arch), 1069 atom_concat('lib/', Arch, ArchLib). 1070user:file_search_path(foreign, swi(ArchLib)) :- 1071 current_prolog_flag(msys2, true), 1072 current_prolog_flag(arch, Arch), 1073 atomic_list_concat([lib, Arch], /, ArchLib). 1074user:file_search_path(foreign, swi(SoLib)) :- 1075 current_prolog_flag(msys2, true), 1076 current_prolog_flag(arch, Arch), 1077 atomic_list_concat([bin, Arch], /, SoLib). 1078user:file_search_path(foreign, swi(SoLib)) :- 1079 ( current_prolog_flag(windows, true) 1080 -> SoLib = bin 1081 ; SoLib = lib 1082 ). 1083user:file_search_path(path, Dir) :- 1084 getenv('PATH', Path), 1085 ( current_prolog_flag(windows, true) 1086 -> atomic_list_concat(Dirs, (;), Path) 1087 ; atomic_list_concat(Dirs, :, Path) 1088 ), 1089 '$member'(Dir, Dirs). 1090user:file_search_path(user_app_data, Dir) :- 1091 '$xdg_prolog_directory'(data, Dir). 1092user:file_search_path(common_app_data, Dir) :- 1093 '$xdg_prolog_directory'(common_data, Dir). 1094user:file_search_path(user_app_config, Dir) :- 1095 '$xdg_prolog_directory'(config, Dir). 1096user:file_search_path(common_app_config, Dir) :- 1097 '$xdg_prolog_directory'(common_config, Dir). 1098user:file_search_path(app_data, user_app_data('.')). 1099user:file_search_path(app_data, common_app_data('.')). 1100user:file_search_path(app_config, user_app_config('.')). 1101user:file_search_path(app_config, common_app_config('.')). 1102% backward compatibility 1103user:file_search_path(app_preferences, user_app_config('.')). 1104user:file_search_path(user_profile, app_preferences('.')). 1105 1106'$xdg_prolog_directory'(Which, Dir) :- 1107 '$xdg_directory'(Which, XDGDir), 1108 '$make_config_dir'(XDGDir), 1109 '$ensure_slash'(XDGDir, XDGDirS), 1110 atom_concat(XDGDirS, 'swi-prolog', Dir), 1111 '$make_config_dir'(Dir). 1112 1113% config 1114'$xdg_directory'(config, Home) :- 1115 current_prolog_flag(windows, true), 1116 catch(win_folder(appdata, Home), _, fail), 1117 !. 1118'$xdg_directory'(config, Home) :- 1119 getenv('XDG_CONFIG_HOME', Home). 1120'$xdg_directory'(config, Home) :- 1121 expand_file_name('~/.config', [Home]). 1122% data 1123'$xdg_directory'(data, Home) :- 1124 current_prolog_flag(windows, true), 1125 catch(win_folder(local_appdata, Home), _, fail), 1126 !. 1127'$xdg_directory'(data, Home) :- 1128 getenv('XDG_DATA_HOME', Home). 1129'$xdg_directory'(data, Home) :- 1130 expand_file_name('~/.local', [Local]), 1131 '$make_config_dir'(Local), 1132 atom_concat(Local, '/share', Home), 1133 '$make_config_dir'(Home). 1134% common data 1135'$xdg_directory'(common_data, Dir) :- 1136 current_prolog_flag(windows, true), 1137 catch(win_folder(common_appdata, Dir), _, fail), 1138 !. 1139'$xdg_directory'(common_data, Dir) :- 1140 '$existing_dir_from_env_path'('XDG_DATA_DIRS', 1141 [ '/usr/local/share', 1142 '/usr/share' 1143 ], 1144 Dir). 1145% common config 1146'$xdg_directory'(common_config, Dir) :- 1147 current_prolog_flag(windows, true), 1148 catch(win_folder(common_appdata, Dir), _, fail), 1149 !. 1150'$xdg_directory'(common_config, Dir) :- 1151 '$existing_dir_from_env_path'('XDG_CONFIG_DIRS', ['/etc/xdg'], Dir). 1152 1153'$existing_dir_from_env_path'(Env, Defaults, Dir) :- 1154 ( getenv(Env, Path) 1155 -> '$path_sep'(Sep), 1156 atomic_list_concat(Dirs, Sep, Path) 1157 ; Dirs = Defaults 1158 ), 1159 '$member'(Dir, Dirs), 1160 Dir \== '', 1161 exists_directory(Dir). 1162 1163'$path_sep'(Char) :- 1164 ( current_prolog_flag(windows, true) 1165 -> Char = ';' 1166 ; Char = ':' 1167 ). 1168 1169'$make_config_dir'(Dir) :- 1170 exists_directory(Dir), 1171 !. 1172'$make_config_dir'(Dir) :- 1173 nb_current('$create_search_directories', true), 1174 file_directory_name(Dir, Parent), 1175 '$my_file'(Parent), 1176 catch(make_directory(Dir), _, fail). 1177 1178'$ensure_slash'(Dir, DirS) :- 1179 ( sub_atom(Dir, _, _, 0, /) 1180 -> DirS = Dir 1181 ; atom_concat(Dir, /, DirS) 1182 ).
1187'$expand_file_search_path'(Spec, Expanded, Cond) :- 1188 '$option'(access(Access), Cond), 1189 memberchk(Access, [write,append]), 1190 !, 1191 setup_call_cleanup( 1192 nb_setval('$create_search_directories', true), 1193 expand_file_search_path(Spec, Expanded), 1194 nb_delete('$create_search_directories')). 1195'$expand_file_search_path'(Spec, Expanded, _Cond) :- 1196 expand_file_search_path(Spec, Expanded).
1204expand_file_search_path(Spec, Expanded) :- 1205 catch('$expand_file_search_path'(Spec, Expanded, 0, []), 1206 loop(Used), 1207 throw(error(loop_error(Spec), file_search(Used)))). 1208 1209'$expand_file_search_path'(Spec, Expanded, N, Used) :- 1210 functor(Spec, Alias, 1), 1211 !, 1212 user:file_search_path(Alias, Exp0), 1213 NN is N + 1, 1214 ( NN > 16 1215 -> throw(loop(Used)) 1216 ; true 1217 ), 1218 '$expand_file_search_path'(Exp0, Exp1, NN, [Alias=Exp0|Used]), 1219 arg(1, Spec, Segments), 1220 '$segments_to_atom'(Segments, File), 1221 '$make_path'(Exp1, File, Expanded). 1222'$expand_file_search_path'(Spec, Path, _, _) :- 1223 '$segments_to_atom'(Spec, Path). 1224 1225'$make_path'(Dir, '.', Path) :- 1226 !, 1227 Path = Dir. 1228'$make_path'(Dir, File, Path) :- 1229 sub_atom(Dir, _, _, 0, /), 1230 !, 1231 atom_concat(Dir, File, Path). 1232'$make_path'(Dir, File, Path) :- 1233 atomic_list_concat([Dir, /, File], Path). 1234 1235 1236 /******************************** 1237 * FILE CHECKING * 1238 *********************************/
1249absolute_file_name(Spec, Options, Path) :- 1250 '$is_options'(Options), 1251 \+ '$is_options'(Path), 1252 !, 1253 '$absolute_file_name'(Spec, Path, Options). 1254absolute_file_name(Spec, Path, Options) :- 1255 '$absolute_file_name'(Spec, Path, Options). 1256 1257'$absolute_file_name'(Spec, Path, Options0) :- 1258 '$options_dict'(Options0, Options), 1259 % get the valid extensions 1260 ( '$select_option'(extensions(Exts), Options, Options1) 1261 -> '$must_be'(list, Exts) 1262 ; '$option'(file_type(Type), Options) 1263 -> '$must_be'(atom, Type), 1264 '$file_type_extensions'(Type, Exts), 1265 Options1 = Options 1266 ; Options1 = Options, 1267 Exts = [''] 1268 ), 1269 '$canonicalise_extensions'(Exts, Extensions), 1270 % unless specified otherwise, ask regular file 1271 ( ( nonvar(Type) 1272 ; '$option'(access(none), Options, none) 1273 ) 1274 -> Options2 = Options1 1275 ; '$merge_options'(_{file_type:regular}, Options1, Options2) 1276 ), 1277 % Det or nondet? 1278 ( '$select_option'(solutions(Sols), Options2, Options3) 1279 -> '$must_be'(oneof(atom, solutions, [first,all]), Sols) 1280 ; Sols = first, 1281 Options3 = Options2 1282 ), 1283 % Errors or not? 1284 ( '$select_option'(file_errors(FileErrors), Options3, Options4) 1285 -> '$must_be'(oneof(atom, file_errors, [error,fail]), FileErrors) 1286 ; FileErrors = error, 1287 Options4 = Options3 1288 ), 1289 % Expand shell patterns? 1290 ( atomic(Spec), 1291 '$select_option'(expand(Expand), Options4, Options5), 1292 '$must_be'(boolean, Expand) 1293 -> expand_file_name(Spec, List), 1294 '$member'(Spec1, List) 1295 ; Spec1 = Spec, 1296 Options5 = Options4 1297 ), 1298 % Search for files 1299 ( Sols == first 1300 -> ( '$chk_file'(Spec1, Extensions, Options5, true, Path) 1301 -> ! % also kill choice point of expand_file_name/2 1302 ; ( FileErrors == fail 1303 -> fail 1304 ; '$current_module'('$bags', _File), 1305 findall(P, 1306 '$chk_file'(Spec1, Extensions, [access(exist)], 1307 false, P), 1308 Candidates), 1309 '$abs_file_error'(Spec, Candidates, Options5) 1310 ) 1311 ) 1312 ; '$chk_file'(Spec1, Extensions, Options5, false, Path) 1313 ). 1314 1315'$abs_file_error'(Spec, Candidates, Conditions) :- 1316 '$member'(F, Candidates), 1317 '$member'(C, Conditions), 1318 '$file_condition'(C), 1319 '$file_error'(C, Spec, F, E, Comment), 1320 !, 1321 throw(error(E, context(_, Comment))). 1322'$abs_file_error'(Spec, _, _) :- 1323 '$existence_error'(source_sink, Spec). 1324 1325'$file_error'(file_type(directory), Spec, File, Error, Comment) :- 1326 \+ exists_directory(File), 1327 !, 1328 Error = existence_error(directory, Spec), 1329 Comment = not_a_directory(File). 1330'$file_error'(file_type(_), Spec, File, Error, Comment) :- 1331 exists_directory(File), 1332 !, 1333 Error = existence_error(file, Spec), 1334 Comment = directory(File). 1335'$file_error'(access(OneOrList), Spec, File, Error, _) :- 1336 '$one_or_member'(Access, OneOrList), 1337 \+ access_file(File, Access), 1338 Error = permission_error(Access, source_sink, Spec). 1339 1340'$one_or_member'(Elem, List) :- 1341 is_list(List), 1342 !, 1343 '$member'(Elem, List). 1344'$one_or_member'(Elem, Elem). 1345 1346 1347'$file_type_extensions'(source, Exts) :- % SICStus 3.9 compatibility 1348 !, 1349 '$file_type_extensions'(prolog, Exts). 1350'$file_type_extensions'(Type, Exts) :- 1351 '$current_module'('$bags', _File), 1352 !, 1353 findall(Ext, user:prolog_file_type(Ext, Type), Exts0), 1354 ( Exts0 == [], 1355 \+ '$ft_no_ext'(Type) 1356 -> '$domain_error'(file_type, Type) 1357 ; true 1358 ), 1359 '$append'(Exts0, [''], Exts). 1360'$file_type_extensions'(prolog, [pl, '']). % findall is not yet defined ... 1361 1362'$ft_no_ext'(txt). 1363'$ft_no_ext'(executable). 1364'$ft_no_ext'(directory). 1365'$ft_no_ext'(regular).
Note that qlf
must be last when searching for Prolog files.
Otherwise use_module/1 will consider the file as not-loaded
because the .qlf file is not the loaded file. Must be fixed
elsewhere.
1378:- multifile(user:prolog_file_type/2). 1379:- dynamic(user:prolog_file_type/2). 1380 1381userprolog_file_type(pl, prolog). 1382userprolog_file_type(prolog, prolog). 1383userprolog_file_type(qlf, prolog). 1384userprolog_file_type(qlf, qlf). 1385userprolog_file_type(Ext, executable) :- 1386 current_prolog_flag(shared_object_extension, Ext). 1387userprolog_file_type(dylib, executable) :- 1388 current_prolog_flag(apple, true).
1395'$chk_file'(Spec, _Extensions, _Cond, _Cache, _FullName) :- 1396 \+ ground(Spec), 1397 !, 1398 '$instantiation_error'(Spec). 1399'$chk_file'(Spec, Extensions, Cond, Cache, FullName) :- 1400 compound(Spec), 1401 functor(Spec, _, 1), 1402 !, 1403 '$relative_to'(Cond, cwd, CWD), 1404 '$chk_alias_file'(Spec, Extensions, Cond, Cache, CWD, FullName). 1405'$chk_file'(Segments, Ext, Cond, Cache, FullName) :- % allow a/b/... 1406 \+ atomic(Segments), 1407 !, 1408 '$segments_to_atom'(Segments, Atom), 1409 '$chk_file'(Atom, Ext, Cond, Cache, FullName). 1410'$chk_file'(File, Exts, Cond, _, FullName) :- 1411 is_absolute_file_name(File), 1412 !, 1413 '$extend_file'(File, Exts, Extended), 1414 '$file_conditions'(Cond, Extended), 1415 '$absolute_file_name'(Extended, FullName). 1416'$chk_file'(File, Exts, Cond, _, FullName) :- 1417 '$relative_to'(Cond, source, Dir), 1418 atomic_list_concat([Dir, /, File], AbsFile), 1419 '$extend_file'(AbsFile, Exts, Extended), 1420 '$file_conditions'(Cond, Extended), 1421 !, 1422 '$absolute_file_name'(Extended, FullName). 1423'$chk_file'(File, Exts, Cond, _, FullName) :- 1424 '$extend_file'(File, Exts, Extended), 1425 '$file_conditions'(Cond, Extended), 1426 '$absolute_file_name'(Extended, FullName). 1427 1428'$segments_to_atom'(Atom, Atom) :- 1429 atomic(Atom), 1430 !. 1431'$segments_to_atom'(Segments, Atom) :- 1432 '$segments_to_list'(Segments, List, []), 1433 !, 1434 atomic_list_concat(List, /, Atom). 1435 1436'$segments_to_list'(A/B, H, T) :- 1437 '$segments_to_list'(A, H, T0), 1438 '$segments_to_list'(B, T0, T). 1439'$segments_to_list'(A, [A|T], T) :- 1440 atomic(A).
relative_to(FileOrDir)
options
or implicitely relative to the working directory or current
source-file.
1450'$relative_to'(Conditions, Default, Dir) :-
1451 ( '$option'(relative_to(FileOrDir), Conditions)
1452 *-> ( exists_directory(FileOrDir)
1453 -> Dir = FileOrDir
1454 ; atom_concat(Dir, /, FileOrDir)
1455 -> true
1456 ; file_directory_name(FileOrDir, Dir)
1457 )
1458 ; Default == cwd
1459 -> '$cwd'(Dir)
1460 ; Default == source
1461 -> source_location(ContextFile, _Line),
1462 file_directory_name(ContextFile, Dir)
1463 ).
1468:- dynamic 1469 '$search_path_file_cache'/3, % SHA1, Time, Path 1470 '$search_path_gc_time'/1. % Time 1471:- volatile 1472 '$search_path_file_cache'/3, 1473 '$search_path_gc_time'/1. 1474 1475:- create_prolog_flag(file_search_cache_time, 10, []). 1476 1477'$chk_alias_file'(Spec, Exts, Cond, true, CWD, FullFile) :- 1478 !, 1479 findall(Exp, '$expand_file_search_path'(Spec, Exp, Cond), Expansions), 1480 current_prolog_flag(emulated_dialect, Dialect), 1481 Cache = cache(Exts, Cond, CWD, Expansions, Dialect), 1482 variant_sha1(Spec+Cache, SHA1), 1483 get_time(Now), 1484 current_prolog_flag(file_search_cache_time, TimeOut), 1485 ( '$search_path_file_cache'(SHA1, CachedTime, FullFile), 1486 CachedTime > Now - TimeOut, 1487 '$file_conditions'(Cond, FullFile) 1488 -> '$search_message'(file_search(cache(Spec, Cond), FullFile)) 1489 ; '$member'(Expanded, Expansions), 1490 '$extend_file'(Expanded, Exts, LibFile), 1491 ( '$file_conditions'(Cond, LibFile), 1492 '$absolute_file_name'(LibFile, FullFile), 1493 '$cache_file_found'(SHA1, Now, TimeOut, FullFile) 1494 -> '$search_message'(file_search(found(Spec, Cond), FullFile)) 1495 ; '$search_message'(file_search(tried(Spec, Cond), LibFile)), 1496 fail 1497 ) 1498 ). 1499'$chk_alias_file'(Spec, Exts, Cond, false, _CWD, FullFile) :- 1500 '$expand_file_search_path'(Spec, Expanded, Cond), 1501 '$extend_file'(Expanded, Exts, LibFile), 1502 '$file_conditions'(Cond, LibFile), 1503 '$absolute_file_name'(LibFile, FullFile). 1504 1505'$cache_file_found'(_, _, TimeOut, _) :- 1506 TimeOut =:= 0, 1507 !. 1508'$cache_file_found'(SHA1, Now, TimeOut, FullFile) :- 1509 '$search_path_file_cache'(SHA1, Saved, FullFile), 1510 !, 1511 ( Now - Saved < TimeOut/2 1512 -> true 1513 ; retractall('$search_path_file_cache'(SHA1, _, _)), 1514 asserta('$search_path_file_cache'(SHA1, Now, FullFile)) 1515 ). 1516'$cache_file_found'(SHA1, Now, TimeOut, FullFile) :- 1517 'gc_file_search_cache'(TimeOut), 1518 asserta('$search_path_file_cache'(SHA1, Now, FullFile)). 1519 1520'gc_file_search_cache'(TimeOut) :- 1521 get_time(Now), 1522 '$search_path_gc_time'(Last), 1523 Now-Last < TimeOut/2, 1524 !. 1525'gc_file_search_cache'(TimeOut) :- 1526 get_time(Now), 1527 retractall('$search_path_gc_time'(_)), 1528 assertz('$search_path_gc_time'(Now)), 1529 Before is Now - TimeOut, 1530 ( '$search_path_file_cache'(SHA1, Cached, FullFile), 1531 Cached < Before, 1532 retractall('$search_path_file_cache'(SHA1, Cached, FullFile)), 1533 fail 1534 ; true 1535 ). 1536 1537 1538'$search_message'(Term) :- 1539 current_prolog_flag(verbose_file_search, true), 1540 !, 1541 print_message(informational, Term). 1542'$search_message'(_).
1549'$file_conditions'(List, File) :- 1550 is_list(List), 1551 !, 1552 \+ ( '$member'(C, List), 1553 '$file_condition'(C), 1554 \+ '$file_condition'(C, File) 1555 ). 1556'$file_conditions'(Map, File) :- 1557 \+ ( get_dict(Key, Map, Value), 1558 C =.. [Key,Value], 1559 '$file_condition'(C), 1560 \+ '$file_condition'(C, File) 1561 ). 1562 1563'$file_condition'(file_type(directory), File) :- 1564 !, 1565 exists_directory(File). 1566'$file_condition'(file_type(_), File) :- 1567 !, 1568 \+ exists_directory(File). 1569'$file_condition'(access(Accesses), File) :- 1570 !, 1571 \+ ( '$one_or_member'(Access, Accesses), 1572 \+ access_file(File, Access) 1573 ). 1574 1575'$file_condition'(exists). 1576'$file_condition'(file_type(_)). 1577'$file_condition'(access(_)). 1578 1579'$extend_file'(File, Exts, FileEx) :- 1580 '$ensure_extensions'(Exts, File, Fs), 1581 '$list_to_set'(Fs, FsSet), 1582 '$member'(FileEx, FsSet). 1583 1584'$ensure_extensions'([], _, []). 1585'$ensure_extensions'([E|E0], F, [FE|E1]) :- 1586 file_name_extension(F, E, FE), 1587 '$ensure_extensions'(E0, F, E1).
1594'$list_to_set'(List, Set) :- 1595 '$number_list'(List, 1, Numbered), 1596 sort(1, @=<, Numbered, ONum), 1597 '$remove_dup_keys'(ONum, NumSet), 1598 sort(2, @=<, NumSet, ONumSet), 1599 '$pairs_keys'(ONumSet, Set). 1600 1601'$number_list'([], _, []). 1602'$number_list'([H|T0], N, [H-N|T]) :- 1603 N1 is N+1, 1604 '$number_list'(T0, N1, T). 1605 1606'$remove_dup_keys'([], []). 1607'$remove_dup_keys'([H|T0], [H|T]) :- 1608 H = V-_, 1609 '$remove_same_key'(T0, V, T1), 1610 '$remove_dup_keys'(T1, T). 1611 1612'$remove_same_key'([V1-_|T0], V, T) :- 1613 V1 == V, 1614 !, 1615 '$remove_same_key'(T0, V, T). 1616'$remove_same_key'(L, _, L). 1617 1618'$pairs_keys'([], []). 1619'$pairs_keys'([K-_|T0], [K|T]) :- 1620 '$pairs_keys'(T0, T). 1621 1622'$pairs_values'([], []). 1623'$pairs_values'([_-V|T0], [V|T]) :- 1624 '$pairs_values'(T0, T). 1625 1626/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1627Canonicalise the extension list. Old SWI-Prolog require `.pl', etc, which 1628the Quintus compatibility requests `pl'. This layer canonicalises all 1629extensions to .ext 1630- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1631 1632'$canonicalise_extensions'([], []) :- !. 1633'$canonicalise_extensions'([H|T], [CH|CT]) :- 1634 !, 1635 '$must_be'(atom, H), 1636 '$canonicalise_extension'(H, CH), 1637 '$canonicalise_extensions'(T, CT). 1638'$canonicalise_extensions'(E, [CE]) :- 1639 '$canonicalise_extension'(E, CE). 1640 1641'$canonicalise_extension'('', '') :- !. 1642'$canonicalise_extension'(DotAtom, DotAtom) :- 1643 sub_atom(DotAtom, 0, _, _, '.'), 1644 !. 1645'$canonicalise_extension'(Atom, DotAtom) :- 1646 atom_concat('.', Atom, DotAtom). 1647 1648 1649 /******************************** 1650 * CONSULT * 1651 *********************************/ 1652 1653:- dynamic 1654 user:library_directory/1, 1655 user:prolog_load_file/2. 1656:- multifile 1657 user:library_directory/1, 1658 user:prolog_load_file/2. 1659 1660:- prompt(_, '|: '). 1661 1662:- thread_local 1663 '$compilation_mode_store'/1, % database, wic, qlf 1664 '$directive_mode_store'/1. % database, wic, qlf 1665:- volatile 1666 '$compilation_mode_store'/1, 1667 '$directive_mode_store'/1. 1668 1669'$compilation_mode'(Mode) :- 1670 ( '$compilation_mode_store'(Val) 1671 -> Mode = Val 1672 ; Mode = database 1673 ). 1674 1675'$set_compilation_mode'(Mode) :- 1676 retractall('$compilation_mode_store'(_)), 1677 assertz('$compilation_mode_store'(Mode)). 1678 1679'$compilation_mode'(Old, New) :- 1680 '$compilation_mode'(Old), 1681 ( New == Old 1682 -> true 1683 ; '$set_compilation_mode'(New) 1684 ). 1685 1686'$directive_mode'(Mode) :- 1687 ( '$directive_mode_store'(Val) 1688 -> Mode = Val 1689 ; Mode = database 1690 ). 1691 1692'$directive_mode'(Old, New) :- 1693 '$directive_mode'(Old), 1694 ( New == Old 1695 -> true 1696 ; '$set_directive_mode'(New) 1697 ). 1698 1699'$set_directive_mode'(Mode) :- 1700 retractall('$directive_mode_store'(_)), 1701 assertz('$directive_mode_store'(Mode)).
1709'$compilation_level'(Level) :- 1710 '$input_context'(Stack), 1711 '$compilation_level'(Stack, Level). 1712 1713'$compilation_level'([], 0). 1714'$compilation_level'([Input|T], Level) :- 1715 ( arg(1, Input, see) 1716 -> '$compilation_level'(T, Level) 1717 ; '$compilation_level'(T, Level0), 1718 Level is Level0+1 1719 ).
1727compiling :- 1728 \+ ( '$compilation_mode'(database), 1729 '$directive_mode'(database) 1730 ). 1731 1732:- meta_predicate 1733 '$ifcompiling'( ). 1734 1735'$ifcompiling'(G) :- 1736 ( '$compilation_mode'(database) 1737 -> true 1738 ; call(G) 1739 ). 1740 1741 /******************************** 1742 * READ SOURCE * 1743 *********************************/
1747'$load_msg_level'(Action, Nesting, Start, Done) :- 1748 '$update_autoload_level'([], 0), 1749 !, 1750 current_prolog_flag(verbose_load, Type0), 1751 '$load_msg_compat'(Type0, Type), 1752 ( '$load_msg_level'(Action, Nesting, Type, Start, Done) 1753 -> true 1754 ). 1755'$load_msg_level'(_, _, silent, silent). 1756 1757'$load_msg_compat'(true, normal) :- !. 1758'$load_msg_compat'(false, silent) :- !. 1759'$load_msg_compat'(X, X). 1760 1761'$load_msg_level'(load_file, _, full, informational, informational). 1762'$load_msg_level'(include_file, _, full, informational, informational). 1763'$load_msg_level'(load_file, _, normal, silent, informational). 1764'$load_msg_level'(include_file, _, normal, silent, silent). 1765'$load_msg_level'(load_file, 0, brief, silent, informational). 1766'$load_msg_level'(load_file, _, brief, silent, silent). 1767'$load_msg_level'(include_file, _, brief, silent, silent). 1768'$load_msg_level'(load_file, _, silent, silent, silent). 1769'$load_msg_level'(include_file, _, silent, silent, silent).
1792'$source_term'(From, Read, RLayout, Term, TLayout, Stream, Options) :- 1793 '$source_term'(From, Read, RLayout, Term, TLayout, Stream, [], Options), 1794 ( Term == end_of_file 1795 -> !, fail 1796 ; Term \== begin_of_file 1797 ). 1798 1799'$source_term'(Input, _,_,_,_,_,_,_) :- 1800 \+ ground(Input), 1801 !, 1802 '$instantiation_error'(Input). 1803'$source_term'(stream(Id, In, Opts), 1804 Read, RLayout, Term, TLayout, Stream, Parents, Options) :- 1805 !, 1806 '$record_included'(Parents, Id, Id, 0.0, Message), 1807 setup_call_cleanup( 1808 '$open_source'(stream(Id, In, Opts), In, State, Parents, Options), 1809 '$term_in_file'(In, Read, RLayout, Term, TLayout, Stream, 1810 [Id|Parents], Options), 1811 '$close_source'(State, Message)). 1812'$source_term'(File, 1813 Read, RLayout, Term, TLayout, Stream, Parents, Options) :- 1814 absolute_file_name(File, Path, 1815 [ file_type(prolog), 1816 access(read) 1817 ]), 1818 time_file(Path, Time), 1819 '$record_included'(Parents, File, Path, Time, Message), 1820 setup_call_cleanup( 1821 '$open_source'(Path, In, State, Parents, Options), 1822 '$term_in_file'(In, Read, RLayout, Term, TLayout, Stream, 1823 [Path|Parents], Options), 1824 '$close_source'(State, Message)). 1825 1826:- thread_local 1827 '$load_input'/2. 1828:- volatile 1829 '$load_input'/2. 1830 1831'$open_source'(stream(Id, In, Opts), In, 1832 restore(In, StreamState, Id, Ref, Opts), Parents, _Options) :- 1833 !, 1834 '$context_type'(Parents, ContextType), 1835 '$push_input_context'(ContextType), 1836 '$prepare_load_stream'(In, Id, StreamState), 1837 asserta('$load_input'(stream(Id), In), Ref). 1838'$open_source'(Path, In, close(In, Path, Ref), Parents, Options) :- 1839 '$context_type'(Parents, ContextType), 1840 '$push_input_context'(ContextType), 1841 '$open_source'(Path, In, Options), 1842 '$set_encoding'(In, Options), 1843 asserta('$load_input'(Path, In), Ref). 1844 1845'$context_type'([], load_file) :- !. 1846'$context_type'(_, include). 1847 1848:- multifile prolog:open_source_hook/3. 1849 1850'$open_source'(Path, In, Options) :- 1851 prolog:open_source_hook(Path, In, Options), 1852 !. 1853'$open_source'(Path, In, _Options) :- 1854 open(Path, read, In). 1855 1856'$close_source'(close(In, _Id, Ref), Message) :- 1857 erase(Ref), 1858 call_cleanup( 1859 close(In), 1860 '$pop_input_context'), 1861 '$close_message'(Message). 1862'$close_source'(restore(In, StreamState, _Id, Ref, Opts), Message) :- 1863 erase(Ref), 1864 call_cleanup( 1865 '$restore_load_stream'(In, StreamState, Opts), 1866 '$pop_input_context'), 1867 '$close_message'(Message). 1868 1869'$close_message'(message(Level, Msg)) :- 1870 !, 1871 '$print_message'(Level, Msg). 1872'$close_message'(_).
1884'$term_in_file'(In, Read, RLayout, Term, TLayout, Stream, Parents, Options) :- 1885 Parents \= [_,_|_], 1886 ( '$load_input'(_, Input) 1887 -> stream_property(Input, file_name(File)) 1888 ), 1889 '$set_source_location'(File, 0), 1890 '$expanded_term'(In, 1891 begin_of_file, 0-0, Read, RLayout, Term, TLayout, 1892 Stream, Parents, Options). 1893'$term_in_file'(In, Read, RLayout, Term, TLayout, Stream, Parents, Options) :- 1894 '$skip_script_line'(In, Options), 1895 '$read_clause_options'(Options, ReadOptions), 1896 '$repeat_and_read_error_mode'(ErrorMode), 1897 read_clause(In, Raw, 1898 [ syntax_errors(ErrorMode), 1899 variable_names(Bindings), 1900 term_position(Pos), 1901 subterm_positions(RawLayout) 1902 | ReadOptions 1903 ]), 1904 b_setval('$term_position', Pos), 1905 b_setval('$variable_names', Bindings), 1906 ( Raw == end_of_file 1907 -> !, 1908 ( Parents = [_,_|_] % Included file 1909 -> fail 1910 ; '$expanded_term'(In, 1911 Raw, RawLayout, Read, RLayout, Term, TLayout, 1912 Stream, Parents, Options) 1913 ) 1914 ; '$expanded_term'(In, Raw, RawLayout, Read, RLayout, Term, TLayout, 1915 Stream, Parents, Options) 1916 ). 1917 1918'$read_clause_options'([], []). 1919'$read_clause_options'([H|T0], List) :- 1920 ( '$read_clause_option'(H) 1921 -> List = [H|T] 1922 ; List = T 1923 ), 1924 '$read_clause_options'(T0, T). 1925 1926'$read_clause_option'(syntax_errors(_)). 1927'$read_clause_option'(term_position(_)). 1928'$read_clause_option'(process_comment(_)).
expand.pl
is not yet
loaded.1936'$repeat_and_read_error_mode'(Mode) :- 1937 ( current_predicate('$including'/0) 1938 -> repeat, 1939 ( '$including' 1940 -> Mode = dec10 1941 ; Mode = quiet 1942 ) 1943 ; Mode = dec10, 1944 repeat 1945 ). 1946 1947 1948'$expanded_term'(In, Raw, RawLayout, Read, RLayout, Term, TLayout, 1949 Stream, Parents, Options) :- 1950 E = error(_,_), 1951 catch('$expand_term'(Raw, RawLayout, Expanded, ExpandedLayout), E, 1952 '$print_message_fail'(E)), 1953 ( Expanded \== [] 1954 -> '$expansion_member'(Expanded, ExpandedLayout, Term1, Layout1) 1955 ; Term1 = Expanded, 1956 Layout1 = ExpandedLayout 1957 ), 1958 ( nonvar(Term1), Term1 = (:-Directive), nonvar(Directive) 1959 -> ( Directive = include(File), 1960 '$current_source_module'(Module), 1961 '$valid_directive'(Module:include(File)) 1962 -> stream_property(In, encoding(Enc)), 1963 '$add_encoding'(Enc, Options, Options1), 1964 '$source_term'(File, Read, RLayout, Term, TLayout, 1965 Stream, Parents, Options1) 1966 ; Directive = encoding(Enc) 1967 -> set_stream(In, encoding(Enc)), 1968 fail 1969 ; Term = Term1, 1970 Stream = In, 1971 Read = Raw 1972 ) 1973 ; Term = Term1, 1974 TLayout = Layout1, 1975 Stream = In, 1976 Read = Raw, 1977 RLayout = RawLayout 1978 ). 1979 1980'$expansion_member'(Var, Layout, Var, Layout) :- 1981 var(Var), 1982 !. 1983'$expansion_member'([], _, _, _) :- !, fail. 1984'$expansion_member'(List, ListLayout, Term, Layout) :- 1985 is_list(List), 1986 !, 1987 ( var(ListLayout) 1988 -> '$member'(Term, List) 1989 ; is_list(ListLayout) 1990 -> '$member_rep2'(Term, Layout, List, ListLayout) 1991 ; Layout = ListLayout, 1992 '$member'(Term, List) 1993 ). 1994'$expansion_member'(X, Layout, X, Layout). 1995 1996% pairwise member, repeating last element of the second 1997% list. 1998 1999'$member_rep2'(H1, H2, [H1|_], [H2|_]). 2000'$member_rep2'(H1, H2, [_|T1], [T2]) :- 2001 !, 2002 '$member_rep2'(H1, H2, T1, [T2]). 2003'$member_rep2'(H1, H2, [_|T1], [_|T2]) :- 2004 '$member_rep2'(H1, H2, T1, T2).
2008'$add_encoding'(Enc, Options0, Options) :- 2009 ( Options0 = [encoding(Enc)|_] 2010 -> Options = Options0 2011 ; Options = [encoding(Enc)|Options0] 2012 ). 2013 2014 2015:- multifile 2016 '$included'/4. % Into, Line, File, LastModified 2017:- dynamic 2018 '$included'/4.
I think that the only sensible solution is to have a special statement for this, that may appear both inside and outside QLF `parts'.
2032'$record_included'([Parent|Parents], File, Path, Time, 2033 message(DoneMsgLevel, 2034 include_file(done(Level, file(File, Path))))) :- 2035 source_location(SrcFile, Line), 2036 !, 2037 '$compilation_level'(Level), 2038 '$load_msg_level'(include_file, Level, StartMsgLevel, DoneMsgLevel), 2039 '$print_message'(StartMsgLevel, 2040 include_file(start(Level, 2041 file(File, Path)))), 2042 '$last'([Parent|Parents], Owner), 2043 ( ( '$compilation_mode'(database) 2044 ; '$qlf_current_source'(Owner) 2045 ) 2046 -> '$store_admin_clause'( 2047 system:'$included'(Parent, Line, Path, Time), 2048 _, Owner, SrcFile:Line) 2049 ; '$qlf_include'(Owner, Parent, Line, Path, Time) 2050 ). 2051'$record_included'(_, _, _, _, true).
2057'$master_file'(File, MasterFile) :- 2058 '$included'(MasterFile0, _Line, File, _Time), 2059 !, 2060 '$master_file'(MasterFile0, MasterFile). 2061'$master_file'(File, File). 2062 2063 2064'$skip_script_line'(_In, Options) :- 2065 '$option'(check_script(false), Options), 2066 !. 2067'$skip_script_line'(In, _Options) :- 2068 ( peek_char(In, #) 2069 -> skip(In, 10) 2070 ; true 2071 ). 2072 2073'$set_encoding'(Stream, Options) :- 2074 '$option'(encoding(Enc), Options), 2075 !, 2076 Enc \== default, 2077 set_stream(Stream, encoding(Enc)). 2078'$set_encoding'(_, _). 2079 2080 2081'$prepare_load_stream'(In, Id, state(HasName,HasPos)) :- 2082 ( stream_property(In, file_name(_)) 2083 -> HasName = true, 2084 ( stream_property(In, position(_)) 2085 -> HasPos = true 2086 ; HasPos = false, 2087 set_stream(In, record_position(true)) 2088 ) 2089 ; HasName = false, 2090 set_stream(In, file_name(Id)), 2091 ( stream_property(In, position(_)) 2092 -> HasPos = true 2093 ; HasPos = false, 2094 set_stream(In, record_position(true)) 2095 ) 2096 ). 2097 2098'$restore_load_stream'(In, _State, Options) :- 2099 memberchk(close(true), Options), 2100 !, 2101 close(In). 2102'$restore_load_stream'(In, state(HasName, HasPos), _Options) :- 2103 ( HasName == false 2104 -> set_stream(In, file_name('')) 2105 ; true 2106 ), 2107 ( HasPos == false 2108 -> set_stream(In, record_position(false)) 2109 ; true 2110 ). 2111 2112 2113 /******************************* 2114 * DERIVED FILES * 2115 *******************************/ 2116 2117:- dynamic 2118 '$derived_source_db'/3. % Loaded, DerivedFrom, Time 2119 2120'$register_derived_source'(_, '-') :- !. 2121'$register_derived_source'(Loaded, DerivedFrom) :- 2122 retractall('$derived_source_db'(Loaded, _, _)), 2123 time_file(DerivedFrom, Time), 2124 assert('$derived_source_db'(Loaded, DerivedFrom, Time)). 2125 2126% Auto-importing dynamic predicates is not very elegant and 2127% leads to problems with qsave_program/[1,2] 2128 2129'$derived_source'(Loaded, DerivedFrom, Time) :- 2130 '$derived_source_db'(Loaded, DerivedFrom, Time). 2131 2132 2133 /******************************** 2134 * LOAD PREDICATES * 2135 *********************************/ 2136 2137:- meta_predicate 2138 ensure_loaded( ), 2139 [, | ] 2140 consult( ), 2141 use_module( ), 2142 use_module( , ), 2143 reexport( ), 2144 reexport( , ), 2145 load_files( ), 2146 load_files( , ).
2154ensure_loaded(Files) :-
2155 load_files(Files, [if(not_loaded)]).
2164use_module(Files) :-
2165 load_files(Files, [ if(not_loaded),
2166 must_be_module(true)
2167 ]).
2174use_module(File, Import) :-
2175 load_files(File, [ if(not_loaded),
2176 must_be_module(true),
2177 imports(Import)
2178 ]).
2184reexport(Files) :-
2185 load_files(Files, [ if(not_loaded),
2186 must_be_module(true),
2187 reexport(true)
2188 ]).
2194reexport(File, Import) :- 2195 load_files(File, [ if(not_loaded), 2196 must_be_module(true), 2197 imports(Import), 2198 reexport(true) 2199 ]). 2200 2201 2202[X] :- 2203 !, 2204 consult(X). 2205[M:F|R] :- 2206 consult(M:[F|R]). 2207 2208consult(M:X) :- 2209 X == user, 2210 !, 2211 flag('$user_consult', N, N+1), 2212 NN is N + 1, 2213 atom_concat('user://', NN, Id), 2214 load_files(M:Id, [stream(user_input), check_script(false), silent(false)]). 2215consult(List) :- 2216 load_files(List, [expand(true)]).
2223load_files(Files) :- 2224 load_files(Files, []). 2225load_files(Module:Files, Options) :- 2226 '$must_be'(list, Options), 2227 '$load_files'(Files, Module, Options). 2228 2229'$load_files'(X, _, _) :- 2230 var(X), 2231 !, 2232 '$instantiation_error'(X). 2233'$load_files'([], _, _) :- !. 2234'$load_files'(Id, Module, Options) :- % load_files(foo, [stream(In)]) 2235 '$option'(stream(_), Options), 2236 !, 2237 ( atom(Id) 2238 -> '$load_file'(Id, Module, Options) 2239 ; throw(error(type_error(atom, Id), _)) 2240 ). 2241'$load_files'(List, Module, Options) :- 2242 List = [_|_], 2243 !, 2244 '$must_be'(list, List), 2245 '$load_file_list'(List, Module, Options). 2246'$load_files'(File, Module, Options) :- 2247 '$load_one_file'(File, Module, Options). 2248 2249'$load_file_list'([], _, _). 2250'$load_file_list'([File|Rest], Module, Options) :- 2251 E = error(_,_), 2252 catch('$load_one_file'(File, Module, Options), E, 2253 '$print_message'(error, E)), 2254 '$load_file_list'(Rest, Module, Options). 2255 2256 2257'$load_one_file'(Spec, Module, Options) :- 2258 atomic(Spec), 2259 '$option'(expand(Expand), Options, false), 2260 Expand == true, 2261 !, 2262 expand_file_name(Spec, Expanded), 2263 ( Expanded = [Load] 2264 -> true 2265 ; Load = Expanded 2266 ), 2267 '$load_files'(Load, Module, [expand(false)|Options]). 2268'$load_one_file'(File, Module, Options) :- 2269 strip_module(Module:File, Into, PlainFile), 2270 '$load_file'(PlainFile, Into, Options).
2277'$noload'(true, _, _) :- 2278 !, 2279 fail. 2280'$noload'(_, FullFile, _Options) :- 2281 '$time_source_file'(FullFile, Time, system), 2282 Time > 0.0, 2283 !. 2284'$noload'(not_loaded, FullFile, _) :- 2285 source_file(FullFile), 2286 !. 2287'$noload'(changed, Derived, _) :- 2288 '$derived_source'(_FullFile, Derived, LoadTime), 2289 time_file(Derived, Modified), 2290 Modified @=< LoadTime, 2291 !. 2292'$noload'(changed, FullFile, Options) :- 2293 '$time_source_file'(FullFile, LoadTime, user), 2294 '$modified_id'(FullFile, Modified, Options), 2295 Modified @=< LoadTime, 2296 !. 2297'$noload'(exists, File, Options) :- 2298 '$noload'(changed, File, Options).
2317'$qlf_file'(Spec, _, Spec, stream, Options) :- 2318 '$option'(stream(_), Options), % stream: no choice 2319 !. 2320'$qlf_file'(Spec, FullFile, FullFile, compile, _) :- 2321 '$spec_extension'(Spec, Ext), % user explicitly specified 2322 user:prolog_file_type(Ext, prolog), 2323 !. 2324'$qlf_file'(Spec, FullFile, LoadFile, Mode, Options) :- 2325 '$compilation_mode'(database), 2326 file_name_extension(Base, PlExt, FullFile), 2327 user:prolog_file_type(PlExt, prolog), 2328 user:prolog_file_type(QlfExt, qlf), 2329 file_name_extension(Base, QlfExt, QlfFile), 2330 ( access_file(QlfFile, read), 2331 ( '$qlf_out_of_date'(FullFile, QlfFile, Why) 2332 -> ( access_file(QlfFile, write) 2333 -> print_message(informational, 2334 qlf(recompile(Spec, FullFile, QlfFile, Why))), 2335 Mode = qcompile, 2336 LoadFile = FullFile 2337 ; Why == old, 2338 ( current_prolog_flag(home, PlHome), 2339 sub_atom(FullFile, 0, _, _, PlHome) 2340 ; sub_atom(QlfFile, 0, _, _, 'res://') 2341 ) 2342 -> print_message(silent, 2343 qlf(system_lib_out_of_date(Spec, QlfFile))), 2344 Mode = qload, 2345 LoadFile = QlfFile 2346 ; print_message(warning, 2347 qlf(can_not_recompile(Spec, QlfFile, Why))), 2348 Mode = compile, 2349 LoadFile = FullFile 2350 ) 2351 ; Mode = qload, 2352 LoadFile = QlfFile 2353 ) 2354 -> ! 2355 ; '$qlf_auto'(FullFile, QlfFile, Options) 2356 -> !, Mode = qcompile, 2357 LoadFile = FullFile 2358 ). 2359'$qlf_file'(_, FullFile, FullFile, compile, _).
2367'$qlf_out_of_date'(PlFile, QlfFile, Why) :-
2368 ( access_file(PlFile, read)
2369 -> time_file(PlFile, PlTime),
2370 time_file(QlfFile, QlfTime),
2371 ( PlTime > QlfTime
2372 -> Why = old % PlFile is newer
2373 ; Error = error(Formal,_),
2374 catch('$qlf_info'(QlfFile, _CVer, _MLVer,
2375 _FVer, _CSig, _FSig),
2376 Error, true),
2377 nonvar(Formal) % QlfFile is incompatible
2378 -> Why = Error
2379 ; fail % QlfFile is up-to-date and ok
2380 )
2381 ; fail % can not read .pl; try .qlf
2382 ).
qcompile(QlfMode)
or, if this is not present, by
the prolog_flag qcompile.2390:- create_prolog_flag(qcompile, false, [type(atom)]). 2391 2392'$qlf_auto'(PlFile, QlfFile, Options) :- 2393 ( memberchk(qcompile(QlfMode), Options) 2394 -> true 2395 ; current_prolog_flag(qcompile, QlfMode), 2396 \+ '$in_system_dir'(PlFile) 2397 ), 2398 ( QlfMode == auto 2399 -> true 2400 ; QlfMode == large, 2401 size_file(PlFile, Size), 2402 Size > 100000 2403 ), 2404 access_file(QlfFile, write). 2405 2406'$in_system_dir'(PlFile) :- 2407 current_prolog_flag(home, Home), 2408 sub_atom(PlFile, 0, _, _, Home). 2409 2410'$spec_extension'(File, Ext) :- 2411 atom(File), 2412 file_name_extension(_, Ext, File). 2413'$spec_extension'(Spec, Ext) :- 2414 compound(Spec), 2415 arg(1, Spec, Arg), 2416 '$spec_extension'(Arg, Ext).
2428:- dynamic 2429 '$resolved_source_path_db'/3. % ?Spec, ?Dialect, ?Path 2430 2431'$load_file'(File, Module, Options) :- 2432 '$error_count'(E0, W0), 2433 '$load_file_e'(File, Module, Options), 2434 '$error_count'(E1, W1), 2435 Errors is E1-E0, 2436 Warnings is W1-W0, 2437 ( Errors+Warnings =:= 0 2438 -> true 2439 ; '$print_message'(silent, load_file_errors(File, Errors, Warnings)) 2440 ). 2441 2442:- if(current_prolog_flag(threads, true)). 2443'$error_count'(Errors, Warnings) :- 2444 current_prolog_flag(threads, true), 2445 !, 2446 thread_self(Me), 2447 thread_statistics(Me, errors, Errors), 2448 thread_statistics(Me, warnings, Warnings). 2449:- endif. 2450'$error_count'(Errors, Warnings) :- 2451 statistics(errors, Errors), 2452 statistics(warnings, Warnings). 2453 2454'$load_file_e'(File, Module, Options) :- 2455 \+ memberchk(stream(_), Options), 2456 user:prolog_load_file(Module:File, Options), 2457 !. 2458'$load_file_e'(File, Module, Options) :- 2459 memberchk(stream(_), Options), 2460 !, 2461 '$assert_load_context_module'(File, Module, Options), 2462 '$qdo_load_file'(File, File, Module, Options). 2463'$load_file_e'(File, Module, Options) :- 2464 ( '$resolved_source_path'(File, FullFile, Options) 2465 -> true 2466 ; '$resolve_source_path'(File, FullFile, Options) 2467 ), 2468 !, 2469 '$mt_load_file'(File, FullFile, Module, Options). 2470'$load_file_e'(_, _, _).
2476'$resolved_source_path'(File, FullFile, Options) :-
2477 current_prolog_flag(emulated_dialect, Dialect),
2478 '$resolved_source_path_db'(File, Dialect, FullFile),
2479 ( '$source_file_property'(FullFile, from_state, true)
2480 ; '$source_file_property'(FullFile, resource, true)
2481 ; '$option'(if(If), Options, true),
2482 '$noload'(If, FullFile, Options)
2483 ),
2484 !.
2491'$resolve_source_path'(File, FullFile, Options) :- 2492 ( '$option'(if(If), Options), 2493 If == exists 2494 -> Extra = [file_errors(fail)] 2495 ; Extra = [] 2496 ), 2497 absolute_file_name(File, FullFile, 2498 [ file_type(prolog), 2499 access(read) 2500 | Extra 2501 ]), 2502 '$register_resolved_source_path'(File, FullFile). 2503 2504'$register_resolved_source_path'(File, FullFile) :- 2505 ( compound(File) 2506 -> current_prolog_flag(emulated_dialect, Dialect), 2507 ( '$resolved_source_path_db'(File, Dialect, FullFile) 2508 -> true 2509 ; asserta('$resolved_source_path_db'(File, Dialect, FullFile)) 2510 ) 2511 ; true 2512 ).
2518:- public '$translated_source'/2. 2519'$translated_source'(Old, New) :- 2520 forall(retract('$resolved_source_path_db'(File, Dialect, Old)), 2521 assertz('$resolved_source_path_db'(File, Dialect, New))).
2528'$register_resource_file'(FullFile) :-
2529 ( sub_atom(FullFile, 0, _, _, 'res://'),
2530 \+ file_name_extension(_, qlf, FullFile)
2531 -> '$set_source_file'(FullFile, resource, true)
2532 ; true
2533 ).
2546'$already_loaded'(_File, FullFile, Module, Options) :- 2547 '$assert_load_context_module'(FullFile, Module, Options), 2548 '$current_module'(LoadModules, FullFile), 2549 !, 2550 ( atom(LoadModules) 2551 -> LoadModule = LoadModules 2552 ; LoadModules = [LoadModule|_] 2553 ), 2554 '$import_from_loaded_module'(LoadModule, Module, Options). 2555'$already_loaded'(_, _, user, _) :- !. 2556'$already_loaded'(File, FullFile, Module, Options) :- 2557 ( '$load_context_module'(FullFile, Module, CtxOptions), 2558 '$load_ctx_options'(Options, CtxOptions) 2559 -> true 2560 ; '$load_file'(File, Module, [if(true)|Options]) 2561 ).
Synchronisation is handled using a message queue that exists while the file is being loaded. This synchronisation relies on the fact that thread_get_message/1 throws an existence_error if the message queue is destroyed. This is hacky. Events or condition variables would have made a cleaner design.
2576:- dynamic 2577 '$loading_file'/3. % File, Queue, Thread 2578:- volatile 2579 '$loading_file'/3. 2580 2581:- if(current_prolog_flag(threads, true)). 2582'$mt_load_file'(File, FullFile, Module, Options) :- 2583 current_prolog_flag(threads, true), 2584 !, 2585 sig_atomic(setup_call_cleanup( 2586 with_mutex('$load_file', 2587 '$mt_start_load'(FullFile, Loading, Options)), 2588 '$mt_do_load'(Loading, File, FullFile, Module, Options), 2589 '$mt_end_load'(Loading))). 2590:- endif. 2591'$mt_load_file'(File, FullFile, Module, Options) :- 2592 '$option'(if(If), Options, true), 2593 '$noload'(If, FullFile, Options), 2594 !, 2595 '$already_loaded'(File, FullFile, Module, Options). 2596:- if(current_prolog_flag(threads, true)). 2597'$mt_load_file'(File, FullFile, Module, Options) :- 2598 sig_atomic('$qdo_load_file'(File, FullFile, Module, Options)). 2599:- else. 2600'$mt_load_file'(File, FullFile, Module, Options) :- 2601 '$qdo_load_file'(File, FullFile, Module, Options). 2602:- endif. 2603 2604:- if(current_prolog_flag(threads, true)). 2605'$mt_start_load'(FullFile, queue(Queue), _) :- 2606 '$loading_file'(FullFile, Queue, LoadThread), 2607 \+ thread_self(LoadThread), 2608 !. 2609'$mt_start_load'(FullFile, already_loaded, Options) :- 2610 '$option'(if(If), Options, true), 2611 '$noload'(If, FullFile, Options), 2612 !. 2613'$mt_start_load'(FullFile, Ref, _) :- 2614 thread_self(Me), 2615 message_queue_create(Queue), 2616 assertz('$loading_file'(FullFile, Queue, Me), Ref). 2617 2618'$mt_do_load'(queue(Queue), File, FullFile, Module, Options) :- 2619 !, 2620 catch(thread_get_message(Queue, _), error(_,_), true), 2621 '$already_loaded'(File, FullFile, Module, Options). 2622'$mt_do_load'(already_loaded, File, FullFile, Module, Options) :- 2623 !, 2624 '$already_loaded'(File, FullFile, Module, Options). 2625'$mt_do_load'(_Ref, File, FullFile, Module, Options) :- 2626 '$assert_load_context_module'(FullFile, Module, Options), 2627 '$qdo_load_file'(File, FullFile, Module, Options). 2628 2629'$mt_end_load'(queue(_)) :- !. 2630'$mt_end_load'(already_loaded) :- !. 2631'$mt_end_load'(Ref) :- 2632 clause('$loading_file'(_, Queue, _), _, Ref), 2633 erase(Ref), 2634 thread_send_message(Queue, done), 2635 message_queue_destroy(Queue). 2636:- endif.
2642'$qdo_load_file'(File, FullFile, Module, Options) :- 2643 '$qdo_load_file2'(File, FullFile, Module, Action, Options), 2644 '$register_resource_file'(FullFile), 2645 '$run_initialization'(FullFile, Action, Options). 2646 2647'$qdo_load_file2'(File, FullFile, Module, Action, Options) :- 2648 memberchk('$qlf'(QlfOut), Options), 2649 '$stage_file'(QlfOut, StageQlf), 2650 !, 2651 setup_call_catcher_cleanup( 2652 '$qstart'(StageQlf, Module, State), 2653 '$do_load_file'(File, FullFile, Module, Action, Options), 2654 Catcher, 2655 '$qend'(State, Catcher, StageQlf, QlfOut)). 2656'$qdo_load_file2'(File, FullFile, Module, Action, Options) :- 2657 '$do_load_file'(File, FullFile, Module, Action, Options). 2658 2659'$qstart'(Qlf, Module, state(OldMode, OldModule)) :- 2660 '$qlf_open'(Qlf), 2661 '$compilation_mode'(OldMode, qlf), 2662 '$set_source_module'(OldModule, Module). 2663 2664'$qend'(state(OldMode, OldModule), Catcher, StageQlf, QlfOut) :- 2665 '$set_source_module'(_, OldModule), 2666 '$set_compilation_mode'(OldMode), 2667 '$qlf_close', 2668 '$install_staged_file'(Catcher, StageQlf, QlfOut, warn). 2669 2670'$set_source_module'(OldModule, Module) :- 2671 '$current_source_module'(OldModule), 2672 '$set_source_module'(Module).
2679'$do_load_file'(File, FullFile, Module, Action, Options) :- 2680 '$option'(derived_from(DerivedFrom), Options, -), 2681 '$register_derived_source'(FullFile, DerivedFrom), 2682 '$qlf_file'(File, FullFile, Absolute, Mode, Options), 2683 ( Mode == qcompile 2684 -> qcompile(Module:File, Options) 2685 ; '$do_load_file_2'(File, Absolute, Module, Action, Options) 2686 ). 2687 2688'$do_load_file_2'(File, Absolute, Module, Action, Options) :- 2689 '$source_file_property'(Absolute, number_of_clauses, OldClauses), 2690 statistics(cputime, OldTime), 2691 2692 '$setup_load'(ScopedFlags, OldSandBoxed, OldVerbose, OldAutoLevel, OldXRef, 2693 Options), 2694 2695 '$compilation_level'(Level), 2696 '$load_msg_level'(load_file, Level, StartMsgLevel, DoneMsgLevel), 2697 '$print_message'(StartMsgLevel, 2698 load_file(start(Level, 2699 file(File, Absolute)))), 2700 2701 ( memberchk(stream(FromStream), Options) 2702 -> Input = stream 2703 ; Input = source 2704 ), 2705 2706 ( Input == stream, 2707 ( '$option'(format(qlf), Options, source) 2708 -> set_stream(FromStream, file_name(Absolute)), 2709 '$qload_stream'(FromStream, Module, Action, LM, Options) 2710 ; '$consult_file'(stream(Absolute, FromStream, []), 2711 Module, Action, LM, Options) 2712 ) 2713 -> true 2714 ; Input == source, 2715 file_name_extension(_, Ext, Absolute), 2716 ( user:prolog_file_type(Ext, qlf), 2717 E = error(_,_), 2718 catch('$qload_file'(Absolute, Module, Action, LM, Options), 2719 E, 2720 print_message(warning, E)) 2721 -> true 2722 ; '$consult_file'(Absolute, Module, Action, LM, Options) 2723 ) 2724 -> true 2725 ; '$print_message'(error, load_file(failed(File))), 2726 fail 2727 ), 2728 2729 '$import_from_loaded_module'(LM, Module, Options), 2730 2731 '$source_file_property'(Absolute, number_of_clauses, NewClauses), 2732 statistics(cputime, Time), 2733 ClausesCreated is NewClauses - OldClauses, 2734 TimeUsed is Time - OldTime, 2735 2736 '$print_message'(DoneMsgLevel, 2737 load_file(done(Level, 2738 file(File, Absolute), 2739 Action, 2740 LM, 2741 TimeUsed, 2742 ClausesCreated))), 2743 2744 '$restore_load'(ScopedFlags, OldSandBoxed, OldVerbose, OldAutoLevel, OldXRef). 2745 2746'$setup_load'(ScopedFlags, OldSandBoxed, OldVerbose, OldAutoLevel, OldXRef, 2747 Options) :- 2748 '$save_file_scoped_flags'(ScopedFlags), 2749 '$set_sandboxed_load'(Options, OldSandBoxed), 2750 '$set_verbose_load'(Options, OldVerbose), 2751 '$set_optimise_load'(Options), 2752 '$update_autoload_level'(Options, OldAutoLevel), 2753 '$set_no_xref'(OldXRef). 2754 2755'$restore_load'(ScopedFlags, OldSandBoxed, OldVerbose, OldAutoLevel, OldXRef) :- 2756 '$set_autoload_level'(OldAutoLevel), 2757 set_prolog_flag(xref, OldXRef), 2758 set_prolog_flag(verbose_load, OldVerbose), 2759 set_prolog_flag(sandboxed_load, OldSandBoxed), 2760 '$restore_file_scoped_flags'(ScopedFlags).
2768'$save_file_scoped_flags'(State) :- 2769 current_predicate(findall/3), % Not when doing boot compile 2770 !, 2771 findall(SavedFlag, '$save_file_scoped_flag'(SavedFlag), State). 2772'$save_file_scoped_flags'([]). 2773 2774'$save_file_scoped_flag'(Flag-Value) :- 2775 '$file_scoped_flag'(Flag, Default), 2776 ( current_prolog_flag(Flag, Value) 2777 -> true 2778 ; Value = Default 2779 ). 2780 2781'$file_scoped_flag'(generate_debug_info, true). 2782'$file_scoped_flag'(optimise, false). 2783'$file_scoped_flag'(xref, false). 2784 2785'$restore_file_scoped_flags'([]). 2786'$restore_file_scoped_flags'([Flag-Value|T]) :- 2787 set_prolog_flag(Flag, Value), 2788 '$restore_file_scoped_flags'(T).
2795'$import_from_loaded_module'(LoadedModule, Module, Options) :- 2796 LoadedModule \== Module, 2797 atom(LoadedModule), 2798 !, 2799 '$option'(imports(Import), Options, all), 2800 '$option'(reexport(Reexport), Options, false), 2801 '$import_list'(Module, LoadedModule, Import, Reexport). 2802'$import_from_loaded_module'(_, _, _).
verbose_load
flag according to Options and unify Old
with the old value.2810'$set_verbose_load'(Options, Old) :- 2811 current_prolog_flag(verbose_load, Old), 2812 ( memberchk(silent(Silent), Options) 2813 -> ( '$negate'(Silent, Level0) 2814 -> '$load_msg_compat'(Level0, Level) 2815 ; Level = Silent 2816 ), 2817 set_prolog_flag(verbose_load, Level) 2818 ; true 2819 ). 2820 2821'$negate'(true, false). 2822'$negate'(false, true).
sandboxed_load
from Options. Old is
unified with the old flag.
2831'$set_sandboxed_load'(Options, Old) :- 2832 current_prolog_flag(sandboxed_load, Old), 2833 ( memberchk(sandboxed(SandBoxed), Options), 2834 '$enter_sandboxed'(Old, SandBoxed, New), 2835 New \== Old 2836 -> set_prolog_flag(sandboxed_load, New) 2837 ; true 2838 ). 2839 2840'$enter_sandboxed'(Old, New, SandBoxed) :- 2841 ( Old == false, New == true 2842 -> SandBoxed = true, 2843 '$ensure_loaded_library_sandbox' 2844 ; Old == true, New == false 2845 -> throw(error(permission_error(leave, sandbox, -), _)) 2846 ; SandBoxed = Old 2847 ). 2848'$enter_sandboxed'(false, true, true). 2849 2850'$ensure_loaded_library_sandbox' :- 2851 source_file_property(library(sandbox), module(sandbox)), 2852 !. 2853'$ensure_loaded_library_sandbox' :- 2854 load_files(library(sandbox), [if(not_loaded), silent(true)]). 2855 2856'$set_optimise_load'(Options) :- 2857 ( '$option'(optimise(Optimise), Options) 2858 -> set_prolog_flag(optimise, Optimise) 2859 ; true 2860 ). 2861 2862'$set_no_xref'(OldXRef) :- 2863 ( current_prolog_flag(xref, OldXRef) 2864 -> true 2865 ; OldXRef = false 2866 ), 2867 set_prolog_flag(xref, false).
2874:- thread_local 2875 '$autoload_nesting'/1. 2876 2877'$update_autoload_level'(Options, AutoLevel) :- 2878 '$option'(autoload(Autoload), Options, false), 2879 ( '$autoload_nesting'(CurrentLevel) 2880 -> AutoLevel = CurrentLevel 2881 ; AutoLevel = 0 2882 ), 2883 ( Autoload == false 2884 -> true 2885 ; NewLevel is AutoLevel + 1, 2886 '$set_autoload_level'(NewLevel) 2887 ). 2888 2889'$set_autoload_level'(New) :- 2890 retractall('$autoload_nesting'(_)), 2891 asserta('$autoload_nesting'(New)).
2899'$print_message'(Level, Term) :- 2900 current_predicate(system:print_message/2), 2901 !, 2902 print_message(Level, Term). 2903'$print_message'(warning, Term) :- 2904 source_location(File, Line), 2905 !, 2906 format(user_error, 'WARNING: ~w:~w: ~p~n', [File, Line, Term]). 2907'$print_message'(error, Term) :- 2908 !, 2909 source_location(File, Line), 2910 !, 2911 format(user_error, 'ERROR: ~w:~w: ~p~n', [File, Line, Term]). 2912'$print_message'(_Level, _Term). 2913 2914'$print_message_fail'(E) :- 2915 '$print_message'(error, E), 2916 fail.
2924'$consult_file'(Absolute, Module, What, LM, Options) :- 2925 '$current_source_module'(Module), % same module 2926 !, 2927 '$consult_file_2'(Absolute, Module, What, LM, Options). 2928'$consult_file'(Absolute, Module, What, LM, Options) :- 2929 '$set_source_module'(OldModule, Module), 2930 '$ifcompiling'('$qlf_start_sub_module'(Module)), 2931 '$consult_file_2'(Absolute, Module, What, LM, Options), 2932 '$ifcompiling'('$qlf_end_part'), 2933 '$set_source_module'(OldModule). 2934 2935'$consult_file_2'(Absolute, Module, What, LM, Options) :- 2936 '$set_source_module'(OldModule, Module), 2937 '$load_id'(Absolute, Id, Modified, Options), 2938 '$compile_type'(What), 2939 '$save_lex_state'(LexState, Options), 2940 '$set_dialect'(Options), 2941 setup_call_cleanup( 2942 '$start_consult'(Id, Modified), 2943 '$load_file'(Absolute, Id, LM, Options), 2944 '$end_consult'(Id, LexState, OldModule)). 2945 2946'$end_consult'(Id, LexState, OldModule) :- 2947 '$end_consult'(Id), 2948 '$restore_lex_state'(LexState), 2949 '$set_source_module'(OldModule). 2950 2951 2952:- create_prolog_flag(emulated_dialect, swi, [type(atom)]).
2956'$save_lex_state'(State, Options) :- 2957 memberchk(scope_settings(false), Options), 2958 !, 2959 State = (-). 2960'$save_lex_state'(lexstate(Style, Dialect), _) :- 2961 '$style_check'(Style, Style), 2962 current_prolog_flag(emulated_dialect, Dialect). 2963 2964'$restore_lex_state'(-) :- !. 2965'$restore_lex_state'(lexstate(Style, Dialect)) :- 2966 '$style_check'(_, Style), 2967 set_prolog_flag(emulated_dialect, Dialect). 2968 2969'$set_dialect'(Options) :- 2970 memberchk(dialect(Dialect), Options), 2971 !, 2972 '$expects_dialect'(Dialect). 2973'$set_dialect'(_). 2974 2975'$load_id'(stream(Id, _, _), Id, Modified, Options) :- 2976 !, 2977 '$modified_id'(Id, Modified, Options). 2978'$load_id'(Id, Id, Modified, Options) :- 2979 '$modified_id'(Id, Modified, Options). 2980 2981'$modified_id'(_, Modified, Options) :- 2982 '$option'(modified(Stamp), Options, Def), 2983 Stamp \== Def, 2984 !, 2985 Modified = Stamp. 2986'$modified_id'(Id, Modified, _) :- 2987 catch(time_file(Id, Modified), 2988 error(_, _), 2989 fail), 2990 !. 2991'$modified_id'(_, 0.0, _). 2992 2993 2994'$compile_type'(What) :- 2995 '$compilation_mode'(How), 2996 ( How == database 2997 -> What = compiled 2998 ; How == qlf 2999 -> What = '*qcompiled*' 3000 ; What = 'boot compiled' 3001 ).
3011:- dynamic 3012 '$load_context_module'/3. 3013:- multifile 3014 '$load_context_module'/3. 3015 3016'$assert_load_context_module'(_, _, Options) :- 3017 memberchk(register(false), Options), 3018 !. 3019'$assert_load_context_module'(File, Module, Options) :- 3020 source_location(FromFile, Line), 3021 !, 3022 '$master_file'(FromFile, MasterFile), 3023 '$check_load_non_module'(File, Module), 3024 '$add_dialect'(Options, Options1), 3025 '$load_ctx_options'(Options1, Options2), 3026 '$store_admin_clause'( 3027 system:'$load_context_module'(File, Module, Options2), 3028 _Layout, MasterFile, FromFile:Line). 3029'$assert_load_context_module'(File, Module, Options) :- 3030 '$check_load_non_module'(File, Module), 3031 '$add_dialect'(Options, Options1), 3032 '$load_ctx_options'(Options1, Options2), 3033 ( clause('$load_context_module'(File, Module, _), true, Ref), 3034 \+ clause_property(Ref, file(_)), 3035 erase(Ref) 3036 -> true 3037 ; true 3038 ), 3039 assertz('$load_context_module'(File, Module, Options2)). 3040 3041'$add_dialect'(Options0, Options) :- 3042 current_prolog_flag(emulated_dialect, Dialect), Dialect \== swi, 3043 !, 3044 Options = [dialect(Dialect)|Options0]. 3045'$add_dialect'(Options, Options).
3052'$load_ctx_options'(Options, CtxOptions) :- 3053 '$load_ctx_options2'(Options, CtxOptions0), 3054 sort(CtxOptions0, CtxOptions). 3055 3056'$load_ctx_options2'([], []). 3057'$load_ctx_options2'([H|T0], [H|T]) :- 3058 '$load_ctx_option'(H), 3059 !, 3060 '$load_ctx_options2'(T0, T). 3061'$load_ctx_options2'([_|T0], T) :- 3062 '$load_ctx_options2'(T0, T). 3063 3064'$load_ctx_option'(derived_from(_)). 3065'$load_ctx_option'(dialect(_)). 3066'$load_ctx_option'(encoding(_)). 3067'$load_ctx_option'(imports(_)). 3068'$load_ctx_option'(reexport(_)).
3076'$check_load_non_module'(File, _) :- 3077 '$current_module'(_, File), 3078 !. % File is a module file 3079'$check_load_non_module'(File, Module) :- 3080 '$load_context_module'(File, OldModule, _), 3081 Module \== OldModule, 3082 !, 3083 format(atom(Msg), 3084 'Non-module file already loaded into module ~w; \c 3085 trying to load into ~w', 3086 [OldModule, Module]), 3087 throw(error(permission_error(load, source, File), 3088 context(load_files/2, Msg))). 3089'$check_load_non_module'(_, _).
state(FirstTerm:boolean,
Module:atom,
AtEnd:atom,
Stop:boolean,
Id:atom,
Dialect:atom)
3102'$load_file'(Path, Id, Module, Options) :- 3103 State = state(true, _, true, false, Id, -), 3104 ( '$source_term'(Path, _Read, _Layout, Term, Layout, 3105 _Stream, Options), 3106 '$valid_term'(Term), 3107 ( arg(1, State, true) 3108 -> '$first_term'(Term, Layout, Id, State, Options), 3109 nb_setarg(1, State, false) 3110 ; '$compile_term'(Term, Layout, Id, Options) 3111 ), 3112 arg(4, State, true) 3113 ; '$fixup_reconsult'(Id), 3114 '$end_load_file'(State) 3115 ), 3116 !, 3117 arg(2, State, Module). 3118 3119'$valid_term'(Var) :- 3120 var(Var), 3121 !, 3122 print_message(error, error(instantiation_error, _)). 3123'$valid_term'(Term) :- 3124 Term \== []. 3125 3126'$end_load_file'(State) :- 3127 arg(1, State, true), % empty file 3128 !, 3129 nb_setarg(2, State, Module), 3130 arg(5, State, Id), 3131 '$current_source_module'(Module), 3132 '$ifcompiling'('$qlf_start_file'(Id)), 3133 '$ifcompiling'('$qlf_end_part'). 3134'$end_load_file'(State) :- 3135 arg(3, State, End), 3136 '$end_load_file'(End, State). 3137 3138'$end_load_file'(true, _). 3139'$end_load_file'(end_module, State) :- 3140 arg(2, State, Module), 3141 '$check_export'(Module), 3142 '$ifcompiling'('$qlf_end_part'). 3143'$end_load_file'(end_non_module, _State) :- 3144 '$ifcompiling'('$qlf_end_part'). 3145 3146 3147'$first_term'(?-(Directive), Layout, Id, State, Options) :- 3148 !, 3149 '$first_term'(:-(Directive), Layout, Id, State, Options). 3150'$first_term'(:-(Directive), _Layout, Id, State, Options) :- 3151 nonvar(Directive), 3152 ( ( Directive = module(Name, Public) 3153 -> Imports = [] 3154 ; Directive = module(Name, Public, Imports) 3155 ) 3156 -> !, 3157 '$module_name'(Name, Id, Module, Options), 3158 '$start_module'(Module, Public, State, Options), 3159 '$module3'(Imports) 3160 ; Directive = expects_dialect(Dialect) 3161 -> !, 3162 '$set_dialect'(Dialect, State), 3163 fail % Still consider next term as first 3164 ). 3165'$first_term'(Term, Layout, Id, State, Options) :- 3166 '$start_non_module'(Id, Term, State, Options), 3167 '$compile_term'(Term, Layout, Id, Options).
3174'$compile_term'(Term, Layout, SrcId, Options) :- 3175 '$compile_term'(Term, Layout, SrcId, -, Options). 3176 3177'$compile_term'(Var, _Layout, _Id, _SrcLoc, _Options) :- 3178 var(Var), 3179 !, 3180 '$instantiation_error'(Var). 3181'$compile_term'((?-Directive), _Layout, Id, _SrcLoc, Options) :- 3182 !, 3183 '$execute_directive'(Directive, Id, Options). 3184'$compile_term'((:-Directive), _Layout, Id, _SrcLoc, Options) :- 3185 !, 3186 '$execute_directive'(Directive, Id, Options). 3187'$compile_term'('$source_location'(File, Line):Term, 3188 Layout, Id, _SrcLoc, Options) :- 3189 !, 3190 '$compile_term'(Term, Layout, Id, File:Line, Options). 3191'$compile_term'(Clause, Layout, Id, SrcLoc, _Options) :- 3192 E = error(_,_), 3193 catch('$store_clause'(Clause, Layout, Id, SrcLoc), E, 3194 '$print_message'(error, E)). 3195 3196'$start_non_module'(_Id, Term, _State, Options) :- 3197 '$option'(must_be_module(true), Options, false), 3198 !, 3199 '$domain_error'(module_header, Term). 3200'$start_non_module'(Id, _Term, State, _Options) :- 3201 '$current_source_module'(Module), 3202 '$ifcompiling'('$qlf_start_file'(Id)), 3203 '$qset_dialect'(State), 3204 nb_setarg(2, State, Module), 3205 nb_setarg(3, State, end_non_module).
Note that expects_dialect/1 itself may be autoloaded from the library.
3218'$set_dialect'(Dialect, State) :- 3219 '$compilation_mode'(qlf, database), 3220 !, 3221 '$expects_dialect'(Dialect), 3222 '$compilation_mode'(_, qlf), 3223 nb_setarg(6, State, Dialect). 3224'$set_dialect'(Dialect, _) :- 3225 '$expects_dialect'(Dialect). 3226 3227'$qset_dialect'(State) :- 3228 '$compilation_mode'(qlf), 3229 arg(6, State, Dialect), Dialect \== (-), 3230 !, 3231 '$add_directive_wic'('$expects_dialect'(Dialect)). 3232'$qset_dialect'(_). 3233 3234'$expects_dialect'(Dialect) :- 3235 Dialect == swi, 3236 !, 3237 set_prolog_flag(emulated_dialect, Dialect). 3238'$expects_dialect'(Dialect) :- 3239 current_predicate(expects_dialect/1), 3240 !, 3241 expects_dialect(Dialect). 3242'$expects_dialect'(Dialect) :- 3243 use_module(library(dialect), [expects_dialect/1]), 3244 expects_dialect(Dialect). 3245 3246 3247 /******************************* 3248 * MODULES * 3249 *******************************/ 3250 3251'$start_module'(Module, _Public, State, _Options) :- 3252 '$current_module'(Module, OldFile), 3253 source_location(File, _Line), 3254 OldFile \== File, OldFile \== [], 3255 same_file(OldFile, File), 3256 !, 3257 nb_setarg(2, State, Module), 3258 nb_setarg(4, State, true). % Stop processing 3259'$start_module'(Module, Public, State, Options) :- 3260 arg(5, State, File), 3261 nb_setarg(2, State, Module), 3262 source_location(_File, Line), 3263 '$option'(redefine_module(Action), Options, false), 3264 '$module_class'(File, Class, Super), 3265 '$reset_dialect'(File, Class), 3266 '$redefine_module'(Module, File, Action), 3267 '$declare_module'(Module, Class, Super, File, Line, false), 3268 '$export_list'(Public, Module, Ops), 3269 '$ifcompiling'('$qlf_start_module'(Module)), 3270 '$export_ops'(Ops, Module, File), 3271 '$qset_dialect'(State), 3272 nb_setarg(3, State, end_module).
swi
dialect.3279'$reset_dialect'(File, library) :- 3280 file_name_extension(_, pl, File), 3281 !, 3282 set_prolog_flag(emulated_dialect, swi). 3283'$reset_dialect'(_, _).
3290'$module3'(Var) :- 3291 var(Var), 3292 !, 3293 '$instantiation_error'(Var). 3294'$module3'([]) :- !. 3295'$module3'([H|T]) :- 3296 !, 3297 '$module3'(H), 3298 '$module3'(T). 3299'$module3'(Id) :- 3300 use_module(library(dialect/Id)).
module(Module)
is given. In that case, use this
module and if Module is the load context, ignore the module
header.3314'$module_name'(_, _, Module, Options) :- 3315 '$option'(module(Module), Options), 3316 !, 3317 '$current_source_module'(Context), 3318 Context \== Module. % cause '$first_term'/5 to fail. 3319'$module_name'(Var, Id, Module, Options) :- 3320 var(Var), 3321 !, 3322 file_base_name(Id, File), 3323 file_name_extension(Var, _, File), 3324 '$module_name'(Var, Id, Module, Options). 3325'$module_name'(Reserved, _, _, _) :- 3326 '$reserved_module'(Reserved), 3327 !, 3328 throw(error(permission_error(load, module, Reserved), _)). 3329'$module_name'(Module, _Id, Module, _). 3330 3331 3332'$reserved_module'(system). 3333'$reserved_module'(user).
3338'$redefine_module'(_Module, _, false) :- !. 3339'$redefine_module'(Module, File, true) :- 3340 !, 3341 ( module_property(Module, file(OldFile)), 3342 File \== OldFile 3343 -> unload_file(OldFile) 3344 ; true 3345 ). 3346'$redefine_module'(Module, File, ask) :- 3347 ( stream_property(user_input, tty(true)), 3348 module_property(Module, file(OldFile)), 3349 File \== OldFile, 3350 '$rdef_response'(Module, OldFile, File, true) 3351 -> '$redefine_module'(Module, File, true) 3352 ; true 3353 ). 3354 3355'$rdef_response'(Module, OldFile, File, Ok) :- 3356 repeat, 3357 print_message(query, redefine_module(Module, OldFile, File)), 3358 get_single_char(Char), 3359 '$rdef_response'(Char, Ok0), 3360 !, 3361 Ok = Ok0. 3362 3363'$rdef_response'(Char, true) :- 3364 memberchk(Char, `yY`), 3365 format(user_error, 'yes~n', []). 3366'$rdef_response'(Char, false) :- 3367 memberchk(Char, `nN`), 3368 format(user_error, 'no~n', []). 3369'$rdef_response'(Char, _) :- 3370 memberchk(Char, `a`), 3371 format(user_error, 'abort~n', []), 3372 abort. 3373'$rdef_response'(_, _) :- 3374 print_message(help, redefine_module_reply), 3375 fail.
system
, while all normal user modules inherit
from user
.3385'$module_class'(File, Class, system) :- 3386 current_prolog_flag(home, Home), 3387 sub_atom(File, 0, Len, _, Home), 3388 ( sub_atom(File, Len, _, _, '/boot/') 3389 -> !, Class = system 3390 ; '$lib_prefix'(Prefix), 3391 sub_atom(File, Len, _, _, Prefix) 3392 -> !, Class = library 3393 ; file_directory_name(File, Home), 3394 file_name_extension(_, rc, File) 3395 -> !, Class = library 3396 ). 3397'$module_class'(_, user, user). 3398 3399'$lib_prefix'('/library'). 3400'$lib_prefix'('/xpce/prolog/'). 3401 3402'$check_export'(Module) :- 3403 '$undefined_export'(Module, UndefList), 3404 ( '$member'(Undef, UndefList), 3405 strip_module(Undef, _, Local), 3406 print_message(error, 3407 undefined_export(Module, Local)), 3408 fail 3409 ; true 3410 ).
all
,
a list of optionally mapped predicate indicators or a term
except(Import)
.3419'$import_list'(_, _, Var, _) :- 3420 var(Var), 3421 !, 3422 throw(error(instantitation_error, _)). 3423'$import_list'(Target, Source, all, Reexport) :- 3424 !, 3425 '$exported_ops'(Source, Import, Predicates), 3426 '$module_property'(Source, exports(Predicates)), 3427 '$import_all'(Import, Target, Source, Reexport, weak). 3428'$import_list'(Target, Source, except(Spec), Reexport) :- 3429 !, 3430 '$exported_ops'(Source, Export, Predicates), 3431 '$module_property'(Source, exports(Predicates)), 3432 ( is_list(Spec) 3433 -> true 3434 ; throw(error(type_error(list, Spec), _)) 3435 ), 3436 '$import_except'(Spec, Export, Import), 3437 '$import_all'(Import, Target, Source, Reexport, weak). 3438'$import_list'(Target, Source, Import, Reexport) :- 3439 !, 3440 is_list(Import), 3441 !, 3442 '$import_all'(Import, Target, Source, Reexport, strong). 3443'$import_list'(_, _, Import, _) :- 3444 throw(error(type_error(import_specifier, Import))). 3445 3446 3447'$import_except'([], List, List). 3448'$import_except'([H|T], List0, List) :- 3449 '$import_except_1'(H, List0, List1), 3450 '$import_except'(T, List1, List). 3451 3452'$import_except_1'(Var, _, _) :- 3453 var(Var), 3454 !, 3455 throw(error(instantitation_error, _)). 3456'$import_except_1'(PI as N, List0, List) :- 3457 '$pi'(PI), atom(N), 3458 !, 3459 '$canonical_pi'(PI, CPI), 3460 '$import_as'(CPI, N, List0, List). 3461'$import_except_1'(op(P,A,N), List0, List) :- 3462 !, 3463 '$remove_ops'(List0, op(P,A,N), List). 3464'$import_except_1'(PI, List0, List) :- 3465 '$pi'(PI), 3466 !, 3467 '$canonical_pi'(PI, CPI), 3468 '$select'(P, List0, List), 3469 '$canonical_pi'(CPI, P), 3470 !. 3471'$import_except_1'(Except, _, _) :- 3472 throw(error(type_error(import_specifier, Except), _)). 3473 3474'$import_as'(CPI, N, [PI2|T], [CPI as N|T]) :- 3475 '$canonical_pi'(PI2, CPI), 3476 !. 3477'$import_as'(PI, N, [H|T0], [H|T]) :- 3478 !, 3479 '$import_as'(PI, N, T0, T). 3480'$import_as'(PI, _, _, _) :- 3481 throw(error(existence_error(export, PI), _)). 3482 3483'$pi'(N/A) :- atom(N), integer(A), !. 3484'$pi'(N//A) :- atom(N), integer(A). 3485 3486'$canonical_pi'(N//A0, N/A) :- 3487 A is A0 + 2. 3488'$canonical_pi'(PI, PI). 3489 3490'$remove_ops'([], _, []). 3491'$remove_ops'([Op|T0], Pattern, T) :- 3492 subsumes_term(Pattern, Op), 3493 !, 3494 '$remove_ops'(T0, Pattern, T). 3495'$remove_ops'([H|T0], Pattern, [H|T]) :- 3496 '$remove_ops'(T0, Pattern, T).
3501'$import_all'(Import, Context, Source, Reexport, Strength) :-
3502 '$import_all2'(Import, Context, Source, Imported, ImpOps, Strength),
3503 ( Reexport == true,
3504 ( '$list_to_conj'(Imported, Conj)
3505 -> export(Context:Conj),
3506 '$ifcompiling'('$add_directive_wic'(export(Context:Conj)))
3507 ; true
3508 ),
3509 source_location(File, _Line),
3510 '$export_ops'(ImpOps, Context, File)
3511 ; true
3512 ).
3516'$import_all2'([], _, _, [], [], _). 3517'$import_all2'([PI as NewName|Rest], Context, Source, 3518 [NewName/Arity|Imported], ImpOps, Strength) :- 3519 !, 3520 '$canonical_pi'(PI, Name/Arity), 3521 length(Args, Arity), 3522 Head =.. [Name|Args], 3523 NewHead =.. [NewName|Args], 3524 ( '$get_predicate_attribute'(Source:Head, transparent, 1) 3525 -> '$set_predicate_attribute'(Context:NewHead, transparent, true) 3526 ; true 3527 ), 3528 ( source_location(File, Line) 3529 -> E = error(_,_), 3530 catch('$store_admin_clause'((NewHead :- Source:Head), 3531 _Layout, File, File:Line), 3532 E, '$print_message'(error, E)) 3533 ; assertz(( :- !, Source:Head)) % ! avoids problems with 3534 ), % duplicate load 3535 '$import_all2'(Rest, Context, Source, Imported, ImpOps, Strength). 3536'$import_all2'([op(P,A,N)|Rest], Context, Source, Imported, 3537 [op(P,A,N)|ImpOps], Strength) :- 3538 !, 3539 '$import_ops'(Context, Source, op(P,A,N)), 3540 '$import_all2'(Rest, Context, Source, Imported, ImpOps, Strength). 3541'$import_all2'([Pred|Rest], Context, Source, [Pred|Imported], ImpOps, Strength) :- 3542 Error = error(_,_), 3543 catch(Context:'$import'(Source:Pred, Strength), Error, 3544 print_message(error, Error)), 3545 '$ifcompiling'('$import_wic'(Source, Pred, Strength)), 3546 '$import_all2'(Rest, Context, Source, Imported, ImpOps, Strength). 3547 3548 3549'$list_to_conj'([One], One) :- !. 3550'$list_to_conj'([H|T], (H,Rest)) :- 3551 '$list_to_conj'(T, Rest).
op(P,A,N)
terms representing the operators
exported from Module.3558'$exported_ops'(Module, Ops, Tail) :- 3559 '$c_current_predicate'(_, Module:'$exported_op'(_,_,_)), 3560 !, 3561 findall(op(P,A,N), Module:'$exported_op'(P,A,N), Ops, Tail). 3562'$exported_ops'(_, Ops, Ops). 3563 3564'$exported_op'(Module, P, A, N) :- 3565 '$c_current_predicate'(_, Module:'$exported_op'(_,_,_)), 3566 Module:'$exported_op'(P, A, N).
3573'$import_ops'(To, From, Pattern) :- 3574 ground(Pattern), 3575 !, 3576 Pattern = op(P,A,N), 3577 op(P,A,To:N), 3578 ( '$exported_op'(From, P, A, N) 3579 -> true 3580 ; print_message(warning, no_exported_op(From, Pattern)) 3581 ). 3582'$import_ops'(To, From, Pattern) :- 3583 ( '$exported_op'(From, Pri, Assoc, Name), 3584 Pattern = op(Pri, Assoc, Name), 3585 op(Pri, Assoc, To:Name), 3586 fail 3587 ; true 3588 ).
3596'$export_list'(Decls, Module, Ops) :- 3597 is_list(Decls), 3598 !, 3599 '$do_export_list'(Decls, Module, Ops). 3600'$export_list'(Decls, _, _) :- 3601 var(Decls), 3602 throw(error(instantiation_error, _)). 3603'$export_list'(Decls, _, _) :- 3604 throw(error(type_error(list, Decls), _)). 3605 3606'$do_export_list'([], _, []) :- !. 3607'$do_export_list'([H|T], Module, Ops) :- 3608 !, 3609 E = error(_,_), 3610 catch('$export1'(H, Module, Ops, Ops1), 3611 E, ('$print_message'(error, E), Ops = Ops1)), 3612 '$do_export_list'(T, Module, Ops1). 3613 3614'$export1'(Var, _, _, _) :- 3615 var(Var), 3616 !, 3617 throw(error(instantiation_error, _)). 3618'$export1'(Op, _, [Op|T], T) :- 3619 Op = op(_,_,_), 3620 !. 3621'$export1'(PI0, Module, Ops, Ops) :- 3622 strip_module(Module:PI0, M, PI), 3623 ( PI = (_//_) 3624 -> non_terminal(M:PI) 3625 ; true 3626 ), 3627 export(M:PI). 3628 3629'$export_ops'([op(Pri, Assoc, Name)|T], Module, File) :- 3630 E = error(_,_), 3631 catch(( '$execute_directive'(op(Pri, Assoc, Module:Name), File, []), 3632 '$export_op'(Pri, Assoc, Name, Module, File) 3633 ), 3634 E, '$print_message'(error, E)), 3635 '$export_ops'(T, Module, File). 3636'$export_ops'([], _, _). 3637 3638'$export_op'(Pri, Assoc, Name, Module, File) :- 3639 ( '$get_predicate_attribute'(Module:'$exported_op'(_,_,_), defined, 1) 3640 -> true 3641 ; '$execute_directive'(discontiguous(Module:'$exported_op'/3), File, []) 3642 ), 3643 '$store_admin_clause'('$exported_op'(Pri, Assoc, Name), _Layout, File, -).
3649'$execute_directive'(Var, _F, _Options) :- 3650 var(Var), 3651 '$instantiation_error'(Var). 3652'$execute_directive'(encoding(Encoding), _F, _Options) :- 3653 !, 3654 ( '$load_input'(_F, S) 3655 -> set_stream(S, encoding(Encoding)) 3656 ). 3657'$execute_directive'(Goal, _, Options) :- 3658 \+ '$compilation_mode'(database), 3659 !, 3660 '$add_directive_wic2'(Goal, Type, Options), 3661 ( Type == call % suspend compiling into .qlf file 3662 -> '$compilation_mode'(Old, database), 3663 setup_call_cleanup( 3664 '$directive_mode'(OldDir, Old), 3665 '$execute_directive_3'(Goal), 3666 ( '$set_compilation_mode'(Old), 3667 '$set_directive_mode'(OldDir) 3668 )) 3669 ; '$execute_directive_3'(Goal) 3670 ). 3671'$execute_directive'(Goal, _, _Options) :- 3672 '$execute_directive_3'(Goal). 3673 3674'$execute_directive_3'(Goal) :- 3675 '$current_source_module'(Module), 3676 '$valid_directive'(Module:Goal), 3677 !, 3678 ( '$pattr_directive'(Goal, Module) 3679 -> true 3680 ; Term = error(_,_), 3681 catch(Module:Goal, Term, '$exception_in_directive'(Term)) 3682 -> true 3683 ; '$print_message'(warning, goal_failed(directive, Module:Goal)), 3684 fail 3685 ). 3686'$execute_directive_3'(_).
sandboxed_load
is true
, this calls
prolog:sandbox_allowed_directive/1. This call can deny execution
of the directive by throwing an exception.3695:- multifile prolog:sandbox_allowed_directive/1. 3696:- multifile prolog:sandbox_allowed_clause/1. 3697:- meta_predicate '$valid_directive'( ). 3698 3699'$valid_directive'(_) :- 3700 current_prolog_flag(sandboxed_load, false), 3701 !. 3702'$valid_directive'(Goal) :- 3703 Error = error(Formal, _), 3704 catch(prolog:sandbox_allowed_directive(Goal), Error, true), 3705 !, 3706 ( var(Formal) 3707 -> true 3708 ; print_message(error, Error), 3709 fail 3710 ). 3711'$valid_directive'(Goal) :- 3712 print_message(error, 3713 error(permission_error(execute, 3714 sandboxed_directive, 3715 Goal), _)), 3716 fail. 3717 3718'$exception_in_directive'(Term) :- 3719 '$print_message'(error, Term), 3720 fail.
load
or call
. Add a call
directive to the QLF file. load
directives continue the
compilation into the QLF file.3728'$add_directive_wic2'(Goal, Type, Options) :- 3729 '$common_goal_type'(Goal, Type, Options), 3730 !, 3731 ( Type == load 3732 -> true 3733 ; '$current_source_module'(Module), 3734 '$add_directive_wic'(Module:Goal) 3735 ). 3736'$add_directive_wic2'(Goal, _, _) :- 3737 ( '$compilation_mode'(qlf) % no problem for qlf files 3738 -> true 3739 ; print_message(error, mixed_directive(Goal)) 3740 ).
load
or call
.3747'$common_goal_type'((A,B), Type, Options) :- 3748 !, 3749 '$common_goal_type'(A, Type, Options), 3750 '$common_goal_type'(B, Type, Options). 3751'$common_goal_type'((A;B), Type, Options) :- 3752 !, 3753 '$common_goal_type'(A, Type, Options), 3754 '$common_goal_type'(B, Type, Options). 3755'$common_goal_type'((A->B), Type, Options) :- 3756 !, 3757 '$common_goal_type'(A, Type, Options), 3758 '$common_goal_type'(B, Type, Options). 3759'$common_goal_type'(Goal, Type, Options) :- 3760 '$goal_type'(Goal, Type, Options). 3761 3762'$goal_type'(Goal, Type, Options) :- 3763 ( '$load_goal'(Goal, Options) 3764 -> Type = load 3765 ; Type = call 3766 ). 3767 3768:- thread_local 3769 '$qlf':qinclude/1. 3770 3771'$load_goal'([_|_], _). 3772'$load_goal'(consult(_), _). 3773'$load_goal'(load_files(_), _). 3774'$load_goal'(load_files(_,Options), _) :- 3775 memberchk(qcompile(QlfMode), Options), 3776 '$qlf_part_mode'(QlfMode). 3777'$load_goal'(ensure_loaded(_), _) :- '$compilation_mode'(wic). 3778'$load_goal'(use_module(_), _) :- '$compilation_mode'(wic). 3779'$load_goal'(use_module(_, _), _) :- '$compilation_mode'(wic). 3780'$load_goal'(reexport(_), _) :- '$compilation_mode'(wic). 3781'$load_goal'(reexport(_, _), _) :- '$compilation_mode'(wic). 3782'$load_goal'(Goal, _Options) :- 3783 '$qlf':qinclude(user), 3784 '$load_goal_file'(Goal, File), 3785 '$all_user_files'(File). 3786 3787 3788'$load_goal_file'(load_files(F), F). 3789'$load_goal_file'(load_files(F, _), F). 3790'$load_goal_file'(ensure_loaded(F), F). 3791'$load_goal_file'(use_module(F), F). 3792'$load_goal_file'(use_module(F, _), F). 3793'$load_goal_file'(reexport(F), F). 3794'$load_goal_file'(reexport(F, _), F). 3795 3796'$all_user_files'([]) :- 3797 !. 3798'$all_user_files'([H|T]) :- 3799 !, 3800 '$is_user_file'(H), 3801 '$all_user_files'(T). 3802'$all_user_files'(F) :- 3803 ground(F), 3804 '$is_user_file'(F). 3805 3806'$is_user_file'(File) :- 3807 absolute_file_name(File, Path, 3808 [ file_type(prolog), 3809 access(read) 3810 ]), 3811 '$module_class'(Path, user, _). 3812 3813'$qlf_part_mode'(part). 3814'$qlf_part_mode'(true). % compatibility 3815 3816 3817 /******************************** 3818 * COMPILE A CLAUSE * 3819 *********************************/
3826'$store_admin_clause'(Clause, Layout, Owner, SrcLoc) :- 3827 Owner \== (-), 3828 !, 3829 setup_call_cleanup( 3830 '$start_aux'(Owner, Context), 3831 '$store_admin_clause2'(Clause, Layout, Owner, SrcLoc), 3832 '$end_aux'(Owner, Context)). 3833'$store_admin_clause'(Clause, Layout, File, SrcLoc) :- 3834 '$store_admin_clause2'(Clause, Layout, File, SrcLoc). 3835 3836'$store_admin_clause2'(Clause, _Layout, File, SrcLoc) :- 3837 ( '$compilation_mode'(database) 3838 -> '$record_clause'(Clause, File, SrcLoc) 3839 ; '$record_clause'(Clause, File, SrcLoc, Ref), 3840 '$qlf_assert_clause'(Ref, development) 3841 ).
3851'$store_clause'((_, _), _, _, _) :- 3852 !, 3853 print_message(error, cannot_redefine_comma), 3854 fail. 3855'$store_clause'((Pre => Body), _Layout, File, SrcLoc) :- 3856 nonvar(Pre), 3857 Pre = (Head,Cond), 3858 !, 3859 ( '$is_true'(Cond), current_prolog_flag(optimise, true) 3860 -> '$store_clause'((Head=>Body), _Layout, File, SrcLoc) 3861 ; '$store_clause'(?=>(Head,(Cond,!,Body)), _Layout, File, SrcLoc) 3862 ). 3863'$store_clause'(Clause, _Layout, File, SrcLoc) :- 3864 '$valid_clause'(Clause), 3865 !, 3866 ( '$compilation_mode'(database) 3867 -> '$record_clause'(Clause, File, SrcLoc) 3868 ; '$record_clause'(Clause, File, SrcLoc, Ref), 3869 '$qlf_assert_clause'(Ref, development) 3870 ). 3871 3872'$is_true'(true) => true. 3873'$is_true'((A,B)) => '$is_true'(A), '$is_true'(B). 3874'$is_true'(_) => fail. 3875 3876'$valid_clause'(_) :- 3877 current_prolog_flag(sandboxed_load, false), 3878 !. 3879'$valid_clause'(Clause) :- 3880 \+ '$cross_module_clause'(Clause), 3881 !. 3882'$valid_clause'(Clause) :- 3883 Error = error(Formal, _), 3884 catch(prolog:sandbox_allowed_clause(Clause), Error, true), 3885 !, 3886 ( var(Formal) 3887 -> true 3888 ; print_message(error, Error), 3889 fail 3890 ). 3891'$valid_clause'(Clause) :- 3892 print_message(error, 3893 error(permission_error(assert, 3894 sandboxed_clause, 3895 Clause), _)), 3896 fail. 3897 3898'$cross_module_clause'(Clause) :- 3899 '$head_module'(Clause, Module), 3900 \+ '$current_source_module'(Module). 3901 3902'$head_module'(Var, _) :- 3903 var(Var), !, fail. 3904'$head_module'((Head :- _), Module) :- 3905 '$head_module'(Head, Module). 3906'$head_module'(Module:_, Module). 3907 3908'$clause_source'('$source_location'(File,Line):Clause, Clause, File:Line) :- !. 3909'$clause_source'(Clause, Clause, -).
3916:- public 3917 '$store_clause'/2. 3918 3919'$store_clause'(Term, Id) :- 3920 '$clause_source'(Term, Clause, SrcLoc), 3921 '$store_clause'(Clause, _, Id, SrcLoc).
If the cross-referencer is active, we should not (re-)assert the clauses. Actually, we should make them known to the cross-referencer. How do we do that? Maybe we need a different API, such as in:
expand_term_aux(Goal, NewGoal, Clauses)
3942compile_aux_clauses(_Clauses) :- 3943 current_prolog_flag(xref, true), 3944 !. 3945compile_aux_clauses(Clauses) :- 3946 source_location(File, _Line), 3947 '$compile_aux_clauses'(Clauses, File). 3948 3949'$compile_aux_clauses'(Clauses, File) :- 3950 setup_call_cleanup( 3951 '$start_aux'(File, Context), 3952 '$store_aux_clauses'(Clauses, File), 3953 '$end_aux'(File, Context)). 3954 3955'$store_aux_clauses'(Clauses, File) :- 3956 is_list(Clauses), 3957 !, 3958 forall('$member'(C,Clauses), 3959 '$compile_term'(C, _Layout, File, [])). 3960'$store_aux_clauses'(Clause, File) :- 3961 '$compile_term'(Clause, _Layout, File, []). 3962 3963 3964 /******************************* 3965 * STAGING * 3966 *******************************/
3976'$stage_file'(Target, Stage) :- 3977 file_directory_name(Target, Dir), 3978 file_base_name(Target, File), 3979 current_prolog_flag(pid, Pid), 3980 format(atom(Stage), '~w/.~w.~d', [Dir,File,Pid]). 3981 3982'$install_staged_file'(exit, Staged, Target, error) :- 3983 !, 3984 rename_file(Staged, Target). 3985'$install_staged_file'(exit, Staged, Target, OnError) :- 3986 !, 3987 InstallError = error(_,_), 3988 catch(rename_file(Staged, Target), 3989 InstallError, 3990 '$install_staged_error'(OnError, InstallError, Staged, Target)). 3991'$install_staged_file'(_, Staged, _, _OnError) :- 3992 E = error(_,_), 3993 catch(delete_file(Staged), E, true). 3994 3995'$install_staged_error'(OnError, Error, Staged, _Target) :- 3996 E = error(_,_), 3997 catch(delete_file(Staged), E, true), 3998 ( OnError = silent 3999 -> true 4000 ; OnError = fail 4001 -> fail 4002 ; print_message(warning, Error) 4003 ). 4004 4005 4006 /******************************* 4007 * READING * 4008 *******************************/ 4009 4010:- multifile 4011 prolog:comment_hook/3. % hook for read_clause/3 4012 4013 4014 /******************************* 4015 * FOREIGN INTERFACE * 4016 *******************************/ 4017 4018% call-back from PL_register_foreign(). First argument is the module 4019% into which the foreign predicate is loaded and second is a term 4020% describing the arguments. 4021 4022:- dynamic 4023 '$foreign_registered'/2. 4024 4025 /******************************* 4026 * TEMPORARY TERM EXPANSION * 4027 *******************************/ 4028 4029% Provide temporary definitions for the boot-loader. These are replaced 4030% by the real thing in load.pl 4031 4032:- dynamic 4033 '$expand_goal'/2, 4034 '$expand_term'/4. 4035 4036'$expand_goal'(In, In). 4037'$expand_term'(In, Layout, In, Layout). 4038 4039 4040 /******************************* 4041 * TYPE SUPPORT * 4042 *******************************/ 4043 4044'$type_error'(Type, Value) :- 4045 ( var(Value) 4046 -> throw(error(instantiation_error, _)) 4047 ; throw(error(type_error(Type, Value), _)) 4048 ). 4049 4050'$domain_error'(Type, Value) :- 4051 throw(error(domain_error(Type, Value), _)). 4052 4053'$existence_error'(Type, Object) :- 4054 throw(error(existence_error(Type, Object), _)). 4055 4056'$permission_error'(Action, Type, Term) :- 4057 throw(error(permission_error(Action, Type, Term), _)). 4058 4059'$instantiation_error'(_Var) :- 4060 throw(error(instantiation_error, _)). 4061 4062'$uninstantiation_error'(NonVar) :- 4063 throw(error(uninstantiation_error(NonVar), _)). 4064 4065'$must_be'(list, X) :- !, 4066 '$skip_list'(_, X, Tail), 4067 ( Tail == [] 4068 -> true 4069 ; '$type_error'(list, Tail) 4070 ). 4071'$must_be'(options, X) :- !, 4072 ( '$is_options'(X) 4073 -> true 4074 ; '$type_error'(options, X) 4075 ). 4076'$must_be'(atom, X) :- !, 4077 ( atom(X) 4078 -> true 4079 ; '$type_error'(atom, X) 4080 ). 4081'$must_be'(integer, X) :- !, 4082 ( integer(X) 4083 -> true 4084 ; '$type_error'(integer, X) 4085 ). 4086'$must_be'(between(Low,High), X) :- !, 4087 ( integer(X) 4088 -> ( between(Low, High, X) 4089 -> true 4090 ; '$domain_error'(between(Low,High), X) 4091 ) 4092 ; '$type_error'(integer, X) 4093 ). 4094'$must_be'(callable, X) :- !, 4095 ( callable(X) 4096 -> true 4097 ; '$type_error'(callable, X) 4098 ). 4099'$must_be'(acyclic, X) :- !, 4100 ( acyclic_term(X) 4101 -> true 4102 ; '$domain_error'(acyclic_term, X) 4103 ). 4104'$must_be'(oneof(Type, Domain, List), X) :- !, 4105 '$must_be'(Type, X), 4106 ( memberchk(X, List) 4107 -> true 4108 ; '$domain_error'(Domain, X) 4109 ). 4110'$must_be'(boolean, X) :- !, 4111 ( (X == true ; X == false) 4112 -> true 4113 ; '$type_error'(boolean, X) 4114 ). 4115'$must_be'(ground, X) :- !, 4116 ( ground(X) 4117 -> true 4118 ; '$instantiation_error'(X) 4119 ). 4120'$must_be'(filespec, X) :- !, 4121 ( ( atom(X) 4122 ; string(X) 4123 ; compound(X), 4124 compound_name_arity(X, _, 1) 4125 ) 4126 -> true 4127 ; '$type_error'(filespec, X) 4128 ). 4129 4130% Use for debugging 4131%'$must_be'(Type, _X) :- format('Unknown $must_be type: ~q~n', [Type]). 4132 4133 4134 /******************************** 4135 * LIST PROCESSING * 4136 *********************************/ 4137 4138'$member'(El, [H|T]) :- 4139 '$member_'(T, El, H). 4140 4141'$member_'(_, El, El). 4142'$member_'([H|T], El, _) :- 4143 '$member_'(T, El, H). 4144 4145'$append'([], L, L). 4146'$append'([H|T], L, [H|R]) :- 4147 '$append'(T, L, R). 4148 4149'$append'(ListOfLists, List) :- 4150 '$must_be'(list, ListOfLists), 4151 '$append_'(ListOfLists, List). 4152 4153'$append_'([], []). 4154'$append_'([L|Ls], As) :- 4155 '$append'(L, Ws, As), 4156 '$append_'(Ls, Ws). 4157 4158'$select'(X, [X|Tail], Tail). 4159'$select'(Elem, [Head|Tail], [Head|Rest]) :- 4160 '$select'(Elem, Tail, Rest). 4161 4162'$reverse'(L1, L2) :- 4163 '$reverse'(L1, [], L2). 4164 4165'$reverse'([], List, List). 4166'$reverse'([Head|List1], List2, List3) :- 4167 '$reverse'(List1, [Head|List2], List3). 4168 4169'$delete'([], _, []) :- !. 4170'$delete'([Elem|Tail], Elem, Result) :- 4171 !, 4172 '$delete'(Tail, Elem, Result). 4173'$delete'([Head|Tail], Elem, [Head|Rest]) :- 4174 '$delete'(Tail, Elem, Rest). 4175 4176'$last'([H|T], Last) :- 4177 '$last'(T, H, Last). 4178 4179'$last'([], Last, Last). 4180'$last'([H|T], _, Last) :- 4181 '$last'(T, H, Last).
4188:- '$iso'((length/2)). 4189 4190length(List, Length) :- 4191 var(Length), 4192 !, 4193 '$skip_list'(Length0, List, Tail), 4194 ( Tail == [] 4195 -> Length = Length0 % +,- 4196 ; var(Tail) 4197 -> Tail \== Length, % avoid length(L,L) 4198 '$length3'(Tail, Length, Length0) % -,- 4199 ; throw(error(type_error(list, List), 4200 context(length/2, _))) 4201 ). 4202length(List, Length) :- 4203 integer(Length), 4204 Length >= 0, 4205 !, 4206 '$skip_list'(Length0, List, Tail), 4207 ( Tail == [] % proper list 4208 -> Length = Length0 4209 ; var(Tail) 4210 -> Extra is Length-Length0, 4211 '$length'(Tail, Extra) 4212 ; throw(error(type_error(list, List), 4213 context(length/2, _))) 4214 ). 4215length(_, Length) :- 4216 integer(Length), 4217 !, 4218 throw(error(domain_error(not_less_than_zero, Length), 4219 context(length/2, _))). 4220length(_, Length) :- 4221 throw(error(type_error(integer, Length), 4222 context(length/2, _))). 4223 4224'$length3'([], N, N). 4225'$length3'([_|List], N, N0) :- 4226 N1 is N0+1, 4227 '$length3'(List, N, N1). 4228 4229 4230 /******************************* 4231 * OPTION PROCESSING * 4232 *******************************/
4238'$is_options'(Map) :- 4239 is_dict(Map, _), 4240 !. 4241'$is_options'(List) :- 4242 is_list(List), 4243 ( List == [] 4244 -> true 4245 ; List = [H|_], 4246 '$is_option'(H, _, _) 4247 ). 4248 4249'$is_option'(Var, _, _) :- 4250 var(Var), !, fail. 4251'$is_option'(F, Name, Value) :- 4252 functor(F, _, 1), 4253 !, 4254 F =.. [Name,Value]. 4255'$is_option'(Name=Value, Name, Value).
4259'$option'(Opt, Options) :- 4260 is_dict(Options), 4261 !, 4262 [Opt] :< Options. 4263'$option'(Opt, Options) :- 4264 memberchk(Opt, Options).
4268'$option'(Term, Options, Default) :-
4269 arg(1, Term, Value),
4270 functor(Term, Name, 1),
4271 ( is_dict(Options)
4272 -> ( get_dict(Name, Options, GVal)
4273 -> Value = GVal
4274 ; Value = Default
4275 )
4276 ; functor(Gen, Name, 1),
4277 arg(1, Gen, GVal),
4278 ( memberchk(Gen, Options)
4279 -> Value = GVal
4280 ; Value = Default
4281 )
4282 ).
4290'$select_option'(Opt, Options, Rest) :-
4291 '$options_dict'(Options, Dict),
4292 select_dict([Opt], Dict, Rest).
4300'$merge_options'(New, Old, Merged) :-
4301 '$options_dict'(New, NewDict),
4302 '$options_dict'(Old, OldDict),
4303 put_dict(NewDict, OldDict, Merged).
4310'$options_dict'(Options, Dict) :- 4311 is_list(Options), 4312 !, 4313 '$keyed_options'(Options, Keyed), 4314 sort(1, @<, Keyed, UniqueKeyed), 4315 '$pairs_values'(UniqueKeyed, Unique), 4316 dict_create(Dict, _, Unique). 4317'$options_dict'(Dict, Dict) :- 4318 is_dict(Dict), 4319 !. 4320'$options_dict'(Options, _) :- 4321 '$domain_error'(options, Options). 4322 4323'$keyed_options'([], []). 4324'$keyed_options'([H0|T0], [H|T]) :- 4325 '$keyed_option'(H0, H), 4326 '$keyed_options'(T0, T). 4327 4328'$keyed_option'(Var, _) :- 4329 var(Var), 4330 !, 4331 '$instantiation_error'(Var). 4332'$keyed_option'(Name=Value, Name-(Name-Value)). 4333'$keyed_option'(NameValue, Name-(Name-Value)) :- 4334 compound_name_arguments(NameValue, Name, [Value]), 4335 !. 4336'$keyed_option'(Opt, _) :- 4337 '$domain_error'(option, Opt). 4338 4339 4340 /******************************* 4341 * HANDLE TRACER 'L'-COMMAND * 4342 *******************************/ 4343 4344:- public '$prolog_list_goal'/1. 4345 4346:- multifile 4347 user:prolog_list_goal/1. 4348 4349'$prolog_list_goal'(Goal) :- 4350 user:prolog_list_goal(Goal), 4351 !. 4352'$prolog_list_goal'(Goal) :- 4353 use_module(library(listing), [listing/1]), 4354 @(listing(Goal), user). 4355 4356 4357 /******************************* 4358 * HALT * 4359 *******************************/ 4360 4361:- '$iso'((halt/0)). 4362 4363halt :- 4364 '$exit_code'(Code), 4365 ( Code == 0 4366 -> true 4367 ; print_message(warning, on_error(halt(1))) 4368 ), 4369 halt(Code).
on_error
and on_warning
flags. Also used by qsave_toplevel/0.
4376'$exit_code'(Code) :-
4377 ( ( current_prolog_flag(on_error, status),
4378 statistics(errors, Count),
4379 Count > 0
4380 ; current_prolog_flag(on_warning, status),
4381 statistics(warnings, Count),
4382 Count > 0
4383 )
4384 -> Code = 1
4385 ; Code = 0
4386 ).
4395:- meta_predicate at_halt( ). 4396:- dynamic system:term_expansion/2, '$at_halt'/2. 4397:- multifile system:term_expansion/2, '$at_halt'/2. 4398 4399systemterm_expansion((:- at_halt(Goal)), 4400 system:'$at_halt'(Module:Goal, File:Line)) :- 4401 \+ current_prolog_flag(xref, true), 4402 source_location(File, Line), 4403 '$current_source_module'(Module). 4404 4405at_halt(Goal) :- 4406 asserta('$at_halt'(Goal, (-):0)). 4407 4408:- public '$run_at_halt'/0. 4409 4410'$run_at_halt' :- 4411 forall(clause('$at_halt'(Goal, Src), true, Ref), 4412 ( '$call_at_halt'(Goal, Src), 4413 erase(Ref) 4414 )). 4415 4416'$call_at_halt'(Goal, _Src) :- 4417 catch(Goal, E, true), 4418 !, 4419 ( var(E) 4420 -> true 4421 ; subsumes_term(cancel_halt(_), E) 4422 -> '$print_message'(informational, E), 4423 fail 4424 ; '$print_message'(error, E) 4425 ). 4426'$call_at_halt'(Goal, _Src) :- 4427 '$print_message'(warning, goal_failed(at_halt, Goal)).
4435cancel_halt(Reason) :-
4436 throw(cancel_halt(Reason)).
heartbeat
is
non-zero.4443:- multifile prolog:heartbeat/0. 4444 4445 4446 /******************************** 4447 * LOAD OTHER MODULES * 4448 *********************************/ 4449 4450:- meta_predicate 4451 '$load_wic_files'( ). 4452 4453'$load_wic_files'(Files) :- 4454 Files = Module:_, 4455 '$execute_directive'('$set_source_module'(OldM, Module), [], []), 4456 '$save_lex_state'(LexState, []), 4457 '$style_check'(_, 0xC7), % see style_name/2 in syspred.pl 4458 '$compilation_mode'(OldC, wic), 4459 consult(Files), 4460 '$execute_directive'('$set_source_module'(OldM), [], []), 4461 '$execute_directive'('$restore_lex_state'(LexState), [], []), 4462 '$set_compilation_mode'(OldC).
compileFileList()
in pl-wic.c. Gets the files from
"-c file ..." and loads them into the module user.4470:- public '$load_additional_boot_files'/0. 4471 4472'$load_additional_boot_files' :- 4473 current_prolog_flag(argv, Argv), 4474 '$get_files_argv'(Argv, Files), 4475 ( Files \== [] 4476 -> format('Loading additional boot files~n'), 4477 '$load_wic_files'(user:Files), 4478 format('additional boot files loaded~n') 4479 ; true 4480 ). 4481 4482'$get_files_argv'([], []) :- !. 4483'$get_files_argv'(['-c'|Files], Files) :- !. 4484'$get_files_argv'([_|Rest], Files) :- 4485 '$get_files_argv'(Rest, Files). 4486 4487'$:-'(('$boot_message'('Loading Prolog startup files~n', []), 4488 source_location(File, _Line), 4489 file_directory_name(File, Dir), 4490 atom_concat(Dir, '/load.pl', LoadFile), 4491 '$load_wic_files'(system:[LoadFile]), 4492 ( current_prolog_flag(windows, true) 4493 -> atom_concat(Dir, '/menu.pl', MenuFile), 4494 '$load_wic_files'(system:[MenuFile]) 4495 ; true 4496 ), 4497 '$boot_message'('SWI-Prolog boot files loaded~n', []), 4498 '$compilation_mode'(OldC, wic), 4499 '$execute_directive'('$set_source_module'(user), [], []), 4500 '$set_compilation_mode'(OldC) 4501 ))