This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/pl/consult.yap
Vítor Santos Costa 15404b3835 small
- do not call goal expansion on meta-calls (that is done by undef).
- docs updates
- fix init code
2015-12-15 09:28:43 +00:00

1631 lines
50 KiB
Prolog

/*************************************************************************
* *
* 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 *
* *
*************************************************************************/
/**
* @file consult.yap
* @author VITOR SANTOS COSTA <vsc@VITORs-MBP.lan>
* @date Wed Nov 18 14:01:10 2015
*
* @brief loading programs into 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 `\<name\>/\<arity\>`. 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'(initialization, 31, Ref) :-
nb:nb_queue(Ref).
'$lf_option'(last_opt, 31).
'$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) -> true ; '$do_error'(existence_error(source_sink,File),Call) ),
( open(Y, read, Stream) -> true ; '$do_error'(permission_error(input,stream,Y),Call) )
;
stream_property(Stream, file_name(Y))
), !,
( 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),
close(Stream).
'$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
->
!
;
close(Stream),
fail
),
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)),
working_directory( _, OldD),
'$exec_initialization_goals',
'$current_module'(_M, Mod).
'$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) :-
prompt1(': '), prompt(_,' '),
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),
( 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_initialization_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_le1vel',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_initialization_goals' :-
recorded('$blocking_code',_,R),
erase(R),
fail.
% system goals must be performed first
'$exec_initialization_goals' :-
recorded('$system_initialization',G,R),
erase(R),
G \= '$',
strip_module(user:G, M0, G0),
( catch(M0:G0, Error, user:'$LoopError'(Error, top))
->
true
;
format(user_error,':- ~w failed.~n',[G])
),
fail.
'$exec_initialization_goals' :-
'$current_module'(M),
'$nb_getval'('$lf_status', TOpts, fail),
'$lf_opt'( initialization, TOpts, Ref),
nb:nb_queue_close(Ref, Answers, []),
lists:member(G, Answers),
strip_module( M:G, M0, G0),
(
catch(M0:G0, Error, user:'$LoopError'(Error, top))
->
true
; format(user_error,':- ~w:~w failed.~n',[M,G])
),
stop_low_level_trace,
fail.
'$exec_initialization_goals'.
/**
@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) :-
catch(load_files(user:X, [silent(true)]), Error, '$LoopError'(Error)),
!,
( 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_clause'(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:
<ul>
A list of predicate declarations to be exported. Each declaration
may be a predicate indicator or of the form `` _PI_ `as`
_NewName_'', meaning that the predicate with indicator _PI_ is
to be exported under name _NewName_.
`except`( _List_)
In this case, all predicates not in _List_ are exported. Moreover,
if ` _PI_ `as` _NewName_` is found, the predicate with
indicator _PI_ is to be exported under name _NewName_ as
before.
Re-exporting predicates must be used with some care. Please, take into
account the following observations:
<ul>
<li> The `reexport` declarations must be the first declarations to
follow the `module` declaration. </li>
<li> It is possible to use both `reexport` and `use_module`, but all
predicates reexported are automatically available for use in the
current module. </li>
<li> In order to obtain efficient execution, YAP compiles
dependencies between re-exported predicates. In practice, this means
that changing a `reexport` declaration and then *just* recompiling
the file may result in incorrect execution. </li>
</ul>
*/
'$reexport'( TOpts, File, Reexport, Imports, OldF ) :-
( Reexport == false -> true ;
'$lf_opt'('$parent_topts', TOpts, OldTOpts),
'$lf_opt'('$context_module', OldTOpts, OldContextModule),
'$import_to_current_module'(File, OldContextModule, Imports, _, TOpts),
'$extend_exports'(File, Imports, OldF )
).
/**
@}
**/
%% @{
/** @defgroup YAPCompilerSettings Directing and Configuring the Compiler
@ingroup YAPProgramming
The YAP system also includes a number of primitives designed to set
compiler parameters and to track the state of the compiler. One
important example is the number of directivees that allow setting up
properties of predicates. It is also possible to enable or disable
waraanings about possible issues with the code in the program, sich
as the occurrence .
This section presents a set of built-ins predicates designed to set the
environment for the compiler.
*/
/** @pred prolog_to_os_filename(+ _PrologPath_,- _OsPath_)
This is an SWI-Prolog built-in. Converts between the internal Prolog
pathname conventions and the operating-system pathname conventions. The
internal conventions are Unix and this predicates is equivalent to =/2
(unify) on Unix systems. On DOS systems it will change the
directory-separator, limit the filename length map dots, except for the
last one, onto underscores.
*/
% add_multifile_predicate when we start consult
'$add_multifile'(Name,Arity,Module) :-
source_location(File,_),
'$add_multifile'(File,Name,Arity,Module).
'$add_multifile'(File,Name,Arity,Module) :-
recorded('$multifile_defs','$defined'(File,Name,Arity,Module), _), !.
% '$early_print'(warning,declaration((multifile Module:Name/Arity),ignored)).
'$add_multifile'(File,Name,Arity,Module) :-
recordz('$multifile_defs','$defined'(File,Name,Arity,Module),_), !,
fail.
'$add_multifile'(File,Name,Arity,Module) :-
recorded('$mf','$mf_clause'(File,Name,Arity,Module,Ref),R),
erase(R),
'$erase_clause'(Ref,Module),
fail.
'$add_multifile'(_,_,_,_).
% retract old multifile clauses for current file.
'$remove_multifile_clauses'(FileName) :-
recorded('$multifile_defs','$defined'(FileName,_,_,_),R1),
erase(R1),
fail.
'$remove_multifile_clauses'(FileName) :-
recorded('$mf','$mf_clause'(FileName,_,_,Module,Ref),R),
'$erase_clause'(Ref, Module),
erase(R),
fail.
'$remove_multifile_clauses'(_).
/** @pred initialization(+ _G_) is iso
The compiler will execute goals _G_ after consulting the current
file.
Notice that the goal will execute in the calling context, not within the file context,
In other words, the source module and execution directory will be the ones of the parent
environment. Use initialization/2 for more flexible behavior.
*/
'$initialization'(G) :-
'$initialization'( G, after_load ).
'$initialization_queue'(G) :-
b_getval('$lf_status', TOpts),
'$lf_opt'( initialization, TOpts, Ref),
nb:nb_queue_enqueue(Ref, G),
fail.
'$initialization_queue'(_).
/** @pred initialization(+ _Goal_,+ _When_)
Similar to initialization/1, but allows for specifying when
_Goal_ is executed while loading the program-text:
+ now
Execute _Goal_ immediately.
+ after_load
Execute _Goal_ after loading program-text. This is the same as initialization/1.
+ restore
Do not execute _Goal_ while loading the program, but only when restoring a state (not implemented yet).
*/
initialization(G0,OPT) :-
expand_goal(G0, G),
catch('$initialization'(G, OPT), Error, '$LoopError'( Error ) ),
fail.
initialization(_G,_OPT).
'$initialization'(G,OPT) :-
error:must_be_of_type(callable, G, initialization(G,OPT)),
error:must_be_of_type(oneof([after_load, now, restore]), OPT, initialization(G0,OPT)),
(
OPT == now
->
( call(G) -> true ; format(user_error,':- ~w:~w failed.~n',[G]) )
;
OPT == after_load
->
'$initialization_queue'(G)
;
OPT == restore
->
recordz('$call_at_restore', G, _ )
).
/**
@}
*/
%% @{
/**
@defgroup Conditional_Compilation Conditional Compilation
@ingroup YAPCompilerSettings
Conditional compilation builds on the same principle as
term_expansion/2, goal_expansion/2 and the expansion of
grammar rules to compile sections of the source-code
conditionally. One of the reasons for introducing conditional
compilation is to simplify writing portable code.
Note that these directives can only be appear as separate terms in the
input. Typical usage scenarios include:
Load different libraries on different dialects
Define a predicate if it is missing as a system predicate
Realise totally different implementations for a particular
part of the code due to different capabilities.
Realise different configuration options for your software.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:- if(test1).
section_1.
:- elif(test2).
section_2.
:- elif(test3).
section_3.
:- else.
section_else.
:- endif.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/** @pred if( : _Goal_)
Compile subsequent code only if _Goal_ succeeds. For enhanced
portability, _Goal_ is processed by `expand_goal/2` before execution.
If an error occurs, the error is printed and processing proceeds as if
_Goal_ has failed.
*/
%
% This is complicated because of embedded ifs.
%
'$if'(_,top) :- !, fail.
'$if'(_Goal,_) :-
'$get_if'(Level0),
Level is Level0 + 1,
nb_setval('$if_level',Level),
( '$nb_getval'('$endif', OldEndif, fail) -> true ; OldEndif=top),
( '$nb_getval'('$if_skip_mode', Mode, fail) -> true ; Mode = run ),
nb_setval('$endif',elif(Level,OldEndif,Mode)),
fail.
% we are in skip mode, ignore....
'$if'(_Goal,_) :-
'$nb_getval'('$endif',elif(Level, OldEndif, skip), fail), !,
nb_setval('$endif',endif(Level, OldEndif, skip)).
% we are in non skip mode, check....
'$if'(Goal,_) :-
('$if_call'(Goal)
->
% we will execute this branch, and later enter skip
'$nb_getval'('$endif', elif(Level,OldEndif,Mode), fail),
nb_setval('$endif',endif(Level,OldEndif,Mode))
;
% we are now in skip, but can start an elif.
nb_setval('$if_skip_mode',skip)
).
/**
@pred else
Start `else' branch.
*/
'$else'(top) :- !, fail.
'$else'(_) :-
'$get_if'(0), !,
'$do_error'(context_error(no_if),(:- else)).
% we have done an if, so just skip
'$else'(_) :-
nb_getval('$endif',endif(_Level,_,_)), !,
nb_setval('$if_skip_mode',skip).
% we can try the elif
'$else'(_) :-
'$get_if'(Level),
nb_getval('$endif',elif(Level,OldEndif,Mode)),
nb_setval('$endif',endif(Level,OldEndif,Mode)),
nb_setval('$if_skip_mode',run).
/** @pred elif(+ _Goal_)
Equivalent to `:- else. :-if(Goal) ... :- endif.` In a sequence
as below, the section below the first matching elif is processed, If
no test succeeds the else branch is processed.
*/
'$elif'(_,top) :- !, fail.
'$elif'(Goal,_) :-
'$get_if'(0),
'$do_error'(context_error(no_if),(:- elif(Goal))).
% we have done an if, so just skip
'$elif'(_,_) :-
nb_getval('$endif',endif(_,_,_)), !,
nb_setval('$if_skip_mode',skip).
% we can try the elif
'$elif'(Goal,_) :-
'$get_if'(Level),
'$nb_getval'('$endif',elif(Level,OldEndif,Mode),fail),
('$if_call'(Goal)
->
% we will not skip, and we will not run any more branches.
nb_setval('$endif',endif(Level,OldEndif,Mode)),
nb_setval('$if_skip_mode',run)
;
% we will (keep) on skipping
nb_setval('$if_skip_mode',skip)
).
'$elif'(_,_).
/** @pred endif
End of conditional compilation.
*/
'$endif'(top) :- !, fail.
'$endif'(_) :-
% unmmatched endif.
'$get_if'(0),
'$do_error'(context_error(no_if),(:- endif)).
'$endif'(_) :-
% back to where you belong.
'$get_if'(Level),
nb_getval('$endif',Endif),
Level0 is Level-1,
nb_setval('$if_level',Level0),
arg(2,Endif,OldEndif),
arg(3,Endif,OldMode),
nb_setval('$endif',OldEndif),
nb_setval('$if_skip_mode',OldMode).
'$if_call'(G) :-
catch('$eval_if'(G), E, ('$early_print'(error, E), fail)).
'$eval_if'(Goal) :-
expand_term(Goal,TrueGoal),
once(TrueGoal).
'$if_directive'((:- if(_))).
'$if_directive'((:- else)).
'$if_directive'((:- elif(_))).
'$if_directive'((:- endif)).
'$comp_mode'( OldCompMode, CompMode) :-
var(CompMode), !,
'$fetch_comp_status'( OldCompMode ).
'$comp_mode'(OldCompMode, assert_all) :-
'$fetch_comp_status'(OldCompMode),
nb_setval('$assert_all',on).
'$comp_mode'(OldCompMode, source) :-
'$fetch_comp_status'(OldCompMode),
set_prolog_flag(source, true).
'$comp_mode'(OldCompMode, compact) :-
'$fetch_comp_status'(OldCompMode),
set_prolog_flag(source, false).
'$fetch_comp_status'(assert_all) :-
'$nb_getval'('$assert_all',on, fail), !.
'$fetch_comp_status'(source) :-
current_prolog_flag(source, true), !.
'$fetch_comp_status'(compact).
consult_depth(LV) :- '$show_consult_level'(LV).
/**
@}
@}
*/