/************************************************************************* * * * YAP Prolog * * * * Yap Prolog was developed at NCCUP - Universidade do Porto * * * * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 * * * ************************************************************************** * * * File: consult.yap * * Last rev: 8/2/88 * * mods: * * comments: Consulting Files in YAP * * * *************************************************************************/ :- system_module( '$_consult', [compile/1, consult/1, db_files/1, ensure_loaded/1, exists_source/1, exo_files/1, (initialization)/2, load_files/2, make/0, make_library_index/1, module/2, prolog_load_context/2, reconsult/1, source_file/1, source_file/2, source_file_property/2, use_module/3], ['$add_multifile'/3, '$csult'/2, '$do_startup_reconsult'/1, '$elif'/2, '$else'/1, '$endif'/1, '$if'/2, '$include'/2, '$initialization'/1, '$initialization'/2, '$lf_opt'/3, '$load_files'/3, '$require'/2, '$set_encoding'/1, '$use_module'/3]). :- use_system_module( '$_absf', ['$full_filename'/3]). :- use_system_module( '$_boot', ['$clear_reconsulting'/0, '$init_system'/0, '$init_win_graphics'/0, '$loop'/2, '$system_catch'/4]). :- use_system_module( '$_errors', ['$do_error'/2]). :- use_system_module( '$_load_foreign', ['$import_foreign'/3]). :- use_system_module( '$_modules', ['$add_to_imports'/3, '$convert_for_export'/7, '$extend_exports'/3]). :- use_system_module( '$_preds', ['$current_predicate'/4]). %% @{ /** @defgroup YAPConsulting Loading files into YAP @ingroup consult We present the main predicates and directives available to load files and to set-up the Prolog environment. We discuss + @ref YAPReadFiles + @ref YAPCompilerSettings @{ @defgroup YAPReadFiles The Predicates that Read Source Files @ingroup YAPConsulting */ /** @pred load_files(+ _Files_, + _Options_) Implementation of the consult/1 family. Execution is controlled by the following flags: + consult(+ _Mode_) This extension controls the type of file to load. If _Mode_ is: `consult`, clauses are added to the data-base, unless from the same file; `reconsult`, clauses are recompiled, `db`, these are facts that need to be added to the data-base, `exo`, these are facts with atoms and integers that can be stored in a compact representation (see load_exo/1). + silent(+ _Bool_) If true, load the file without printing a message. The specified value is the default for all files loaded as a result of loading the specified files. + stream(+ _Input_) This SWI-Prolog extension compiles the data from the stream _Input_. If this option is used, _Files_ must be a single atom which is used to identify the source-location of the loaded clauses as well as remove all clauses if the data is re-consulted. This option is added to allow compiling from non-file locations such as databases, the web, the user (see consult/1) or other servers. + compilation_mode(+ _Mode_) This extension controls how procedures are compiled. If _Mode_ is `compact` clauses are compiled and no source code is stored; if it is `source` clauses are compiled and source code is stored; if it is `assert_all` clauses are asserted into the data-base. + encoding(+ _Encoding_) Character encoding used in consulting files. Please (see [Encoding](@ref Encoding)) for supported encodings. + expand(+ _Bool_) If `true`, run the filenames through expand_file_name/2 and load the returned files. Default is false, except for consult/1 which is intended for interactive use. + if(+ _Condition_) Load the file only if the specified _Condition_ is satisfied. The value `true` the file unconditionally, `changed` loads the file if it was not loaded before, or has been modified since it was loaded the last time, `not_loaded` loads the file if it was not loaded before. + imports(+ _ListOrAll_) If `all` and the file is a module file, import all public predicates. Otherwise import only the named predicates. Each predicate is referred to as `\/\`. This option has no effect if the file is not a module file. + must_be_module(+ _Bool_) If true, raise an error if the file is not a module file. Used by ` use_module/1 and use_module/2. + qcompile(+ _Value_) SWI-Prolog flag that controls whether loaded files should be also compiled into `qly` files. The default value is obtained from the flag `qcompile`: `never`, no `qly` file is generated unless the user calls qsave_file/1 and friends, or sets the qcompile option in load_files/2; `auto`, all files are qcompiled. `large`, files above 100KB are qcompiled. `part`, not supported in YAP. + autoload(+ _Autoload_) SWI-compatible option where if _Autoload_ is `true` undefined predicates are loaded on first call. + derived_from(+ _File_) SWI-compatible option to control make/0. Currently not supported. */ % % SWI options % autoload(true,false) % derived_from(File) -> make % encoding(Encoding) => implemented % expand(true,false) % if(changed,true,not_loaded) => implemented % imports(all,List) => implemented % qcompile() => implemented % silent(true,false) => implemented % stream(Stream) => implemented % consult(consult,reconsult,exo,db) => implemented % compilation_mode(compact,source,assert_all) => implemented % register(true, false) => implemented % load_files(Files,Opts) :- '$load_files'(Files,Opts,load_files(Files,Opts)). '$lf_option'(autoload, 1, _). '$lf_option'(derived_from, 2, false). '$lf_option'(encoding, 3, default). '$lf_option'(expand, 4, false). '$lf_option'(if, 5, true). '$lf_option'(imports, 6, all). '$lf_option'(qcompile, 7, Current) :- '$nb_getval'('$qcompile', Current, Current = never). '$lf_option'(silent, 8, _). '$lf_option'(skip_unix_header, 9, true). '$lf_option'(compilation_mode, 10, Flag) :- current_prolog_flag(source, YFlag), ( YFlag == false -> Flag = compact ; Flag = source ). '$lf_option'(consult, 11, reconsult). '$lf_option'(stream, 12, _). '$lf_option'(register, 13, true). '$lf_option'('$files', 14, _). '$lf_option'('$call', 15, _). '$lf_option'('$use_module', 16, _). '$lf_option'('$consulted_at', 17, _). '$lf_option'('$options', 18, _). '$lf_option'('$location', 19, _). '$lf_option'(dialect, 20, yap). '$lf_option'(format, 21, source). '$lf_option'(redefine_module, 22, Warn) :- ( var(Warn) -> current_prolog_flag( redefine_warnings, Redefine ), Redefine = Warn ; true ). '$lf_option'(reexport, 23, false). '$lf_option'(sandboxed, 24, false). '$lf_option'(scope_settings, 25, false). '$lf_option'(modified, 26, _). '$lf_option'('$context_module', 27, _). '$lf_option'('$parent_topts', 28, _). '$lf_option'(must_be_module, 29, false). '$lf_option'('$source_pos', 30, _). '$lf_option'(last_opt, 30). '$lf_opt'( Op, TOpts, Val) :- '$lf_option'(Op, Id, _), arg( Id, TOpts, Val ). '$set_lf_opt'( Op, TOpts, Val) :- '$lf_option'(Op, Id, _), setarg( Id, TOpts, Val ). '$load_files'(Files, Opts, Call) :- ( '$nb_getval'('$lf_status', OldTOpts, fail), nonvar(OldTOpts) -> '$lf_opt'(silent, OldTOpts, OldVerbosity), '$lf_opt'(autoload, OldTOpts, OldAutoload) ; '$lf_option'(last_opt, LastOpt), functor( OldTOpts, opt, LastOpt ), '$lf_opt'('$context_module', OldTOpts, user) ), '$check_files'(Files,load_files(Files,Opts)), '$lf_option'(last_opt, LastOpt), functor( TOpts, opt, LastOpt ), ( source_location(ParentF, Line) -> true ; ParentF = user_input, Line = -1 ), '$lf_opt'('$location', TOpts, ParentF:Line), '$lf_opt'('$files', TOpts, Files), '$lf_opt'('$call', TOpts, Call), '$lf_opt'('$options', TOpts, Opts), '$lf_opt'('$parent_topts', TOpts, OldTOpts), '$process_lf_opts'(Opts,TOpts,Files,Call), '$lf_default_opts'(1, LastOpt, TOpts), '$check_use_module'(Call,UseModule), '$lf_opt'('$use_module', TOpts, UseModule), '$current_module'(M0), ( '$lf_opt'(silent, TOpts, Verbosity), var(Verbosity) -> Verbosity = OldVerbosity ; true ), ( '$lf_opt'(autoload, TOpts, Autoload), var(Autoload) -> Autoload = OldAutoload ; true ), % make sure we can run consult '$init_system', '$lf'(Files, M0, Call, TOpts). '$check_files'(Files, Call) :- var(Files), !, '$do_error'(instantiation_error, Call). '$check_files'(M:Files, Call) :- !, (var(M) -> '$do_error'(instantiation_error, Call) ; atom(M) -> '$check_files'(Files,Call) ; '$do_error'(type_error(atom,M), Call) ). '$check_files'(Files, Call) :- ( ground(Files) -> true ; '$do_error'(instantiation_error, Call) ). '$process_lf_opts'(V, _, _, Call) :- var(V), !, '$do_error'(instantiation_error,Call). '$process_lf_opts'([], _, _, _). '$process_lf_opts'([Opt|Opts],TOpt,Files,Call) :- Opt =.. [Op, Val], ground(Val), '$lf_opt'(Op, TOpt, Val), '$process_lf_opt'(Op, Val,Call), !, '$process_lf_opts'(Opts, TOpt, Files, Call). '$process_lf_opts'([Opt|_],_,_,Call) :- '$do_error'(domain_error(unimplemented_option,Opt),Call). '$process_lf_opt'(autoload, Val, Call) :- ( Val == false -> true ; Val == true -> true ; '$do_error'(domain_error(unimplemented_option,autoload(Val)),Call) ). '$process_lf_opt'(derived_from, File, Call) :- ( atom(File) -> true ; '$do_error'(type_error(atom,File),Call) ). '$process_lf_opt'(encoding, Encoding, _Call) :- atom(Encoding). '$process_lf_opt'(expand, Val, Call) :- ( Val == true -> '$do_error'(domain_error(unimplemented_option,expand),Call) ; Val == false -> true ; '$do_error'(domain_error(unimplemented_option,expand(Val)),Call) ). '$process_lf_opt'(if, If, Call) :- ( If == changed -> true ; If == true -> true ; If == not_loaded -> true ; '$do_error'(domain_error(unimplemented_option,if),Call) ). '$process_lf_opt'(imports, Val, Call) :- ( Val == all -> true ; var(Val) -> Val = all ; is_list(Val) -> ( ground(Val) -> true ; '$do_error'(instantiation_error,Call) ) ; '$do_error'(domain_error(unimplemented_option,imports(Val)),Call) ). '$process_lf_opt'(qcompile, Val,Call) :- ( Val == part -> '$do_error'(domain_error(unimplemented_option,expand),Call) ; Val == never -> true ; Val == auto -> true ; Val == large -> true ; '$do_error'(domain_error(unknown_option,qcompile(Val)),Call) ). '$process_lf_opt'(silent, Val, Call) :- ( Val == false -> true ; Val == true -> true ; '$do_error'(domain_error(unimplemented_option,silent(Val)),Call) ). '$process_lf_opt'(skip_unix_header, Val, Call) :- ( Val == false -> true ; Val == true -> true ; '$do_error'(domain_error(unimplemented_option,skip_unix_header(Val)),Call) ). '$process_lf_opt'(compilation_mode, Val, Call) :- ( Val == source -> true ; Val == compact -> true ; Val == assert_all -> true ; '$do_error'(domain_error(unimplemented_option,compilation_mode(Val)),Call) ). '$process_lf_opt'(consult, Val , Call) :- ( Val == reconsult -> true ; Val == consult -> true ; Val == exo -> true ; Val == db -> true ; '$do_error'(domain_error(unimplemented_option,consult(Val)),Call) ). '$process_lf_opt'(reexport, Val , Call) :- ( Val == true -> true ; Val == false -> true ; '$do_error'(domain_error(unimplemented_option,reexport(Val)),Call) ). '$process_lf_opt'(must_be_module, Val , Call) :- ( Val == true -> true ; Val == false -> true ; '$do_error'(domain_error(unimplemented_option,must_be_module(Val)),Call) ). '$process_lf_opt'(stream, Val, Call) :- ( current_stream(_,_,Val) -> true ; '$do_error'(type_error(stream,Val),Call) ). '$process_lf_opt'(register, Val, Call) :- ( Val == false -> true ; Val == true -> true ; '$do_error'(domain_error(unimplemented_option,register(Val)),Call) ). '$process_lf_opt'('$context_module', Mod, Call) :- ( atom(Mod) -> true ; '$do_error'(type_error(atom,Mod),Call) ). '$lf_default_opts'(I, LastOpt, _TOpts) :- I > LastOpt, !. '$lf_default_opts'(I, LastOpt, TOpts) :- I1 is I+1, arg(I, TOpts, A), ( nonvar(A) -> true ; '$lf_option'(_Name, I, A) ), '$lf_default_opts'(I1, LastOpt, TOpts). '$check_use_module'(use_module(_), use_module(_)) :- !. '$check_use_module'(use_module(_,_), use_module(_)) :- !. '$check_use_module'(use_module(M,_,_), use_module(M)) :- !. '$check_use_module'(_, load_files) :- !. '$lf'(V,_,Call, _ ) :- var(V), !, '$do_error'(instantiation_error,Call). '$lf'([], _, _, _) :- !. '$lf'(M:X, _, Call, TOpts) :- !, ( atom(M) -> '$lf'(X, M, Call, TOpts) ; '$do_error'(type_error(atom,M),Call) ). '$lf'([F|Fs], Mod, Call, TOpts) :- !, % clean up after each consult ( '$lf'(F,Mod,Call, TOpts), fail ; '$lf'(Fs, Mod, Call, TOpts), fail; true ). '$lf'(user, Mod, _, TOpts) :- !, b_setval('$source_file', user_input), '$do_lf'(Mod, user_input, user_input, user_input, TOpts). '$lf'(user_input, Mod, _, TOpts) :- !, b_setval('$source_file', user_input), '$do_lf'(Mod, user_input, user_input, user_input, TOpts). '$lf'(File, Mod, Call, TOpts) :- '$lf_opt'(stream, TOpts, Stream), b_setval('$source_file', File), ( var(Stream) -> /* need_to_open_file */ '$full_filename'(File, Y, Call), open(Y, read, Stream) ; stream_property(Stream, file_name(Y)) ), !, % start_low_level_trace, ( file_size(Stream, Pos) -> true ; Pos = 0), '$set_lf_opt'('$source_pos', TOpts, Pos), '$lf_opt'(reexport, TOpts, Reexport), '$lf_opt'(if, TOpts, If), ( var(If) -> If = true ; true ), '$lf_opt'(imports, TOpts, Imports), '$start_lf'(If, Mod, Stream, TOpts, File, Y, Reexport, Imports), % stop_low_level_trace, close(Stream). '$lf'(X, _, Call, _) :- '$do_error'(permission_error(input,stream,X),Call). '$start_lf'(not_loaded, Mod, _Stream, TOpts, UserFile, File, Reexport,Imports) :- '$file_loaded'(File, Mod, Imports, TOpts), !, '$lf_opt'('$options', TOpts, Opts), '$lf_opt'('$location', TOpts, ParentF:Line), '$loaded'(File, UserFile, Mod, ParentF, Line, not_loaded, _, _Dir, Opts), '$reexport'( TOpts, ParentF, Reexport, Imports, File ). '$start_lf'(changed, Mod, _Stream, TOpts, UserFile, File, Reexport, Imports) :- '$file_unchanged'(File, Mod, Imports, TOpts), !, '$lf_opt'('$options', TOpts, Opts), '$lf_opt'('$location', TOpts, ParentF:Line), '$loaded'(File, UserFile, Mod, ParentF, Line, changed, _, _Dir, Opts), '$reexport'( TOpts, ParentF, Reexport, Imports, File ). '$start_lf'(_, Mod, PlStream, TOpts, _UserFile, File, Reexport, ImportList) :- % check if there is a qly file % start_low_level_trace, '$absolute_file_name'(File,[access(read),file_type(qly),file_errors(fail),solutions(first),expand(true)],F,qload_file(File)), open( F, read, Stream , [type(binary)] ), '$q_header'( Stream, Type ), ( Type == file -> H0 is heapused, '$cputime'(T0,_), time_file64(F, T0F), stream_property(PlStream, file_name(FilePl)), time_file64(FilePl, T0Fl), T0F >= T0Fl, !, file_directory_name(F, Dir), working_directory(OldD, Dir), '$msg_level'( TOpts, Verbosity), '$qload_file'(Stream, Mod, F, FilePl, File, ImportList, TOpts), close( Stream ), H is heapused-H0, '$cputime'(TF,_), T is TF-T0, '$current_module'(M, Mod), working_directory( _, OldD), '$lf_opt'('$location', TOpts, ParentF:_Line), '$reexport'( TOpts, ParentF, Reexport, ImportList, File ), '$early_print'(Verbosity, loaded( loaded, F, M, T, H)), % stop_low_level_trace, '$exec_initialisation_goals' ; close( Stream), fail ). '$start_lf'(_, Mod, Stream, TOpts, UserFile, File, _Reexport, _Imports) :- '$do_lf'(Mod, Stream, UserFile, File, TOpts). /** @pred ensure_loaded(+ _F_) is iso When the files specified by _F_ are module files, ensure_loaded/1 loads them if they have note been previously loaded, otherwise advertises the user about the existing name clashes and prompts about importing or not those predicates. Predicates which are not public remain invisible. When the files are not module files, ensure_loaded/1 loads them if they have not been loaded before, and does nothing otherwise. _F_ must be a list containing the names of the files to load. */ ensure_loaded(Fs) :- '$load_files'(Fs, [if(not_loaded)],ensure_loaded(Fs)). compile(Fs) :- '$load_files'(Fs, [], compile(Fs)). /** @pred [ _F_ ] @pred consult(+ _F_) Adds the clauses written in file _F_ or in the list of files _F_ to the program. In YAP consult/1 does not remove previous clauses for the procedures defined in other files than _F_, but since YAP-6.4.3 it will redefine all procedures defined in _F_. All code in YAP is compiled, and the compileer generates static procedures by default. In case you need to manipulate the original code, the expanded version of the original source code is available by calling source/0 or by enabling the source flag. */ % consult(Fs) :- % '$has_yap_or', % '$do_error'(context_error(consult(Fs),clause),query). consult(V) :- var(V), !, '$do_error'(instantiation_error,consult(V)). consult(M0:Fs) :- !, '$consult'(Fs, M0). consult(Fs) :- '$current_module'(M0), '$consult'(Fs, M0). '$consult'(Fs,Module) :- current_prolog_flag(language_mode, iso), % SICStus Prolog compatibility !, '$load_files'(Module:Fs,[],consult(Fs)). '$consult'(Fs, Module) :- '$load_files'(Module:Fs,[consult(consult)],consult(Fs)). /** @pred [ - _F_ ] @pred reconsult(+ _F_ ) @pred compile(+ _F_ ) Updates the program by replacing the previous definitions for the predicates defined in _F_. It differs from consult/1 in that it only multifile/1 predicates are not reset in a reconsult. Instead, consult/1 sees all predicates as multifile. YAP also offers no difference between consult/1 and compile/1. The two are implemented by the same exact code. Example: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ?- [file1, -file2, -file3, file4]. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ will consult `file1` `file4` and reconsult `file2` and `file3`. That is, it could be written as: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ?- consult(file1), reconsult( [file2, file3], consult( [file4] ). ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ reconsult(Fs) :- '$load_files'(Fs, [], reconsult(Fs)). /* exo_files(+ _Files_) Load compactly a database of facts with equal structure, see @cite x. Useful when wanting to read in a very compact way database tables, it saves space by storing data, not a compiled program. The idea was introduced in @cite y, but never implemented because often indexing just takes more room. It was redefined recebtly by exploiting different forms of indexing, as shown in @cite x. @note implementation The function Yap_ExoLookup() is the mai interface betwwen the WAM and exo components. The algorithms are straightforward, that is, mostly hash-tables but have close to linear performance.. */ exo_files(Fs) :- '$load_files'(Fs, [consult(exo), if(not_loaded)], exo_files(Fs)). /** @pred load_db(+ _Files_) Load a database of ground facts. All facts must take up the same amount of storage, so that a fact $I$ can be accessed at position _P[I-1]_. This representation thus stores the facts as a huge continuous array, the so-called mega clause. See \cite for a motivation for this technique. YAP implements this optimization by default whenever it loads a large number of facts (see Yap_BuildMegaClause(PredEntry *ap) ) for the details. On the other hand, loading the data-base will cause fragmentation because individual facts facts need extra headers ands tails, and because often new atoms will be stored in the Symbol Table, see LookupAtom(const char *atom). The main advantage of load_db/1 is that it allocates the necessary memory only once. Just doing this may halve total memory usage in large in-memory database-oriented applications. @note Implementation YAP implements load_db/1 as a two-step non-optimised process. First, it counts the nmuber of facts and checks their size. Second, it allocates and fills the memory. The first step of the algorithm is implemented by dbload_get_space(), and the second by dbload_add_facts(). db_files/1 itself is just a call to load_files/2. */ db_files(Fs) :- '$load_files'(Fs, [consult(db), if(not_loaded)], exo_files(Fs)). '$csult'(Fs, M) :- '$extract_minus'(Fs, MFs), !, '$load_files'(M:MFs,[],[M:Fs]). '$csult'(Fs, M) :- '$load_files'(M:Fs,[consult(consult)],[M:Fs]). '$extract_minus'([], []). '$extract_minus'([-F|Fs], [F|MFs]) :- '$extract_minus'(Fs, MFs). '$do_lf'(ContextModule, Stream, UserFile, File, TOpts) :- stream_property(OldStream, alias(loop_stream) ), '$lf_opt'(encoding, TOpts, Encoding), set_stream( Stream, [alias(loop_stream), encoding(Encoding)] ), '$lf_opt'('$context_module', TOpts, ContextModule), '$lf_opt'(reexport, TOpts, Reexport), '$msg_level'( TOpts, Verbosity), '$lf_opt'(qcompile, TOpts, QCompiling), '$nb_getval'('$qcompile', ContextQCompiling, ContextQCompiling = never), nb_setval('$qcompile', QCompiling), % format( 'I=~w~n', [Verbosity=UserFile] ), % export to process b_setval('$lf_status', TOpts), '$reset_if'(OldIfLevel), % take care with [a:f], a is the ContextModule '$current_module'(SourceModule, ContextModule), '$lf_opt'(consult, TOpts, Reconsult0), '$lf_opt'('$options', TOpts, Opts), '$lf_opt'('$location', TOpts, ParentF:Line), '$loaded'(File, UserFile, SourceModule, ParentF, Line, Reconsult0, Reconsult, Dir, Opts), working_directory(OldD, Dir), H0 is heapused, '$cputime'(T0,_), current_prolog_flag(generate_debug_info, GenerateDebug), '$lf_opt'(compilation_mode, TOpts, CompMode), '$comp_mode'(OldCompMode, CompMode), recorda('$initialisation','$',_), ( Reconsult \== consult -> '$start_reconsulting'(File), '$start_consult'(Reconsult,File,LC), '$remove_multifile_clauses'(File), StartMsg = reconsulting, EndMsg = reconsulted ; '$start_consult'(Reconsult,File,LC), ( File \= user_input, File \= [] -> '$remove_multifile_clauses'(File) ; true ), StartMsg = consulting, EndMsg = consulted ), '$early_print'(Verbosity, loading(StartMsg, UserFile)), '$lf_opt'(skip_unix_header , TOpts, SkipUnixHeader), ( SkipUnixHeader == true -> '$skip_unix_header'(Stream) ; true ), '$loop'(Stream,Reconsult), '$lf_opt'(imports, TOpts, Imports), '$import_to_current_module'(File, ContextModule, Imports, _, TOpts), '$current_module'(Mod, SourceModule), H is heapused-H0, '$cputime'(TF,_), T is TF-T0, '$early_print'(Verbosity, loaded(EndMsg, File, Mod, T, H)), '$end_consult', '$q_do_save_file'(File, UserFile, TOpts ), ( Reconsult = reconsult -> '$clear_reconsulting' ; true ), set_stream( OldStream, alias(loop_stream) ), set_prolog_flag(generate_debug_info, GenerateDebug), '$comp_mode'(_CompMode, OldCompMode), working_directory(_,OldD), % surely, we were in run mode or we would not have included the file! nb_setval('$if_skip_mode',run), % back to include mode! nb_setval('$if_level',OldIfLevel), '$lf_opt'('$use_module', TOpts, UseModule), '$bind_module'(Mod, UseModule), '$reexport'( TOpts, ParentF, Reexport, Imports, File ), nb_setval('$qcompile', ContextQCompiling), ( LC == 0 -> prompt(_,' |: ') ; true), '$exec_initialisation_goals', % format( 'O=~w~n', [Mod=UserFile] ), !. '$q_do_save_file'(File, UserF, TOpts ) :- '$lf_opt'(qcompile, TOpts, QComp), '$lf_opt'('$source_pos', TOpts, Pos), ( QComp == auto ; QComp == large, Pos > 100*1024), '$absolute_file_name'(UserF,[file_type(qly),solutions(first),expand(true)],F,load_files(File)), !, '$qsave_file_'( File, UserF, F ). '$q_do_save_file'(_File, _, _TOpts ). % are we in autoload and autoload_flag is false? '$msg_level'( TOpts, Verbosity) :- '$lf_opt'(autoload, TOpts, AutoLoad), AutoLoad == true, current_prolog_flag(verbose_autoload, false), !, Verbosity = silent. '$msg_level'( _TOpts, Verbosity) :- current_prolog_flag(verbose_load, false), !, Verbosity = silent. '$msg_level'( _TOpts, Verbosity) :- current_prolog_flag(verbose, silent), !, Verbosity = silent. '$msg_level'( TOpts, Verbosity) :- '$lf_opt'(silent, TOpts, Silent), Silent == true, !, Verbosity = silent. '$msg_level'( _TOpts, informational). '$reset_if'(OldIfLevel) :- '$nb_getval'('$if_level', OldIfLevel, fail), !, nb_setval('$if_level',0). '$reset_if'(0) :- nb_setval('$if_level',0). '$get_if'(Level0) :- '$nb_getval'('$if_level', Level, fail), !, Level0 = Level. '$get_if'(0). '$bind_module'(_, load_files). '$bind_module'(Mod, use_module(Mod)). '$import_to_current_module'(File, ContextModule, _Imports, _RemainingImports, _TOpts) :- \+ recorded('$module','$module'(File, _Module, _, _ModExports, _),_), % enable loading C-predicates from a different file recorded( '$load_foreign_done', [File, M0], _), '$import_foreign'(File, M0, ContextModule ), fail. '$import_to_current_module'(File, ContextModule, Imports, RemainingImports, TOpts) :- recorded('$module','$module'(File, Module, _Source, ModExports, _),_), Module \= ContextModule, !, '$lf_opt'('$call', TOpts, Goal), '$convert_for_export'(Imports, ModExports, Module, ContextModule, TranslationTab, RemainingImports, Goal), '$add_to_imports'(TranslationTab, Module, ContextModule). '$import_to_current_module'(_, _, _, _, _). '$start_reconsulting'(F) :- recorda('$reconsulted','$',_), recorda('$reconsulting',F,_). '$exec_initialisation_goals' :- nb_setval('$initialization_goals',on), fail. '$exec_initialisation_goals' :- recorded('$blocking_code',_,R), erase(R), fail. % system goals must be performed first '$exec_initialisation_goals' :- recorded('$system_initialisation',G,R), erase(R), G \= '$', once( call(G) ), fail. '$exec_initialisation_goals' :- '$show_consult_level'(Level), '$current_module'(M), recorded('$initialisation',do(Level,_),_), findall(G, '$fetch_init_goal'(Level, G), LGs), lists:member(G,LGs), % run initialization under user control (so allow debugging this stuff). ( '$system_catch'('$user_call'(G,M), M, Error, user:'$LoopError'(Error, top)) -> fail ). '$exec_initialisation_goals' :- nb_setval('$initialization_goals',off). '$fetch_init_goal'(Level, G) :- recorded('$initialisation',do(Level,G),R), erase(R), G\='$'. /** @pred include(+ _F_) is directive The `include` directive adds the text files or sequence of text files specified by _F_ into the files being currently consulted. It may be used as an replacement to consult/1 by allowing the programmer to include a data-base split into several files. */ '$include'(V, _) :- var(V), !, '$do_error'(instantiation_error,include(V)). '$include'([], _) :- !. '$include'([F|Fs], Status) :- !, '$include'(F, Status), '$include'(Fs, Status). '$include'(X, Status) :- b_getval('$lf_status', TOpts), '$msg_level'( TOpts, Verbosity), '$full_filename'(X, Y , ( :- include(X)) ), '$including'(Old, Y), '$lf_opt'(stream, TOpts, OldStream), '$current_module'(Mod), ( open(Y, read, Stream) -> true ; '$do_error'(permission_error(input,stream,Y),include(X)) ), file_directory_name(Y, Dir), H0 is heapused, '$cputime'(T0,_), working_directory(Dir0, Dir), '$lf_opt'(encoding, TOpts, Encoding), set_stream(Stream, [encoding(Encoding),alias(loop_stream)] ), '$loaded'(Y, X, Mod, _OldY, _L, include, _, Dir, []), ( '$nb_getval'('$included_file', OY, fail ) -> true ; OY = [] ), nb_setval('$included_file', Y), '$early_print'(Verbosity, loading(including, Y)), '$loop'(Stream,Status), set_stream(OldStream, alias(loop_stream) ), close(Stream), H is heapused-H0, '$cputime'(TF,_), T is TF-T0, '$early_print'(Verbosity, loaded(included, Y, Mod, T, H)), working_directory(_Dir, Dir0), '$including'(Y, Old), nb_setval('$included_file',OY). % % reconsult at startup... % '$do_startup_reconsult'(_X) :- '$init_win_graphics', fail. '$do_startup_reconsult'(X) :- ( current_prolog_flag(halt_after_consult, false) -> '$system_catch'(load_files(X, [silent(true)]), Module, Error, '$Error'(Error)) ; set_prolog_flag(verbose, silent), '$system_catch'(load_files(X, [silent(true),skip_unix_header(true)]),Module,_,fail) ; true ), !, ( current_prolog_flag(halt_after_consult, false) -> true ; halt). '$do_startup_reconsult'(_). '$skip_unix_header'(Stream) :- peek_code(Stream, 0'#), !, % 35 is ASCII for '# skip(Stream, 10), '$skip_unix_header'(Stream). '$skip_unix_header'(_). source_file(FileName) :- recorded('$source_file','$source_file'(FileName, _, _),_). source_file(Mod:Pred, FileName) :- current_module(Mod), Mod \= prolog, '$current_predicate'(_,Mod,Pred,all), '$owned_by'(Pred, Mod, FileName). '$owned_by'(T, Mod, FileName) :- '$is_multifile'(T, Mod), functor(T, Name, Arity), setof(FileName, Ref^recorded('$multifile_defs','$defined'(FileName,Name,Arity,Mod), Ref), L), lists:member(FileName, L). '$owned_by'(T, Mod, FileName) :- '$owner_file'(T, Mod, FileName). /** @pred prolog_load_context(? _Key_, ? _Value_) Obtain information on what is going on in the compilation process. The following keys are available: + directory (prolog_load_context/2 option) Full name for the directory where YAP is currently consulting the file. + file (prolog_load_context/2 option) Full name for the file currently being consulted. Notice that included filed are ignored. + module (prolog_load_context/2 option) Current source module. + `source` (prolog_load_context/2 option) Full name for the file currently being read in, which may be consulted, reconsulted, or included. + `stream` (prolog_load_context/2 option) Stream currently being read in. + `term_position` (prolog_load_context/2 option) Stream position at the stream currently being read in. For SWI compatibility, it is a term of the form '$stream_position'(0,Line,0,0). + `source_location(? _File Name_, ? _Line_)` (prolog_load_context/2 option) SWI-compatible predicate. If the last term has been read from a physical file (i.e., not from the file user or a string), unify File with an absolute path to the file and Line with the line-number in the file. Please use prolog_load_context/2. + `source_file(? _File_)` (prolog_load_context/2 option) SWI-compatible predicate. True if _File_ is a loaded Prolog source file. + `source_file(? _ModuleAndPred_ ,? _File_)` (prolog_load_context/2 option) SWI-compatible predicate. True if the predicate specified by _ModuleAndPred_ was loaded from file _File_, where _File_ is an absolute path name (see `absolute_file_name/2`). */ %% @} %% @{ /** @addtogroup YAPLibraries Library Predicates Library files reside in the library_directory path (set by the `LIBDIR` variable in the Makefile for YAP). Currently, most files in the library are from the Edinburgh Prolog library. */ prolog_load_context(directory, DirName) :- ( source_location(F, _) -> file_directory_name(F, DirName) ; working_directory( DirName, DirName ) ). prolog_load_context(file, FileName) :- ( source_location(FileName, _) -> true ; FileName = user_input ). prolog_load_context(module, X) :- '$nb_getval'('$consulting_file', _, fail), '$current_module'(X). prolog_load_context(source, F0) :- ( source_location(F0, _) /*, '$input_context'(Context), '$top_file'(Context, F0, F) */ -> true ; F0 = user_input ). prolog_load_context(stream, Stream) :- stream_property(Stream, alias(loop_stream) ). % if the file exports a module, then we can % be imported from any module. '$file_loaded'(F0, M, Imports, TOpts) :- %format( 'L=~w~n', [(F0)] ), ( atom_concat(Prefix, '.qly', F0 ), '$absolute_file_name'(Prefix,[access(read),file_type(prolog),file_errors(fail),solutions(first),expand(true)],F,load_files(Prefix)) ; F0 = F ), '$ensure_file_loaded'(F, M), !, '$import_to_current_module'(F, M, Imports, _, TOpts). '$ensure_file_loaded'(F, M) :- % loaded from the same module, but does not define a module. recorded('$source_file','$source_file'(F, _Age, NM), _R), % make sure: it either defines a new module or it was loaded in the same context ( M == NM -> true ; recorded('$module','$module'(F,NM,_Source,_P,_),_) ), !. % if the file exports a module, then we can % be imported from any module. '$file_unchanged'(F, M, Imports, TOpts) :- '$ensure_file_unchanged'(F, M), % format( 'IU=~w~n', [(F1:Imports->M)] ), '$import_to_current_module'(F, M, Imports, _, TOpts). % module can be reexported. '$ensure_file_unchanged'(F, M) :- % loaded from the same module, but does not define a module. recorded('$source_file','$source_file'(F, Age, NM), R), % make sure: it either defines a new module or it was loaded in the same context '$file_is_unchanged'(F, R, Age), !, % ( F = '/usr/local/share/Yap/rbtrees.yap' ->start_low_level_trace ; true), recorded('$module','$module'(F,NM,_ASource,_P,_),_), ( M == NM -> true ; recorded('$module','$module'(F,NM,_Source,_P,_),_) ), !. '$file_is_unchanged'(F, R, Age) :- time_file64(F,CurrentAge), ( (Age == CurrentAge ; Age = -1) -> true; erase(R), fail). % inform the file has been loaded and is now available. '$loaded'(F, UserFile, M, OldF, Line, Reconsult0, Reconsult, Dir, Opts) :- ( F == user_input -> working_directory(Dir,Dir) ; file_directory_name(F, Dir) ), nb_setval('$consulting_file', F ), ( % if we are reconsulting, always start from scratch Reconsult0 \== consult, Reconsult0 \== not_loaded, Reconsult0 \== changed, recorded('$source_file','$source_file'(F, _,_),R), erase(R), fail ; var(Reconsult0) -> Reconsult = consult ; Reconsult = Reconsult0 ), ( Reconsult \== consult, recorded('$lf_loaded','$lf_loaded'(F, _, _, _, _, _, _),R), erase(R), fail ; var(Reconsult) -> Reconsult = consult ; Reconsult = Reconsult0 ), ( F == user_input -> Age = 0 ; time_file64(F, Age) ), % modules are logically loaded only once ( recorded('$module','$module'(F,_DonorM,_SourceF, _AllExports, _Line),_) -> true ; recordaifnot('$source_file','$source_file'( F, Age, M), _) -> true ; true ), recorda('$lf_loaded','$lf_loaded'( F, M, Reconsult, UserFile, OldF, Line, Opts), _). /** @pred make is det SWI-Prolog originally included this built-in as a Prolog version of the Unix `make` utility program. In this case the idea is to reconsult all source files that have been changed since they were originally compiled into Prolog. YAP has a limited implementation of make/0 that just goes through every loaded file and verifies whether reloading is needed. */ make :- recorded('$lf_loaded','$lf_loaded'(F1,_M,reconsult,_,_,_,_),_), '$load_files'(F1, [if(changed)],make), fail. make. make_library_index(_Directory). '$fetch_stream_alias'(OldStream,Alias) :- stream_property(OldStream, alias(Alias)), !. '$require'(_Ps, _M). '$store_clause'('$source_location'(File, _Line):Clause, File) :- assert_static(Clause). exists_source(File) :- '$full_filename'(File, _AbsFile, exists_source(File)). % reload_file(File) :- % ' $source_base_name'(File, Compile), % findall(M-Opts, % source_file_property(File, load_context(M, _, Opts)), % Modules), % ( Modules = [First-OptsFirst|Rest] % -> Extra = [ silent(false), % register(false) % ], % merge_options([if(true)|Extra], OptsFirst, OFirst), % % debug(make, 'Make: First load ~q', [load_files(First:Compile, OFirst)]), % load_files(First:Compile, OFirst), % forall(member(Context-Opts, Rest), % ( merge_options([if(not_loaded)|Extra], Opts, O), % % debug(make, 'Make: re-import: ~q', % % [load_files(Context:Compile, O)]), % load_files(Context:Compile, O) % )) % ; load_files(user:Compile) % ). % ' $source_base_name'(File, Compile) :- % file_name_extension(Compile, Ext, File), % user:prolog_file_type(Ext, prolog), !. % ' $source_base_name'(File, File). source_file_property( File0, Prop) :- ( nonvar(File0) -> absolute_file_name(File0,File) ; File = File0 ), '$source_file_property'( File, Prop). '$source_file_property'( OldF, includes(F, Age)) :- recorded('$lf_loaded','$lf_loaded'( F, _M, include, _File, OldF, _Line, _), _), recorded('$source_file','$source_file'( F, Age, _), _). '$source_file_property'( F, included_in(OldF, Line)) :- recorded('$lf_loaded','$lf_loaded'( F, _M, include, _File, OldF, Line, _), _). '$source_file_property'( F, load_context(OldF, Line, Options)) :- recorded('$lf_loaded','$lf_loaded'( F, _M, V, _File, OldF, Line, Options), _), V \== include. '$source_file_property'( F, modified(Age)) :- recorded('$source_file','$source_file'( F, Age, _), _). '$source_file_property'( F, module(M)) :- recorded('$module','$module'(F,M,_,_,_),_). unload_file( F0 ) :- absolute_file_name( F0, F1, [expand(true),file_type(prolog)] ), '$unload_file'( F1, F0 ). % eliminate multi-files; % get rid of file-only predicataes. '$unload_file'( FileName, _F0 ) :- current_module(Mod), '$current_predicate'(_A,Mod,P,all), '$owner_file'(P,Mod,FileName), \+ '$is_multifile'(P,Mod), functor( P, Na, Ar), abolish(Mod:Na/Ar), fail. %next multi-file. '$unload_file'( FileName, _F0 ) :- recorded('$source_file','$source_file'( FileName, _Age, _), R), erase(R), fail. '$unload_file'( FileName, _F0 ) :- recorded('$mf','$mf_clause'(FileName,_Name,_Arity,_Module,ClauseRef), R), erase(R), erase(ClauseRef), fail. '$unload_file'( FileName, _F0 ) :- recorded('$multifile_dynamic'(_,_,_), '$mf'(_Na,_A,_M,FileName,R), R1), erase(R1), erase(R), fail. '$unload_file'( FileName, _F0 ) :- recorded('$multifile_defs','$defined'(FileName,_Name,_Arity,_Mod), R), erase(R), fail. '$unload_file'( FileName, _F0 ) :- recorded('$module','$module'( FileName, Mod, _SourceF, _, _), R), erase( R ), unload_module(Mod), fail. '$unload_file'( FileName, _F0 ) :- recorded('$directive','$d'( FileName, _M:_G, _Mode, _VL, _Pos ), R), erase(R), fail. %% @} /** @{ @addtogroup YAPModules **/ % % stub to prevent modules defined within the prolog module. % module(Mod, Decls) :- '$current_module'(prolog, Mod), !, '$export_preds'(Decls). '$export_preds'([]). '$export_preds'([N/A|Decls]) :- functor(S, N, A), '$sys_export'(S, prolog), '$export_preds'(Decls). % prevent modules within the kernel module... /** @pred use_module(? _M_,? _F_,+ _L_) is directive SICStus compatible way of using a module If module _M_ is instantiated, import the procedures in _L_ to the current module. Otherwise, operate as use_module/2, and load the files specified by _F_, importing the predicates specified in the list _L_. */ use_module(M,F,Is) :- '$use_module'(M,F,Is). '$use_module'(M,F,Is) :- var(Is), !, '$use_module'(M,F,all). '$use_module'(M,F,Is) :- nonvar(F), !, strip_module(F, M0, F0), '$load_files'(M0:F0, [if(not_loaded),must_be_module(true),imports(Is)], use_module(M,F,Is)), ( var(M) -> true ; absolute_file_name( F0, F1, [expand(true),file_type(prolog)] ), recorded('$module','$module'(F1,M,_,_,_),_) ). '$use_module'(M,F,Is) :- nonvar(M), !, strip_module(F, M0, F0), ( recorded('$module','$module'(F1,M,_,_,_),_) -> '$load_files'(M0:F1, [if(not_loaded),must_be_module(true),imports(Is)], use_module(M,F,Is)) ), (var(F0) -> F0 = F1 ; absolute_file_name( F1, F2, [expand(true),file_type(prolog)] ) -> F2 = F0 ). '$use_module'(M,F,Is) :- '$do_error'(instantiation_error,use_module(M,F,Is)). /** @pred reexport(+F) is directive @pred reexport(+F, +Decls ) is directive allow a module to use and export predicates from another module Export all predicates defined in list _F_ as if they were defined in the current module. Export predicates defined in file _F_ according to _Decls_. The declarations should be of the form: