From 61d9980cf3497c0c33c9ae4d52081cee986ea968 Mon Sep 17 00:00:00 2001 From: vsc <vsc@b08c6af1-5177-4d33-ba66-4b1c6b8b522a> Date: Mon, 31 Oct 2005 18:12:51 +0000 Subject: [PATCH] updates do documentation put_attrs git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@1433 b08c6af1-5177-4d33-ba66-4b1c6b8b522a --- C/attvar.c | 34 +++ changes-5.1.html | 1 + docs/yap.tex | 678 ++++++++++++++++++++++++++++++++++++----------- library/swi.yap | 11 +- 4 files changed, 570 insertions(+), 154 deletions(-) diff --git a/C/attvar.c b/C/attvar.c index 0f0f45bdb..ed3992d26 100644 --- a/C/attvar.c +++ b/C/attvar.c @@ -451,6 +451,39 @@ p_put_att(void) { } } +static Int +p_put_att_term(void) { + /* receive a variable in ARG1 */ + Term inp = Deref(ARG1); + /* if this is unbound, ok */ + if (IsVarTerm(inp)) { + attvar_record *attv; + int new = FALSE; + + if (IsAttachedTerm(inp)) { + attv = (attvar_record *)VarOfTerm(inp); + } else { + while (!(attv = BuildNewAttVar())) { + if (!Yap_growglobal(NULL)) { + Yap_Error(OUT_OF_ATTVARS_ERROR, ARG1, Yap_ErrorMessage); + return FALSE; + } + inp = Deref(ARG1); + } + new = TRUE; + } + if (new) { + attv->Atts = Deref(ARG2); + } else { + MaBind(&(attv->Atts), Deref(ARG2)); + } + return TRUE; + } else { + Yap_Error(TYPE_ERROR_VARIABLE,inp,"put_attributes/2"); + return(FALSE); + } +} + static Int p_rm_att(void) { /* receive a variable in ARG1 */ @@ -890,6 +923,7 @@ void Yap_InitAttVarPreds(void) Yap_InitCPred("get_all_swi_atts", 2, p_swi_all_atts, SafePredFlag); Yap_InitCPred("free_att", 3, p_free_att, SafePredFlag); Yap_InitCPred("put_att", 5, p_put_att, 0); + Yap_InitCPred("put_att_term", 5, p_put_att_term, 0); Yap_InitCPred("put_module_atts", 2, p_put_atts, 0); Yap_InitCPred("del_all_module_atts", 2, p_del_atts, 0); Yap_InitCPred("rm_att", 4, p_rm_att, 0); diff --git a/changes-5.1.html b/changes-5.1.html index c76022d82..c8a8f5177 100644 --- a/changes-5.1.html +++ b/changes-5.1.html @@ -16,6 +16,7 @@ <h2>Yap-5.1.0:</h2> <ul> +<li> NEW: put_attrs/2. </li> <li> FIXED: don't install CLP unless coroutining && rational trees are active. </li> <li> FIXED: syntax error in ypp.yap (obs Paulo Moura). </li> diff --git a/docs/yap.tex b/docs/yap.tex index 85b1a12be..20cd489a3 100644 --- a/docs/yap.tex +++ b/docs/yap.tex @@ -8,7 +8,7 @@ @c @setchapternewpage odd @c %**end of header -@set VERSION: 5.1.0 +@set VERSION 5.1.0 @set EDITION 4.2.4 @set UPDATED December 2004 @@ -128,6 +128,7 @@ us to include his text in this document. * Modules:: Using Modules in YAP * Builtins:: Built In Predicates * Library:: Library Predicates +* SWI-Prolog:: SWI-Prolog emulation * Extensions:: Extensions to Standard YAP * Rational Trees:: Working with Rational Trees * Coroutining:: Changing the Execution of Goals @@ -234,7 +235,6 @@ Subnodes of Library * System:: System Utilities * Terms:: Utilities on Terms * Cleanup:: Call With registered Cleanup Calls -* SWI-Prolog:: SWI-Prolog emulation * Timeout:: Call With Timeout * Trees:: Updatable Binary Trees * UGraphs:: Unweighted Graphs @@ -256,6 +256,12 @@ Subnodes of Attributes * Projecting Attributes:: Obtaining the Attributes of Interest * Attribute Examples:: Two Simple Examples of how to use Attributes. +Subnodes of SWI-Prolog +* Invoking Predicates on all Members of a List :: maplist and friends +* Forall :: forall builtin +* hProlog and SWI-Prolog Attributed Variables :: Emulating SWI-like attributed variables +* SWI-Prolog Global Variables :: Emulating SWI-like attributed variables + Subnodes of CLP(Q,R) * Introduction to CLPQR:: The CLP(Q,R) System * Referencing CLPQR:: How to Reference CLP(Q,R) @@ -306,7 +312,7 @@ Subnodes of C-Interface * Yap4 Notes:: Changes in Foreign Predicates Interface Subnodes of C-Prolog -* Major Differences from C-Prolog:: Major Differences between YAP and C-Prolog +* Major Differences with C-Prolog:: Major Differences between YAP and C-Prolog * Fully C-Prolog Compatible:: Yap predicates fully compatible with C-Prolog * Not Strictly C-Prolog Compatible:: Yap predicates not strictly as C-Prolog @@ -314,7 +320,7 @@ C-Prolog * Not in YAP:: C-Prolog predicates not available in YAP Subnodes of SICStus Prolog -* Major Differences from SICStus:: Major Differences between YAP and SICStus Prolog +* Major Differences with SICStus:: Major Differences between YAP and SICStus Prolog * Fully SICStus Compatible:: Yap predicates fully compatible with SICStus Prolog * Not Strictly SICStus Compatible:: Yap predicates not strictly as @@ -6734,7 +6740,7 @@ Stream position at the stream currently being read in. @end table -@node Library, Extensions, Builtins, Top +@node Library, SWI-Prolog, Builtins, Top @chapter Library Predicates @@ -6762,7 +6768,6 @@ Library, Extensions, Builtins, Top * System:: System Utilities * Terms:: Utilities on Terms * Cleanup:: Call With registered Cleanup Calls -* SWI-Prolog:: SWI-Prolog emulation * Timeout:: Call With Timeout * Trees:: Updatable Binary Trees * UGraphs:: Unweighted Graphs @@ -8408,7 +8413,7 @@ term @var{Term}. @end table -@node Cleanup, SWI-Prolog, Cleanup, Library +@node Cleanup, Timeout, Terms, Library @section Call Cleanup @cindex cleanup @@ -8474,134 +8479,7 @@ CleanUpGoals for other than the current cleanup-context. Read the Source Luke. -@node SWI-Prolog, Timeout, SWI-Prolog, Library -@section SWI-Prolog Emulation -@cindex SWI-Prolog - -This library provides a number of SWI-Prolog builtins that are not by -default in YAP. This library is loaded with the -@code{use_module(library(swi))} command. - -@table @code - -@item append(?@var{List1},?@var{List2},?@var{List3}) -@findex append/3 -@snindex append/3 -@cnindex append/3 -Succeeds when @var{List3} unifies with the concatenation of @var{List1} -and @var{List2}. The predicate can be used with any instantiation -pattern (even three variables). - -@item between(+@var{Low},+@var{High},?@var{Value}) -@findex between/3 -@snindex between/3 -@cnindex between/3 - -@var{Low} and @var{High} are integers, @var{High} less or equal than -@var{Low}. If @var{Value} is an integer, $@var{Low} less or equal than -@var{Value} less or equal than @var{High}$. When @var{Value} is a -variable it is successively bound to all integers between @var{Low} and -@var{High}. If @var{High} is @const{inf} @code{between/3| is true iff -@var{Value} less or equal than @var{Low}, a feature that is particularly -interesting for generating integers from a certain value. - -@item chdir(+@var{Dir}) -@findex chdir/1 -@snindex chdir/1 -@cnindex chdir/1 - -Compatibility predicate. New code should use @code{working_directory/2}. - -@item concat_atom(+@var{List},-@var{Atom}) -@findex concat_atom/2 -@snindex concat_atom/2 -@cnindex concat_atom/2 - -@var{List} is a list of atoms, integers or floating point numbers. Succeeds -if @var{Atom} can be unified with the concatenated elements of @var{List}. If -@var{List} has exactly 2 elements it is equivalent to @code{atom_concat/3}, -allowing for variables in the list. - -@item concat_atom(?@var{List},+@var{Separator},?@var{Atom}) -@findex concat_atom/3 -@snindex concat_atom/3 -@cnindex concat_atom/3 - -Creates an atom just like concat_atom/2, but inserts @var{Separator} -between each pair of atoms. For example: -\@example -?- concat_atom([gnu, gnat], ', ', A). - -A = 'gnu, gnat' -@end example - -(Unimplemented) This predicate can also be used to split atoms by -instantiating @var{Separator} and @var{Atom}: - -@example -?- concat_atom(L, -, 'gnu-gnat'). - -L = [gnu, gnat] -@end example - -@item forall(+@var{Cond},+@var{Action}) -@findex forall/2 -@snindex forall/2 -@cnindex forall/2 - -For all alternative bindings of @var{Cond} @var{Action} can be proven. -The next example verifies that all arithmetic statements in the list -@var{L} are correct. It does not say which is wrong if one proves wrong. - -@example -?- forall(member(Result = Formula, [2 = 1 + 1, 4 = 2 * 2]), - Result =:= Formula). -@end example - -@item nth1(+@var{Index},?@var{List},?@var{Elem}) -@findex nth1/3 -@snindex nth1/3 -@cnindex nth1/3 -Succeeds when the @var{Index}-th element of @var{List} unifies with -@var{Elem}. Counting starts at 1. - -Set environment variable. @var{Name} and @var{Value} should be -instantiated to atoms or integers. The environment variable will be -passed to @code{shell/[0-2]} and can be requested using @code{getenv/2}. -They also influence @code{expand_file_name/2}. - -@item setenv(+@var{Name},+@var{Value}) -@findex setenv/2 -@snindex setenv/2 -@cnindex setenv/2 -Set environment variable. @var{Name} and @var{Value} should be -instantiated to atoms or integers. The environment variable will be -passed to @code{shell/[0-2]} and can be requested using @code{getenv/2}. -They also influence @code{expand_file_name/2}. - -@item term_to_atom(?@var{Term},?@var{Atom}) -@findex term_to_atom/2 -@snindex term_to_atom/2 -@cnindex term_to_atom/2 -Succeeds if @var{Atom} describes a term that unifies with @var{Term}. When -@var{Atom} is instantiated @var{Atom} is converted and then unified with -@var{Term}. If @var{Atom} has no valid syntax, a @code{syntax_error} -exception is raised. Otherwise @var{Term} is ``written'' on @var{Atom} -using @code{write/1}. - -@item working_directory(-@var{Old},+@var{New}) -@findex working_directory/2 -@snindex working_directory/2 -@cnindex working_directory/2 - -Unify @var{Old} with an absolute path to the current working directory -and change working directory to @var{New}. Use the pattern -@code{working_directory(CWD, CWD)} to get the current directory. See -also @code{absolute_file_name/2} and @code{chdir/1}. - -@end table - -@node Timeout, Trees, SWI-Prolog, Library +@node Timeout, Trees, Cleanup, Library @section Calls With Timeout @cindex timeout @@ -8611,6 +8489,7 @@ available with the @code{use_module(library(timeout))} command. @table @code + @item time_out(+@var{Goal}, +@var{Timeout}, -@var{Result}) @findex time_out/3 @syindex time_out/3 @@ -8936,8 +8815,506 @@ V = [1,3,5] @end table -@node Extensions,Debugging,Library,Top -@chapter Extensions +@node SWI-Prolog, Extensions, Library, Top +@chapter SWI-Prolog Emulation +@cindex SWI-Prolog + +@menu SWI-Prolog Emulation +Subnodes of SWI-Prolog +* Invoking Predicates on all Members of a List :: maplist and friends +* Forall :: forall builtin +* hProlog and SWI-Prolog Attributed Variables :: Emulating SWI-like attributed variables +* SWI-Prolog Global Variables :: Emulating SWI-like attributed variables +@end menu + +This library provides a number of SWI-Prolog builtins that are not by +default in YAP. This library is loaded with the +@code{use_module(library(swi))} command. + +@table @code + +@item append(?@var{List1},?@var{List2},?@var{List3}) +@findex append/3 +@snindex append/3 +@cnindex append/3 +Succeeds when @var{List3} unifies with the concatenation of @var{List1} +and @var{List2}. The predicate can be used with any instantiation +pattern (even three variables). + +@item between(+@var{Low},+@var{High},?@var{Value}) +@findex between/3 +@snindex between/3 +@cnindex between/3 + +@var{Low} and @var{High} are integers, @var{High} less or equal than +@var{Low}. If @var{Value} is an integer, @var{Low} less or equal than +@var{Value} less or equal than @var{High}. When @var{Value} is a +variable it is successively bound to all integers between @var{Low} and +@var{High}. If @var{High} is @code{inf}, @code{between/3} is true iff +@var{Value} less or equal than @var{Low}, a feature that is particularly +interesting for generating integers from a certain value. + +@item chdir(+@var{Dir}) +@findex chdir/1 +@snindex chdir/1 +@cnindex chdir/1 + +Compatibility predicate. New code should use @code{working_directory/2}. + +@item concat_atom(+@var{List},-@var{Atom}) +@findex concat_atom/2 +@snindex concat_atom/2 +@cnindex concat_atom/2 + +@var{List} is a list of atoms, integers or floating point numbers. Succeeds +if @var{Atom} can be unified with the concatenated elements of @var{List}. If +@var{List} has exactly 2 elements it is equivalent to @code{atom_concat/3}, +allowing for variables in the list. + +@item concat_atom(?@var{List},+@var{Separator},?@var{Atom}) +@findex concat_atom/3 +@snindex concat_atom/3 +@cnindex concat_atom/3 + +Creates an atom just like concat_atom/2, but inserts @var{Separator} +between each pair of atoms. For example: +\@example +?- concat_atom([gnu, gnat], ', ', A). + +A = 'gnu, gnat' +@end example + +(Unimplemented) This predicate can also be used to split atoms by +instantiating @var{Separator} and @var{Atom}: + +@example +?- concat_atom(L, -, 'gnu-gnat'). + +L = [gnu, gnat] +@end example + +@item nth1(+@var{Index},?@var{List},?@var{Elem}) +@findex nth1/3 +@snindex nth1/3 +@cnindex nth1/3 +Succeeds when the @var{Index}-th element of @var{List} unifies with +@var{Elem}. Counting starts at 1. + +Set environment variable. @var{Name} and @var{Value} should be +instantiated to atoms or integers. The environment variable will be +passed to @code{shell/[0-2]} and can be requested using @code{getenv/2}. +They also influence @code{expand_file_name/2}. + +@item setenv(+@var{Name},+@var{Value}) +@findex setenv/2 +@snindex setenv/2 +@cnindex setenv/2 +Set environment variable. @var{Name} and @var{Value} should be +instantiated to atoms or integers. The environment variable will be +passed to @code{shell/[0-2]} and can be requested using @code{getenv/2}. +They also influence @code{expand_file_name/2}. + +@item term_to_atom(?@var{Term},?@var{Atom}) +@findex term_to_atom/2 +@snindex term_to_atom/2 +@cnindex term_to_atom/2 +Succeeds if @var{Atom} describes a term that unifies with @var{Term}. When +@var{Atom} is instantiated @var{Atom} is converted and then unified with +@var{Term}. If @var{Atom} has no valid syntax, a @code{syntax_error} +exception is raised. Otherwise @var{Term} is ``written'' on @var{Atom} +using @code{write/1}. + +@item working_directory(-@var{Old},+@var{New}) +@findex working_directory/2 +@snindex working_directory/2 +@cnindex working_directory/2 + +Unify @var{Old} with an absolute path to the current working directory +and change working directory to @var{New}. Use the pattern +@code{working_directory(CWD, CWD)} to get the current directory. See +also @code{absolute_file_name/2} and @code{chdir/1}. + +@end table + +@node Invoking Predicates on all Members of a List,Forall, , SWI-Prolog +@section Invoking Predicates on all Members of a List +@c \label{sec:applylist} + +All the predicates in this section call a predicate on all members of a +list or until the predicate called fails. The predicate is called via +@code{call/[2..]}, which implies common arguments can be put in +front of the arguments obtained from the list(s). For example: + +@example +?- maplist(plus(1), [0, 1, 2], X). + +X = [1, 2, 3] +@end example + +we will phrase this as ``@var{Predicate} is applied on ...'' + +@table @code + +@item maplist(+@var{Pred},+@var{List}) +@findex maplist/2 +@snindex maplist/2 +@cnindex maplist/2 +@var{Pred} is applied successively on each element of @var{List} until +the end of the list or @var{Pred} fails. In the latter case +@code{maplist/2} fails. + +@item maplist(+@var{Pred},+@var{List1},+@var{List2}) +@findex maplist/3 +@snindex maplist/3 +@cnindex maplist/3 +Apply @var{Pred} on all successive triples of elements from +@var{List1} and +@var{List2}. Fails if @var{Pred} can not be applied to a +pair. See the example above. + +@item maplist(+@var{Pred},+@var{List1},+@var{List2},+@var{List4}) +@findex maplist/4 +@snindex maplist/4 +@cnindex maplist/4 +Apply @var{Pred} on all successive triples of elements from @var{List1}, +@var{List2} and @var{List3}. Fails if @var{Pred} can not be applied to a +triple. See the example above. + +@c @item findlist(+@var{Pred},+@var{List1},?@var{List2}) +@c @findex findlist/3 +@c @snindex findlist/3 +@c @cnindex findlist/3 +@c Unify @var{List2} with a list of all elements of @var{List1} to which +@c @var{Pred} applies. +@end table + +@node Forall,hProlog and SWI-Prolog Attributed Variables,Invoking Predicates on all Members of a List, SWI-Prolog +@section Forall +@c \label{sec:forall2} + +@table @code +@item forall(+@var{Cond},+@var{Action}) +@findex forall/2 +@snindex forall/2 +@cnindex forall/2 + +For all alternative bindings of @var{Cond} @var{Action} can be proven. +The next example verifies that all arithmetic statements in the list +@var{L} are correct. It does not say which is wrong if one proves wrong. + +@example +?- forall(member(Result = Formula, [2 = 1 + 1, 4 = 2 * 2]), + Result =:= Formula). +@end example + +@end table + +@node hProlog and SWI-Prolog Attributed Variables, SWI-Prolog Global Variables, Forall,SWI-Prolog +@section hProlog and SWI-Prolog Attributed Variables +@cindex hProlog Attributed Variables + +Attributed variables +@c @ref{Attributed variables} +provide a technique for extending the +Prolog unification algorithm by hooking the binding of attributed +variables. There is little consensus in the Prolog community on the +exact definition and interface to attributed variables. Yap Prolog +traditionally implements a SICStus-like interface, but to enable +SWI-compatibility we have implemented the SWI-Prolog interface, +identical to the one realised by Bart Demoen for hProlog. + +Binding an attributed variable schedules a goal to be executed at the +first possible opportunity. In the current implementation the hooks are +executed immediately after a successful unification of the clause-head +or successful completion of a foreign language (builtin) predicate. Each +attribute is associated to a module and the hook (attr_unify_hook/2) is +executed in this module. The example below realises a very simple and +incomplete finite domain reasoner. + +@example +:- module(domain, + [ domain/2 % Var, ?Domain + ]). +:- use_module(library(oset)). + +domain(X, Dom) :- + var(Dom), !, + get_attr(X, domain, Dom). +domain(X, List) :- + sort(List, Domain), + put_attr(Y, domain, Domain), + X = Y. + +% An attributed variable with attribute value Domain has been +% assigned the value Y + +attr_unify_hook(Domain, Y) :- + ( get_attr(Y, domain, Dom2) + -> oset_int(Domain, Dom2, NewDomain), + ( NewDomain == [] + -> fail + ; NewDomain = [Value] + -> Y = Value + ; put_attr(Y, domain, NewDomain) + ) + ; var(Y) + -> put_attr( Y, domain, Domain ) + ; memberchk(Y, Domain) + ). +@end example + + +Before explaining the code we give some example queries: + +@table @code +@item ?- domain(X, [a,b]), X = c +no +@item ?- domain(X, [a,b]), domain(X, [a,c]). + X = a +@item ?- domain(X, [a,b,c]), domain(X, [a,c]). + X = _D0 +@end table + +The predicate @code{domain/2} fetches (first clause) or assigns +(second clause) the variable a @emph{domain}, a set of values it can +be unified with. In the second clause first associates the domain +with a fresh variable and then unifies X to this variable to deal +with the possibility that X already has a domain. The +predicate @code{attr_unify_hook/2} is a hook called after a variable with +a domain is assigned a value. In the simple case where the variable +is bound to a concrete value we simply check whether this value is in +the domain. Otherwise we take the intersection of the domains and either +fail if the intersection is empty (first example), simply assign the +value if there is only one value in the intersection (second example) or +assign the intersection as the new domain of the variable (third +example). + + +@table @code + +@item put_attr(+@var{Var},+@var{Module},+@var{Value}) +@findex put_attr/3 +@snindex put_attr/3 +@cnindex put_attr/3 +If @var{Var} is a variable or attributed variable, set the value for the +attribute named @var{Module} to @var{Value}. If an attribute with this +name is already associated with @var{Var}, the old value is replaced. +Backtracking will restore the old value (i.e. an attribute is a mutable +term. See also @code{setarg/3}). This predicate raises a type error if +@var{Var} is not a variable or @var{Module} is not an atom. + +@item get_attr(+@var{Var},+@var{Module},+@var{Value}) +@findex get_attr/3 +@snindex get_attr/3 +@cnindex get_attr/3 +Request the current @var{value} for the attribute named @var{Module}. If +@var{Var} is not an attributed variable or the named attribute is not +associated to @var{Var} this predicate fails silently. If @var{Module} +is not an atom, a type error is raised. + +@item del_attr(+@var{Var},+@var{Module}) +@findex del_attr/2 +@snindex del_attr/2 +@cnindex del_attr/2 +Delete the named attribute. If @var{Var} loses its last attribute it +is transformed back into a traditional Prolog variable. If @var{Module} +is not an atom, a type error is raised. In all other cases this +predicate succeeds regarless whether or not the named attribute is +present. + +@item attr_unify_hook(+@var{AttValue},+@var{VarValue}) +@findex attr_unify_hook/2 +@snindex attr_unify_hook/2 +@cnindex attr_unify_hook/2 +Hook that must be defined in the module an attributed variable refers +to. Is is called @emph{after} the attributed variable has been +unified with a non-var term, possibly another attributed variable. +@var{AttValue} is the attribute that was associated to the variable +in this module and @var{VarValue} is the new value of the variable. +Normally this predicate fails to veto binding the variable to +@var{VarValue}, forcing backtracking to undo the binding. If +@var{VarValue} is another attributed variable the hook often combines +the two attribute and associates the combined attribute with +@var{VarValue} using @code{put_attr/3}. + +@c \predicate{attr_portray_hook}{2}{+AttValue, +Var} +@c Called by write_term/2 and friends for each attribute if the option +@c \term{attributes}{portray} is in effect. If the hook succeeds the +@c attribute is considered printed. Otherwise \exam{Module = ...} is +@c printed to indicate the existence of a variable. +@end table + +@subsection Special Purpose SWI Predicates for Attributes + +Normal user code should deal with @code{put_attr/3}, @code{get_attr/3} +and @code{del_attr/2}. The routines in this section fetch or set the +entire attribute list of a variables. Use of these predicates is +anticipated to be restricted to printing and other special purpose +operations. + +@table @code +@item get_attrs(+@var{Var},-@var{Attributes}) +@findex get_attrs/2 +@snindex get_attrs/2 +@cnindex get_attrs/2 +Get all attributes of @var{Var}. @var{Attributes} is a term of the form +@code{att(Module, Value, MoreAttributes)}, where @var{MoreAttributes} is +@code{[]} for the last attribute. + +@item put_attrs(+@var{Var},+@var{Attributes}) +@findex put_attrs/2 +@snindex put_attrs/2 +@cnindex put_attrs/2 +Set all attributes of @var{Var}. See get_attrs/2 for a description of +@var{Attributes}. + +@item copy_term_nat(?@var{TI},-@var{TF}) +@findex copy_term_nat/2 +@snindex copy_term_nat/2 +@cnindex copy_term_nat/2 +As @code{copy_term/2}. Attributes however, are @emph{not} copied but replaced +by fresh variables. +@end table + + +@node SWI-Prolog Global Variables, ,hProlog and SWI-Prolog Attributed Variables,SWI-Prolog +@section SWI Global variables +@c \label{sec:gvar} + +SWI-Prolog global variables are associations between names (atoms) and +terms. They differ in various ways from storing information using +@code{assert/1} or @code{recorda/3}. + +@itemize @bullet +@item The value lives on the Prolog (global) stack. This implies + that lookup time is independent from the size of the term. + This is particulary interesting for large data structures + such as parsed XML documents or the CHR global constraint + store. + +@item They support both global assignment using @code{nb_setval/2} and + backtrackable assignment using @code{b_setval/2}. + +@item Only one value (which can be an arbitrary complex Prolog + term) can be associated to a variable at a time. + +@item Their value cannot be shared among threads. Each thread + has its own namespace and values for global variables. + +@item Currently global variables are scoped globally. We may + consider module scoping in future versions. +@end itemize + +Both @code{b_setval/2} and @code{nb_setval/2} implicitely create a variable if the +referenced name does not already refer to a variable. + +Global variables may be initialised from directives to make them +available during the program lifetime, but some considerations are +necessary for saved-states and threads. Saved-states to not store global +variables, which implies they have to be declared with @code{initialization/1} +to recreate them after loading the saved state. Each thread has +its own set of global variables, starting with an empty set. Using +@code{thread_inititialization/1} to define a global variable it will be +defined, restored after reloading a saved state and created in all +threads that are created @emph{after} the registration. + + +@table @code +@item b_setval(+@var{Name},+@var{Value}) +@findex b_setval/2 +@snindex b_setval/2 +@cnindex b_setval/2 +Associate the term @var{Value} with the atom @var{Name} or replaces +the currently associated value with @var{Value}. If @var{Name} does +not refer to an existing global variable a variable with initial value +@code{[]} is created (the empty list). On backtracking the +assignment is reversed. + +@item b_getval(+@var{Name},-@var{Value}) +@findex b_getval/2 +@snindex b_getval/2 +@cnindex b_getval/2 +Get the value associated with the global variable @var{Name} and unify +it with @var{Value}. Note that this unification may further instantiate +the value of the global variable. If this is undesirable the normal +precautions (double negation or @code{copy_term/2}) must be taken. The +@code{b_getval/2} predicate generates errors if @var{Name} is not an atom or +the requested variable does not exist. +@end table + +@table @code + +@item nb_setval(+@var{Name},+@var{Value}) +@findex nb_setval/2 +@snindex nb_setval/2 +@cnindex nb_setval/2 +Associates a copy of @var{Value} created with @code{duplicate_term/2} +with the atom @var{Name}. Note that this can be used to set an +initial value other than @code{[]} prior to backtrackable assignment. + +@item nb_getval(+@var{Name},-@var{Value}) +@findex nb_getval/2 +@snindex nb_getval/2 +@cnindex nb_getval/2 +The @code{nb_getval/2} predicate is a synonym for b_getval/2, introduced for +compatibility and symetry. As most scenarios will use a particular +global variable either using non-backtracable or backtrackable +assignment, using @code{nb_getval/2} can be used to document that the +variable is used non-backtracable. + +@c \predicate{nb_linkval}{2}{+Name, +Value} +@c Associates the term @var{Value} with the atom @var{Name} without copying +@c it. This is a fast special-purpose variation of nb_setval/2 intended for +@c expert users only because the semantics on backtracking to a point +@c before creating the link are poorly defined for compound terms. The +@c principal term is always left untouched, but backtracking behaviour on +@c arguments is undone if the orginal assignment was \jargon{trailed} and +@c left alone otherwise, which implies that the history that created the +@c term affects the behaviour on backtracking. Please consider the +@c following example: + +@c \begin{code} +@c demo_nb_linkval :- +@c T = nice(N), +@c ( N = world, +@c nb_linkval(myvar, T), +@c fail +@c ; nb_getval(myvar, V), +@c writeln(V) +@c ). +@c \end{code} + +@item nb_current(?@var{Name},?@var{Value}) +@findex nb_current/2 +@snindex nb_current/2 +@cnindex nb_current/2 +Enumerate all defined variables with their value. The order of +enumeration is undefined. + +@item nb_delete(?@var{Name}) +@findex nb_delete/1 +@snindex nb_delete/1 +@cnindex nb_delete/1 +Delete the named global variable. +@end table + +@subsection Compatibility of SWI-Prolog Global Variables + +Global variables have been introduced by various Prolog +implementations recently. The implementation of them in SWI-Prolog is +based on hProlog by Bart Demoen. In discussion with Bart it was +decided that the semantics if hProlog @code{nb_setval/2}, which is +equivalent to @code{nb_linkval/2} is not acceptable for normal Prolog +users as the behaviour is influenced by how builtin predicates +constructing terms (@code{read/1}, @code{=../2}, etc.) are implemented. + +GNU-Prolog provides a rich set of global variables, including arrays. +Arrays can be implemented easily in SWI-Prolog using @code{functor/3} and +@code{setarg/3} due to the unrestricted arity of compound terms. + + +@node Extensions,Debugging,SWI-Prolog,Top +@chapter Extensions to Prolog YAP includes several extensions that are not enabled by default, but that can be used to extend the functionality of the @@ -8945,7 +9322,6 @@ system. These options can be set at compilation time by enabling the related compilation flag, as explained in the @code{Makefile} @menu - Extensions to Traditional Prolog * Rational Trees:: Working with Rational Trees @@ -8961,7 +9337,7 @@ Extensions to Traditional Prolog @end menu @node Rational Trees, Coroutining, , Extensions -@chapter Rational Trees +@section Rational Trees Prolog unification is not a complete implementation. For efficiency considerations, Prolog systems do not perform occur checks while @@ -8969,9 +9345,10 @@ unifying terms. As an example, @code{X = a(X)} will not fail but instead will create an infinite term of the form @code{a(a(a(a(a(...)))))}, or @emph{rational tree}. -By default, rational trees are not supported in YAP, and these -terms can easily lead to infinite computation. For example, @code{X = -a(X), X = X} will enter an infinite loop. +Rational trees are no supported by default in YAP. In previous +versions, this was not the default and these terms could easily lead +to infinite computation. For example, @code{X = a(X), X = X} would +enter an infinite loop. The @code{RATIONAL_TREES} flag improves support for these terms. Internal primitives are now aware that these terms can exist, and @@ -8985,7 +9362,7 @@ rational trees, and you need to use @code{write_depth/2} to avoid entering an infinite cycle when trying to write an infinite term. @node Coroutining, Attributed Variables, Rational Trees, Extensions -@chapter Coroutining +@section Coroutining Prolog uses a simple left-to-right flow of control. It is sometimes convenient to change this control so that goals will only be executed @@ -9088,7 +9465,6 @@ suspended. @end table - @node Attributed Variables, CLPQR, Coroutining, Extensions @chapter Attributed Variables @cindex attributed variables @@ -14078,9 +14454,9 @@ would have something like @example void init_n100(void) -{ +@{ YAP_UserBackCPredicate("n100", start_n100, continue_n100, 1, 1); -} +@} @end example @@ -14449,7 +14825,7 @@ YAP compatible with the ISO-Prolog standard. @menu C-Prolog Compatibility -* Major Differences from C-Prolog:: Major Differences between YAP and C-Prolog +* Major Differences with C-Prolog:: Major Differences between YAP and C-Prolog * Fully C-Prolog Compatible:: Yap predicates fully compatible with C-Prolog * Not Strictly C-Prolog Compatible:: Yap predicates not strictly as C-Prolog @@ -14457,7 +14833,7 @@ C-Prolog * Not in YAP:: C-Prolog predicates not available in YAP @end menu -@node Major Differences from C-Prolog, Fully C-Prolog Compatible, , C-Prolog +@node Major Differences with C-Prolog, Fully C-Prolog Compatible, , C-Prolog @subsection Major Differences between YAP and C-Prolog. YAP includes several extensions over the original C-Prolog system. Even @@ -14496,7 +14872,7 @@ or by using: @code{:- yap_flag(language,cprolog).} @end example -@node Fully C-Prolog Compatible, Not Strictly C-Prolog Compatible, Major Differences from C-Prolog, C-Prolog +@node Fully C-Prolog Compatible, Not Strictly C-Prolog Compatible, Major Differences with C-Prolog, C-Prolog @subsection Yap predicates fully compatible with C-Prolog These are the Prolog built-ins that are fully compatible in both @@ -14559,7 +14935,7 @@ for maximum compatibility with SICStus Prolog. @menu SICStus Compatibility -* Major Differences from SICStus:: Major Differences between YAP and SICStus Prolog +* Major Differences with SICStus:: Major Differences between YAP and SICStus Prolog * Fully SICStus Compatible:: Yap predicates fully compatible with SICStus Prolog * Not Strictly SICStus Compatible:: Yap predicates not strictly as @@ -14567,7 +14943,7 @@ SICStus Prolog * Not in SICstus Prolog:: Yap predicates not available in SICStus Prolog @end menu -@node Major Differences from SICStus, Fully SICStus Compatible, , SICStus Prolog +@node Major Differences with SICStus, Fully SICStus Compatible, , SICStus Prolog @subsection Major Differences between YAP and SICStus Prolog. Both YAP and SICStus Prolog obey the Edinburgh Syntax and are based on diff --git a/library/swi.yap b/library/swi.yap index 8538c1b9b..314753c21 100644 --- a/library/swi.yap +++ b/library/swi.yap @@ -152,9 +152,14 @@ prolog:get_attrs(AttVar, SWIAtts) :- get_all_swi_atts(AttVar,SWIAtts). prolog:put_attrs(_, []). -prolog:put_attrs(V, att(Mod,Att,Atts)) :- - prolog:put_attr(V,Mod,Att), - prolog:put_attrs(V, Atts). +prolog:put_attrs(V, Atts) :- + cvt_to_swi_atts(Atts, YapAtts), + attributes:put_att_term(V, YapAtts). + +cvt_to_swi_atts([], _). +cvt_to_swi_atts(att(Mod,Attribute,Atts), ModAttribute) :- + ModAttribute =.. [Mod, YapAtts, Attribute], + cvt_to_swi_atts(Atts, YapAtts). bindings_message(V) --> { cvt_bindings(V, Bindings) },