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-2023, 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'( ), 102 '$notransact'( ).
public
also plays this role. in SWI,
public
means that the predicate can be called, even if we cannot
find a reference to it.134dynamic(Spec) :- '$set_pattr'(Spec, pred, dynamic(true)). 135multifile(Spec) :- '$set_pattr'(Spec, pred, multifile(true)). 136module_transparent(Spec) :- '$set_pattr'(Spec, pred, transparent(true)). 137discontiguous(Spec) :- '$set_pattr'(Spec, pred, discontiguous(true)). 138volatile(Spec) :- '$set_pattr'(Spec, pred, volatile(true)). 139thread_local(Spec) :- '$set_pattr'(Spec, pred, thread_local(true)). 140noprofile(Spec) :- '$set_pattr'(Spec, pred, noprofile(true)). 141public(Spec) :- '$set_pattr'(Spec, pred, public(true)). 142non_terminal(Spec) :- '$set_pattr'(Spec, pred, non_terminal(true)). 143det(Spec) :- '$set_pattr'(Spec, pred, det(true)). 144'$iso'(Spec) :- '$set_pattr'(Spec, pred, iso(true)). 145'$clausable'(Spec) :- '$set_pattr'(Spec, pred, clausable(true)). 146'$hide'(Spec) :- '$set_pattr'(Spec, pred, trace(false)). 147'$notransact'(Spec) :- '$set_pattr'(Spec, pred, transact(false)). 148 149'$set_pattr'(M:Pred, How, Attr) :- 150 '$set_pattr'(Pred, M, How, Attr).
pred
or directive
.156'$set_pattr'(X, _, _, _) :- 157 var(X), 158 '$uninstantiation_error'(X). 159'$set_pattr'(as(Spec,Options), M, How, Attr0) :- 160 !, 161 '$attr_options'(Options, Attr0, Attr), 162 '$set_pattr'(Spec, M, How, Attr). 163'$set_pattr'([], _, _, _) :- !. 164'$set_pattr'([H|T], M, How, Attr) :- % ISO 165 !, 166 '$set_pattr'(H, M, How, Attr), 167 '$set_pattr'(T, M, How, Attr). 168'$set_pattr'((A,B), M, How, Attr) :- % ISO and traditional 169 !, 170 '$set_pattr'(A, M, How, Attr), 171 '$set_pattr'(B, M, How, Attr). 172'$set_pattr'(M:T, _, How, Attr) :- 173 !, 174 '$set_pattr'(T, M, How, Attr). 175'$set_pattr'(PI, M, _, []) :- 176 !, 177 '$pi_head'(M:PI, Pred), 178 '$set_table_wrappers'(Pred). 179'$set_pattr'(A, M, How, [O|OT]) :- 180 !, 181 '$set_pattr'(A, M, How, O), 182 '$set_pattr'(A, M, How, OT). 183'$set_pattr'(A, M, pred, Attr) :- 184 !, 185 Attr =.. [Name,Val], 186 '$set_pi_attr'(M:A, Name, Val). 187'$set_pattr'(A, M, directive, Attr) :- 188 !, 189 Attr =.. [Name,Val], 190 catch('$set_pi_attr'(M:A, Name, Val), 191 error(E, _), 192 print_message(error, error(E, context((Name)/1,_)))). 193 194'$set_pi_attr'(PI, Name, Val) :- 195 '$pi_head'(PI, Head), 196 '$set_predicate_attribute'(Head, Name, Val). 197 198'$attr_options'(Var, _, _) :- 199 var(Var), 200 !, 201 '$uninstantiation_error'(Var). 202'$attr_options'((A,B), Attr0, Attr) :- 203 !, 204 '$attr_options'(A, Attr0, Attr1), 205 '$attr_options'(B, Attr1, Attr). 206'$attr_options'(Opt, Attr0, Attrs) :- 207 '$must_be'(ground, Opt), 208 ( '$attr_option'(Opt, AttrX) 209 -> ( is_list(Attr0) 210 -> '$join_attrs'(AttrX, Attr0, Attrs) 211 ; '$join_attrs'(AttrX, [Attr0], Attrs) 212 ) 213 ; '$domain_error'(predicate_option, Opt) 214 ). 215 216'$join_attrs'([], Attrs, Attrs) :- 217 !. 218'$join_attrs'([H|T], Attrs0, Attrs) :- 219 !, 220 '$join_attrs'(H, Attrs0, Attrs1), 221 '$join_attrs'(T, Attrs1, Attrs). 222'$join_attrs'(Attr, Attrs, Attrs) :- 223 memberchk(Attr, Attrs), 224 !. 225'$join_attrs'(Attr, Attrs, Attrs) :- 226 Attr =.. [Name,Value], 227 Gen =.. [Name,Existing], 228 memberchk(Gen, Attrs), 229 !, 230 throw(error(conflict_error(Name, Value, Existing), _)). 231'$join_attrs'(Attr, Attrs0, Attrs) :- 232 '$append'(Attrs0, [Attr], Attrs). 233 234'$attr_option'(incremental, [incremental(true),opaque(false)]). 235'$attr_option'(monotonic, monotonic(true)). 236'$attr_option'(lazy, lazy(true)). 237'$attr_option'(opaque, [incremental(false),opaque(true)]). 238'$attr_option'(abstract(Level0), abstract(Level)) :- 239 '$table_option'(Level0, Level). 240'$attr_option'(subgoal_abstract(Level0), subgoal_abstract(Level)) :- 241 '$table_option'(Level0, Level). 242'$attr_option'(answer_abstract(Level0), answer_abstract(Level)) :- 243 '$table_option'(Level0, Level). 244'$attr_option'(max_answers(Level0), max_answers(Level)) :- 245 '$table_option'(Level0, Level). 246'$attr_option'(volatile, volatile(true)). 247'$attr_option'(multifile, multifile(true)). 248'$attr_option'(discontiguous, discontiguous(true)). 249'$attr_option'(shared, thread_local(false)). 250'$attr_option'(local, thread_local(true)). 251'$attr_option'(private, thread_local(true)). 252 253'$table_option'(Value0, _Value) :- 254 var(Value0), 255 !, 256 '$instantiation_error'(Value0). 257'$table_option'(Value0, Value) :- 258 integer(Value0), 259 Value0 >= 0, 260 !, 261 Value = Value0. 262'$table_option'(off, -1) :- 263 !. 264'$table_option'(false, -1) :- 265 !. 266'$table_option'(infinite, -1) :- 267 !. 268'$table_option'(Value, _) :- 269 '$domain_error'(nonneg_or_false, Value).
279'$pattr_directive'(dynamic(Spec), M) :- 280 '$set_pattr'(Spec, M, directive, dynamic(true)). 281'$pattr_directive'(multifile(Spec), M) :- 282 '$set_pattr'(Spec, M, directive, multifile(true)). 283'$pattr_directive'(module_transparent(Spec), M) :- 284 '$set_pattr'(Spec, M, directive, transparent(true)). 285'$pattr_directive'(discontiguous(Spec), M) :- 286 '$set_pattr'(Spec, M, directive, discontiguous(true)). 287'$pattr_directive'(volatile(Spec), M) :- 288 '$set_pattr'(Spec, M, directive, volatile(true)). 289'$pattr_directive'(thread_local(Spec), M) :- 290 '$set_pattr'(Spec, M, directive, thread_local(true)). 291'$pattr_directive'(noprofile(Spec), M) :- 292 '$set_pattr'(Spec, M, directive, noprofile(true)). 293'$pattr_directive'(public(Spec), M) :- 294 '$set_pattr'(Spec, M, directive, public(true)). 295'$pattr_directive'(det(Spec), M) :- 296 '$set_pattr'(Spec, M, directive, det(true)).
300'$pi_head'(PI, Head) :- 301 var(PI), 302 var(Head), 303 '$instantiation_error'([PI,Head]). 304'$pi_head'(M:PI, M:Head) :- 305 !, 306 '$pi_head'(PI, Head). 307'$pi_head'(Name/Arity, Head) :- 308 !, 309 '$head_name_arity'(Head, Name, Arity). 310'$pi_head'(Name//DCGArity, Head) :- 311 !, 312 ( nonvar(DCGArity) 313 -> Arity is DCGArity+2, 314 '$head_name_arity'(Head, Name, Arity) 315 ; '$head_name_arity'(Head, Name, Arity), 316 DCGArity is Arity - 2 317 ). 318'$pi_head'(PI, _) :- 319 '$type_error'(predicate_indicator, PI).
324'$head_name_arity'(Goal, Name, Arity) :- 325 ( atom(Goal) 326 -> Name = Goal, Arity = 0 327 ; compound(Goal) 328 -> compound_name_arity(Goal, Name, Arity) 329 ; var(Goal) 330 -> ( Arity == 0 331 -> ( atom(Name) 332 -> Goal = Name 333 ; Name == [] 334 -> Goal = Name 335 ; blob(Name, closure) 336 -> Goal = Name 337 ; '$type_error'(atom, Name) 338 ) 339 ; compound_name_arity(Goal, Name, Arity) 340 ) 341 ; '$type_error'(callable, Goal) 342 ). 343 344:- '$iso'(((dynamic)/1, (multifile)/1, (discontiguous)/1)). 345 346 347 /******************************** 348 * CALLING, CONTROL * 349 *********************************/ 350 351:- noprofile((call/1, 352 catch/3, 353 once/1, 354 ignore/1, 355 call_cleanup/2, 356 setup_call_cleanup/3, 357 setup_call_catcher_cleanup/4, 358 notrace/1)). 359 360:- meta_predicate 361 ';'( , ), 362 ','( , ), 363 @( , ), 364 call( ), 365 call( , ), 366 call( , , ), 367 call( , , , ), 368 call( , , , , ), 369 call( , , , , , ), 370 call( , , , , , , ), 371 call( , , , , , , , ), 372 not( ), 373 \+( ), 374 $( ), 375 '->'( , ), 376 '*->'( , ), 377 once( ), 378 ignore( ), 379 catch( , , ), 380 reset( , , ), 381 setup_call_cleanup( , , ), 382 setup_call_catcher_cleanup( , , , ), 383 call_cleanup( , ), 384 catch_with_backtrace( , , ), 385 notrace( ), 386 '$meta_call'( ). 387 388:- '$iso'((call/1, (\+)/1, once/1, (;)/2, (',')/2, (->)/2, catch/3)). 389 390% The control structures are always compiled, both if they appear in a 391% clause body and if they are handed to call/1. The only way to call 392% these predicates is by means of call/2.. In that case, we call the 393% hole control structure again to get it compiled by call/1 and properly 394% deal with !, etc. Another reason for having these things as 395% predicates is to be able to define properties for them, helping code 396% analyzers. 397 398(M0:If ; M0:Then) :- !, call(M0:(If ; Then)). 399(M1:If ; M2:Then) :- call(M1:(If ; M2:Then)). 400(G1 , G2) :- call((G1 , G2)). 401(If -> Then) :- call((If -> Then)). 402(If *-> Then) :- call((If *-> Then)). 403@(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.
417'$meta_call'(M:G) :- 418 prolog_current_choice(Ch), 419 '$meta_call'(G, M, Ch). 420 421'$meta_call'(Var, _, _) :- 422 var(Var), 423 !, 424 '$instantiation_error'(Var). 425'$meta_call'((A,B), M, Ch) :- 426 !, 427 '$meta_call'(A, M, Ch), 428 '$meta_call'(B, M, Ch). 429'$meta_call'((I->T;E), M, Ch) :- 430 !, 431 ( prolog_current_choice(Ch2), 432 '$meta_call'(I, M, Ch2) 433 -> '$meta_call'(T, M, Ch) 434 ; '$meta_call'(E, M, Ch) 435 ). 436'$meta_call'((I*->T;E), M, Ch) :- 437 !, 438 ( prolog_current_choice(Ch2), 439 '$meta_call'(I, M, Ch2) 440 *-> '$meta_call'(T, M, Ch) 441 ; '$meta_call'(E, M, Ch) 442 ). 443'$meta_call'((I->T), M, Ch) :- 444 !, 445 ( prolog_current_choice(Ch2), 446 '$meta_call'(I, M, Ch2) 447 -> '$meta_call'(T, M, Ch) 448 ). 449'$meta_call'((I*->T), M, Ch) :- 450 !, 451 prolog_current_choice(Ch2), 452 '$meta_call'(I, M, Ch2), 453 '$meta_call'(T, M, Ch). 454'$meta_call'((A;B), M, Ch) :- 455 !, 456 ( '$meta_call'(A, M, Ch) 457 ; '$meta_call'(B, M, Ch) 458 ). 459'$meta_call'(\+(G), M, _) :- 460 !, 461 prolog_current_choice(Ch), 462 \+ '$meta_call'(G, M, Ch). 463'$meta_call'($(G), M, _) :- 464 !, 465 prolog_current_choice(Ch), 466 $('$meta_call'(G, M, Ch)). 467'$meta_call'(call(G), M, _) :- 468 !, 469 prolog_current_choice(Ch), 470 '$meta_call'(G, M, Ch). 471'$meta_call'(M:G, _, Ch) :- 472 !, 473 '$meta_call'(G, M, Ch). 474'$meta_call'(!, _, Ch) :- 475 prolog_cut_to(Ch). 476'$meta_call'(G, M, _Ch) :- 477 call(M:G).
493:- '$iso'((call/2, 494 call/3, 495 call/4, 496 call/5, 497 call/6, 498 call/7, 499 call/8)). 500 501call(Goal) :- % make these available as predicates 502 . 503call(Goal, A) :- 504 call(Goal, A). 505call(Goal, A, B) :- 506 call(Goal, A, B). 507call(Goal, A, B, C) :- 508 call(Goal, A, B, C). 509call(Goal, A, B, C, D) :- 510 call(Goal, A, B, C, D). 511call(Goal, A, B, C, D, E) :- 512 call(Goal, A, B, C, D, E). 513call(Goal, A, B, C, D, E, F) :- 514 call(Goal, A, B, C, D, E, F). 515call(Goal, A, B, C, D, E, F, G) :- 516 call(Goal, A, B, C, D, E, F, G).
523not(Goal) :-
524 \+ .
530\+ Goal :-
531 \+ .
call((Goal, !))
.
537once(Goal) :-
538 ,
539 !.
546ignore(Goal) :- 547 , 548 !. 549ignore(_Goal). 550 551:- '$iso'((false/0)).
557false :-
558 fail.
564catch(_Goal, _Catcher, _Recover) :- 565 '$catch'. % Maps to I_CATCH, I_EXITCATCH
571prolog_cut_to(_Choice) :- 572 '$cut'. % Maps to I_CUTCHP
578'$' :- '$'.
584$(Goal) :- $(Goal).
590:- '$hide'(notrace/1). 591 592notrace(Goal) :- 593 setup_call_cleanup( 594 '$notrace'(Flags, SkipLevel), 595 once(Goal), 596 '$restore_trace'(Flags, SkipLevel)).
603reset(_Goal, _Ball, _Cont) :-
604 '$reset'.
613shift(Ball) :- 614 '$shift'(Ball). 615 616shift_for_copy(Ball) :- 617 '$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.
631call_continuation([]). 632call_continuation([TB|Rest]) :- 633 ( Rest == [] 634 -> '$call_continuation'(TB) 635 ; '$call_continuation'(TB), 636 call_continuation(Rest) 637 ).
644catch_with_backtrace(Goal, Ball, Recover) :- 645 catch(Goal, Ball, Recover), 646 '$no_lco'. 647 648'$no_lco'.
658:- public '$recover_and_rethrow'/2. 659 660'$recover_and_rethrow'(Goal, Exception) :- 661 call_cleanup(Goal, throw(Exception)), 662 !.
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
.676setup_call_catcher_cleanup(Setup, _Goal, _Catcher, _Cleanup) :- 677 sig_atomic(Setup), 678 '$call_cleanup'. 679 680setup_call_cleanup(Setup, _Goal, _Cleanup) :- 681 sig_atomic(Setup), 682 '$call_cleanup'. 683 684call_cleanup(_Goal, _Cleanup) :- 685 '$call_cleanup'. 686 687 688 /******************************* 689 * INITIALIZATION * 690 *******************************/ 691 692:- meta_predicate 693 initialization( , ). 694 695:- multifile '$init_goal'/3. 696:- dynamic '$init_goal'/3. 697:- '$notransact'('$init_goal'/3).
-g goal
goals.Note that all goals are executed when a program is restored.
723initialization(Goal, When) :- 724 '$must_be'(oneof(atom, initialization_type, 725 [ now, 726 after_load, 727 restore, 728 restore_state, 729 prepare_state, 730 program, 731 main 732 ]), When), 733 '$initialization_context'(Source, Ctx), 734 '$initialization'(When, Goal, Source, Ctx). 735 736'$initialization'(now, Goal, _Source, Ctx) :- 737 '$run_init_goal'(Goal, Ctx), 738 '$compile_init_goal'(-, Goal, Ctx). 739'$initialization'(after_load, Goal, Source, Ctx) :- 740 ( Source \== (-) 741 -> '$compile_init_goal'(Source, Goal, Ctx) 742 ; throw(error(context_error(nodirective, 743 initialization(Goal, after_load)), 744 _)) 745 ). 746'$initialization'(restore, Goal, Source, Ctx) :- % deprecated 747 '$initialization'(restore_state, Goal, Source, Ctx). 748'$initialization'(restore_state, Goal, _Source, Ctx) :- 749 ( \+ current_prolog_flag(sandboxed_load, true) 750 -> '$compile_init_goal'(-, Goal, Ctx) 751 ; '$permission_error'(register, initialization(restore), Goal) 752 ). 753'$initialization'(prepare_state, Goal, _Source, Ctx) :- 754 ( \+ current_prolog_flag(sandboxed_load, true) 755 -> '$compile_init_goal'(when(prepare_state), Goal, Ctx) 756 ; '$permission_error'(register, initialization(restore), Goal) 757 ). 758'$initialization'(program, Goal, _Source, Ctx) :- 759 ( \+ current_prolog_flag(sandboxed_load, true) 760 -> '$compile_init_goal'(when(program), Goal, Ctx) 761 ; '$permission_error'(register, initialization(restore), Goal) 762 ). 763'$initialization'(main, Goal, _Source, Ctx) :- 764 ( \+ current_prolog_flag(sandboxed_load, true) 765 -> '$compile_init_goal'(when(main), Goal, Ctx) 766 ; '$permission_error'(register, initialization(restore), Goal) 767 ). 768 769 770'$compile_init_goal'(Source, Goal, Ctx) :- 771 atom(Source), 772 Source \== (-), 773 !, 774 '$store_admin_clause'(system:'$init_goal'(Source, Goal, Ctx), 775 _Layout, Source, Ctx). 776'$compile_init_goal'(Source, Goal, Ctx) :- 777 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.789'$run_initialization'(_, loaded, _) :- !. 790'$run_initialization'(File, _Action, Options) :- 791 '$run_initialization'(File, Options). 792 793'$run_initialization'(File, Options) :- 794 setup_call_cleanup( 795 '$start_run_initialization'(Options, Restore), 796 '$run_initialization_2'(File), 797 '$end_run_initialization'(Restore)). 798 799'$start_run_initialization'(Options, OldSandBoxed) :- 800 '$push_input_context'(initialization), 801 '$set_sandboxed_load'(Options, OldSandBoxed). 802'$end_run_initialization'(OldSandBoxed) :- 803 set_prolog_flag(sandboxed_load, OldSandBoxed), 804 '$pop_input_context'. 805 806'$run_initialization_2'(File) :- 807 ( '$init_goal'(File, Goal, Ctx), 808 File \= when(_), 809 '$run_init_goal'(Goal, Ctx), 810 fail 811 ; true 812 ). 813 814'$run_init_goal'(Goal, Ctx) :- 815 ( catch_with_backtrace('$run_init_goal'(Goal), E, 816 '$initialization_error'(E, Goal, Ctx)) 817 -> true 818 ; '$initialization_failure'(Goal, Ctx) 819 ). 820 821:- multifile prolog:sandbox_allowed_goal/1. 822 823'$run_init_goal'(Goal) :- 824 current_prolog_flag(sandboxed_load, false), 825 !, 826 call(Goal). 827'$run_init_goal'(Goal) :- 828 prolog:sandbox_allowed_goal(Goal), 829 call(Goal). 830 831'$initialization_context'(Source, Ctx) :- 832 ( source_location(File, Line) 833 -> Ctx = File:Line, 834 '$input_context'(Context), 835 '$top_file'(Context, File, Source) 836 ; Ctx = (-), 837 File = (-) 838 ). 839 840'$top_file'([input(include, F1, _, _)|T], _, F) :- 841 !, 842 '$top_file'(T, F1, F). 843'$top_file'(_, F, F). 844 845 846'$initialization_error'(E, Goal, Ctx) :- 847 print_message(error, initialization_error(Goal, E, Ctx)). 848 849'$initialization_failure'(Goal, Ctx) :- 850 print_message(warning, initialization_failure(Goal, Ctx)).
858:- public '$clear_source_admin'/1. 859 860'$clear_source_admin'(File) :- 861 retractall('$init_goal'(_, _, File:_)), 862 retractall('$load_context_module'(File, _, _)), 863 retractall('$resolved_source_path_db'(_, _, File)). 864 865 866 /******************************* 867 * STREAM * 868 *******************************/ 869 870:- '$iso'(stream_property/2). 871stream_property(Stream, Property) :- 872 nonvar(Stream), 873 nonvar(Property), 874 !, 875 '$stream_property'(Stream, Property). 876stream_property(Stream, Property) :- 877 nonvar(Stream), 878 !, 879 '$stream_properties'(Stream, Properties), 880 '$member'(Property, Properties). 881stream_property(Stream, Property) :- 882 nonvar(Property), 883 !, 884 ( Property = alias(Alias), 885 atom(Alias) 886 -> '$alias_stream'(Alias, Stream) 887 ; '$streams_properties'(Property, Pairs), 888 '$member'(Stream-Property, Pairs) 889 ). 890stream_property(Stream, Property) :- 891 '$streams_properties'(Property, Pairs), 892 '$member'(Stream-Properties, Pairs), 893 '$member'(Property, Properties). 894 895 896 /******************************** 897 * MODULES * 898 *********************************/ 899 900% '$prefix_module'(+Module, +Context, +Term, -Prefixed) 901% Tags `Term' with `Module:' if `Module' is not the context module. 902 903'$prefix_module'(Module, Module, Head, Head) :- !. 904'$prefix_module'(Module, _, Head, Module:Head).
910default_module(Me, Super) :- 911 ( atom(Me) 912 -> ( var(Super) 913 -> '$default_module'(Me, Super) 914 ; '$default_module'(Me, Super), ! 915 ) 916 ; '$type_error'(module, Me) 917 ). 918 919'$default_module'(Me, Me). 920'$default_module'(Me, Super) :- 921 import_module(Me, S), 922 '$default_module'(S, Super). 923 924 925 /******************************** 926 * TRACE AND EXCEPTIONS * 927 *********************************/ 928 929:- dynamic user:exception/3. 930:- multifile user:exception/3. 931:- '$hide'(user:exception/3).
940:- public 941 '$undefined_procedure'/4. 942 943'$undefined_procedure'(Module, Name, Arity, Action) :- 944 '$prefix_module'(Module, user, Name/Arity, Pred), 945 user:exception(undefined_predicate, Pred, Action0), 946 !, 947 Action = Action0. 948'$undefined_procedure'(Module, Name, Arity, Action) :- 949 \+ current_prolog_flag(autoload, false), 950 '$autoload'(Module:Name/Arity), 951 !, 952 Action = retry. 953'$undefined_procedure'(_, _, _, error).
965'$loading'(Library) :- 966 current_prolog_flag(threads, true), 967 ( '$loading_file'(Library, _Queue, _LoadThread) 968 -> true 969 ; '$loading_file'(FullFile, _Queue, _LoadThread), 970 file_name_extension(Library, _, FullFile) 971 -> true 972 ). 973 974% handle debugger 'w', 'p' and <N> depth options. 975 976'$set_debugger_write_options'(write) :- 977 !, 978 create_prolog_flag(debugger_write_options, 979 [ quoted(true), 980 attributes(dots), 981 spacing(next_argument) 982 ], []). 983'$set_debugger_write_options'(print) :- 984 !, 985 create_prolog_flag(debugger_write_options, 986 [ quoted(true), 987 portray(true), 988 max_depth(10), 989 attributes(portray), 990 spacing(next_argument) 991 ], []). 992'$set_debugger_write_options'(Depth) :- 993 current_prolog_flag(debugger_write_options, Options0), 994 ( '$select'(max_depth(_), Options0, Options) 995 -> true 996 ; Options = Options0 997 ), 998 create_prolog_flag(debugger_write_options, 999 [max_depth(Depth)|Options], []). 1000 1001 1002 /******************************** 1003 * SYSTEM MESSAGES * 1004 *********************************/
query
channel. This
predicate may be hooked using confirm/2, which must return
a boolean.1013:- multifile 1014 prolog:confirm/2. 1015 1016'$confirm'(Spec) :- 1017 prolog:confirm(Spec, Result), 1018 !, 1019 Result == true. 1020'$confirm'(Spec) :- 1021 print_message(query, Spec), 1022 between(0, 5, _), 1023 get_single_char(Answer), 1024 ( '$in_reply'(Answer, 'yYjJ \n') 1025 -> !, 1026 print_message(query, if_tty([yes-[]])) 1027 ; '$in_reply'(Answer, 'nN') 1028 -> !, 1029 print_message(query, if_tty([no-[]])), 1030 fail 1031 ; print_message(help, query(confirm)), 1032 fail 1033 ). 1034 1035'$in_reply'(Code, Atom) :- 1036 char_code(Char, Code), 1037 sub_atom(Atom, _, _, _, Char), 1038 !. 1039 1040:- dynamic 1041 user:portray/1. 1042:- multifile 1043 user:portray/1. 1044:- '$notransact'(user:portray/1). 1045 1046 1047 /******************************* 1048 * FILE_SEARCH_PATH * 1049 *******************************/ 1050 1051:- dynamic 1052 user:file_search_path/2, 1053 user:library_directory/1. 1054:- multifile 1055 user:file_search_path/2, 1056 user:library_directory/1. 1057:- '$notransact'((user:file_search_path/2, 1058 user:library_directory/1)). 1059 1060user(file_search_path(library, Dir) :- 1061 library_directory(Dir)). 1062user:file_search_path(swi, Home) :- 1063 current_prolog_flag(home, Home). 1064user:file_search_path(swi, Home) :- 1065 current_prolog_flag(shared_home, Home). 1066user:file_search_path(library, app_config(lib)). 1067user:file_search_path(library, swi(library)). 1068user:file_search_path(library, swi(library/clp)). 1069user:file_search_path(library, Dir) :- 1070 '$ext_library_directory'(Dir). 1071user:file_search_path(foreign, swi(ArchLib)) :- 1072 current_prolog_flag(apple_universal_binary, true), 1073 ArchLib = 'lib/fat-darwin'. 1074user:file_search_path(path, Dir) :- 1075 getenv('PATH', Path), 1076 ( current_prolog_flag(windows, true) 1077 -> atomic_list_concat(Dirs, (;), Path) 1078 ; atomic_list_concat(Dirs, :, Path) 1079 ), 1080 '$member'(Dir, Dirs). 1081user:file_search_path(user_app_data, Dir) :- 1082 '$xdg_prolog_directory'(data, Dir). 1083user:file_search_path(common_app_data, Dir) :- 1084 '$xdg_prolog_directory'(common_data, Dir). 1085user:file_search_path(user_app_config, Dir) :- 1086 '$xdg_prolog_directory'(config, Dir). 1087user:file_search_path(common_app_config, Dir) :- 1088 '$xdg_prolog_directory'(common_config, Dir). 1089user:file_search_path(app_data, user_app_data('.')). 1090user:file_search_path(app_data, common_app_data('.')). 1091user:file_search_path(app_config, user_app_config('.')). 1092user:file_search_path(app_config, common_app_config('.')). 1093% backward compatibility 1094user:file_search_path(app_preferences, user_app_config('.')). 1095user:file_search_path(user_profile, app_preferences('.')). 1096user:file_search_path(app, swi(app)). 1097user:file_search_path(app, app_data(app)). 1098 1099'$xdg_prolog_directory'(Which, Dir) :- 1100 '$xdg_directory'(Which, XDGDir), 1101 '$make_config_dir'(XDGDir), 1102 '$ensure_slash'(XDGDir, XDGDirS), 1103 atom_concat(XDGDirS, 'swi-prolog', Dir), 1104 '$make_config_dir'(Dir). 1105 1106% config 1107'$xdg_directory'(config, Home) :- 1108 current_prolog_flag(windows, true), 1109 catch(win_folder(appdata, Home), _, fail), 1110 !. 1111'$xdg_directory'(config, Home) :- 1112 getenv('XDG_CONFIG_HOME', Home). 1113'$xdg_directory'(config, Home) :- 1114 expand_file_name('~/.config', [Home]). 1115% data 1116'$xdg_directory'(data, Home) :- 1117 current_prolog_flag(windows, true), 1118 catch(win_folder(local_appdata, Home), _, fail), 1119 !. 1120'$xdg_directory'(data, Home) :- 1121 getenv('XDG_DATA_HOME', Home). 1122'$xdg_directory'(data, Home) :- 1123 expand_file_name('~/.local', [Local]), 1124 '$make_config_dir'(Local), 1125 atom_concat(Local, '/share', Home), 1126 '$make_config_dir'(Home). 1127% common data 1128'$xdg_directory'(common_data, Dir) :- 1129 current_prolog_flag(windows, true), 1130 catch(win_folder(common_appdata, Dir), _, fail), 1131 !. 1132'$xdg_directory'(common_data, Dir) :- 1133 '$existing_dir_from_env_path'('XDG_DATA_DIRS', 1134 [ '/usr/local/share', 1135 '/usr/share' 1136 ], 1137 Dir). 1138% common config 1139'$xdg_directory'(common_config, Dir) :- 1140 current_prolog_flag(windows, true), 1141 catch(win_folder(common_appdata, Dir), _, fail), 1142 !. 1143'$xdg_directory'(common_config, Dir) :- 1144 '$existing_dir_from_env_path'('XDG_CONFIG_DIRS', ['/etc/xdg'], Dir). 1145 1146'$existing_dir_from_env_path'(Env, Defaults, Dir) :- 1147 ( getenv(Env, Path) 1148 -> current_prolog_flag(path_sep, Sep), 1149 atomic_list_concat(Dirs, Sep, Path) 1150 ; Dirs = Defaults 1151 ), 1152 '$member'(Dir, Dirs), 1153 Dir \== '', 1154 exists_directory(Dir). 1155 1156'$make_config_dir'(Dir) :- 1157 exists_directory(Dir), 1158 !. 1159'$make_config_dir'(Dir) :- 1160 nb_current('$create_search_directories', true), 1161 file_directory_name(Dir, Parent), 1162 '$my_file'(Parent), 1163 catch(make_directory(Dir), _, fail). 1164 1165'$ensure_slash'(Dir, DirS) :- 1166 ( sub_atom(Dir, _, _, 0, /) 1167 -> DirS = Dir 1168 ; atom_concat(Dir, /, DirS) 1169 ). 1170 1171:- dynamic '$ext_lib_dirs'/1. 1172:- volatile '$ext_lib_dirs'/1. 1173 1174'$ext_library_directory'(Dir) :- 1175 '$ext_lib_dirs'(Dirs), 1176 !, 1177 '$member'(Dir, Dirs). 1178'$ext_library_directory'(Dir) :- 1179 current_prolog_flag(home, Home), 1180 atom_concat(Home, '/library/ext/*', Pattern), 1181 expand_file_name(Pattern, Dirs0), 1182 '$include'(exists_directory, Dirs0, Dirs), 1183 asserta('$ext_lib_dirs'(Dirs)), 1184 '$member'(Dir, Dirs).
1189'$expand_file_search_path'(Spec, Expanded, Cond) :- 1190 '$option'(access(Access), Cond), 1191 memberchk(Access, [write,append]), 1192 !, 1193 setup_call_cleanup( 1194 nb_setval('$create_search_directories', true), 1195 expand_file_search_path(Spec, Expanded), 1196 nb_delete('$create_search_directories')). 1197'$expand_file_search_path'(Spec, Expanded, _Cond) :- 1198 expand_file_search_path(Spec, Expanded).
1206expand_file_search_path(Spec, Expanded) :- 1207 catch('$expand_file_search_path'(Spec, Expanded, 0, []), 1208 loop(Used), 1209 throw(error(loop_error(Spec), file_search(Used)))). 1210 1211'$expand_file_search_path'(Spec, Expanded, N, Used) :- 1212 functor(Spec, Alias, 1), 1213 !, 1214 user:file_search_path(Alias, Exp0), 1215 NN is N + 1, 1216 ( NN > 16 1217 -> throw(loop(Used)) 1218 ; true 1219 ), 1220 '$expand_file_search_path'(Exp0, Exp1, NN, [Alias=Exp0|Used]), 1221 arg(1, Spec, Segments), 1222 '$segments_to_atom'(Segments, File), 1223 '$make_path'(Exp1, File, Expanded). 1224'$expand_file_search_path'(Spec, Path, _, _) :- 1225 '$segments_to_atom'(Spec, Path). 1226 1227'$make_path'(Dir, '.', Path) :- 1228 !, 1229 Path = Dir. 1230'$make_path'(Dir, File, Path) :- 1231 sub_atom(Dir, _, _, 0, /), 1232 !, 1233 atom_concat(Dir, File, Path). 1234'$make_path'(Dir, File, Path) :- 1235 atomic_list_concat([Dir, /, File], Path). 1236 1237 1238 /******************************** 1239 * FILE CHECKING * 1240 *********************************/
1251absolute_file_name(Spec, Options, Path) :- 1252 '$is_options'(Options), 1253 \+ '$is_options'(Path), 1254 !, 1255 '$absolute_file_name'(Spec, Path, Options). 1256absolute_file_name(Spec, Path, Options) :- 1257 '$absolute_file_name'(Spec, Path, Options). 1258 1259'$absolute_file_name'(Spec, Path, Options0) :- 1260 '$options_dict'(Options0, Options), 1261 % get the valid extensions 1262 ( '$select_option'(extensions(Exts), Options, Options1) 1263 -> '$must_be'(list, Exts) 1264 ; '$option'(file_type(Type), Options) 1265 -> '$must_be'(atom, Type), 1266 '$file_type_extensions'(Type, Exts), 1267 Options1 = Options 1268 ; Options1 = Options, 1269 Exts = [''] 1270 ), 1271 '$canonicalise_extensions'(Exts, Extensions), 1272 % unless specified otherwise, ask regular file 1273 ( ( nonvar(Type) 1274 ; '$option'(access(none), Options, none) 1275 ) 1276 -> Options2 = Options1 1277 ; '$merge_options'(_{file_type:regular}, Options1, Options2) 1278 ), 1279 % Det or nondet? 1280 ( '$select_option'(solutions(Sols), Options2, Options3) 1281 -> '$must_be'(oneof(atom, solutions, [first,all]), Sols) 1282 ; Sols = first, 1283 Options3 = Options2 1284 ), 1285 % Errors or not? 1286 ( '$select_option'(file_errors(FileErrors), Options3, Options4) 1287 -> '$must_be'(oneof(atom, file_errors, [error,fail]), FileErrors) 1288 ; FileErrors = error, 1289 Options4 = Options3 1290 ), 1291 % Expand shell patterns? 1292 ( atomic(Spec), 1293 '$select_option'(expand(Expand), Options4, Options5), 1294 '$must_be'(boolean, Expand) 1295 -> expand_file_name(Spec, List), 1296 '$member'(Spec1, List) 1297 ; Spec1 = Spec, 1298 Options5 = Options4 1299 ), 1300 % Search for files 1301 ( Sols == first 1302 -> ( '$chk_file'(Spec1, Extensions, Options5, true, Path) 1303 -> ! % also kill choice point of expand_file_name/2 1304 ; ( FileErrors == fail 1305 -> fail 1306 ; '$current_module'('$bags', _File), 1307 findall(P, 1308 '$chk_file'(Spec1, Extensions, [access(exist)], 1309 false, P), 1310 Candidates), 1311 '$abs_file_error'(Spec, Candidates, Options5) 1312 ) 1313 ) 1314 ; '$chk_file'(Spec1, Extensions, Options5, false, Path) 1315 ). 1316 1317'$abs_file_error'(Spec, Candidates, Conditions) :- 1318 '$member'(F, Candidates), 1319 '$member'(C, Conditions), 1320 '$file_condition'(C), 1321 '$file_error'(C, Spec, F, E, Comment), 1322 !, 1323 throw(error(E, context(_, Comment))). 1324'$abs_file_error'(Spec, _, _) :- 1325 '$existence_error'(source_sink, Spec). 1326 1327'$file_error'(file_type(directory), Spec, File, Error, Comment) :- 1328 \+ exists_directory(File), 1329 !, 1330 Error = existence_error(directory, Spec), 1331 Comment = not_a_directory(File). 1332'$file_error'(file_type(_), Spec, File, Error, Comment) :- 1333 exists_directory(File), 1334 !, 1335 Error = existence_error(file, Spec), 1336 Comment = directory(File). 1337'$file_error'(access(OneOrList), Spec, File, Error, _) :- 1338 '$one_or_member'(Access, OneOrList), 1339 \+ access_file(File, Access), 1340 Error = permission_error(Access, source_sink, Spec). 1341 1342'$one_or_member'(Elem, List) :- 1343 is_list(List), 1344 !, 1345 '$member'(Elem, List). 1346'$one_or_member'(Elem, Elem). 1347 1348 1349'$file_type_extensions'(source, Exts) :- % SICStus 3.9 compatibility 1350 !, 1351 '$file_type_extensions'(prolog, Exts). 1352'$file_type_extensions'(Type, Exts) :- 1353 '$current_module'('$bags', _File), 1354 !, 1355 findall(Ext, user:prolog_file_type(Ext, Type), Exts0), 1356 ( Exts0 == [], 1357 \+ '$ft_no_ext'(Type) 1358 -> '$domain_error'(file_type, Type) 1359 ; true 1360 ), 1361 '$append'(Exts0, [''], Exts). 1362'$file_type_extensions'(prolog, [pl, '']). % findall is not yet defined ... 1363 1364'$ft_no_ext'(txt). 1365'$ft_no_ext'(executable). 1366'$ft_no_ext'(directory). 1367'$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.
1380:- multifile(user:prolog_file_type/2). 1381:- dynamic(user:prolog_file_type/2). 1382 1383userprolog_file_type(pl, prolog). 1384userprolog_file_type(prolog, prolog). 1385userprolog_file_type(qlf, prolog). 1386userprolog_file_type(qlf, qlf). 1387userprolog_file_type(Ext, executable) :- 1388 current_prolog_flag(shared_object_extension, Ext). 1389userprolog_file_type(dylib, executable) :- 1390 current_prolog_flag(apple, true).
1397'$chk_file'(Spec, _Extensions, _Cond, _Cache, _FullName) :- 1398 \+ ground(Spec), 1399 !, 1400 '$instantiation_error'(Spec). 1401'$chk_file'(Spec, Extensions, Cond, Cache, FullName) :- 1402 compound(Spec), 1403 functor(Spec, _, 1), 1404 !, 1405 '$relative_to'(Cond, cwd, CWD), 1406 '$chk_alias_file'(Spec, Extensions, Cond, Cache, CWD, FullName). 1407'$chk_file'(Segments, Ext, Cond, Cache, FullName) :- % allow a/b/... 1408 \+ atomic(Segments), 1409 !, 1410 '$segments_to_atom'(Segments, Atom), 1411 '$chk_file'(Atom, Ext, Cond, Cache, FullName). 1412'$chk_file'(File, Exts, Cond, _, FullName) :- 1413 is_absolute_file_name(File), 1414 !, 1415 '$extend_file'(File, Exts, Extended), 1416 '$file_conditions'(Cond, Extended), 1417 '$absolute_file_name'(Extended, FullName). 1418'$chk_file'(File, Exts, Cond, _, FullName) :- 1419 '$relative_to'(Cond, source, Dir), 1420 atomic_list_concat([Dir, /, File], AbsFile), 1421 '$extend_file'(AbsFile, Exts, Extended), 1422 '$file_conditions'(Cond, Extended), 1423 !, 1424 '$absolute_file_name'(Extended, FullName). 1425'$chk_file'(File, Exts, Cond, _, FullName) :- 1426 '$extend_file'(File, Exts, Extended), 1427 '$file_conditions'(Cond, Extended), 1428 '$absolute_file_name'(Extended, FullName). 1429 1430'$segments_to_atom'(Atom, Atom) :- 1431 atomic(Atom), 1432 !. 1433'$segments_to_atom'(Segments, Atom) :- 1434 '$segments_to_list'(Segments, List, []), 1435 !, 1436 atomic_list_concat(List, /, Atom). 1437 1438'$segments_to_list'(A/B, H, T) :- 1439 '$segments_to_list'(A, H, T0), 1440 '$segments_to_list'(B, T0, T). 1441'$segments_to_list'(A, [A|T], T) :- 1442 atomic(A).
relative_to(FileOrDir)
options
or implicitely relative to the working directory or current
source-file.
1452'$relative_to'(Conditions, Default, Dir) :-
1453 ( '$option'(relative_to(FileOrDir), Conditions)
1454 *-> ( exists_directory(FileOrDir)
1455 -> Dir = FileOrDir
1456 ; atom_concat(Dir, /, FileOrDir)
1457 -> true
1458 ; file_directory_name(FileOrDir, Dir)
1459 )
1460 ; Default == cwd
1461 -> '$cwd'(Dir)
1462 ; Default == source
1463 -> source_location(ContextFile, _Line),
1464 file_directory_name(ContextFile, Dir)
1465 ).
1470:- dynamic 1471 '$search_path_file_cache'/3, % SHA1, Time, Path 1472 '$search_path_gc_time'/1. % Time 1473:- volatile 1474 '$search_path_file_cache'/3, 1475 '$search_path_gc_time'/1. 1476:- '$notransact'(('$search_path_file_cache'/3, 1477 '$search_path_gc_time'/1)). 1478 1479:- create_prolog_flag(file_search_cache_time, 10, []). 1480 1481'$chk_alias_file'(Spec, Exts, Cond, true, CWD, FullFile) :- 1482 !, 1483 findall(Exp, '$expand_file_search_path'(Spec, Exp, Cond), Expansions), 1484 current_prolog_flag(emulated_dialect, Dialect), 1485 Cache = cache(Exts, Cond, CWD, Expansions, Dialect), 1486 variant_sha1(Spec+Cache, SHA1), 1487 get_time(Now), 1488 current_prolog_flag(file_search_cache_time, TimeOut), 1489 ( '$search_path_file_cache'(SHA1, CachedTime, FullFile), 1490 CachedTime > Now - TimeOut, 1491 '$file_conditions'(Cond, FullFile) 1492 -> '$search_message'(file_search(cache(Spec, Cond), FullFile)) 1493 ; '$member'(Expanded, Expansions), 1494 '$extend_file'(Expanded, Exts, LibFile), 1495 ( '$file_conditions'(Cond, LibFile), 1496 '$absolute_file_name'(LibFile, FullFile), 1497 '$cache_file_found'(SHA1, Now, TimeOut, FullFile) 1498 -> '$search_message'(file_search(found(Spec, Cond), FullFile)) 1499 ; '$search_message'(file_search(tried(Spec, Cond), LibFile)), 1500 fail 1501 ) 1502 ). 1503'$chk_alias_file'(Spec, Exts, Cond, false, _CWD, FullFile) :- 1504 '$expand_file_search_path'(Spec, Expanded, Cond), 1505 '$extend_file'(Expanded, Exts, LibFile), 1506 '$file_conditions'(Cond, LibFile), 1507 '$absolute_file_name'(LibFile, FullFile). 1508 1509'$cache_file_found'(_, _, TimeOut, _) :- 1510 TimeOut =:= 0, 1511 !. 1512'$cache_file_found'(SHA1, Now, TimeOut, FullFile) :- 1513 '$search_path_file_cache'(SHA1, Saved, FullFile), 1514 !, 1515 ( Now - Saved < TimeOut/2 1516 -> true 1517 ; retractall('$search_path_file_cache'(SHA1, _, _)), 1518 asserta('$search_path_file_cache'(SHA1, Now, FullFile)) 1519 ). 1520'$cache_file_found'(SHA1, Now, TimeOut, FullFile) :- 1521 'gc_file_search_cache'(TimeOut), 1522 asserta('$search_path_file_cache'(SHA1, Now, FullFile)). 1523 1524'gc_file_search_cache'(TimeOut) :- 1525 get_time(Now), 1526 '$search_path_gc_time'(Last), 1527 Now-Last < TimeOut/2, 1528 !. 1529'gc_file_search_cache'(TimeOut) :- 1530 get_time(Now), 1531 retractall('$search_path_gc_time'(_)), 1532 assertz('$search_path_gc_time'(Now)), 1533 Before is Now - TimeOut, 1534 ( '$search_path_file_cache'(SHA1, Cached, FullFile), 1535 Cached < Before, 1536 retractall('$search_path_file_cache'(SHA1, Cached, FullFile)), 1537 fail 1538 ; true 1539 ). 1540 1541 1542'$search_message'(Term) :- 1543 current_prolog_flag(verbose_file_search, true), 1544 !, 1545 print_message(informational, Term). 1546'$search_message'(_).
1553'$file_conditions'(List, File) :- 1554 is_list(List), 1555 !, 1556 \+ ( '$member'(C, List), 1557 '$file_condition'(C), 1558 \+ '$file_condition'(C, File) 1559 ). 1560'$file_conditions'(Map, File) :- 1561 \+ ( get_dict(Key, Map, Value), 1562 C =.. [Key,Value], 1563 '$file_condition'(C), 1564 \+ '$file_condition'(C, File) 1565 ). 1566 1567'$file_condition'(file_type(directory), File) :- 1568 !, 1569 exists_directory(File). 1570'$file_condition'(file_type(_), File) :- 1571 !, 1572 \+ exists_directory(File). 1573'$file_condition'(access(Accesses), File) :- 1574 !, 1575 \+ ( '$one_or_member'(Access, Accesses), 1576 \+ access_file(File, Access) 1577 ). 1578 1579'$file_condition'(exists). 1580'$file_condition'(file_type(_)). 1581'$file_condition'(access(_)). 1582 1583'$extend_file'(File, Exts, FileEx) :- 1584 '$ensure_extensions'(Exts, File, Fs), 1585 '$list_to_set'(Fs, FsSet), 1586 '$member'(FileEx, FsSet). 1587 1588'$ensure_extensions'([], _, []). 1589'$ensure_extensions'([E|E0], F, [FE|E1]) :- 1590 file_name_extension(F, E, FE), 1591 '$ensure_extensions'(E0, F, E1).
1598'$list_to_set'(List, Set) :- 1599 '$number_list'(List, 1, Numbered), 1600 sort(1, @=<, Numbered, ONum), 1601 '$remove_dup_keys'(ONum, NumSet), 1602 sort(2, @=<, NumSet, ONumSet), 1603 '$pairs_keys'(ONumSet, Set). 1604 1605'$number_list'([], _, []). 1606'$number_list'([H|T0], N, [H-N|T]) :- 1607 N1 is N+1, 1608 '$number_list'(T0, N1, T). 1609 1610'$remove_dup_keys'([], []). 1611'$remove_dup_keys'([H|T0], [H|T]) :- 1612 H = V-_, 1613 '$remove_same_key'(T0, V, T1), 1614 '$remove_dup_keys'(T1, T). 1615 1616'$remove_same_key'([V1-_|T0], V, T) :- 1617 V1 == V, 1618 !, 1619 '$remove_same_key'(T0, V, T). 1620'$remove_same_key'(L, _, L). 1621 1622'$pairs_keys'([], []). 1623'$pairs_keys'([K-_|T0], [K|T]) :- 1624 '$pairs_keys'(T0, T). 1625 1626'$pairs_values'([], []). 1627'$pairs_values'([_-V|T0], [V|T]) :- 1628 '$pairs_values'(T0, T). 1629 1630/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1631Canonicalise the extension list. Old SWI-Prolog require `.pl', etc, which 1632the Quintus compatibility requests `pl'. This layer canonicalises all 1633extensions to .ext 1634- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1635 1636'$canonicalise_extensions'([], []) :- !. 1637'$canonicalise_extensions'([H|T], [CH|CT]) :- 1638 !, 1639 '$must_be'(atom, H), 1640 '$canonicalise_extension'(H, CH), 1641 '$canonicalise_extensions'(T, CT). 1642'$canonicalise_extensions'(E, [CE]) :- 1643 '$canonicalise_extension'(E, CE). 1644 1645'$canonicalise_extension'('', '') :- !. 1646'$canonicalise_extension'(DotAtom, DotAtom) :- 1647 sub_atom(DotAtom, 0, _, _, '.'), 1648 !. 1649'$canonicalise_extension'(Atom, DotAtom) :- 1650 atom_concat('.', Atom, DotAtom). 1651 1652 1653 /******************************** 1654 * CONSULT * 1655 *********************************/ 1656 1657:- dynamic 1658 user:library_directory/1, 1659 user:prolog_load_file/2. 1660:- multifile 1661 user:library_directory/1, 1662 user:prolog_load_file/2. 1663 1664:- prompt(_, '|: '). 1665 1666:- thread_local 1667 '$compilation_mode_store'/1, % database, wic, qlf 1668 '$directive_mode_store'/1. % database, wic, qlf 1669:- volatile 1670 '$compilation_mode_store'/1, 1671 '$directive_mode_store'/1. 1672:- '$notransact'(('$compilation_mode_store'/1, 1673 '$directive_mode_store'/1)). 1674 1675'$compilation_mode'(Mode) :- 1676 ( '$compilation_mode_store'(Val) 1677 -> Mode = Val 1678 ; Mode = database 1679 ). 1680 1681'$set_compilation_mode'(Mode) :- 1682 retractall('$compilation_mode_store'(_)), 1683 assertz('$compilation_mode_store'(Mode)). 1684 1685'$compilation_mode'(Old, New) :- 1686 '$compilation_mode'(Old), 1687 ( New == Old 1688 -> true 1689 ; '$set_compilation_mode'(New) 1690 ). 1691 1692'$directive_mode'(Mode) :- 1693 ( '$directive_mode_store'(Val) 1694 -> Mode = Val 1695 ; Mode = database 1696 ). 1697 1698'$directive_mode'(Old, New) :- 1699 '$directive_mode'(Old), 1700 ( New == Old 1701 -> true 1702 ; '$set_directive_mode'(New) 1703 ). 1704 1705'$set_directive_mode'(Mode) :- 1706 retractall('$directive_mode_store'(_)), 1707 assertz('$directive_mode_store'(Mode)).
1715'$compilation_level'(Level) :- 1716 '$input_context'(Stack), 1717 '$compilation_level'(Stack, Level). 1718 1719'$compilation_level'([], 0). 1720'$compilation_level'([Input|T], Level) :- 1721 ( arg(1, Input, see) 1722 -> '$compilation_level'(T, Level) 1723 ; '$compilation_level'(T, Level0), 1724 Level is Level0+1 1725 ).
1733compiling :- 1734 \+ ( '$compilation_mode'(database), 1735 '$directive_mode'(database) 1736 ). 1737 1738:- meta_predicate 1739 '$ifcompiling'( ). 1740 1741'$ifcompiling'(G) :- 1742 ( '$compilation_mode'(database) 1743 -> true 1744 ; call(G) 1745 ). 1746 1747 /******************************** 1748 * READ SOURCE * 1749 *********************************/
1753'$load_msg_level'(Action, Nesting, Start, Done) :- 1754 '$update_autoload_level'([], 0), 1755 !, 1756 current_prolog_flag(verbose_load, Type0), 1757 '$load_msg_compat'(Type0, Type), 1758 ( '$load_msg_level'(Action, Nesting, Type, Start, Done) 1759 -> true 1760 ). 1761'$load_msg_level'(_, _, silent, silent). 1762 1763'$load_msg_compat'(true, normal) :- !. 1764'$load_msg_compat'(false, silent) :- !. 1765'$load_msg_compat'(X, X). 1766 1767'$load_msg_level'(load_file, _, full, informational, informational). 1768'$load_msg_level'(include_file, _, full, informational, informational). 1769'$load_msg_level'(load_file, _, normal, silent, informational). 1770'$load_msg_level'(include_file, _, normal, silent, silent). 1771'$load_msg_level'(load_file, 0, brief, silent, informational). 1772'$load_msg_level'(load_file, _, brief, silent, silent). 1773'$load_msg_level'(include_file, _, brief, silent, silent). 1774'$load_msg_level'(load_file, _, silent, silent, silent). 1775'$load_msg_level'(include_file, _, silent, silent, silent).
1798'$source_term'(From, Read, RLayout, Term, TLayout, Stream, Options) :- 1799 '$source_term'(From, Read, RLayout, Term, TLayout, Stream, [], Options), 1800 ( Term == end_of_file 1801 -> !, fail 1802 ; Term \== begin_of_file 1803 ). 1804 1805'$source_term'(Input, _,_,_,_,_,_,_) :- 1806 \+ ground(Input), 1807 !, 1808 '$instantiation_error'(Input). 1809'$source_term'(stream(Id, In, Opts), 1810 Read, RLayout, Term, TLayout, Stream, Parents, Options) :- 1811 !, 1812 '$record_included'(Parents, Id, Id, 0.0, Message), 1813 setup_call_cleanup( 1814 '$open_source'(stream(Id, In, Opts), In, State, Parents, Options), 1815 '$term_in_file'(In, Read, RLayout, Term, TLayout, Stream, 1816 [Id|Parents], Options), 1817 '$close_source'(State, Message)). 1818'$source_term'(File, 1819 Read, RLayout, Term, TLayout, Stream, Parents, Options) :- 1820 absolute_file_name(File, Path, 1821 [ file_type(prolog), 1822 access(read) 1823 ]), 1824 time_file(Path, Time), 1825 '$record_included'(Parents, File, Path, Time, Message), 1826 setup_call_cleanup( 1827 '$open_source'(Path, In, State, Parents, Options), 1828 '$term_in_file'(In, Read, RLayout, Term, TLayout, Stream, 1829 [Path|Parents], Options), 1830 '$close_source'(State, Message)). 1831 1832:- thread_local 1833 '$load_input'/2. 1834:- volatile 1835 '$load_input'/2. 1836:- '$notransact'('$load_input'/2). 1837 1838'$open_source'(stream(Id, In, Opts), In, 1839 restore(In, StreamState, Id, Ref, Opts), Parents, _Options) :- 1840 !, 1841 '$context_type'(Parents, ContextType), 1842 '$push_input_context'(ContextType), 1843 '$prepare_load_stream'(In, Id, StreamState), 1844 asserta('$load_input'(stream(Id), In), Ref). 1845'$open_source'(Path, In, close(In, Path, Ref), Parents, Options) :- 1846 '$context_type'(Parents, ContextType), 1847 '$push_input_context'(ContextType), 1848 '$open_source'(Path, In, Options), 1849 '$set_encoding'(In, Options), 1850 asserta('$load_input'(Path, In), Ref). 1851 1852'$context_type'([], load_file) :- !. 1853'$context_type'(_, include). 1854 1855:- multifile prolog:open_source_hook/3. 1856 1857'$open_source'(Path, In, Options) :- 1858 prolog:open_source_hook(Path, In, Options), 1859 !. 1860'$open_source'(Path, In, _Options) :- 1861 open(Path, read, In). 1862 1863'$close_source'(close(In, _Id, Ref), Message) :- 1864 erase(Ref), 1865 call_cleanup( 1866 close(In), 1867 '$pop_input_context'), 1868 '$close_message'(Message). 1869'$close_source'(restore(In, StreamState, _Id, Ref, Opts), Message) :- 1870 erase(Ref), 1871 call_cleanup( 1872 '$restore_load_stream'(In, StreamState, Opts), 1873 '$pop_input_context'), 1874 '$close_message'(Message). 1875 1876'$close_message'(message(Level, Msg)) :- 1877 !, 1878 '$print_message'(Level, Msg). 1879'$close_message'(_).
1891'$term_in_file'(In, Read, RLayout, Term, TLayout, Stream, Parents, Options) :- 1892 Parents \= [_,_|_], 1893 ( '$load_input'(_, Input) 1894 -> stream_property(Input, file_name(File)) 1895 ), 1896 '$set_source_location'(File, 0), 1897 '$expanded_term'(In, 1898 begin_of_file, 0-0, Read, RLayout, Term, TLayout, 1899 Stream, Parents, Options). 1900'$term_in_file'(In, Read, RLayout, Term, TLayout, Stream, Parents, Options) :- 1901 '$skip_script_line'(In, Options), 1902 '$read_clause_options'(Options, ReadOptions), 1903 '$repeat_and_read_error_mode'(ErrorMode), 1904 read_clause(In, Raw, 1905 [ syntax_errors(ErrorMode), 1906 variable_names(Bindings), 1907 term_position(Pos), 1908 subterm_positions(RawLayout) 1909 | ReadOptions 1910 ]), 1911 b_setval('$term_position', Pos), 1912 b_setval('$variable_names', Bindings), 1913 ( Raw == end_of_file 1914 -> !, 1915 ( Parents = [_,_|_] % Included file 1916 -> fail 1917 ; '$expanded_term'(In, 1918 Raw, RawLayout, Read, RLayout, Term, TLayout, 1919 Stream, Parents, Options) 1920 ) 1921 ; '$expanded_term'(In, Raw, RawLayout, Read, RLayout, Term, TLayout, 1922 Stream, Parents, Options) 1923 ). 1924 1925'$read_clause_options'([], []). 1926'$read_clause_options'([H|T0], List) :- 1927 ( '$read_clause_option'(H) 1928 -> List = [H|T] 1929 ; List = T 1930 ), 1931 '$read_clause_options'(T0, T). 1932 1933'$read_clause_option'(syntax_errors(_)). 1934'$read_clause_option'(term_position(_)). 1935'$read_clause_option'(process_comment(_)).
expand.pl
is not yet
loaded.1943'$repeat_and_read_error_mode'(Mode) :- 1944 ( current_predicate('$including'/0) 1945 -> repeat, 1946 ( '$including' 1947 -> Mode = dec10 1948 ; Mode = quiet 1949 ) 1950 ; Mode = dec10, 1951 repeat 1952 ). 1953 1954 1955'$expanded_term'(In, Raw, RawLayout, Read, RLayout, Term, TLayout, 1956 Stream, Parents, Options) :- 1957 E = error(_,_), 1958 catch('$expand_term'(Raw, RawLayout, Expanded, ExpandedLayout), E, 1959 '$print_message_fail'(E)), 1960 ( Expanded \== [] 1961 -> '$expansion_member'(Expanded, ExpandedLayout, Term1, Layout1) 1962 ; Term1 = Expanded, 1963 Layout1 = ExpandedLayout 1964 ), 1965 ( nonvar(Term1), Term1 = (:-Directive), nonvar(Directive) 1966 -> ( Directive = include(File), 1967 '$current_source_module'(Module), 1968 '$valid_directive'(Module:include(File)) 1969 -> stream_property(In, encoding(Enc)), 1970 '$add_encoding'(Enc, Options, Options1), 1971 '$source_term'(File, Read, RLayout, Term, TLayout, 1972 Stream, Parents, Options1) 1973 ; Directive = encoding(Enc) 1974 -> set_stream(In, encoding(Enc)), 1975 fail 1976 ; Term = Term1, 1977 Stream = In, 1978 Read = Raw 1979 ) 1980 ; Term = Term1, 1981 TLayout = Layout1, 1982 Stream = In, 1983 Read = Raw, 1984 RLayout = RawLayout 1985 ). 1986 1987'$expansion_member'(Var, Layout, Var, Layout) :- 1988 var(Var), 1989 !. 1990'$expansion_member'([], _, _, _) :- !, fail. 1991'$expansion_member'(List, ListLayout, Term, Layout) :- 1992 is_list(List), 1993 !, 1994 ( var(ListLayout) 1995 -> '$member'(Term, List) 1996 ; is_list(ListLayout) 1997 -> '$member_rep2'(Term, Layout, List, ListLayout) 1998 ; Layout = ListLayout, 1999 '$member'(Term, List) 2000 ). 2001'$expansion_member'(X, Layout, X, Layout). 2002 2003% pairwise member, repeating last element of the second 2004% list. 2005 2006'$member_rep2'(H1, H2, [H1|_], [H2|_]). 2007'$member_rep2'(H1, H2, [_|T1], [T2]) :- 2008 !, 2009 '$member_rep2'(H1, H2, T1, [T2]). 2010'$member_rep2'(H1, H2, [_|T1], [_|T2]) :- 2011 '$member_rep2'(H1, H2, T1, T2).
2015'$add_encoding'(Enc, Options0, Options) :- 2016 ( Options0 = [encoding(Enc)|_] 2017 -> Options = Options0 2018 ; Options = [encoding(Enc)|Options0] 2019 ). 2020 2021 2022:- multifile 2023 '$included'/4. % Into, Line, File, LastModified 2024:- dynamic 2025 '$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'.
2039'$record_included'([Parent|Parents], File, Path, Time, 2040 message(DoneMsgLevel, 2041 include_file(done(Level, file(File, Path))))) :- 2042 source_location(SrcFile, Line), 2043 !, 2044 '$compilation_level'(Level), 2045 '$load_msg_level'(include_file, Level, StartMsgLevel, DoneMsgLevel), 2046 '$print_message'(StartMsgLevel, 2047 include_file(start(Level, 2048 file(File, Path)))), 2049 '$last'([Parent|Parents], Owner), 2050 ( ( '$compilation_mode'(database) 2051 ; '$qlf_current_source'(Owner) 2052 ) 2053 -> '$store_admin_clause'( 2054 system:'$included'(Parent, Line, Path, Time), 2055 _, Owner, SrcFile:Line) 2056 ; '$qlf_include'(Owner, Parent, Line, Path, Time) 2057 ). 2058'$record_included'(_, _, _, _, true).
2064'$master_file'(File, MasterFile) :- 2065 '$included'(MasterFile0, _Line, File, _Time), 2066 !, 2067 '$master_file'(MasterFile0, MasterFile). 2068'$master_file'(File, File). 2069 2070 2071'$skip_script_line'(_In, Options) :- 2072 '$option'(check_script(false), Options), 2073 !. 2074'$skip_script_line'(In, _Options) :- 2075 ( peek_char(In, #) 2076 -> skip(In, 10) 2077 ; true 2078 ). 2079 2080'$set_encoding'(Stream, Options) :- 2081 '$option'(encoding(Enc), Options), 2082 !, 2083 Enc \== default, 2084 set_stream(Stream, encoding(Enc)). 2085'$set_encoding'(_, _). 2086 2087 2088'$prepare_load_stream'(In, Id, state(HasName,HasPos)) :- 2089 ( stream_property(In, file_name(_)) 2090 -> HasName = true, 2091 ( stream_property(In, position(_)) 2092 -> HasPos = true 2093 ; HasPos = false, 2094 set_stream(In, record_position(true)) 2095 ) 2096 ; HasName = false, 2097 set_stream(In, file_name(Id)), 2098 ( stream_property(In, position(_)) 2099 -> HasPos = true 2100 ; HasPos = false, 2101 set_stream(In, record_position(true)) 2102 ) 2103 ). 2104 2105'$restore_load_stream'(In, _State, Options) :- 2106 memberchk(close(true), Options), 2107 !, 2108 close(In). 2109'$restore_load_stream'(In, state(HasName, HasPos), _Options) :- 2110 ( HasName == false 2111 -> set_stream(In, file_name('')) 2112 ; true 2113 ), 2114 ( HasPos == false 2115 -> set_stream(In, record_position(false)) 2116 ; true 2117 ). 2118 2119 2120 /******************************* 2121 * DERIVED FILES * 2122 *******************************/ 2123 2124:- dynamic 2125 '$derived_source_db'/3. % Loaded, DerivedFrom, Time 2126 2127'$register_derived_source'(_, '-') :- !. 2128'$register_derived_source'(Loaded, DerivedFrom) :- 2129 retractall('$derived_source_db'(Loaded, _, _)), 2130 time_file(DerivedFrom, Time), 2131 assert('$derived_source_db'(Loaded, DerivedFrom, Time)). 2132 2133% Auto-importing dynamic predicates is not very elegant and 2134% leads to problems with qsave_program/[1,2] 2135 2136'$derived_source'(Loaded, DerivedFrom, Time) :- 2137 '$derived_source_db'(Loaded, DerivedFrom, Time). 2138 2139 2140 /******************************** 2141 * LOAD PREDICATES * 2142 *********************************/ 2143 2144:- meta_predicate 2145 ensure_loaded( ), 2146 [, | ] 2147 consult( ), 2148 use_module( ), 2149 use_module( , ), 2150 reexport( ), 2151 reexport( , ), 2152 load_files( ), 2153 load_files( , ).
2161ensure_loaded(Files) :-
2162 load_files(Files, [if(not_loaded)]).
2171use_module(Files) :-
2172 load_files(Files, [ if(not_loaded),
2173 must_be_module(true)
2174 ]).
2181use_module(File, Import) :-
2182 load_files(File, [ if(not_loaded),
2183 must_be_module(true),
2184 imports(Import)
2185 ]).
2191reexport(Files) :-
2192 load_files(Files, [ if(not_loaded),
2193 must_be_module(true),
2194 reexport(true)
2195 ]).
2201reexport(File, Import) :- 2202 load_files(File, [ if(not_loaded), 2203 must_be_module(true), 2204 imports(Import), 2205 reexport(true) 2206 ]). 2207 2208 2209[X] :- 2210 !, 2211 consult(X). 2212[M:F|R] :- 2213 consult(M:[F|R]). 2214 2215consult(M:X) :- 2216 X == user, 2217 !, 2218 flag('$user_consult', N, N+1), 2219 NN is N + 1, 2220 atom_concat('user://', NN, Id), 2221 load_files(M:Id, [stream(user_input), check_script(false), silent(false)]). 2222consult(List) :- 2223 load_files(List, [expand(true)]).
2230load_files(Files) :- 2231 load_files(Files, []). 2232load_files(Module:Files, Options) :- 2233 '$must_be'(list, Options), 2234 '$load_files'(Files, Module, Options). 2235 2236'$load_files'(X, _, _) :- 2237 var(X), 2238 !, 2239 '$instantiation_error'(X). 2240'$load_files'([], _, _) :- !. 2241'$load_files'(Id, Module, Options) :- % load_files(foo, [stream(In)]) 2242 '$option'(stream(_), Options), 2243 !, 2244 ( atom(Id) 2245 -> '$load_file'(Id, Module, Options) 2246 ; throw(error(type_error(atom, Id), _)) 2247 ). 2248'$load_files'(List, Module, Options) :- 2249 List = [_|_], 2250 !, 2251 '$must_be'(list, List), 2252 '$load_file_list'(List, Module, Options). 2253'$load_files'(File, Module, Options) :- 2254 '$load_one_file'(File, Module, Options). 2255 2256'$load_file_list'([], _, _). 2257'$load_file_list'([File|Rest], Module, Options) :- 2258 E = error(_,_), 2259 catch('$load_one_file'(File, Module, Options), E, 2260 '$print_message'(error, E)), 2261 '$load_file_list'(Rest, Module, Options). 2262 2263 2264'$load_one_file'(Spec, Module, Options) :- 2265 atomic(Spec), 2266 '$option'(expand(Expand), Options, false), 2267 Expand == true, 2268 !, 2269 expand_file_name(Spec, Expanded), 2270 ( Expanded = [Load] 2271 -> true 2272 ; Load = Expanded 2273 ), 2274 '$load_files'(Load, Module, [expand(false)|Options]). 2275'$load_one_file'(File, Module, Options) :- 2276 strip_module(Module:File, Into, PlainFile), 2277 '$load_file'(PlainFile, Into, Options).
2284'$noload'(true, _, _) :- 2285 !, 2286 fail. 2287'$noload'(_, FullFile, _Options) :- 2288 '$time_source_file'(FullFile, Time, system), 2289 Time > 0.0, 2290 !. 2291'$noload'(not_loaded, FullFile, _) :- 2292 source_file(FullFile), 2293 !. 2294'$noload'(changed, Derived, _) :- 2295 '$derived_source'(_FullFile, Derived, LoadTime), 2296 time_file(Derived, Modified), 2297 Modified @=< LoadTime, 2298 !. 2299'$noload'(changed, FullFile, Options) :- 2300 '$time_source_file'(FullFile, LoadTime, user), 2301 '$modified_id'(FullFile, Modified, Options), 2302 Modified @=< LoadTime, 2303 !. 2304'$noload'(exists, File, Options) :- 2305 '$noload'(changed, File, Options).
2324'$qlf_file'(Spec, _, Spec, stream, Options) :- 2325 '$option'(stream(_), Options), % stream: no choice 2326 !. 2327'$qlf_file'(Spec, FullFile, FullFile, compile, _) :- 2328 '$spec_extension'(Spec, Ext), % user explicitly specified 2329 user:prolog_file_type(Ext, prolog), 2330 !. 2331'$qlf_file'(Spec, FullFile, LoadFile, Mode, Options) :- 2332 '$compilation_mode'(database), 2333 file_name_extension(Base, PlExt, FullFile), 2334 user:prolog_file_type(PlExt, prolog), 2335 user:prolog_file_type(QlfExt, qlf), 2336 file_name_extension(Base, QlfExt, QlfFile), 2337 ( access_file(QlfFile, read), 2338 ( '$qlf_out_of_date'(FullFile, QlfFile, Why) 2339 -> ( access_file(QlfFile, write) 2340 -> print_message(informational, 2341 qlf(recompile(Spec, FullFile, QlfFile, Why))), 2342 Mode = qcompile, 2343 LoadFile = FullFile 2344 ; Why == old, 2345 ( current_prolog_flag(home, PlHome), 2346 sub_atom(FullFile, 0, _, _, PlHome) 2347 ; sub_atom(QlfFile, 0, _, _, 'res://') 2348 ) 2349 -> print_message(silent, 2350 qlf(system_lib_out_of_date(Spec, QlfFile))), 2351 Mode = qload, 2352 LoadFile = QlfFile 2353 ; print_message(warning, 2354 qlf(can_not_recompile(Spec, QlfFile, Why))), 2355 Mode = compile, 2356 LoadFile = FullFile 2357 ) 2358 ; Mode = qload, 2359 LoadFile = QlfFile 2360 ) 2361 -> ! 2362 ; '$qlf_auto'(FullFile, QlfFile, Options) 2363 -> !, Mode = qcompile, 2364 LoadFile = FullFile 2365 ). 2366'$qlf_file'(_, FullFile, FullFile, compile, _).
2374'$qlf_out_of_date'(PlFile, QlfFile, Why) :-
2375 ( access_file(PlFile, read)
2376 -> time_file(PlFile, PlTime),
2377 time_file(QlfFile, QlfTime),
2378 ( PlTime > QlfTime
2379 -> Why = old % PlFile is newer
2380 ; Error = error(Formal,_),
2381 catch('$qlf_is_compatible'(QlfFile), Error, true),
2382 nonvar(Formal) % QlfFile is incompatible
2383 -> Why = Error
2384 ; fail % QlfFile is up-to-date and ok
2385 )
2386 ; fail % can not read .pl; try .qlf
2387 ).
qcompile(QlfMode)
or, if this is not present, by
the prolog_flag qcompile.2395:- create_prolog_flag(qcompile, false, [type(atom)]). 2396 2397'$qlf_auto'(PlFile, QlfFile, Options) :- 2398 ( memberchk(qcompile(QlfMode), Options) 2399 -> true 2400 ; current_prolog_flag(qcompile, QlfMode), 2401 \+ '$in_system_dir'(PlFile) 2402 ), 2403 ( QlfMode == auto 2404 -> true 2405 ; QlfMode == large, 2406 size_file(PlFile, Size), 2407 Size > 100000 2408 ), 2409 access_file(QlfFile, write). 2410 2411'$in_system_dir'(PlFile) :- 2412 current_prolog_flag(home, Home), 2413 sub_atom(PlFile, 0, _, _, Home). 2414 2415'$spec_extension'(File, Ext) :- 2416 atom(File), 2417 file_name_extension(_, Ext, File). 2418'$spec_extension'(Spec, Ext) :- 2419 compound(Spec), 2420 arg(1, Spec, Arg), 2421 '$spec_extension'(Arg, Ext).
2433:- dynamic 2434 '$resolved_source_path_db'/3. % ?Spec, ?Dialect, ?Path 2435:- '$notransact'('$resolved_source_path_db'/3). 2436 2437'$load_file'(File, Module, Options) :- 2438 '$error_count'(E0, W0), 2439 '$load_file_e'(File, Module, Options), 2440 '$error_count'(E1, W1), 2441 Errors is E1-E0, 2442 Warnings is W1-W0, 2443 ( Errors+Warnings =:= 0 2444 -> true 2445 ; '$print_message'(silent, load_file_errors(File, Errors, Warnings)) 2446 ). 2447 2448:- if(current_prolog_flag(threads, true)). 2449'$error_count'(Errors, Warnings) :- 2450 current_prolog_flag(threads, true), 2451 !, 2452 thread_self(Me), 2453 thread_statistics(Me, errors, Errors), 2454 thread_statistics(Me, warnings, Warnings). 2455:- endif. 2456'$error_count'(Errors, Warnings) :- 2457 statistics(errors, Errors), 2458 statistics(warnings, Warnings). 2459 2460'$load_file_e'(File, Module, Options) :- 2461 \+ memberchk(stream(_), Options), 2462 user:prolog_load_file(Module:File, Options), 2463 !. 2464'$load_file_e'(File, Module, Options) :- 2465 memberchk(stream(_), Options), 2466 !, 2467 '$assert_load_context_module'(File, Module, Options), 2468 '$qdo_load_file'(File, File, Module, Options). 2469'$load_file_e'(File, Module, Options) :- 2470 ( '$resolved_source_path'(File, FullFile, Options) 2471 -> true 2472 ; '$resolve_source_path'(File, FullFile, Options) 2473 ), 2474 !, 2475 '$mt_load_file'(File, FullFile, Module, Options). 2476'$load_file_e'(_, _, _).
2482'$resolved_source_path'(File, FullFile, Options) :-
2483 current_prolog_flag(emulated_dialect, Dialect),
2484 '$resolved_source_path_db'(File, Dialect, FullFile),
2485 ( '$source_file_property'(FullFile, from_state, true)
2486 ; '$source_file_property'(FullFile, resource, true)
2487 ; '$option'(if(If), Options, true),
2488 '$noload'(If, FullFile, Options)
2489 ),
2490 !.
2497'$resolve_source_path'(File, FullFile, Options) :- 2498 ( '$option'(if(If), Options), 2499 If == exists 2500 -> Extra = [file_errors(fail)] 2501 ; Extra = [] 2502 ), 2503 absolute_file_name(File, FullFile, 2504 [ file_type(prolog), 2505 access(read) 2506 | Extra 2507 ]), 2508 '$register_resolved_source_path'(File, FullFile). 2509 2510'$register_resolved_source_path'(File, FullFile) :- 2511 ( compound(File) 2512 -> current_prolog_flag(emulated_dialect, Dialect), 2513 ( '$resolved_source_path_db'(File, Dialect, FullFile) 2514 -> true 2515 ; asserta('$resolved_source_path_db'(File, Dialect, FullFile)) 2516 ) 2517 ; true 2518 ).
2524:- public '$translated_source'/2. 2525'$translated_source'(Old, New) :- 2526 forall(retract('$resolved_source_path_db'(File, Dialect, Old)), 2527 assertz('$resolved_source_path_db'(File, Dialect, New))).
2534'$register_resource_file'(FullFile) :-
2535 ( sub_atom(FullFile, 0, _, _, 'res://'),
2536 \+ file_name_extension(_, qlf, FullFile)
2537 -> '$set_source_file'(FullFile, resource, true)
2538 ; true
2539 ).
2552'$already_loaded'(_File, FullFile, Module, Options) :- 2553 '$assert_load_context_module'(FullFile, Module, Options), 2554 '$current_module'(LoadModules, FullFile), 2555 !, 2556 ( atom(LoadModules) 2557 -> LoadModule = LoadModules 2558 ; LoadModules = [LoadModule|_] 2559 ), 2560 '$import_from_loaded_module'(LoadModule, Module, Options). 2561'$already_loaded'(_, _, user, _) :- !. 2562'$already_loaded'(File, FullFile, Module, Options) :- 2563 ( '$load_context_module'(FullFile, Module, CtxOptions), 2564 '$load_ctx_options'(Options, CtxOptions) 2565 -> true 2566 ; '$load_file'(File, Module, [if(true)|Options]) 2567 ).
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.
2582:- dynamic 2583 '$loading_file'/3. % File, Queue, Thread 2584:- volatile 2585 '$loading_file'/3. 2586:- '$notransact'('$loading_file'/3). 2587 2588:- if(current_prolog_flag(threads, true)). 2589'$mt_load_file'(File, FullFile, Module, Options) :- 2590 current_prolog_flag(threads, true), 2591 !, 2592 sig_atomic(setup_call_cleanup( 2593 with_mutex('$load_file', 2594 '$mt_start_load'(FullFile, Loading, Options)), 2595 '$mt_do_load'(Loading, File, FullFile, Module, Options), 2596 '$mt_end_load'(Loading))). 2597:- endif. 2598'$mt_load_file'(File, FullFile, Module, Options) :- 2599 '$option'(if(If), Options, true), 2600 '$noload'(If, FullFile, Options), 2601 !, 2602 '$already_loaded'(File, FullFile, Module, Options). 2603:- if(current_prolog_flag(threads, true)). 2604'$mt_load_file'(File, FullFile, Module, Options) :- 2605 sig_atomic('$qdo_load_file'(File, FullFile, Module, Options)). 2606:- else. 2607'$mt_load_file'(File, FullFile, Module, Options) :- 2608 '$qdo_load_file'(File, FullFile, Module, Options). 2609:- endif. 2610 2611:- if(current_prolog_flag(threads, true)). 2612'$mt_start_load'(FullFile, queue(Queue), _) :- 2613 '$loading_file'(FullFile, Queue, LoadThread), 2614 \+ thread_self(LoadThread), 2615 !. 2616'$mt_start_load'(FullFile, already_loaded, Options) :- 2617 '$option'(if(If), Options, true), 2618 '$noload'(If, FullFile, Options), 2619 !. 2620'$mt_start_load'(FullFile, Ref, _) :- 2621 thread_self(Me), 2622 message_queue_create(Queue), 2623 assertz('$loading_file'(FullFile, Queue, Me), Ref). 2624 2625'$mt_do_load'(queue(Queue), File, FullFile, Module, Options) :- 2626 !, 2627 catch(thread_get_message(Queue, _), error(_,_), true), 2628 '$already_loaded'(File, FullFile, Module, Options). 2629'$mt_do_load'(already_loaded, File, FullFile, Module, Options) :- 2630 !, 2631 '$already_loaded'(File, FullFile, Module, Options). 2632'$mt_do_load'(_Ref, File, FullFile, Module, Options) :- 2633 '$assert_load_context_module'(FullFile, Module, Options), 2634 '$qdo_load_file'(File, FullFile, Module, Options). 2635 2636'$mt_end_load'(queue(_)) :- !. 2637'$mt_end_load'(already_loaded) :- !. 2638'$mt_end_load'(Ref) :- 2639 clause('$loading_file'(_, Queue, _), _, Ref), 2640 erase(Ref), 2641 thread_send_message(Queue, done), 2642 message_queue_destroy(Queue). 2643:- endif.
2649'$qdo_load_file'(File, FullFile, Module, Options) :- 2650 '$qdo_load_file2'(File, FullFile, Module, Action, Options), 2651 '$register_resource_file'(FullFile), 2652 '$run_initialization'(FullFile, Action, Options). 2653 2654'$qdo_load_file2'(File, FullFile, Module, Action, Options) :- 2655 memberchk('$qlf'(QlfOut), Options), 2656 '$stage_file'(QlfOut, StageQlf), 2657 !, 2658 setup_call_catcher_cleanup( 2659 '$qstart'(StageQlf, Module, State), 2660 '$do_load_file'(File, FullFile, Module, Action, Options), 2661 Catcher, 2662 '$qend'(State, Catcher, StageQlf, QlfOut)). 2663'$qdo_load_file2'(File, FullFile, Module, Action, Options) :- 2664 '$do_load_file'(File, FullFile, Module, Action, Options). 2665 2666'$qstart'(Qlf, Module, state(OldMode, OldModule)) :- 2667 '$qlf_open'(Qlf), 2668 '$compilation_mode'(OldMode, qlf), 2669 '$set_source_module'(OldModule, Module). 2670 2671'$qend'(state(OldMode, OldModule), Catcher, StageQlf, QlfOut) :- 2672 '$set_source_module'(_, OldModule), 2673 '$set_compilation_mode'(OldMode), 2674 '$qlf_close', 2675 '$install_staged_file'(Catcher, StageQlf, QlfOut, warn). 2676 2677'$set_source_module'(OldModule, Module) :- 2678 '$current_source_module'(OldModule), 2679 '$set_source_module'(Module).
2686'$do_load_file'(File, FullFile, Module, Action, Options) :- 2687 '$option'(derived_from(DerivedFrom), Options, -), 2688 '$register_derived_source'(FullFile, DerivedFrom), 2689 '$qlf_file'(File, FullFile, Absolute, Mode, Options), 2690 ( Mode == qcompile 2691 -> qcompile(Module:File, Options) 2692 ; '$do_load_file_2'(File, Absolute, Module, Action, Options) 2693 ). 2694 2695'$do_load_file_2'(File, Absolute, Module, Action, Options) :- 2696 '$source_file_property'(Absolute, number_of_clauses, OldClauses), 2697 statistics(cputime, OldTime), 2698 2699 '$setup_load'(ScopedFlags, OldSandBoxed, OldVerbose, OldAutoLevel, OldXRef, 2700 Options), 2701 2702 '$compilation_level'(Level), 2703 '$load_msg_level'(load_file, Level, StartMsgLevel, DoneMsgLevel), 2704 '$print_message'(StartMsgLevel, 2705 load_file(start(Level, 2706 file(File, Absolute)))), 2707 2708 ( memberchk(stream(FromStream), Options) 2709 -> Input = stream 2710 ; Input = source 2711 ), 2712 2713 ( Input == stream, 2714 ( '$option'(format(qlf), Options, source) 2715 -> set_stream(FromStream, file_name(Absolute)), 2716 '$qload_stream'(FromStream, Module, Action, LM, Options) 2717 ; '$consult_file'(stream(Absolute, FromStream, []), 2718 Module, Action, LM, Options) 2719 ) 2720 -> true 2721 ; Input == source, 2722 file_name_extension(_, Ext, Absolute), 2723 ( user:prolog_file_type(Ext, qlf), 2724 E = error(_,_), 2725 catch('$qload_file'(Absolute, Module, Action, LM, Options), 2726 E, 2727 print_message(warning, E)) 2728 -> true 2729 ; '$consult_file'(Absolute, Module, Action, LM, Options) 2730 ) 2731 -> true 2732 ; '$print_message'(error, load_file(failed(File))), 2733 fail 2734 ), 2735 2736 '$import_from_loaded_module'(LM, Module, Options), 2737 2738 '$source_file_property'(Absolute, number_of_clauses, NewClauses), 2739 statistics(cputime, Time), 2740 ClausesCreated is NewClauses - OldClauses, 2741 TimeUsed is Time - OldTime, 2742 2743 '$print_message'(DoneMsgLevel, 2744 load_file(done(Level, 2745 file(File, Absolute), 2746 Action, 2747 LM, 2748 TimeUsed, 2749 ClausesCreated))), 2750 2751 '$restore_load'(ScopedFlags, OldSandBoxed, OldVerbose, OldAutoLevel, OldXRef). 2752 2753'$setup_load'(ScopedFlags, OldSandBoxed, OldVerbose, OldAutoLevel, OldXRef, 2754 Options) :- 2755 '$save_file_scoped_flags'(ScopedFlags), 2756 '$set_sandboxed_load'(Options, OldSandBoxed), 2757 '$set_verbose_load'(Options, OldVerbose), 2758 '$set_optimise_load'(Options), 2759 '$update_autoload_level'(Options, OldAutoLevel), 2760 '$set_no_xref'(OldXRef). 2761 2762'$restore_load'(ScopedFlags, OldSandBoxed, OldVerbose, OldAutoLevel, OldXRef) :- 2763 '$set_autoload_level'(OldAutoLevel), 2764 set_prolog_flag(xref, OldXRef), 2765 set_prolog_flag(verbose_load, OldVerbose), 2766 set_prolog_flag(sandboxed_load, OldSandBoxed), 2767 '$restore_file_scoped_flags'(ScopedFlags).
2775'$save_file_scoped_flags'(State) :- 2776 current_predicate(findall/3), % Not when doing boot compile 2777 !, 2778 findall(SavedFlag, '$save_file_scoped_flag'(SavedFlag), State). 2779'$save_file_scoped_flags'([]). 2780 2781'$save_file_scoped_flag'(Flag-Value) :- 2782 '$file_scoped_flag'(Flag, Default), 2783 ( current_prolog_flag(Flag, Value) 2784 -> true 2785 ; Value = Default 2786 ). 2787 2788'$file_scoped_flag'(generate_debug_info, true). 2789'$file_scoped_flag'(optimise, false). 2790'$file_scoped_flag'(xref, false). 2791 2792'$restore_file_scoped_flags'([]). 2793'$restore_file_scoped_flags'([Flag-Value|T]) :- 2794 set_prolog_flag(Flag, Value), 2795 '$restore_file_scoped_flags'(T).
2802'$import_from_loaded_module'(LoadedModule, Module, Options) :- 2803 LoadedModule \== Module, 2804 atom(LoadedModule), 2805 !, 2806 '$option'(imports(Import), Options, all), 2807 '$option'(reexport(Reexport), Options, false), 2808 '$import_list'(Module, LoadedModule, Import, Reexport). 2809'$import_from_loaded_module'(_, _, _).
verbose_load
flag according to Options and unify Old
with the old value.2817'$set_verbose_load'(Options, Old) :- 2818 current_prolog_flag(verbose_load, Old), 2819 ( memberchk(silent(Silent), Options) 2820 -> ( '$negate'(Silent, Level0) 2821 -> '$load_msg_compat'(Level0, Level) 2822 ; Level = Silent 2823 ), 2824 set_prolog_flag(verbose_load, Level) 2825 ; true 2826 ). 2827 2828'$negate'(true, false). 2829'$negate'(false, true).
sandboxed_load
from Options. Old is
unified with the old flag.
2838'$set_sandboxed_load'(Options, Old) :- 2839 current_prolog_flag(sandboxed_load, Old), 2840 ( memberchk(sandboxed(SandBoxed), Options), 2841 '$enter_sandboxed'(Old, SandBoxed, New), 2842 New \== Old 2843 -> set_prolog_flag(sandboxed_load, New) 2844 ; true 2845 ). 2846 2847'$enter_sandboxed'(Old, New, SandBoxed) :- 2848 ( Old == false, New == true 2849 -> SandBoxed = true, 2850 '$ensure_loaded_library_sandbox' 2851 ; Old == true, New == false 2852 -> throw(error(permission_error(leave, sandbox, -), _)) 2853 ; SandBoxed = Old 2854 ). 2855'$enter_sandboxed'(false, true, true). 2856 2857'$ensure_loaded_library_sandbox' :- 2858 source_file_property(library(sandbox), module(sandbox)), 2859 !. 2860'$ensure_loaded_library_sandbox' :- 2861 load_files(library(sandbox), [if(not_loaded), silent(true)]). 2862 2863'$set_optimise_load'(Options) :- 2864 ( '$option'(optimise(Optimise), Options) 2865 -> set_prolog_flag(optimise, Optimise) 2866 ; true 2867 ). 2868 2869'$set_no_xref'(OldXRef) :- 2870 ( current_prolog_flag(xref, OldXRef) 2871 -> true 2872 ; OldXRef = false 2873 ), 2874 set_prolog_flag(xref, false).
2881:- thread_local 2882 '$autoload_nesting'/1. 2883:- '$notransact'('$autoload_nesting'/1). 2884 2885'$update_autoload_level'(Options, AutoLevel) :- 2886 '$option'(autoload(Autoload), Options, false), 2887 ( '$autoload_nesting'(CurrentLevel) 2888 -> AutoLevel = CurrentLevel 2889 ; AutoLevel = 0 2890 ), 2891 ( Autoload == false 2892 -> true 2893 ; NewLevel is AutoLevel + 1, 2894 '$set_autoload_level'(NewLevel) 2895 ). 2896 2897'$set_autoload_level'(New) :- 2898 retractall('$autoload_nesting'(_)), 2899 asserta('$autoload_nesting'(New)).
2907'$print_message'(Level, Term) :- 2908 current_predicate(system:print_message/2), 2909 !, 2910 print_message(Level, Term). 2911'$print_message'(warning, Term) :- 2912 source_location(File, Line), 2913 !, 2914 format(user_error, 'WARNING: ~w:~w: ~p~n', [File, Line, Term]). 2915'$print_message'(error, Term) :- 2916 !, 2917 source_location(File, Line), 2918 !, 2919 format(user_error, 'ERROR: ~w:~w: ~p~n', [File, Line, Term]). 2920'$print_message'(_Level, _Term). 2921 2922'$print_message_fail'(E) :- 2923 '$print_message'(error, E), 2924 fail.
2932'$consult_file'(Absolute, Module, What, LM, Options) :- 2933 '$current_source_module'(Module), % same module 2934 !, 2935 '$consult_file_2'(Absolute, Module, What, LM, Options). 2936'$consult_file'(Absolute, Module, What, LM, Options) :- 2937 '$set_source_module'(OldModule, Module), 2938 '$ifcompiling'('$qlf_start_sub_module'(Module)), 2939 '$consult_file_2'(Absolute, Module, What, LM, Options), 2940 '$ifcompiling'('$qlf_end_part'), 2941 '$set_source_module'(OldModule). 2942 2943'$consult_file_2'(Absolute, Module, What, LM, Options) :- 2944 '$set_source_module'(OldModule, Module), 2945 '$load_id'(Absolute, Id, Modified, Options), 2946 '$compile_type'(What), 2947 '$save_lex_state'(LexState, Options), 2948 '$set_dialect'(Options), 2949 setup_call_cleanup( 2950 '$start_consult'(Id, Modified), 2951 '$load_file'(Absolute, Id, LM, Options), 2952 '$end_consult'(Id, LexState, OldModule)). 2953 2954'$end_consult'(Id, LexState, OldModule) :- 2955 '$end_consult'(Id), 2956 '$restore_lex_state'(LexState), 2957 '$set_source_module'(OldModule). 2958 2959 2960:- create_prolog_flag(emulated_dialect, swi, [type(atom)]).
2964'$save_lex_state'(State, Options) :- 2965 memberchk(scope_settings(false), Options), 2966 !, 2967 State = (-). 2968'$save_lex_state'(lexstate(Style, Dialect), _) :- 2969 '$style_check'(Style, Style), 2970 current_prolog_flag(emulated_dialect, Dialect). 2971 2972'$restore_lex_state'(-) :- !. 2973'$restore_lex_state'(lexstate(Style, Dialect)) :- 2974 '$style_check'(_, Style), 2975 set_prolog_flag(emulated_dialect, Dialect). 2976 2977'$set_dialect'(Options) :- 2978 memberchk(dialect(Dialect), Options), 2979 !, 2980 '$expects_dialect'(Dialect). 2981'$set_dialect'(_). 2982 2983'$load_id'(stream(Id, _, _), Id, Modified, Options) :- 2984 !, 2985 '$modified_id'(Id, Modified, Options). 2986'$load_id'(Id, Id, Modified, Options) :- 2987 '$modified_id'(Id, Modified, Options). 2988 2989'$modified_id'(_, Modified, Options) :- 2990 '$option'(modified(Stamp), Options, Def), 2991 Stamp \== Def, 2992 !, 2993 Modified = Stamp. 2994'$modified_id'(Id, Modified, _) :- 2995 catch(time_file(Id, Modified), 2996 error(_, _), 2997 fail), 2998 !. 2999'$modified_id'(_, 0.0, _). 3000 3001 3002'$compile_type'(What) :- 3003 '$compilation_mode'(How), 3004 ( How == database 3005 -> What = compiled 3006 ; How == qlf 3007 -> What = '*qcompiled*' 3008 ; What = 'boot compiled' 3009 ).
3019:- dynamic 3020 '$load_context_module'/3. 3021:- multifile 3022 '$load_context_module'/3. 3023:- '$notransact'('$load_context_module'/3). 3024 3025'$assert_load_context_module'(_, _, Options) :- 3026 memberchk(register(false), Options), 3027 !. 3028'$assert_load_context_module'(File, Module, Options) :- 3029 source_location(FromFile, Line), 3030 !, 3031 '$master_file'(FromFile, MasterFile), 3032 '$check_load_non_module'(File, Module), 3033 '$add_dialect'(Options, Options1), 3034 '$load_ctx_options'(Options1, Options2), 3035 '$store_admin_clause'( 3036 system:'$load_context_module'(File, Module, Options2), 3037 _Layout, MasterFile, FromFile:Line). 3038'$assert_load_context_module'(File, Module, Options) :- 3039 '$check_load_non_module'(File, Module), 3040 '$add_dialect'(Options, Options1), 3041 '$load_ctx_options'(Options1, Options2), 3042 ( clause('$load_context_module'(File, Module, _), true, Ref), 3043 \+ clause_property(Ref, file(_)), 3044 erase(Ref) 3045 -> true 3046 ; true 3047 ), 3048 assertz('$load_context_module'(File, Module, Options2)). 3049 3050'$add_dialect'(Options0, Options) :- 3051 current_prolog_flag(emulated_dialect, Dialect), Dialect \== swi, 3052 !, 3053 Options = [dialect(Dialect)|Options0]. 3054'$add_dialect'(Options, Options).
3061'$load_ctx_options'(Options, CtxOptions) :- 3062 '$load_ctx_options2'(Options, CtxOptions0), 3063 sort(CtxOptions0, CtxOptions). 3064 3065'$load_ctx_options2'([], []). 3066'$load_ctx_options2'([H|T0], [H|T]) :- 3067 '$load_ctx_option'(H), 3068 !, 3069 '$load_ctx_options2'(T0, T). 3070'$load_ctx_options2'([_|T0], T) :- 3071 '$load_ctx_options2'(T0, T). 3072 3073'$load_ctx_option'(derived_from(_)). 3074'$load_ctx_option'(dialect(_)). 3075'$load_ctx_option'(encoding(_)). 3076'$load_ctx_option'(imports(_)). 3077'$load_ctx_option'(reexport(_)).
3085'$check_load_non_module'(File, _) :- 3086 '$current_module'(_, File), 3087 !. % File is a module file 3088'$check_load_non_module'(File, Module) :- 3089 '$load_context_module'(File, OldModule, _), 3090 Module \== OldModule, 3091 !, 3092 format(atom(Msg), 3093 'Non-module file already loaded into module ~w; \c 3094 trying to load into ~w', 3095 [OldModule, Module]), 3096 throw(error(permission_error(load, source, File), 3097 context(load_files/2, Msg))). 3098'$check_load_non_module'(_, _).
state(FirstTerm:boolean,
Module:atom,
AtEnd:atom,
Stop:boolean,
Id:atom,
Dialect:atom)
3111'$load_file'(Path, Id, Module, Options) :- 3112 State = state(true, _, true, false, Id, -), 3113 ( '$source_term'(Path, _Read, _Layout, Term, Layout, 3114 _Stream, Options), 3115 '$valid_term'(Term), 3116 ( arg(1, State, true) 3117 -> '$first_term'(Term, Layout, Id, State, Options), 3118 nb_setarg(1, State, false) 3119 ; '$compile_term'(Term, Layout, Id, Options) 3120 ), 3121 arg(4, State, true) 3122 ; '$fixup_reconsult'(Id), 3123 '$end_load_file'(State) 3124 ), 3125 !, 3126 arg(2, State, Module). 3127 3128'$valid_term'(Var) :- 3129 var(Var), 3130 !, 3131 print_message(error, error(instantiation_error, _)). 3132'$valid_term'(Term) :- 3133 Term \== []. 3134 3135'$end_load_file'(State) :- 3136 arg(1, State, true), % empty file 3137 !, 3138 nb_setarg(2, State, Module), 3139 arg(5, State, Id), 3140 '$current_source_module'(Module), 3141 '$ifcompiling'('$qlf_start_file'(Id)), 3142 '$ifcompiling'('$qlf_end_part'). 3143'$end_load_file'(State) :- 3144 arg(3, State, End), 3145 '$end_load_file'(End, State). 3146 3147'$end_load_file'(true, _). 3148'$end_load_file'(end_module, State) :- 3149 arg(2, State, Module), 3150 '$check_export'(Module), 3151 '$ifcompiling'('$qlf_end_part'). 3152'$end_load_file'(end_non_module, _State) :- 3153 '$ifcompiling'('$qlf_end_part'). 3154 3155 3156'$first_term'(?-(Directive), Layout, Id, State, Options) :- 3157 !, 3158 '$first_term'(:-(Directive), Layout, Id, State, Options). 3159'$first_term'(:-(Directive), _Layout, Id, State, Options) :- 3160 nonvar(Directive), 3161 ( ( Directive = module(Name, Public) 3162 -> Imports = [] 3163 ; Directive = module(Name, Public, Imports) 3164 ) 3165 -> !, 3166 '$module_name'(Name, Id, Module, Options), 3167 '$start_module'(Module, Public, State, Options), 3168 '$module3'(Imports) 3169 ; Directive = expects_dialect(Dialect) 3170 -> !, 3171 '$set_dialect'(Dialect, State), 3172 fail % Still consider next term as first 3173 ). 3174'$first_term'(Term, Layout, Id, State, Options) :- 3175 '$start_non_module'(Id, Term, State, Options), 3176 '$compile_term'(Term, Layout, Id, Options).
3183'$compile_term'(Term, Layout, SrcId, Options) :- 3184 '$compile_term'(Term, Layout, SrcId, -, Options). 3185 3186'$compile_term'(Var, _Layout, _Id, _SrcLoc, _Options) :- 3187 var(Var), 3188 !, 3189 '$instantiation_error'(Var). 3190'$compile_term'((?-Directive), _Layout, Id, _SrcLoc, Options) :- 3191 !, 3192 '$execute_directive'(Directive, Id, Options). 3193'$compile_term'((:-Directive), _Layout, Id, _SrcLoc, Options) :- 3194 !, 3195 '$execute_directive'(Directive, Id, Options). 3196'$compile_term'('$source_location'(File, Line):Term, 3197 Layout, Id, _SrcLoc, Options) :- 3198 !, 3199 '$compile_term'(Term, Layout, Id, File:Line, Options). 3200'$compile_term'(Clause, Layout, Id, SrcLoc, _Options) :- 3201 E = error(_,_), 3202 catch('$store_clause'(Clause, Layout, Id, SrcLoc), E, 3203 '$print_message'(error, E)). 3204 3205'$start_non_module'(_Id, Term, _State, Options) :- 3206 '$option'(must_be_module(true), Options, false), 3207 !, 3208 '$domain_error'(module_header, Term). 3209'$start_non_module'(Id, _Term, State, _Options) :- 3210 '$current_source_module'(Module), 3211 '$ifcompiling'('$qlf_start_file'(Id)), 3212 '$qset_dialect'(State), 3213 nb_setarg(2, State, Module), 3214 nb_setarg(3, State, end_non_module).
Note that expects_dialect/1 itself may be autoloaded from the library.
3227'$set_dialect'(Dialect, State) :- 3228 '$compilation_mode'(qlf, database), 3229 !, 3230 '$expects_dialect'(Dialect), 3231 '$compilation_mode'(_, qlf), 3232 nb_setarg(6, State, Dialect). 3233'$set_dialect'(Dialect, _) :- 3234 '$expects_dialect'(Dialect). 3235 3236'$qset_dialect'(State) :- 3237 '$compilation_mode'(qlf), 3238 arg(6, State, Dialect), Dialect \== (-), 3239 !, 3240 '$add_directive_wic'('$expects_dialect'(Dialect)). 3241'$qset_dialect'(_). 3242 3243'$expects_dialect'(Dialect) :- 3244 Dialect == swi, 3245 !, 3246 set_prolog_flag(emulated_dialect, Dialect). 3247'$expects_dialect'(Dialect) :- 3248 current_predicate(expects_dialect/1), 3249 !, 3250 expects_dialect(Dialect). 3251'$expects_dialect'(Dialect) :- 3252 use_module(library(dialect), [expects_dialect/1]), 3253 expects_dialect(Dialect). 3254 3255 3256 /******************************* 3257 * MODULES * 3258 *******************************/ 3259 3260'$start_module'(Module, _Public, State, _Options) :- 3261 '$current_module'(Module, OldFile), 3262 source_location(File, _Line), 3263 OldFile \== File, OldFile \== [], 3264 same_file(OldFile, File), 3265 !, 3266 nb_setarg(2, State, Module), 3267 nb_setarg(4, State, true). % Stop processing 3268'$start_module'(Module, Public, State, Options) :- 3269 arg(5, State, File), 3270 nb_setarg(2, State, Module), 3271 source_location(_File, Line), 3272 '$option'(redefine_module(Action), Options, false), 3273 '$module_class'(File, Class, Super), 3274 '$reset_dialect'(File, Class), 3275 '$redefine_module'(Module, File, Action), 3276 '$declare_module'(Module, Class, Super, File, Line, false), 3277 '$export_list'(Public, Module, Ops), 3278 '$ifcompiling'('$qlf_start_module'(Module)), 3279 '$export_ops'(Ops, Module, File), 3280 '$qset_dialect'(State), 3281 nb_setarg(3, State, end_module).
swi
dialect.3288'$reset_dialect'(File, library) :- 3289 file_name_extension(_, pl, File), 3290 !, 3291 set_prolog_flag(emulated_dialect, swi). 3292'$reset_dialect'(_, _).
3299'$module3'(Var) :- 3300 var(Var), 3301 !, 3302 '$instantiation_error'(Var). 3303'$module3'([]) :- !. 3304'$module3'([H|T]) :- 3305 !, 3306 '$module3'(H), 3307 '$module3'(T). 3308'$module3'(Id) :- 3309 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.3323'$module_name'(_, _, Module, Options) :- 3324 '$option'(module(Module), Options), 3325 !, 3326 '$current_source_module'(Context), 3327 Context \== Module. % cause '$first_term'/5 to fail. 3328'$module_name'(Var, Id, Module, Options) :- 3329 var(Var), 3330 !, 3331 file_base_name(Id, File), 3332 file_name_extension(Var, _, File), 3333 '$module_name'(Var, Id, Module, Options). 3334'$module_name'(Reserved, _, _, _) :- 3335 '$reserved_module'(Reserved), 3336 !, 3337 throw(error(permission_error(load, module, Reserved), _)). 3338'$module_name'(Module, _Id, Module, _). 3339 3340 3341'$reserved_module'(system). 3342'$reserved_module'(user).
3347'$redefine_module'(_Module, _, false) :- !. 3348'$redefine_module'(Module, File, true) :- 3349 !, 3350 ( module_property(Module, file(OldFile)), 3351 File \== OldFile 3352 -> unload_file(OldFile) 3353 ; true 3354 ). 3355'$redefine_module'(Module, File, ask) :- 3356 ( stream_property(user_input, tty(true)), 3357 module_property(Module, file(OldFile)), 3358 File \== OldFile, 3359 '$rdef_response'(Module, OldFile, File, true) 3360 -> '$redefine_module'(Module, File, true) 3361 ; true 3362 ). 3363 3364'$rdef_response'(Module, OldFile, File, Ok) :- 3365 repeat, 3366 print_message(query, redefine_module(Module, OldFile, File)), 3367 get_single_char(Char), 3368 '$rdef_response'(Char, Ok0), 3369 !, 3370 Ok = Ok0. 3371 3372'$rdef_response'(Char, true) :- 3373 memberchk(Char, `yY`), 3374 format(user_error, 'yes~n', []). 3375'$rdef_response'(Char, false) :- 3376 memberchk(Char, `nN`), 3377 format(user_error, 'no~n', []). 3378'$rdef_response'(Char, _) :- 3379 memberchk(Char, `a`), 3380 format(user_error, 'abort~n', []), 3381 abort. 3382'$rdef_response'(_, _) :- 3383 print_message(help, redefine_module_reply), 3384 fail.
system
, while all normal user modules inherit
from user
.3394'$module_class'(File, Class, system) :- 3395 current_prolog_flag(home, Home), 3396 sub_atom(File, 0, Len, _, Home), 3397 ( sub_atom(File, Len, _, _, '/boot/') 3398 -> !, Class = system 3399 ; '$lib_prefix'(Prefix), 3400 sub_atom(File, Len, _, _, Prefix) 3401 -> !, Class = library 3402 ; file_directory_name(File, Home), 3403 file_name_extension(_, rc, File) 3404 -> !, Class = library 3405 ). 3406'$module_class'(_, user, user). 3407 3408'$lib_prefix'('/library'). 3409'$lib_prefix'('/xpce/prolog/'). 3410 3411'$check_export'(Module) :- 3412 '$undefined_export'(Module, UndefList), 3413 ( '$member'(Undef, UndefList), 3414 strip_module(Undef, _, Local), 3415 print_message(error, 3416 undefined_export(Module, Local)), 3417 fail 3418 ; true 3419 ).
all
,
a list of optionally mapped predicate indicators or a term
except(Import)
.3428'$import_list'(_, _, Var, _) :- 3429 var(Var), 3430 !, 3431 throw(error(instantitation_error, _)). 3432'$import_list'(Target, Source, all, Reexport) :- 3433 !, 3434 '$exported_ops'(Source, Import, Predicates), 3435 '$module_property'(Source, exports(Predicates)), 3436 '$import_all'(Import, Target, Source, Reexport, weak). 3437'$import_list'(Target, Source, except(Spec), Reexport) :- 3438 !, 3439 '$exported_ops'(Source, Export, Predicates), 3440 '$module_property'(Source, exports(Predicates)), 3441 ( is_list(Spec) 3442 -> true 3443 ; throw(error(type_error(list, Spec), _)) 3444 ), 3445 '$import_except'(Spec, Export, Import), 3446 '$import_all'(Import, Target, Source, Reexport, weak). 3447'$import_list'(Target, Source, Import, Reexport) :- 3448 !, 3449 is_list(Import), 3450 !, 3451 '$import_all'(Import, Target, Source, Reexport, strong). 3452'$import_list'(_, _, Import, _) :- 3453 throw(error(type_error(import_specifier, Import))). 3454 3455 3456'$import_except'([], List, List). 3457'$import_except'([H|T], List0, List) :- 3458 '$import_except_1'(H, List0, List1), 3459 '$import_except'(T, List1, List). 3460 3461'$import_except_1'(Var, _, _) :- 3462 var(Var), 3463 !, 3464 throw(error(instantitation_error, _)). 3465'$import_except_1'(PI as N, List0, List) :- 3466 '$pi'(PI), atom(N), 3467 !, 3468 '$canonical_pi'(PI, CPI), 3469 '$import_as'(CPI, N, List0, List). 3470'$import_except_1'(op(P,A,N), List0, List) :- 3471 !, 3472 '$remove_ops'(List0, op(P,A,N), List). 3473'$import_except_1'(PI, List0, List) :- 3474 '$pi'(PI), 3475 !, 3476 '$canonical_pi'(PI, CPI), 3477 '$select'(P, List0, List), 3478 '$canonical_pi'(CPI, P), 3479 !. 3480'$import_except_1'(Except, _, _) :- 3481 throw(error(type_error(import_specifier, Except), _)). 3482 3483'$import_as'(CPI, N, [PI2|T], [CPI as N|T]) :- 3484 '$canonical_pi'(PI2, CPI), 3485 !. 3486'$import_as'(PI, N, [H|T0], [H|T]) :- 3487 !, 3488 '$import_as'(PI, N, T0, T). 3489'$import_as'(PI, _, _, _) :- 3490 throw(error(existence_error(export, PI), _)). 3491 3492'$pi'(N/A) :- atom(N), integer(A), !. 3493'$pi'(N//A) :- atom(N), integer(A). 3494 3495'$canonical_pi'(N//A0, N/A) :- 3496 A is A0 + 2. 3497'$canonical_pi'(PI, PI). 3498 3499'$remove_ops'([], _, []). 3500'$remove_ops'([Op|T0], Pattern, T) :- 3501 subsumes_term(Pattern, Op), 3502 !, 3503 '$remove_ops'(T0, Pattern, T). 3504'$remove_ops'([H|T0], Pattern, [H|T]) :- 3505 '$remove_ops'(T0, Pattern, T).
3510'$import_all'(Import, Context, Source, Reexport, Strength) :-
3511 '$import_all2'(Import, Context, Source, Imported, ImpOps, Strength),
3512 ( Reexport == true,
3513 ( '$list_to_conj'(Imported, Conj)
3514 -> export(Context:Conj),
3515 '$ifcompiling'('$add_directive_wic'(export(Context:Conj)))
3516 ; true
3517 ),
3518 source_location(File, _Line),
3519 '$export_ops'(ImpOps, Context, File)
3520 ; true
3521 ).
3525'$import_all2'([], _, _, [], [], _). 3526'$import_all2'([PI as NewName|Rest], Context, Source, 3527 [NewName/Arity|Imported], ImpOps, Strength) :- 3528 !, 3529 '$canonical_pi'(PI, Name/Arity), 3530 length(Args, Arity), 3531 Head =.. [Name|Args], 3532 NewHead =.. [NewName|Args], 3533 ( '$get_predicate_attribute'(Source:Head, transparent, 1) 3534 -> '$set_predicate_attribute'(Context:NewHead, transparent, true) 3535 ; true 3536 ), 3537 ( source_location(File, Line) 3538 -> E = error(_,_), 3539 catch('$store_admin_clause'((NewHead :- Source:Head), 3540 _Layout, File, File:Line), 3541 E, '$print_message'(error, E)) 3542 ; assertz(( :- !, Source:Head)) % ! avoids problems with 3543 ), % duplicate load 3544 '$import_all2'(Rest, Context, Source, Imported, ImpOps, Strength). 3545'$import_all2'([op(P,A,N)|Rest], Context, Source, Imported, 3546 [op(P,A,N)|ImpOps], Strength) :- 3547 !, 3548 '$import_ops'(Context, Source, op(P,A,N)), 3549 '$import_all2'(Rest, Context, Source, Imported, ImpOps, Strength). 3550'$import_all2'([Pred|Rest], Context, Source, [Pred|Imported], ImpOps, Strength) :- 3551 Error = error(_,_), 3552 catch(Context:'$import'(Source:Pred, Strength), Error, 3553 print_message(error, Error)), 3554 '$ifcompiling'('$import_wic'(Source, Pred, Strength)), 3555 '$import_all2'(Rest, Context, Source, Imported, ImpOps, Strength). 3556 3557 3558'$list_to_conj'([One], One) :- !. 3559'$list_to_conj'([H|T], (H,Rest)) :- 3560 '$list_to_conj'(T, Rest).
op(P,A,N)
terms representing the operators
exported from Module.3567'$exported_ops'(Module, Ops, Tail) :- 3568 '$c_current_predicate'(_, Module:'$exported_op'(_,_,_)), 3569 !, 3570 findall(op(P,A,N), Module:'$exported_op'(P,A,N), Ops, Tail). 3571'$exported_ops'(_, Ops, Ops). 3572 3573'$exported_op'(Module, P, A, N) :- 3574 '$c_current_predicate'(_, Module:'$exported_op'(_,_,_)), 3575 Module:'$exported_op'(P, A, N).
3582'$import_ops'(To, From, Pattern) :- 3583 ground(Pattern), 3584 !, 3585 Pattern = op(P,A,N), 3586 op(P,A,To:N), 3587 ( '$exported_op'(From, P, A, N) 3588 -> true 3589 ; print_message(warning, no_exported_op(From, Pattern)) 3590 ). 3591'$import_ops'(To, From, Pattern) :- 3592 ( '$exported_op'(From, Pri, Assoc, Name), 3593 Pattern = op(Pri, Assoc, Name), 3594 op(Pri, Assoc, To:Name), 3595 fail 3596 ; true 3597 ).
3605'$export_list'(Decls, Module, Ops) :- 3606 is_list(Decls), 3607 !, 3608 '$do_export_list'(Decls, Module, Ops). 3609'$export_list'(Decls, _, _) :- 3610 var(Decls), 3611 throw(error(instantiation_error, _)). 3612'$export_list'(Decls, _, _) :- 3613 throw(error(type_error(list, Decls), _)). 3614 3615'$do_export_list'([], _, []) :- !. 3616'$do_export_list'([H|T], Module, Ops) :- 3617 !, 3618 E = error(_,_), 3619 catch('$export1'(H, Module, Ops, Ops1), 3620 E, ('$print_message'(error, E), Ops = Ops1)), 3621 '$do_export_list'(T, Module, Ops1). 3622 3623'$export1'(Var, _, _, _) :- 3624 var(Var), 3625 !, 3626 throw(error(instantiation_error, _)). 3627'$export1'(Op, _, [Op|T], T) :- 3628 Op = op(_,_,_), 3629 !. 3630'$export1'(PI0, Module, Ops, Ops) :- 3631 strip_module(Module:PI0, M, PI), 3632 ( PI = (_//_) 3633 -> non_terminal(M:PI) 3634 ; true 3635 ), 3636 export(M:PI). 3637 3638'$export_ops'([op(Pri, Assoc, Name)|T], Module, File) :- 3639 E = error(_,_), 3640 catch(( '$execute_directive'(op(Pri, Assoc, Module:Name), File, []), 3641 '$export_op'(Pri, Assoc, Name, Module, File) 3642 ), 3643 E, '$print_message'(error, E)), 3644 '$export_ops'(T, Module, File). 3645'$export_ops'([], _, _). 3646 3647'$export_op'(Pri, Assoc, Name, Module, File) :- 3648 ( '$get_predicate_attribute'(Module:'$exported_op'(_,_,_), defined, 1) 3649 -> true 3650 ; '$execute_directive'(discontiguous(Module:'$exported_op'/3), File, []) 3651 ), 3652 '$store_admin_clause'('$exported_op'(Pri, Assoc, Name), _Layout, File, -).
3658'$execute_directive'(Var, _F, _Options) :- 3659 var(Var), 3660 '$instantiation_error'(Var). 3661'$execute_directive'(encoding(Encoding), _F, _Options) :- 3662 !, 3663 ( '$load_input'(_F, S) 3664 -> set_stream(S, encoding(Encoding)) 3665 ). 3666'$execute_directive'(Goal, _, Options) :- 3667 \+ '$compilation_mode'(database), 3668 !, 3669 '$add_directive_wic2'(Goal, Type, Options), 3670 ( Type == call % suspend compiling into .qlf file 3671 -> '$compilation_mode'(Old, database), 3672 setup_call_cleanup( 3673 '$directive_mode'(OldDir, Old), 3674 '$execute_directive_3'(Goal), 3675 ( '$set_compilation_mode'(Old), 3676 '$set_directive_mode'(OldDir) 3677 )) 3678 ; '$execute_directive_3'(Goal) 3679 ). 3680'$execute_directive'(Goal, _, _Options) :- 3681 '$execute_directive_3'(Goal). 3682 3683'$execute_directive_3'(Goal) :- 3684 '$current_source_module'(Module), 3685 '$valid_directive'(Module:Goal), 3686 !, 3687 ( '$pattr_directive'(Goal, Module) 3688 -> true 3689 ; Term = error(_,_), 3690 catch(Module:Goal, Term, '$exception_in_directive'(Term)) 3691 -> true 3692 ; '$print_message'(warning, goal_failed(directive, Module:Goal)), 3693 fail 3694 ). 3695'$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.3704:- multifile prolog:sandbox_allowed_directive/1. 3705:- multifile prolog:sandbox_allowed_clause/1. 3706:- meta_predicate '$valid_directive'( ). 3707 3708'$valid_directive'(_) :- 3709 current_prolog_flag(sandboxed_load, false), 3710 !. 3711'$valid_directive'(Goal) :- 3712 Error = error(Formal, _), 3713 catch(prolog:sandbox_allowed_directive(Goal), Error, true), 3714 !, 3715 ( var(Formal) 3716 -> true 3717 ; print_message(error, Error), 3718 fail 3719 ). 3720'$valid_directive'(Goal) :- 3721 print_message(error, 3722 error(permission_error(execute, 3723 sandboxed_directive, 3724 Goal), _)), 3725 fail. 3726 3727'$exception_in_directive'(Term) :- 3728 '$print_message'(error, Term), 3729 fail.
load
or call
. Add a call
directive to the QLF file. load
directives continue the
compilation into the QLF file.3737'$add_directive_wic2'(Goal, Type, Options) :- 3738 '$common_goal_type'(Goal, Type, Options), 3739 !, 3740 ( Type == load 3741 -> true 3742 ; '$current_source_module'(Module), 3743 '$add_directive_wic'(Module:Goal) 3744 ). 3745'$add_directive_wic2'(Goal, _, _) :- 3746 ( '$compilation_mode'(qlf) % no problem for qlf files 3747 -> true 3748 ; print_message(error, mixed_directive(Goal)) 3749 ).
load
or call
.3756'$common_goal_type'((A,B), Type, Options) :- 3757 !, 3758 '$common_goal_type'(A, Type, Options), 3759 '$common_goal_type'(B, Type, Options). 3760'$common_goal_type'((A;B), Type, Options) :- 3761 !, 3762 '$common_goal_type'(A, Type, Options), 3763 '$common_goal_type'(B, Type, Options). 3764'$common_goal_type'((A->B), Type, Options) :- 3765 !, 3766 '$common_goal_type'(A, Type, Options), 3767 '$common_goal_type'(B, Type, Options). 3768'$common_goal_type'(Goal, Type, Options) :- 3769 '$goal_type'(Goal, Type, Options). 3770 3771'$goal_type'(Goal, Type, Options) :- 3772 ( '$load_goal'(Goal, Options) 3773 -> Type = load 3774 ; Type = call 3775 ). 3776 3777:- thread_local 3778 '$qlf':qinclude/1. 3779 3780'$load_goal'([_|_], _). 3781'$load_goal'(consult(_), _). 3782'$load_goal'(load_files(_), _). 3783'$load_goal'(load_files(_,Options), _) :- 3784 memberchk(qcompile(QlfMode), Options), 3785 '$qlf_part_mode'(QlfMode). 3786'$load_goal'(ensure_loaded(_), _) :- '$compilation_mode'(wic). 3787'$load_goal'(use_module(_), _) :- '$compilation_mode'(wic). 3788'$load_goal'(use_module(_, _), _) :- '$compilation_mode'(wic). 3789'$load_goal'(reexport(_), _) :- '$compilation_mode'(wic). 3790'$load_goal'(reexport(_, _), _) :- '$compilation_mode'(wic). 3791'$load_goal'(Goal, _Options) :- 3792 '$qlf':qinclude(user), 3793 '$load_goal_file'(Goal, File), 3794 '$all_user_files'(File). 3795 3796 3797'$load_goal_file'(load_files(F), F). 3798'$load_goal_file'(load_files(F, _), F). 3799'$load_goal_file'(ensure_loaded(F), F). 3800'$load_goal_file'(use_module(F), F). 3801'$load_goal_file'(use_module(F, _), F). 3802'$load_goal_file'(reexport(F), F). 3803'$load_goal_file'(reexport(F, _), F). 3804 3805'$all_user_files'([]) :- 3806 !. 3807'$all_user_files'([H|T]) :- 3808 !, 3809 '$is_user_file'(H), 3810 '$all_user_files'(T). 3811'$all_user_files'(F) :- 3812 ground(F), 3813 '$is_user_file'(F). 3814 3815'$is_user_file'(File) :- 3816 absolute_file_name(File, Path, 3817 [ file_type(prolog), 3818 access(read) 3819 ]), 3820 '$module_class'(Path, user, _). 3821 3822'$qlf_part_mode'(part). 3823'$qlf_part_mode'(true). % compatibility 3824 3825 3826 /******************************** 3827 * COMPILE A CLAUSE * 3828 *********************************/
3835'$store_admin_clause'(Clause, Layout, Owner, SrcLoc) :- 3836 Owner \== (-), 3837 !, 3838 setup_call_cleanup( 3839 '$start_aux'(Owner, Context), 3840 '$store_admin_clause2'(Clause, Layout, Owner, SrcLoc), 3841 '$end_aux'(Owner, Context)). 3842'$store_admin_clause'(Clause, Layout, File, SrcLoc) :- 3843 '$store_admin_clause2'(Clause, Layout, File, SrcLoc). 3844 3845'$store_admin_clause2'(Clause, _Layout, File, SrcLoc) :- 3846 ( '$compilation_mode'(database) 3847 -> '$record_clause'(Clause, File, SrcLoc) 3848 ; '$record_clause'(Clause, File, SrcLoc, Ref), 3849 '$qlf_assert_clause'(Ref, development) 3850 ).
3860'$store_clause'((_, _), _, _, _) :- 3861 !, 3862 print_message(error, cannot_redefine_comma), 3863 fail. 3864'$store_clause'((Pre => Body), _Layout, File, SrcLoc) :- 3865 nonvar(Pre), 3866 Pre = (Head,Cond), 3867 !, 3868 ( '$is_true'(Cond), current_prolog_flag(optimise, true) 3869 -> '$store_clause'((Head=>Body), _Layout, File, SrcLoc) 3870 ; '$store_clause'(?=>(Head,(Cond,!,Body)), _Layout, File, SrcLoc) 3871 ). 3872'$store_clause'(Clause, _Layout, File, SrcLoc) :- 3873 '$valid_clause'(Clause), 3874 !, 3875 ( '$compilation_mode'(database) 3876 -> '$record_clause'(Clause, File, SrcLoc) 3877 ; '$record_clause'(Clause, File, SrcLoc, Ref), 3878 '$qlf_assert_clause'(Ref, development) 3879 ). 3880 3881'$is_true'(true) => true. 3882'$is_true'((A,B)) => '$is_true'(A), '$is_true'(B). 3883'$is_true'(_) => fail. 3884 3885'$valid_clause'(_) :- 3886 current_prolog_flag(sandboxed_load, false), 3887 !. 3888'$valid_clause'(Clause) :- 3889 \+ '$cross_module_clause'(Clause), 3890 !. 3891'$valid_clause'(Clause) :- 3892 Error = error(Formal, _), 3893 catch(prolog:sandbox_allowed_clause(Clause), Error, true), 3894 !, 3895 ( var(Formal) 3896 -> true 3897 ; print_message(error, Error), 3898 fail 3899 ). 3900'$valid_clause'(Clause) :- 3901 print_message(error, 3902 error(permission_error(assert, 3903 sandboxed_clause, 3904 Clause), _)), 3905 fail. 3906 3907'$cross_module_clause'(Clause) :- 3908 '$head_module'(Clause, Module), 3909 \+ '$current_source_module'(Module). 3910 3911'$head_module'(Var, _) :- 3912 var(Var), !, fail. 3913'$head_module'((Head :- _), Module) :- 3914 '$head_module'(Head, Module). 3915'$head_module'(Module:_, Module). 3916 3917'$clause_source'('$source_location'(File,Line):Clause, Clause, File:Line) :- !. 3918'$clause_source'(Clause, Clause, -).
3925:- public 3926 '$store_clause'/2. 3927 3928'$store_clause'(Term, Id) :- 3929 '$clause_source'(Term, Clause, SrcLoc), 3930 '$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)
3951compile_aux_clauses(_Clauses) :- 3952 current_prolog_flag(xref, true), 3953 !. 3954compile_aux_clauses(Clauses) :- 3955 source_location(File, _Line), 3956 '$compile_aux_clauses'(Clauses, File). 3957 3958'$compile_aux_clauses'(Clauses, File) :- 3959 setup_call_cleanup( 3960 '$start_aux'(File, Context), 3961 '$store_aux_clauses'(Clauses, File), 3962 '$end_aux'(File, Context)). 3963 3964'$store_aux_clauses'(Clauses, File) :- 3965 is_list(Clauses), 3966 !, 3967 forall('$member'(C,Clauses), 3968 '$compile_term'(C, _Layout, File, [])). 3969'$store_aux_clauses'(Clause, File) :- 3970 '$compile_term'(Clause, _Layout, File, []). 3971 3972 3973 /******************************* 3974 * STAGING * 3975 *******************************/
3985'$stage_file'(Target, Stage) :- 3986 file_directory_name(Target, Dir), 3987 file_base_name(Target, File), 3988 current_prolog_flag(pid, Pid), 3989 format(atom(Stage), '~w/.~w.~d', [Dir,File,Pid]). 3990 3991'$install_staged_file'(exit, Staged, Target, error) :- 3992 !, 3993 rename_file(Staged, Target). 3994'$install_staged_file'(exit, Staged, Target, OnError) :- 3995 !, 3996 InstallError = error(_,_), 3997 catch(rename_file(Staged, Target), 3998 InstallError, 3999 '$install_staged_error'(OnError, InstallError, Staged, Target)). 4000'$install_staged_file'(_, Staged, _, _OnError) :- 4001 E = error(_,_), 4002 catch(delete_file(Staged), E, true). 4003 4004'$install_staged_error'(OnError, Error, Staged, _Target) :- 4005 E = error(_,_), 4006 catch(delete_file(Staged), E, true), 4007 ( OnError = silent 4008 -> true 4009 ; OnError = fail 4010 -> fail 4011 ; print_message(warning, Error) 4012 ). 4013 4014 4015 /******************************* 4016 * READING * 4017 *******************************/ 4018 4019:- multifile 4020 prolog:comment_hook/3. % hook for read_clause/3 4021 4022 4023 /******************************* 4024 * FOREIGN INTERFACE * 4025 *******************************/ 4026 4027% call-back from PL_register_foreign(). First argument is the module 4028% into which the foreign predicate is loaded and second is a term 4029% describing the arguments. 4030 4031:- dynamic 4032 '$foreign_registered'/2. 4033 4034 /******************************* 4035 * TEMPORARY TERM EXPANSION * 4036 *******************************/ 4037 4038% Provide temporary definitions for the boot-loader. These are replaced 4039% by the real thing in load.pl 4040 4041:- dynamic 4042 '$expand_goal'/2, 4043 '$expand_term'/4. 4044 4045'$expand_goal'(In, In). 4046'$expand_term'(In, Layout, In, Layout). 4047 4048 4049 /******************************* 4050 * TYPE SUPPORT * 4051 *******************************/ 4052 4053'$type_error'(Type, Value) :- 4054 ( var(Value) 4055 -> throw(error(instantiation_error, _)) 4056 ; throw(error(type_error(Type, Value), _)) 4057 ). 4058 4059'$domain_error'(Type, Value) :- 4060 throw(error(domain_error(Type, Value), _)). 4061 4062'$existence_error'(Type, Object) :- 4063 throw(error(existence_error(Type, Object), _)). 4064 4065'$permission_error'(Action, Type, Term) :- 4066 throw(error(permission_error(Action, Type, Term), _)). 4067 4068'$instantiation_error'(_Var) :- 4069 throw(error(instantiation_error, _)). 4070 4071'$uninstantiation_error'(NonVar) :- 4072 throw(error(uninstantiation_error(NonVar), _)). 4073 4074'$must_be'(list, X) :- !, 4075 '$skip_list'(_, X, Tail), 4076 ( Tail == [] 4077 -> true 4078 ; '$type_error'(list, Tail) 4079 ). 4080'$must_be'(options, X) :- !, 4081 ( '$is_options'(X) 4082 -> true 4083 ; '$type_error'(options, X) 4084 ). 4085'$must_be'(atom, X) :- !, 4086 ( atom(X) 4087 -> true 4088 ; '$type_error'(atom, X) 4089 ). 4090'$must_be'(integer, X) :- !, 4091 ( integer(X) 4092 -> true 4093 ; '$type_error'(integer, X) 4094 ). 4095'$must_be'(between(Low,High), X) :- !, 4096 ( integer(X) 4097 -> ( between(Low, High, X) 4098 -> true 4099 ; '$domain_error'(between(Low,High), X) 4100 ) 4101 ; '$type_error'(integer, X) 4102 ). 4103'$must_be'(callable, X) :- !, 4104 ( callable(X) 4105 -> true 4106 ; '$type_error'(callable, X) 4107 ). 4108'$must_be'(acyclic, X) :- !, 4109 ( acyclic_term(X) 4110 -> true 4111 ; '$domain_error'(acyclic_term, X) 4112 ). 4113'$must_be'(oneof(Type, Domain, List), X) :- !, 4114 '$must_be'(Type, X), 4115 ( memberchk(X, List) 4116 -> true 4117 ; '$domain_error'(Domain, X) 4118 ). 4119'$must_be'(boolean, X) :- !, 4120 ( (X == true ; X == false) 4121 -> true 4122 ; '$type_error'(boolean, X) 4123 ). 4124'$must_be'(ground, X) :- !, 4125 ( ground(X) 4126 -> true 4127 ; '$instantiation_error'(X) 4128 ). 4129'$must_be'(filespec, X) :- !, 4130 ( ( atom(X) 4131 ; string(X) 4132 ; compound(X), 4133 compound_name_arity(X, _, 1) 4134 ) 4135 -> true 4136 ; '$type_error'(filespec, X) 4137 ). 4138 4139% Use for debugging 4140%'$must_be'(Type, _X) :- format('Unknown $must_be type: ~q~n', [Type]). 4141 4142 4143 /******************************** 4144 * LIST PROCESSING * 4145 *********************************/ 4146 4147'$member'(El, [H|T]) :- 4148 '$member_'(T, El, H). 4149 4150'$member_'(_, El, El). 4151'$member_'([H|T], El, _) :- 4152 '$member_'(T, El, H). 4153 4154'$append'([], L, L). 4155'$append'([H|T], L, [H|R]) :- 4156 '$append'(T, L, R). 4157 4158'$append'(ListOfLists, List) :- 4159 '$must_be'(list, ListOfLists), 4160 '$append_'(ListOfLists, List). 4161 4162'$append_'([], []). 4163'$append_'([L|Ls], As) :- 4164 '$append'(L, Ws, As), 4165 '$append_'(Ls, Ws). 4166 4167'$select'(X, [X|Tail], Tail). 4168'$select'(Elem, [Head|Tail], [Head|Rest]) :- 4169 '$select'(Elem, Tail, Rest). 4170 4171'$reverse'(L1, L2) :- 4172 '$reverse'(L1, [], L2). 4173 4174'$reverse'([], List, List). 4175'$reverse'([Head|List1], List2, List3) :- 4176 '$reverse'(List1, [Head|List2], List3). 4177 4178'$delete'([], _, []) :- !. 4179'$delete'([Elem|Tail], Elem, Result) :- 4180 !, 4181 '$delete'(Tail, Elem, Result). 4182'$delete'([Head|Tail], Elem, [Head|Rest]) :- 4183 '$delete'(Tail, Elem, Rest). 4184 4185'$last'([H|T], Last) :- 4186 '$last'(T, H, Last). 4187 4188'$last'([], Last, Last). 4189'$last'([H|T], _, Last) :- 4190 '$last'(T, H, Last). 4191 4192:- meta_predicate '$include'( , , ). 4193'$include'(_, [], []). 4194'$include'(G, [H|T0], L) :- 4195 ( call(G,H) 4196 -> L = [H|T] 4197 ; T = L 4198 ), 4199 '$include'(G, T0, T).
4206:- '$iso'((length/2)). 4207 4208length(List, Length) :- 4209 var(Length), 4210 !, 4211 '$skip_list'(Length0, List, Tail), 4212 ( Tail == [] 4213 -> Length = Length0 % +,- 4214 ; var(Tail) 4215 -> Tail \== Length, % avoid length(L,L) 4216 '$length3'(Tail, Length, Length0) % -,- 4217 ; throw(error(type_error(list, List), 4218 context(length/2, _))) 4219 ). 4220length(List, Length) :- 4221 integer(Length), 4222 Length >= 0, 4223 !, 4224 '$skip_list'(Length0, List, Tail), 4225 ( Tail == [] % proper list 4226 -> Length = Length0 4227 ; var(Tail) 4228 -> Extra is Length-Length0, 4229 '$length'(Tail, Extra) 4230 ; throw(error(type_error(list, List), 4231 context(length/2, _))) 4232 ). 4233length(_, Length) :- 4234 integer(Length), 4235 !, 4236 throw(error(domain_error(not_less_than_zero, Length), 4237 context(length/2, _))). 4238length(_, Length) :- 4239 throw(error(type_error(integer, Length), 4240 context(length/2, _))). 4241 4242'$length3'([], N, N). 4243'$length3'([_|List], N, N0) :- 4244 N1 is N0+1, 4245 '$length3'(List, N, N1). 4246 4247 4248 /******************************* 4249 * OPTION PROCESSING * 4250 *******************************/
4256'$is_options'(Map) :- 4257 is_dict(Map, _), 4258 !. 4259'$is_options'(List) :- 4260 is_list(List), 4261 ( List == [] 4262 -> true 4263 ; List = [H|_], 4264 '$is_option'(H, _, _) 4265 ). 4266 4267'$is_option'(Var, _, _) :- 4268 var(Var), !, fail. 4269'$is_option'(F, Name, Value) :- 4270 functor(F, _, 1), 4271 !, 4272 F =.. [Name,Value]. 4273'$is_option'(Name=Value, Name, Value).
4277'$option'(Opt, Options) :- 4278 is_dict(Options), 4279 !, 4280 [Opt] :< Options. 4281'$option'(Opt, Options) :- 4282 memberchk(Opt, Options).
4286'$option'(Term, Options, Default) :-
4287 arg(1, Term, Value),
4288 functor(Term, Name, 1),
4289 ( is_dict(Options)
4290 -> ( get_dict(Name, Options, GVal)
4291 -> Value = GVal
4292 ; Value = Default
4293 )
4294 ; functor(Gen, Name, 1),
4295 arg(1, Gen, GVal),
4296 ( memberchk(Gen, Options)
4297 -> Value = GVal
4298 ; Value = Default
4299 )
4300 ).
4308'$select_option'(Opt, Options, Rest) :-
4309 '$options_dict'(Options, Dict),
4310 select_dict([Opt], Dict, Rest).
4318'$merge_options'(New, Old, Merged) :-
4319 '$options_dict'(New, NewDict),
4320 '$options_dict'(Old, OldDict),
4321 put_dict(NewDict, OldDict, Merged).
4328'$options_dict'(Options, Dict) :- 4329 is_list(Options), 4330 !, 4331 '$keyed_options'(Options, Keyed), 4332 sort(1, @<, Keyed, UniqueKeyed), 4333 '$pairs_values'(UniqueKeyed, Unique), 4334 dict_create(Dict, _, Unique). 4335'$options_dict'(Dict, Dict) :- 4336 is_dict(Dict), 4337 !. 4338'$options_dict'(Options, _) :- 4339 '$domain_error'(options, Options). 4340 4341'$keyed_options'([], []). 4342'$keyed_options'([H0|T0], [H|T]) :- 4343 '$keyed_option'(H0, H), 4344 '$keyed_options'(T0, T). 4345 4346'$keyed_option'(Var, _) :- 4347 var(Var), 4348 !, 4349 '$instantiation_error'(Var). 4350'$keyed_option'(Name=Value, Name-(Name-Value)). 4351'$keyed_option'(NameValue, Name-(Name-Value)) :- 4352 compound_name_arguments(NameValue, Name, [Value]), 4353 !. 4354'$keyed_option'(Opt, _) :- 4355 '$domain_error'(option, Opt). 4356 4357 4358 /******************************* 4359 * HANDLE TRACER 'L'-COMMAND * 4360 *******************************/ 4361 4362:- public '$prolog_list_goal'/1. 4363 4364:- multifile 4365 user:prolog_list_goal/1. 4366 4367'$prolog_list_goal'(Goal) :- 4368 user:prolog_list_goal(Goal), 4369 !. 4370'$prolog_list_goal'(Goal) :- 4371 use_module(library(listing), [listing/1]), 4372 @(listing(Goal), user). 4373 4374 4375 /******************************* 4376 * HALT * 4377 *******************************/ 4378 4379:- '$iso'((halt/0)). 4380 4381halt :- 4382 '$exit_code'(Code), 4383 ( Code == 0 4384 -> true 4385 ; print_message(warning, on_error(halt(1))) 4386 ), 4387 halt(Code).
on_error
and on_warning
flags. Also used by qsave_toplevel/0.
4394'$exit_code'(Code) :-
4395 ( ( current_prolog_flag(on_error, status),
4396 statistics(errors, Count),
4397 Count > 0
4398 ; current_prolog_flag(on_warning, status),
4399 statistics(warnings, Count),
4400 Count > 0
4401 )
4402 -> Code = 1
4403 ; Code = 0
4404 ).
4413:- meta_predicate at_halt( ). 4414:- dynamic system:term_expansion/2, '$at_halt'/2. 4415:- multifile system:term_expansion/2, '$at_halt'/2. 4416 4417systemterm_expansion((:- at_halt(Goal)), 4418 system:'$at_halt'(Module:Goal, File:Line)) :- 4419 \+ current_prolog_flag(xref, true), 4420 source_location(File, Line), 4421 '$current_source_module'(Module). 4422 4423at_halt(Goal) :- 4424 asserta('$at_halt'(Goal, (-):0)). 4425 4426:- public '$run_at_halt'/0. 4427 4428'$run_at_halt' :- 4429 forall(clause('$at_halt'(Goal, Src), true, Ref), 4430 ( '$call_at_halt'(Goal, Src), 4431 erase(Ref) 4432 )). 4433 4434'$call_at_halt'(Goal, _Src) :- 4435 catch(Goal, E, true), 4436 !, 4437 ( var(E) 4438 -> true 4439 ; subsumes_term(cancel_halt(_), E) 4440 -> '$print_message'(informational, E), 4441 fail 4442 ; '$print_message'(error, E) 4443 ). 4444'$call_at_halt'(Goal, _Src) :- 4445 '$print_message'(warning, goal_failed(at_halt, Goal)).
4453cancel_halt(Reason) :-
4454 throw(cancel_halt(Reason)).
heartbeat
is
non-zero.4461:- multifile prolog:heartbeat/0. 4462 4463 4464 /******************************** 4465 * LOAD OTHER MODULES * 4466 *********************************/ 4467 4468:- meta_predicate 4469 '$load_wic_files'( ). 4470 4471'$load_wic_files'(Files) :- 4472 Files = Module:_, 4473 '$execute_directive'('$set_source_module'(OldM, Module), [], []), 4474 '$save_lex_state'(LexState, []), 4475 '$style_check'(_, 0xC7), % see style_name/2 in syspred.pl 4476 '$compilation_mode'(OldC, wic), 4477 consult(Files), 4478 '$execute_directive'('$set_source_module'(OldM), [], []), 4479 '$execute_directive'('$restore_lex_state'(LexState), [], []), 4480 '$set_compilation_mode'(OldC).
compileFileList()
in pl-wic.c. Gets the files from
"-c file ..." and loads them into the module user.4488:- public '$load_additional_boot_files'/0. 4489 4490'$load_additional_boot_files' :- 4491 current_prolog_flag(argv, Argv), 4492 '$get_files_argv'(Argv, Files), 4493 ( Files \== [] 4494 -> format('Loading additional boot files~n'), 4495 '$load_wic_files'(user:Files), 4496 format('additional boot files loaded~n') 4497 ; true 4498 ). 4499 4500'$get_files_argv'([], []) :- !. 4501'$get_files_argv'(['-c'|Files], Files) :- !. 4502'$get_files_argv'([_|Rest], Files) :- 4503 '$get_files_argv'(Rest, Files). 4504 4505'$:-'(('$boot_message'('Loading Prolog startup files~n', []), 4506 source_location(File, _Line), 4507 file_directory_name(File, Dir), 4508 atom_concat(Dir, '/load.pl', LoadFile), 4509 '$load_wic_files'(system:[LoadFile]), 4510 ( current_prolog_flag(windows, true) 4511 -> atom_concat(Dir, '/menu.pl', MenuFile), 4512 '$load_wic_files'(system:[MenuFile]) 4513 ; true 4514 ), 4515 '$boot_message'('SWI-Prolog boot files loaded~n', []), 4516 '$compilation_mode'(OldC, wic), 4517 '$execute_directive'('$set_source_module'(user), [], []), 4518 '$set_compilation_mode'(OldC) 4519 ))