allow conditional compilation

git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@1965 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
This commit is contained in:
vsc 2007-10-21 08:48:06 +00:00
parent 268ad4ab73
commit ff4aa369be
6 changed files with 330 additions and 129 deletions

View File

@ -3492,10 +3492,6 @@ compaction_phase(tr_fr_ptr old_TR, CELL *current_env, yamop *curp, CELL *max)
total_marked += total_oldies; total_marked += total_oldies;
} }
} else { } else {
if (GcCalls==355) {
fprintf(stderr,"Start=%p,%pn %ld, %ld\n",H0,HGEN, total_oldies, total_marked);
}
if (HGEN != H0) { if (HGEN != H0) {
CurrentH0 = H0; CurrentH0 = H0;
H0 = HGEN; H0 = HGEN;

View File

@ -17,6 +17,7 @@
<h2>Yap-5.1.3:</h2> <h2>Yap-5.1.3:</h2>
<ul> <ul>
<li> NEW: support conditional compilation using if/1,elif/1,else/0,endif/0 directives.</li>
<li> FIXED: delay abort until garbage collection or stack shifting is over.</li> <li> FIXED: delay abort until garbage collection or stack shifting is over.</li>
<li> FIXED: grow_trail assumed SREG points to stack top!</li> <li> FIXED: grow_trail assumed SREG points to stack top!</li>
<li> FIXED: latest SWI chr.</li> <li> FIXED: latest SWI chr.</li>

View File

@ -160,6 +160,7 @@ Subnodes of Encoding
Subnodes of Loading Programs Subnodes of Loading Programs
* Compiling:: Program Loading and Updating * Compiling:: Program Loading and Updating
* Setting the Compiler:: Changing the compiler's parameters * Setting the Compiler:: Changing the compiler's parameters
* Conditional Compilation:: Compiling program fragments
* Saving:: Saving and Restoring Programs * Saving:: Saving and Restoring Programs
Subnodes of Modules Subnodes of Modules
@ -1535,6 +1536,7 @@ writing, writing a BOM can be requested using the option
Loading Programs Loading Programs
* Compiling:: Program Loading and Updating * Compiling:: Program Loading and Updating
* Setting the Compiler:: Changing the compiler's parameters * Setting the Compiler:: Changing the compiler's parameters
* Conditional Compilation:: Compiling program fragments
* Saving:: Saving and Restoring Programs * Saving:: Saving and Restoring Programs
@end menu @end menu
@ -1616,7 +1618,7 @@ files specified by @var{F} into the file being currently consulted.
@end table @end table
@node Setting the Compiler, Saving, Compiling, Loading Programs @node Setting the Compiler, Conditional Compilation, Compiling, Loading Programs
@section Changing the Compiler's Behavior @section Changing the Compiler's Behavior
This section presents a set of built-ins predicates designed to set the This section presents a set of built-ins predicates designed to set the
@ -1869,7 +1871,85 @@ Since YAP4.3.0 multifile procedures can be static or dynamic.
@end table @end table
@node Saving, , Setting the Compiler, Loading Programs @node Conditional Compilation, Saving, Setting the Compiler, Loading Programs
@section Conditional Compilation
@c \index{if, directive}%
Conditional compilation builds on the same principle as
@code{term_expansion/2}, @code{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.
@c See \secref{dialect}
@c for more information. Here is a simple example:
@c @table code
@c :- if(\+source_exports(library(lists), suffix/2)).
@c suffix(Suffix, List) :-
@c append(_, Suffix, List).
@c :- endif.
@c \end{code}
Note that these directives can only be appear as separate terms in the
input. Typical usage scenarios include:
@itemize @bullet
@item Load different libraries on different dialects
@item Define a predicate if it is missing as a system predicate
@item Realise totally different implementations for a particular
part of the code due to different capabilities.
@item Realise different configuration options for your software.
@end itemize
@table @code
@item if(+@var{Goal})
@findex if/1 directive
@snindex if/1
@cnindex if/1
Compile subsequent code only if @var{Goal} succeeds. For enhanced
portability, @var{Goal} is processed by @code{expand_goal/2} before execution.
If an error occurs, the error is printed and processing proceeds as if
@var{Goal} has failed.
@item else
@findex else/0 directive
@snindex else/0
@cnindex else/0
Start `else' branch.
@item endif
@findex endif/0 directive
@snindex endif/0
@cnindex endif/0
End of conditional compilation.
@item elif(+@var{Goal})
@findex elif/1 directive
@snindex elif/1
@cnindex elif/1
Equivalent to @code{:- 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.
@example
:- if(test1).
section_1.
:- elif(test2).
section_2.
:- elif(test3).
section_3.
:- else.
section_else.
:- endif.
@end example
@end table
@node Saving, , Conditional Compilation, Loading Programs
@section Saving and Loading Prolog States @section Saving and Loading Prolog States
@table @code @table @code

View File

@ -56,6 +56,8 @@ true :- true.
('$exit_undefp' -> true ; true), ('$exit_undefp' -> true ; true),
prompt(' ?- '), prompt(' ?- '),
nb_setval('$break',0), nb_setval('$break',0),
nb_setval('$if_level',0),
nb_setval('$endif',off),
% '$set_read_error_handler'(error), let the user do that % '$set_read_error_handler'(error), let the user do that
nb_setval('$debug',off), nb_setval('$debug',off),
nb_setval('$trace',off), nb_setval('$trace',off),
@ -241,7 +243,10 @@ true :- true.
'$repeat'. '$repeat'.
'$repeat' :- '$repeat'. '$repeat' :- '$repeat'.
'$start_corouts' :- recorded('$corout','$corout'(Name,_,_),R), Name \= main, finish_corout(R), '$start_corouts' :-
recorded('$corout','$corout'(Name,_,_),R),
Name \= main,
finish_corout(R),
fail. fail.
'$start_corouts' :- '$start_corouts' :-
eraseall('$corout'), eraseall('$corout'),
@ -289,6 +294,11 @@ true :- true.
'$execute_command'(R,_,top,Source) :- db_reference(R), !, '$execute_command'(R,_,top,Source) :- db_reference(R), !,
'$do_error'(type_error(callable,R),meta_call(Source)). '$do_error'(type_error(callable,R),meta_call(Source)).
'$execute_command'(end_of_file,_,_,_) :- !. '$execute_command'(end_of_file,_,_,_) :- !.
'$execute_command'(Command,_,_,_) :-
nb_getval('$if_skip_mode',skip),
\+ '$if_directive'(Command),
!,
fail.
'$execute_command'((:-G),_,Option,_) :- !, '$execute_command'((:-G),_,Option,_) :- !,
'$current_module'(M), '$current_module'(M),
% allow user expansion % allow user expansion

View File

@ -200,6 +200,8 @@ use_module(M,F,Is) :-
'$csult'([F|L], M) :- '$consult'(F, M), '$csult'(L, M). '$csult'([F|L], M) :- '$consult'(F, M), '$csult'(L, M).
'$do_lf'(ContextModule, Stream, InfLevel, _, Imports, SkipUnixComments, Reconsult, UseModule) :- '$do_lf'(ContextModule, Stream, InfLevel, _, Imports, SkipUnixComments, Reconsult, UseModule) :-
nb_getval('$if_level',OldIncludeLevel),
nb_setval('$if_level',0),
nb_getval('$system_mode', OldMode), nb_getval('$system_mode', OldMode),
( OldMode == off -> '$enter_system_mode' ; true ), ( OldMode == off -> '$enter_system_mode' ; true ),
'$record_loaded'(Stream, ContextModule), '$record_loaded'(Stream, ContextModule),
@ -246,6 +248,11 @@ use_module(M,F,Is) :-
set_value('$consulting',Old), set_value('$consulting',Old),
set_value('$consulting_file',OldF), set_value('$consulting_file',OldF),
cd(OldD), cd(OldD),
nb_setval('$if_level',OldIncludeLevel),
% 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',OldIncludeLevel),
'$current_module'(Mod,OldModule), '$current_module'(Mod,OldModule),
'$bind_module'(Mod, UseModule), '$bind_module'(Mod, UseModule),
'$import_to_current_module'(File, ContextModule, Imports), '$import_to_current_module'(File, ContextModule, Imports),
@ -758,3 +765,98 @@ absolute_file_name(File,Opts,TrueFileName) :-
NewName =.. [N,NFile], NewName =.. [N,NFile],
'$find_in_path'(NewName, Opts, OFile, Goal). '$find_in_path'(NewName, Opts, OFile, Goal).
%
% This is complicated because of embedded ifs.
%
'$if'(_,top) :- !, fail.
'$if'(Goal,_) :-
nb_getval('$if_level',Level0),
Level is Level0 + 1,
nb_setval('$if_level',Level),
nb_getval('$endif',OldEndif),
nb_getval('$if_skip_mode',Mode),
nb_setval('$endif',elif(Level,OldEndif,Mode)),
fail.
% we are in skip mode, ignore....
'$if'(Goal,_) :-
nb_getval('$endif',elif(Level, OldEndif, skip)), !,
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)),
nb_setval('$endif',endif(Level,OldEndif,Mode))
;
% we are now in skip, but can start an elif.
nb_setval('$if_skip_mode',skip)
).
'$else'(top) :- !, fail.
'$else'(_) :-
nb_getval('$if_level',0), !,
'$do_error'(context_error(no_if),(:- else)).
% we have done an if, so just skip
'$else'(_) :-
nb_getval('$endif',endif(_,_,_)), !,
nb_setval('$if_skip_mode',skip).
% we can try the elif
'$else'(_) :-
nb_getval('$if_level',Level),
nb_getval('$endif',elif(Level,OldEndif,Mode)),
nb_setval('$endif',endif(Level,OldEndif,Mode)),
nb_setval('$if_skip_mode',run).
'$elif'(_,top) :- !, fail.
'$elif'(Goal,_) :-
nb_getval('$if_level',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,_) :-
nb_getval('$if_level',Level),
nb_getval('$endif',elif(Level,OldEndif,Mode)),
('$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'(_,_).
'$endif'(top) :- !, fail.
'$endif'(_) :-
% unmmatched endif.
nb_getval('$if_level',0),
'$do_error'(context_error(no_if),(:- endif)).
'$endif'(_) :-
% back to where you belong.
nb_getval('$if_level',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, (print_message(error, E), fail)).
'$eval_if'(Goal) :-
expand_term(Goal,TrueGoal),
once(TrueGoal).
'$if_directive'((:- if(_))).
'$if_directive'((:- else)).
'$if_directive'((:- elif(_))).
'$if_directive'((:- endif)).

View File

@ -50,6 +50,10 @@
'$directive'(thread_local(_)). '$directive'(thread_local(_)).
'$directive'(uncutable(_)). '$directive'(uncutable(_)).
'$directive'(encoding(_)). '$directive'(encoding(_)).
'$directive'(if(_)).
'$directive'(else).
'$directive'(elif(_)).
'$directive'(endif).
'$exec_directives'((G1,G2), Mode, M) :- !, '$exec_directives'((G1,G2), Mode, M) :- !,
'$exec_directives'(G1, Mode, M), '$exec_directives'(G1, Mode, M),
@ -117,6 +121,14 @@
'$table'(PredSpec, M). '$table'(PredSpec, M).
'$exec_directive'(uncutable(PredSpec), _, M) :- '$exec_directive'(uncutable(PredSpec), _, M) :-
'$uncutable'(PredSpec, M). '$uncutable'(PredSpec, M).
'$exec_directive'(if(Goal), Context, M) :-
'$if'(M:Goal, Context).
'$exec_directive'(else, Context, _) :-
'$else'(Context).
'$exec_directive'(elif(Goal), Context, M) :-
'$elif'(M:Goal, Context).
'$exec_directive'(endif, Context, _) :-
'$endif'(Context).
yap_flag(V,Out) :- yap_flag(V,Out) :-