1% BEGIN LICENSE BLOCK
2% Version: CMPL 1.1
3%
4% The contents of this file are subject to the Cisco-style Mozilla Public
5% License Version 1.1 (the "License"); you may not use this file except
6% in compliance with the License.  You may obtain a copy of the License
7% at www.eclipse-clp.org/license.
8% 
9% Software distributed under the License is distributed on an "AS IS"
10% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
11% the License for the specific language governing rights and limitations
12% under the License. 
13% 
14% The Original Code is  The ECLiPSe Constraint Logic Programming System. 
15% The Initial Developer of the Original Code is  Cisco Systems, Inc. 
16% Portions created by the Initial Developer are
17% Copyright (C) 2006 Cisco Systems, Inc.  All Rights Reserved.
18% 
19% Contributor(s): 
20% 
21% END LICENSE BLOCK
22
23:- comment(alias, "Non-logical Variables, Arrays, Bags, Shelves and Stores").
24:- comment(summary, "Built-ins to store data across backtracking").
25:- comment(categories, ["Built-In Predicates","Data Structures"]).
26
27:- tool(current_array / 2).
28:- tool(erase_array / 1).
29:- tool(current_store / 1).
30:- tool(decval / 1).
31:- tool(getval / 2).
32:- tool(incval / 1).
33:- tool(setval / 2).
34:- tool(shelf_dec / 2).
35:- tool(shelf_get / 3).
36:- tool(shelf_inc / 2).
37:- tool(shelf_set / 3).
38:- tool(store_contains / 2).
39:- tool(store_count / 2).
40:- tool(store_delete / 2).
41:- tool(store_erase / 1).
42:- tool(store_get / 3).
43:- tool(store_inc / 2).
44:- tool(store_set / 3).
45:- tool(stored_keys / 2).
46:- tool(stored_keys_and_values / 2).
47:- tool(test_and_setval / 3).
48
49:- comment(desc, html("\
50	ECLiPSe provides several facilities to store information across
51	backtracking. The following table gives an overview. If at all
52	possible, the handle-based facilities (bags, records, shelves,
53	stores) should be preferred because they lead to cleaner, reentrant
54	code (without global state) and reduce the risk of memory leaks.
55<PRE>
56    Facility        Type            Reference       See
57    ================================================================
58    bags            unordered bag   by handle       bag_create/1
59    ----------------------------------------------------------------
60    anon.records    ordered list    by handle       record_create/1
61    ----------------------------------------------------------------
62    shelves         array           by handle       shelf_create/2,3
63    ----------------------------------------------------------------
64    stores          hash table      by handle       store_create/1
65    ----------------------------------------------------------------
66    named shelves   array           by name         shelf/2
67    ----------------------------------------------------------------
68    named stores    hash table      by name         store/1
69    ----------------------------------------------------------------
70    non-logical     single cell     by name         variable/1,2
71    variables
72    ----------------------------------------------------------------
73    non-logical     array           by name         array/1,2
74    arrays
75    ----------------------------------------------------------------
76    named records   ordered list    by name         record/1,2
77    ----------------------------------------------------------------
78    dynamic         ordered list    by name         dynamic/1,assert/1
79    predicates
80    ----------------------------------------------------------------
81</PRE>
82    ")).
83
84:- comment(bag_create/1, [
85    summary:"Create a bag object which can store data across failures",
86    desc:html("\
87    	This creates an anonymous bag object which can be used to store
88	information across failures.  A typical application is the
89	implementation of the findall/3 predicate or similar functionality.
90	Bags are similar to records, with two differences: First, a bag
91	is considered unordered, so one should not expect the bag content
92	to indicate the order in which information was entered.
93	Second, bags are referred to by handle, not by name, so they make
94	it much easier to write robust, reentrant code.
95    "),
96    amode:(bag_create(-) is det),
97    args:["BagHandle":"A free variable"],
98    exceptions:[5 : "BagHandle is not a variable"],
99    eg:"
100    simple_findall(Goal, Solutions) :-
101    	bag_create(Bag),
102	(
103	    call(Goal),
104	    bag_enter(Bag, Goal),
105	    fail
106	;
107	    true
108	),
109	bag_dissolve(Bag, Solutions).
110    ",
111    see_also:[bag_erase/1, bag_enter / 2, bag_count/2, bag_dissolve / 2, bag_retrieve/2, bag_abolish/1]
112    ]).
113
114:- comment(bag_abolish/1, [
115    summary:"Destroy a bag explicitly",
116    desc:html("\
117	This explicitly destroys a previously created bag object and
118	frees all its memory.  Invoking bag_abolish/1 is optional,
119	the bag will be automatically destroyed when the system
120	backtracks across the call to bag_create/1, or when the
121	BagHandle is no longer needed and gets garbage collected.
122	bag_dissolve/2 will also destroy the bag.
123<P>
124	Using the BagHandle after it has been destroyed will lead
125	to an error message. Destroying an already destroyed bag
126	does nothing and is silently accepted.
127    "),
128    amode:(bag_abolish(+) is det),
129    args:["BagHandle":"A bag handle"],
130    exceptions:[4: "BagHandle is not instantiated",
131    	5 : "BagHandle is not a bag",
132    	40 : "BagHandle refers to an already destroyed bag"],
133    see_also:[bag_create/1, bag_enter/2, bag_count/2, bag_erase/1, bag_retrieve/2, bag_dissolve/2]
134    ]).
135
136:- comment(bag_erase/1, [
137    summary:"Erase the contents of a bag",
138    desc:html("\
139	This explicitly erases the contents of a previously created
140	bag object and frees the associated memory. After erasing,
141	the bag is in the same state as immediately after creation,
142	and can be filled with new contents.
143    "),
144    amode:(bag_erase(+) is det),
145    args:["BagHandle":"A bag handle"],
146    exceptions:[4: "BagHandle is not instantiated",
147    	5 : "BagHandle is not a bag",
148    	40 : "BagHandle refers to an already destroyed bag"],
149    eg:"
150    ?- bag_create(B), bag_enter(B, one), bag_erase(B), bag_enter(B, two), bag_retrieve(B, L).
151    B = 'BAG'(16'0030db60)
152    L = [two]
153    Yes (0.00s cpu)
154    ",
155    see_also:[bag_create/1, bag_abolish/1, bag_enter/2, bag_count/2, bag_retrieve/2, bag_dissolve/2]
156    ]).
157
158:- comment(bag_enter/2, [
159    summary:"Enter a term into an existing bag object",
160    desc:html("\
161    	This enters an arbitrary term into a bag object that has previously
162	been created with bag_create/1. The order in which terms are entered
163	into a bag should not be considered relevant, a bag is conceptually
164	unordered. Entering and retrieving terms from a bag involves
165	copying the term each time, similar to what happens in setval/getval
166	and record/recorded. In particular, if the term contains variables,
167	they lose their identity and are replaced with fresh ones.
168    "),
169    amode:(bag_enter(+,+) is det),
170    args:["BagHandle":"A bag", "Term":"An arbitrary term"],
171    exceptions:[4: "BagHandle is not instantiated",
172    	5 : "BagHandle is not a bag",
173    	40 : "BagHandle refers to an already destroyed bag"],
174    eg:"
175    simple_findall(Goal, Solutions) :-
176    	bag_create(Bag),
177	(
178	    call(Goal),
179	    bag_enter(Bag, Goal),
180	    fail
181	;
182	    true
183	),
184	bag_dissolve(Bag, Solutions).
185    ",
186    see_also:[bag_create / 1, bag_count/2, bag_abolish/1, bag_erase/1, bag_retrieve/2, bag_dissolve / 2]
187    ]).
188
189:- comment(bag_count/2, [
190    summary:"Get the number of entries in a bag",
191    desc:html("\
192	This returns an integer corresponding to the number of entries
193	currently in the bag. A fresh or erased bag has zero entries.
194    "),
195    amode:(bag_count(+,-) is det),
196    args:["BagHandle":"A bag", "Count":"A variable or integer"],
197    exceptions:[4: "BagHandle is not instantiated",
198    	5 : "BagHandle is not a bag",
199    	40 : "BagHandle refers to an already destroyed bag"],
200    eg:"
201    ?- bag_create(B), bag_count(B, N0), bag_enter(B, one), bag_count(B, N1).
202    N0 = 0
203    B = 'BAG'(16'0030dc48)
204    N1 = 1
205    Yes (0.00s cpu)
206    ",
207    see_also:[bag_create / 1, bag_enter / 2, bag_count/2, bag_erase/1, bag_abolish/1, bag_retrieve/2, bag_dissolve/2]
208    ]).
209
210:- comment(bag_retrieve/2, [
211    summary:"Retrieve a bag's contents",
212    desc:html("\
213	This returns a list containing a copy of every term that has
214	been entered into the bag since it was created.  It should not
215	be assumed that the list order reflects the order in which the
216	terms were entered into the bag.  Entering and retrieving
217	terms from a bag involves copying the term each time, similar
218	to what happens in setval/getval and record/recorded.  In
219	particular, if the term contains variables, they lose their
220	identity and are replaced with fresh ones.
221    "),
222    amode:(bag_retrieve(+,-) is det),
223    args:["BagHandle":"A bag", "List":"A variable or list of terms"],
224    exceptions:[4: "BagHandle is not instantiated",
225    	5 : "BagHandle is not a bag",
226    	40 : "BagHandle refers to an already destroyed bag"],
227    eg:"
228    simple_findall(Goal, Solutions) :-
229    	bag_create(Bag),
230	(
231	    call(Goal),
232	    bag_enter(Bag, Goal),
233	    fail
234	;
235	    true
236	),
237	bag_retrieve(Bag, Solutions),
238	bag_abolish(Bag).
239    ",
240    see_also:[bag_create / 1, bag_enter / 2, bag_count/2, bag_erase/1, bag_abolish/1, bag_dissolve/2]
241    ]).
242
243:- comment(bag_dissolve/2, [
244    summary:"Retrieve a bag's contents and destroy the bag",
245    desc:html("\
246	This returns a list containing a copy of every term that has
247	been entered into the bag since it was created.  The bag is
248	also destoyed.  It should not be assumed that the list order
249	reflects the order in which the terms were entered into the
250	bag.  Entering and retrieving terms from a bag involves
251	copying the term each time, similar to what happens in
252	setval/getval and record/recorded.  In particular, if the term
253	contains variables, they lose their identity and are replaced
254	with fresh ones.
255<P>
256	bag_dissolve/2 is equivalent to bag_retrieve/2, followed by
257	bag_abolish/1.  Using the BagHandle after it has been dissolved
258	will lead to an error message.
259    "),
260    amode:(bag_dissolve(+,-) is det),
261    args:["BagHandle":"A bag", "List":"A variable or list of terms"],
262    exceptions:[4: "BagHandle is not instantiated",
263    	5 : "BagHandle is not a bag",
264    	40 : "BagHandle refers to an already destroyed bag"],
265    eg:"
266    simple_findall(Goal, Solutions) :-
267    	bag_create(Bag),
268	(
269	    call(Goal),
270	    bag_enter(Bag, Goal),
271	    fail
272	;
273	    true
274	),
275	bag_dissolve(Bag, Solutions).
276    ",
277    see_also:[bag_create / 1, bag_enter / 2, bag_count/2, bag_erase/1, bag_retrieve/2, bag_abolish/1]
278    ]).
279
280:- comment(shelf_create/2, [
281    summary:"Create a shelf object which can store data across failures",
282    desc:html("\
283    	This creates a 'shelf' object which can be used to store
284	information across failures.  A typical application is counting
285	of solutions, keeping track of the best solution, aggregating
286	information across multiple solutions etc.
287<P>
288	A shelf is an object with multiple slots whose contents survive
289	backtracking. The content of each slot can be set and retrieved
290	individually, or the whole shelf can be retrieved as a term.
291<P>
292	Shelves are referred to by handle, not by name, so they make
293	it easy to write robust, reentrant code. A shelf disappears when
294	the system backtracks over its creation, when the shelf handle
295	gets garbage collected, or when it is explicitly destroyed.
296<P>
297	A shelf is initialized from a compound term InitTerm. InitTerm's
298	arity determines the number of slots the shelf provides, and
299	InitTerm's arguments are used to initialize the corresponding
300	shelf slots.
301    "),
302    amode:(shelf_create(+,-) is det),
303    args:["InitTerm":"A compound term",
304    	"ShelfHandle":"A free variable"],
305    exceptions:[
306    	4 : "InitTerm is not instantiated",
307    	5 : "InitTerm is instantiated but not to a compound term",
308    	5 : "ShelfHandle is not a variable"],
309    eg:"
310
311% a meta-predicate to count the number of solutions to a goal:
312
313    count_solutions(Goal, Total) :-
314    	shelf_create(count(0), Shelf),
315	(
316	    call(Goal),
317	    shelf_inc(Shelf, 1),
318	    fail
319	;
320	    shelf_get(Shelf, 1, Total)
321	),
322	shelf_abolish(Shelf).
323
324
325% finding the sum and maximum of data/1 facts:
326
327    data(2).
328    data(9).
329    data(3).
330    data(5).
331    data(7).
332
333    sum_and_max(Sum, Max) :-
334    	shelf_create(agg(0,0), Shelf),
335	(
336	    data(X),
337	    shelf_get(Shelf, 1, OldMax),
338	    ( X > OldMax -> shelf_set(Shelf, 1, X) ; true ),
339	    shelf_get(Shelf, 2, OldSum),
340	    NewSum is OldSum + X,
341	    shelf_set(Shelf, 2, NewSum),
342	    fail
343	;
344	    shelf_get(Shelf, 0, agg(Max, Sum))
345	),
346	shelf_abolish(Shelf).
347
348
349% if-then-else with backtracking over the condition:
350
351    if(Cond, Then, Else) :-
352	shelf_create(sol(no), SolFlag),
353	(
354	    call(Cond),
355	    shelf_set(SolFlag, 1, yes),   % remember there was a solution
356	    call(Then)
357	;
358	    shelf_get(SolFlag, 1, no),    % fail if there was a solution
359	    call(Else)
360	).
361    ",
362    see_also:[shelf_create/3, shelf_set/3, shelf_get/3, shelf_abolish/1,
363    	array/1, bag_create/1]
364    ]).
365
366:- comment(shelf_create/3, [
367    summary:"Create a shelf object which can store data across failures",
368    desc:html("\
369    	This creates a 'shelf' object which can be used to store
370	information across failures.  A typical application is counting
371	of solutions, keeping track of the best solution, aggregating
372	information across multiple solutions etc.
373<P>
374	A shelf is an object with multiple slots whose contents survive
375	backtracking. The content of each slot can be set and retrieved
376	individually, or the whole shelf can be retrieved as a term.
377<P>
378	Shelves are referred to by handle, not by name, so they make
379	it easy to write robust, reentrant code. A shelf disappears when
380	the system backtracks over its creation, when the shelf handle
381	gets garbage collected, or when it is explicitly destroyed.
382<P>
383	When using shelf_create/3, ShelfSpec determines the number of
384	slots on the shelf, and all slots get initialized identically
385	with the value SlotInit.
386    "),
387    amode:(shelf_create(++,?,-) is det),
388    args:["ShelfSpec":"A term of the form Name/Arity",
389    	"SlotInit":"The value used to initialize the slots (any term)",
390    	"ShelfHandle":"A free variable"],
391    exceptions:[
392    	4 : "ShelfSpec is not fully instantiated",
393    	5 : "ShelfSpec is fully instantiated but not to a term of the form Atom/Integer",
394    	5 : "ShelfHandle is not a variable"],
395    eg:"
396% finding the sum and maximum of data/1 facts:
397
398    data(2).
399    data(9).
400    data(3).
401    data(5).
402    data(7).
403
404    sum_and_max(Sum, Max) :-
405    	shelf_create(agg/2, 0, Shelf),
406	(
407	    data(X),
408	    shelf_get(Shelf, 1, OldMax),
409	    ( X > OldMax -> shelf_set(Shelf, 1, X) ; true ),
410	    shelf_get(Shelf, 2, OldSum),
411	    NewSum is OldSum + X,
412	    shelf_set(Shelf, 2, NewSum),
413	    fail
414	;
415	    shelf_get(Shelf, 0, agg(Max, Sum))
416	),
417	shelf_abolish(Shelf).
418    ",
419    see_also:[shelf_create/2, shelf_set/3, shelf_get/3, shelf_abolish/1]
420    ]).
421
422:- comment(shelf/2, [
423    summary:"Create a named shelf object which can store data across failures",
424    desc:html("\
425    	This creates a 'shelf' object which can be used to store
426	information across failures.  A typical application is counters
427	for statistics, etc.
428<P>
429	A shelf is an object with multiple slots whose contents survive
430	backtracking. The content of each slot can be set and retrieved
431	individually, or the whole shelf can be retrieved as a term.
432<P>
433	Shelves can be referred to either by handle or by name. Whenever
434	possible, handles should be used, because this naturally leads to
435	robust, reentrant code, and avoids the danger of memory leaks.
436	See shelf_create/2,3 for how to create shelves with a handle.
437<P>
438	Named shelves are identified by a functor. This is usually simply
439	an atom, but in general it can be name/arity pair.
440<P>
441	When named shelves are used, the visibility of the shelf name is
442	local to the module where it was created. A named shelf never
443	disappears, therefore, in order to free the associated memory,
444	its contents should be erased when no longer needed.
445<P>
446	Duplicate shelf declarations are silently ignored.
447    "),
448    template:"local shelf(++Name, +Init)",
449    amode:(shelf(++, +) is det),
450    args:["Name":"An atom, or an atom/integer structure",
451    	"Init":"A structure"],
452    exceptions:[
453	4 : "Name or Init is uninstantiated",
454	5 : "Init is not a structure",
455	5 : "Name is neither an atom nor an atom/integer structure"],
456    eg:"
457
458    % A store with the simple, atomic name 'counters'
459
460    :- local shelf(counters, count(0,0,0)).
461
462    main :-
463	shelf_get(counters,1,N0), N1 is N0+1, shelf_set(counters,1,N1),
464	printf(\"main has been called %d times%n\", [N1]).
465    ",
466    see_also:[shelf_create/2, shelf_create/3, (local)/1, shelf_set/3, shelf_get/3,
467	store_delete/2,
468    	store_contains/2, stored_keys/2, stored_keys_and_values/2,
469	store_erase/1, store_count/2]
470    ]).
471
472
473:- comment(shelf_set/3, [
474    summary:"Store a term in a shelf object",
475    desc:html("\
476	This stores an arbitrary term in the Index'th slot of the
477	shelf object denoted by ShelfHandle.  All other slots of the
478	shelf remain untouched.  The setting will persist until it is
479	replaced with a new setting, or until the shelf is destroyed. 
480	In particular, the setting will survive backtracking across
481	the call to shelf_set/3.
482<P>
483	The slots are numbered from 1 to the maximum which was determined
484	during shelf creation (but note that ECLiPSe's struct-syntax can
485	be used to give the slots symbolic names, see struct/1).
486<P>
487	Calling shelf_set/3 with an Index of 0 can be used to set all
488	slots at once. In this case, Term must be a compound term whose
489	functor corresponds to the one that was given during shelf creation.
490	Every shelf slot is set from the corresponding term argument.
491<P>
492	Storing and retrieving terms from a shelf involves copying the
493	term each time, similar to what happens in setval/getval and
494	record/recorded.  In particular, if the term contains variables,
495	they lose their identity and are replaced with fresh ones.
496	Also, the different slots of a shelf are separate entities,
497	in particular, they cannot share variables between each other.
498<P>
499	Note: If ShelfHandle is not a handle, then it must be an atom or a
500	compound term, and the shelf is identified by this term's toplevel
501	functor together with the context module.
502    "),
503    amode:(shelf_set(+,+,?) is det),
504    args:["ShelfHandle":"A shelf handle or shelf name",
505	    "Index":"An integer",
506	    "Term":"An arbitrary term"],
507    exceptions:[4: "ShelfHandle is not instantiated",
508    	5 : "Index is not instantiated",
509    	5 : "ShelfHandle is not a shelf",
510    	5 : "Index is not an integer",
511    	6 : "Index is negative or greater than the number of slots on the shelf",
512    	40 : "ShelfHandle refers to an already destroyed shelf"],
513    eg:"For examples see shelf_create/2,3.",
514    see_also:[shelf_create/2, shelf_create/3, shelf_get/3, shelf_abolish/1, struct/1]
515    ]).
516
517:- comment(shelf_get/3, [
518    summary:"Retrieve a stored term from a shelf object",
519    desc:html("\
520	This retrieves a copy of the stored term from the Index'th slot
521	of the shelf object denoted by ShelfHandle.
522<P>
523	The slots are numbered from 1 to the maximum which was determined
524	during shelf creation (but note that ECLiPSe's struct-syntax can
525	be used to give the slots symbolic names, see struct/1).
526<P>
527	Calling shelf_get/3 with an Index of 0 retrieves the whole
528	shelf with all its slots as a single compound term whose functor
529	corresponds to the one that was given during shelf creation.
530<P>
531	Storing and retrieving terms from a shelf involves copying the
532	term each time, similar to what happens in setval/getval and
533	record/recorded.  In particular, if the term contains variables,
534	they lose their identity and are replaced with fresh ones.
535<P>
536	Note: If ShelfHandle is not a handle, then it must be an atom or a
537	compound term, and the shelf is identified by this term's toplevel
538	functor together with the context module.
539    "),
540    amode:(shelf_get(+,+,-) is det),
541    args:["ShelfHandle":"A shelf handle or shelf name",
542	    "Index":"An integer",
543	    "Term":"An arbitrary term or a variable"],
544    exceptions:[4: "ShelfHandle is not instantiated",
545    	5 : "Index is not instantiated",
546    	5 : "ShelfHandle is not a shelf",
547    	5 : "Index is not an integer",
548    	6 : "Index is negative or greater than the number of slots on the shelf",
549    	40 : "ShelfHandle refers to an already destroyed shelf"],
550    eg:"For examples see shelf_create/2,3.",
551    see_also:[shelf_create/2, shelf_create/3, shelf_set/3, shelf_abolish/1, struct/1]
552    ]).
553
554:- comment(shelf_inc/2, [
555    summary:"Increment an integer slot within a shelf object",
556    desc:html("\
557	This looks up the entry in the Index'th slot of the shelf object
558	denoted by ShelfHandle, and if such an entry exists, and is of integer
559	type, it is incremented by one.  This predicate is a shorthand for:
560<PRE>
561	shelf_inc(ShelfHandle, Index) :-
562	    shelf_get(ShelfHandle, Index, C0),
563	    C1 is C0 + 1,
564	    shelf_set(ShelfHandle, Index, C1).
565</PRE>
566	The slots are numbered from 1 to the maximum which was determined
567	during shelf creation (but note that ECLiPSe's struct-syntax can
568	be used to give the slots symbolic names, see struct/1).
569<P>
570	Note: If ShelfHandle is not a handle, then it must be an atom or a
571	compound term, and the shelf is identified by this term's toplevel
572	functor together with the context module.
573    "),
574    amode:(shelf_inc(+,+) is det),
575    args:["ShelfHandle":"A shelf handle or shelf name",
576	    "Index":"An integer"],
577    exceptions:[4: "ShelfHandle is not instantiated",
578    	5 : "Index is not instantiated",
579    	5 : "ShelfHandle is not a shelf",
580    	5 : "Index is not an integer",
581    	6 : "Index is less than 1 or greater than the number of slots on the shelf",
582    	6 : "The counter value exceeds an implementation-defined limit (at least 2^31)",
583    	40 : "ShelfHandle refers to an already destroyed shelf"],
584    eg:"For examples see shelf_create/2,3.",
585    see_also:[shelf_create/2, shelf_create/3, shelf_dec/2, shelf_set/3, shelf_abolish/1, struct/1]
586    ]).
587
588:- comment(shelf_dec/2, [
589    summary:"Decrement an integer slot within a shelf object but fail if is zero",
590    desc:html("\
591	This looks up the entry in the Index'th slot of the shelf object
592	denoted by ShelfHandle, and if such an entry exists, and is of integer
593	type, it is decremented by one.  If the old value is already zero
594	(or less), the predicate fails and the shelf remains unchanged.
595	This predicate is a shorthand for:
596<PRE>
597	shelf_dec(ShelfHandle, Index) :-
598	    shelf_get(ShelfHandle, Index, C0),
599	    C0 > 0,
600	    C1 is C0 - 1,
601	    shelf_set(ShelfHandle, Index, C1).
602</PRE>
603	The slots are numbered from 1 to the maximum which was determined
604	during shelf creation (but note that ECLiPSe's struct-syntax can
605	be used to give the slots symbolic names, see struct/1).
606<P>
607	Note: If ShelfHandle is not a handle, then it must be an atom or a
608	compound term, and the shelf is identified by this term's toplevel
609	functor together with the context module.
610    "),
611    amode:(shelf_dec(+,+) is semidet),
612    args:["ShelfHandle":"A shelf handle or shelf name",
613	    "Index":"An integer"],
614    fail_if:"Fails if decrementing the value would result in a negative number",
615    exceptions:[4: "ShelfHandle is not instantiated",
616    	5 : "Index is not instantiated",
617    	5 : "ShelfHandle is not a shelf",
618    	5 : "Index is not an integer",
619    	6 : "Index is less than 1 or greater than the number of slots on the shelf",
620    	6 : "The old counter value exceeds an implementation-defined limit (at least 2^31)",
621    	40 : "ShelfHandle refers to an already destroyed shelf"],
622    eg:"
623    :- local shelf(backtrack_limit, count(100)).
624
625    nat(0).
626    nat(N) :-
627	shelf_dec(backtrack_limit, 1),   % fail when limit reached
628	nat(N0),
629    	N is N0+1.
630
631    ?- shelf_set(backtrack_limit, 1, 5),
632       findall(X, nat(X), L).
633
634    X = X
635    L = [0, 1, 2, 3, 4, 5]
636    Yes (0.00s cpu)
637    ",
638    see_also:[shelf_create/2, shelf_create/3, shelf_inc/2, shelf_set/3, shelf_abolish/1, struct/1]
639    ]).
640
641:- comment(shelf_abolish/1, [
642    summary:"Destroy a shelf explicitly",
643    desc:html("\
644	This explicitly destroys a previously created shelf object and
645	frees all its memory.  Invoking shelf_abolish/1 is optional,
646	the shelf will be automatically destroyed when the system
647	backtracks across the call to shelf_create/2,3, or when the
648	ShelfHandle is no longer needed and gets garbage collected.
649<P>
650	Using the ShelfHandle after it has been destroyed will lead
651	to an error message. Destroying an already destroyed shelf
652	does nothing and is silently accepted.
653    "),
654    amode:(shelf_abolish(+) is det),
655    args:["ShelfHandle":"A shelf handle"],
656    exceptions:[4: "ShelfHandle is not instantiated",
657    	5 : "ShelfHandle is not a shelf",
658    	40 : "ShelfHandle refers to an already destroyed shelf"],
659    eg:"For examples see shelf_create/2,3.",
660    see_also:[shelf_create/2, shelf_create/3, shelf_get/3, shelf_set/3]
661    ]).
662
663:- comment(current_array / 2, [
664	summary:"Succeeds if there exists an array as denoted by Array and with type and
665visibility as given in the list Options.
666
667",
668	amode:(current_array(-,-) is nondet),
669	amode:(current_array(+,-) is semidet),
670	desc:html("\
671   current_array/2 is used to retrieve information about existing
672   visible arrays, non-logical variables and references.  Array is a
673   term denoting the array's name and dimensions and Options is a list
674   describing the array's type (prolog, float, integer or byte) and visibility.
675"),
676	args:["Array" : "Atom or compound term.",
677	"Options" : "Variable or list."],
678	fail_if:"Fails if there is no array whose name unifies with ArrayName",
679	exceptions:[5 : "Array is neither variable, atom nor compound term.", 5 : "Options is neither a list nor a variable."],
680	eg:"
681[eclipse 1]: local array(a(2)), array(b(2,3,4), float).
682
683yes.
684[eclipse 2]: current_array(a(Size), [Type,Vis|_]).
685
686Size = 2
687Type = prolog
688Vis = local
689yes.
690[eclipse 3]: current_array(Array, Props).
691
692Array = a(2)
693Props = [prolog, local]     More? (;)
694
695Array = b(2, 3, 4)
696Props = [float, local]     More? (;)
697
698no (more) solution.
699
700Error:
701      current_array(\"a\", L).    (Error 5).
702      current_array(a, 9).      (Error 5).
703
704
705",
706	see_also:[array / 1, array / 2, variable / 1]]).
707
708:- comment(decval / 1, [
709	summary:"Decrements the contents of the visible non-logical variable or array element ElemSpec by one.",
710	amode:(decval(++) is det),
711	desc:html("\
712   Decrements by one the value of ElemSpec that must be of type integer.
713<P>
714   If ElemSpec is an atom, it must specify a non-logical variable visible
715   from the caller module.
716<P>
717   If ElemSpec is a compound term, it must specify an element visible
718   array.  All its arguments must be non negative integer smallers than the
719   bound specified with array/1/2 or variable/1.
720<P>
721"),
722	args:["ElemSpec" : "Atom or ground compound term whose arguments are non negative integers."],
723	exceptions:[4 : "ElemSpec is not instantiated.",
724	    5 : "ElemSpec is a structure whose arguments are not all integers.",
725	    5 : "ElemSpec is neither an atom nor a ground structure.",
726	    5 : "The value or type of ElemSpec is not integer.",
727	    6 : "Array index in ElemSpec is out of bounds.",
728	    41 : "ElemSpec does not designate an existing array, variable or reference."],
729	eg:"
730Success:
731      [eclipse]: local(array(a(4), prolog)),
732              setval(a(0), -2),
733              decval(a(0)),
734              getval(a(0),X).
735      X = -3
736      yes.
737
738      [eclipse]: local(array(g(4, 5), integer)),
739              decval(g(3, 2)),
740              getval(g(3, 2), X).
741      X = -1
742      yes.
743
744      [eclipse]: setval(a, 3),
745              decval(a),
746              getval(a, X).
747      X = 2
748      yes.
749
750Error:
751      decval(X).                          (Error 4).
752      setval(a, 2.0),
753          decval(a).                      (Error 5).
754      local(array(a(2), float)),
755          decval(a(1)).                   (Error 5).
756      local(array(a(2))),
757          decval(a(2)).                   (Error 6).
758      decval(no_var).                     (Error 41).
759      decval(noarray(2, 4)).              (Error 41).
760
761
762
763",
764	see_also:[getval / 2, incval / 1, array / 1, array / 2, variable / 1, setval / 2]]).
765
766:- comment(erase_array / 1, [
767	summary:"Erases existing visible array, non-logical variable or reference.",
768	amode:(erase_array(++) is det),
769	desc:html("\
770   Used to erase the visible array uniquely specified by ArraySpec.
771<P>
772   Also used to erase the existing non-logical variable or reference ArraySpec.
773   ArraySpec is of the form Atom/0, or just Atom.
774<P>
775   Erasing reclaims the memory occupied by the array or variable.
776"),
777	args:["ArraySpec" : "Of the form Atom/Integer or just atom."],
778	exceptions:[4 : "ArraySpec is not instantiated.",
779	    5 : "ArraySpec is not an atom or of the form Atom/Integer.",
780	    41 : "ArraySpec specifies an array, variable or reference which does not exist."],
781	eg:"
782Success:
783      local(array(a(4,3))), erase_array(a/2).
784      setval(i,1), erase_array(i).
785      setval(i,1), erase_array(i/0).
786
787Error:
788      erase_array(X).                  (Error 4).
789      local(array(a(4,2))),
790          erase_array(a(4,2)).         (Error 5).
791      erase_array(no_array/1).         (Error 41).
792      erase_array(no_array).           (Error 41).
793
794
795
796",
797	see_also:[current_array / 2, array / 1, array / 2, variable / 1, setval / 2]]).
798
799:- comment(getval / 2, [
800	summary:"Retrieves the value of the visible array element, non-logical variable or reference ElemSpec",
801	amode:(getval(++,-) is det),
802	desc:html("\
803   If ElemSpec is the name of a visible non-logical variable, it unifies
804   the copied value of the variable with Value.
805<P>
806   If ElemSpec is a compound term, it must specify an element of a visible
807   non-logical array, all its arguments must be non negative integers smaller
808   than the bounds specified with array/1/2 or variable/1. The copied value
809   of the array element is unified with Value.
810<P>
811   If Element is the name of a reference, Value is unified with
812   the actual term the reference refers to (no copying involved).
813"),
814	args:["ElemSpec" : "Atom or ground compound term with non negative integer arguments.", "Value" : "Prolog term."],
815	exceptions:[4 : "ElemSpec is not ground.",
816	    5 : "ElemSpec is neither an atom nor a structure whose arguments are integers.",
817	    6 : "An array index in ElemSpec is out of bounds",
818	    41 : "ElemSpec does not designate an existing array, variable or reference."],
819	eg:"
820Success:
821      local(array(a(4), float)),
822          setval(a(2), 2.0),
823          getval(a(2), 2.0).
824      setval(i, \"2\"),
825          getval(i, V)).   (gives V = \"2\").
826
827Failure:
828      local(array(a(2))),
829          setval(a(1), 8.6),
830          getval(a(1), 10.0).
831      setval(i, 3),
832          getval(i, 0)).
833
834Error:
835      getval(X, 1).                   (Error 4).
836      getval(a(X), 1).                (Error 4).
837      getval(\"a\", V).                 (Error 5).
838      getval(a(2.0), V).              (Error 5).
839      getval(a(-1), V).               (Error 6).
840      getval(no_array(0), X).         (Error 41).
841      getval(no_var, X).              (Error 41).
842
843
844
845",
846	see_also:[decval / 1, incval / 1, array / 1, array / 2, variable / 1, setval / 2]]).
847
848:- comment(incval / 1, [
849	summary:"Increments the contents of the visible non-logical variable or array element ElemSpec by one.",
850	amode:(incval(++) is det),
851	desc:html("   Increments the value of the element ElemSpec that must be of type
852   integer.
853
854<P>
855   If ElemSpec is an atom, it must specify a non-logical variable visible from
856   the caller module.
857<P>
858   If ElemSpec is a compound term, it must specify a visible array element.
859   all its arguments must be non negative integers smaller than the bounds
860   specified with array/1/2 or variable/1.
861"),
862	args:["ElemSpec" : "Atom or ground compound term with non negative integer arguments."],
863	exceptions:[4 : "ElemSpec is not instantiated.",
864	    5 : "ElemSpec is a structure whose arguments are not all    integers.",
865	    5 : "ElemSpec is neither an atom nor a ground structure.",
866	    5 : "The value or type of ElemSpec is not integer.",
867	    6 : "Array index in ElemSpec is out of range.",
868	    41 : "ElemSpec does not designate an existing array, variable or reference."],
869	eg:"
870Success:
871      [eclipse]: local(array(a(4), prolog)),
872              setval(a(1), -2),
873              incval(a(1)),
874              getval(a(1), X).
875      X = -1
876      yes.
877
878      [eclipse]: local(array(g(4), integer)),
879              incval(g(1)),
880              getval(g(1), X).
881      X = 1
882      yes.
883
884      [eclipse]: setval(count, 0),
885              repeat,
886              writeln(hello),
887              incval(count),
888              getval(count, X),
889              X >= 3, !.
890      hello
891      hello
892      hello
893      X = 3
894      yes.
895
896Error:
897
898      incval(X).                            (Error 4).
899      incval(a(2.0)).                       (Error 5).
900      setval(a, 2.0), incval(a).            (Error 5).
901      local(array(a(2), float)),
902          incval(a(1)).                     (Error 5).
903      local(array(a(10), integer)),
904          incval(a(-2)).                    (Error 6).
905      incval(no_array(0)).                  (Error 41).
906      incval(no_var).                       (Error 41).
907
908
909
910",
911	see_also:[decval / 1, array / 1, array / 2, variable / 1, getval / 2, setval / 2]]).
912
913
914:- comment(array / 1, [
915	summary:"Creates the untyped non-logical array Array.",
916	template:"local array(++Array)",
917	amode:(array(++) is det),
918	desc:html("\
919   If Array is a compound term, a non-logical array (visible only in
920   the caller module) of type prolog is created.  Its dimension is the
921   arity of the term Array and the size of each dimension is specified
922   by the corresponding argument of the term Array.  The elements of
923   arrays of type prolog are initialised to free variables.
924<P>
925   The array indexes in the array range from 0 to the dimension minus one.
926   For example myarray create with <CODE>local array(myarray(3,4,5))</CODE>
927   contains 60 elements that may be accessed from myarray(0,0,0)
928   to myarray(2,3,4).
929<P>
930   The contents of the array persists across failures.
931   The value of the array elements can be changed with
932   setval/2 and retrieved with getval/2.  Setting and retrieving terms
933   from a non-logical arrays involves copying the term each time. 
934   In particular, if the term contains variables, they lose their
935   identity and are replaced with fresh ones.
936<P>
937   Notes:
938<P>
939   <CODE>local array(A)</CODE> is equivalent to <CODE>local array(A, prolog)</CODE>.
940"),
941	args:["Array" : "Ground compound term with integer arguments."],
942	exceptions:[4 : "Array is not ground.",
943	    5 : "Array is not a structure with integer arguments.",
944	    6 : "The ground structure Array has arguments that are integers not greater than 0.",
945	    24: "The ground structure Array has arguments that are non-numbers.",
946	    42 : "An array with the same name and dimension as Array already exists."],
947	eg:"
948Success:
949      local array(a(4)).
950      local array(b(2,3)).
951      local array(a(4)), array(a(4,1)).
952
953Error:
954      local array(X).                        (Error 4).
955      local array(a(6.0)).                   (Error 5).
956      local array(a(0)).                     (Error 6).
957      local array(a(-2)).                    (Error 6).
958      local array(a(4)), array(a(5)).        (Warning 42).
959",
960	see_also:[current_array/2, array / 2, decval / 1, incval / 1, bag_create / 1, shelf_create/2, shelf_create/3, getval / 2, setval / 2]]).
961
962
963:- comment(array / 2, [
964	summary:"Creates a non-logical array Array with given Type.",
965	template:"local array(+Array, +Type)",
966	amode:(array(++,+) is det),
967	desc:html("\
968   If Array is a compound term, a non-logical array (visible only in
969   the caller module) of type prolog is created.  Its dimension is the
970   arity of the term Array and the size of each dimension is specified
971   by the corresponding argument of the term Array.
972   The elements of the array are initialised depending on the type:
973   float, integer and byte arrays are initialised with 0 values, prolog
974   arrays are initialised with free variables.
975<P>
976   The array indexes in the array range from 0 to the dimension minus one.
977   For example myarray create with <CODE>local array(myarray(3,4,5), integer)</CODE>
978   contains 60 integers that may be accessed from myarray(0,0,0) to
979   myarray(2,3,4).
980<P>
981   The contents of the array persists across failures.
982   The value of the array elements can be changed with
983   setval/2 and retrieved with getval/2.  Setting and retrieving terms
984   from a non-logical arrays involves copying the term each time. 
985   In particular, if the term contains variables, they lose their
986   identity and are replaced with fresh ones.
987<P>
988   Notes:
989<P>
990   Re-declaring an existing array with the same dimension but different
991   sizes or type raises a warning.
992"),
993	args:["Array" : "Ground compound term with integer arguments.",
994		"Type": "One of the atoms: float, integer, byte, prolog"],
995	exceptions:[4 : "Array or Type is not ground.",
996	    5 : "Array is not a structure with integer arguments.",
997	    5 : "Type is not an atom.",
998	    6 : "Type is not a valid type name.",
999	    6 : "The ground structure Array has arguments that are integers not greater than 0.",
1000	    24: "The ground structure Array has arguments that are non-numbers.",
1001	    42 : "An array with the same name and dimension as Array already exists."],
1002	eg:"
1003Success:
1004      local array(a(4), prolog).
1005      local array(b(2,3), integer).
1006      local array(a(4), float), array(a(4,1), byte).
1007
1008Error:
1009      local array(X, prolog).                         (Error 4).
1010      local array(a(6.0), integer).                   (Error 5).
1011      local array(a(0), integer).                     (Error 6).
1012      local array(a(-2), integer).                    (Error 6).
1013      local array(a(4), integer), array(a(5), float).  (Warning 42).
1014",
1015	see_also:[current_array/2, array / 2, decval / 1, incval / 1, bag_create / 1, shelf_create/2, shelf_create/3, getval / 2, setval / 2]]).
1016
1017
1018:- comment(variable / 1, [
1019	summary:"Creates the untyped non-logical variable Name.",
1020	template:"local variable(+Name)",
1021	amode:(variable(+) is det),
1022	desc:html("\
1023   If Name is an Atom, a non-logical variable (visible only in the
1024   caller module) is created.  Its value is initialised to a free
1025   variable.  The contents of the variable persists across failures.
1026   The value of a non-logical variable can be changed with
1027   setval/2 and retrieved with getval/2.  Setting and retrieving terms
1028   from a non-logical variable involves copying the term each time. 
1029   In particular, if the term contains variables, they lose their
1030   identity and are replaced with fresh ones.
1031<P>
1032   Notes:
1033<P>
1034   Declaring a variable twice is silently accepted.
1035"),
1036	args:["Name" : "An atom."],
1037	exceptions:[4 : "Name is not instantiated.",
1038	    5 : "Name is not an atom."],
1039	eg:"
1040Success:
1041      :- local variable(a).
1042      :- local variable(count), variable(value).
1043
1044Error:
1045      :- local variable(X).                        (Error 4).
1046      :- local variable(6).                        (Error 5).
1047",
1048	see_also:[current_array/2, array/1, array / 2, decval / 1, incval / 1, bag_create / 1, getval / 2, setval / 2, reference/1, reference/2, variable/2]]).
1049
1050
1051:- comment(variable / 2, [
1052	summary:"Creates the untyped non-logical variable Name.",
1053	template:"local variable(+Name, ?Init)",
1054	amode:(variable(+,?) is det),
1055	desc:html("\
1056   A non-logical variable with name Name (visible only in the
1057   caller module) is created.  Its value is initialised to Init.
1058   The contents of the variable persists across failures.
1059   The value of a non-logical variable can be changed with
1060   setval/2 and retrieved with getval/2.  Setting and retrieving terms
1061   from a non-logical variable involves copying the term each time. 
1062   In particular, if the term contains variables, they lose their
1063   identity and are replaced with fresh ones.
1064<P>
1065   Notes:
1066<P>
1067   Declaring a variable twice is silently accepted, and the second
1068   declaration is ignored.
1069"),
1070	args:["Name" : "An atom.", "Init":"Any term"],
1071	exceptions:[4 : "Name is not instantiated.",
1072	    5 : "Name is not an atom."],
1073	eg:"
1074Success:
1075      :- local variable(a,[]).
1076      :- local variable(count,0), variable(value,colour(red)).
1077
1078Error:
1079      :- local variable(X, []).                      (Error 4).
1080      :- local variable(6, 0).                       (Error 5).
1081",
1082	see_also:[current_array/2, array/1, array / 2, decval / 1, incval / 1, bag_create / 1, getval / 2, setval / 2, reference/1, reference/2, variable/1]]).
1083
1084
1085:- comment(reference / 1, [
1086	summary:"Creates a named reference called Name.",
1087	template:"local reference(+Name)",
1088	amode:(reference(+) is det),
1089	desc:html("\
1090   This creates a named reference with the atomic name Name.  A named
1091   reference can be used to hold a reference to a term in the same way
1092   as a logical variable.  Unlike the non-logical variables, the value
1093   of a reference is not a copy, but identical to the original term it
1094   was set to.  This implies that the value behaves logically, i.e. 
1095   it disappears on backtracking, bindings to the variables inside it
1096   are undone on backtracking etc.  A typical example of it use is global
1097   state that a set of predicates wants to share without having to
1098   pass an argument pair through all the predicate invocations. 
1099<P>
1100   Changing the value of a reference is similar to changing an argument
1101   of a compound term using setarg/3.
1102<P>
1103   The initial value of a reference is the integer 0. To have a different
1104   initial value, use reference/2.
1105<P>
1106   There are no arrays of references, but the same effect can be
1107   achieved by storing a structure in a reference and using the
1108   structure's arguments.  The arguments can then be accessed and
1109   modified using arg/3 and setarg/3 respectively. 
1110<P>
1111   Note: Declaring a reference twice is silently accepted, and the second
1112   declaration is ignored.
1113"),
1114	args:["Name" : "An atom."],
1115	exceptions:[4 : "Name is not instantiated.",
1116	    5 : "Name is not an atom."],
1117	eg:"
1118% comparison between references and nonlogical variables
1119
1120      [eclipse 1]: local reference(a), variable(b).
1121
1122      yes.
1123      [eclipse 2]: Term = p(X), setval(a, Term), getval(a, Y), Y == Term.
1124      X = X
1125      Y = p(X)
1126      Term = p(X)
1127      yes.
1128      [eclipse 3]: Term = p(X), setval(b, Term), getval(b, Y), Y == Term.
1129
1130      no (more) solution.
1131
1132% values of references are subject to backtracking:
1133
1134    [eclipse 4]: setval(a, 1), (setval(a, 2), getval(a, X); getval(a, Y)).
1135      X = 2
1136      Y = Y     More? (;) 
1137
1138      X = X
1139      Y = 1
1140
1141",
1142	see_also:[reference/2, setval/2, getval/2, setarg / 3, arg/3]]).
1143
1144
1145:- comment(reference / 2, [
1146	summary:"Creates a named reference called Name with intial value Init.",
1147	template:"local reference(+Name, ++Init)",
1148	amode:(reference(+,++) is det),
1149	desc:html("\
1150   This creates a named reference with the atomic name Name.  A named
1151   reference can be used to hold a reference to a term in the same way
1152   as a logical variable.  Unlike the non-logical variables, the value
1153   of a reference is not a copy, but identical to the original term it
1154   was set to.  This implies that the value behaves logically, i.e. 
1155   it disappears on backtracking, bindings to the variables inside it
1156   are undone on backtracking etc.  A typical example of it use is global
1157   state that a set of predicates wants to share without having to
1158   pass an argument pair through all the predicate invocations. 
1159<P>
1160   Changing the value of a reference is similar to changing an argument
1161   of a compound term using setarg/3.
1162<P>
1163   The initial value of the reference is Init, which must be a ground term.
1164<P>
1165   There are no arrays of references, but the same effect can be
1166   achieved by storing a structure in a reference and using the
1167   structure's arguments.  The arguments can then be accessed and
1168   modified using arg/3 and setarg/3 respectively. 
1169<P>
1170   Note: Declaring a reference twice is silently accepted, and the second
1171   declaration is ignored.
1172"),
1173	args:["Name" : "An atom.", "Init":"A ground term"],
1174	exceptions:[4 : "Name is not instantiated.",
1175	    4 : "Init is not a ground term.",
1176	    5 : "Name is not an atom."],
1177	eg:"
1178
1179      [eclipse 1]: local reference(a,0).
1180
1181      yes.
1182      [eclipse 2]: ( getval(a, Old), setval(a, 27), getval(a, New)
1183		   ; getval(a, Then) ).
1184      Old = 0
1185      New = 27
1186      Then = Then
1187      Yes (0.00s cpu, solution 1, maybe more) ? ;
1188
1189      Old = Old
1190      New = New
1191      Then = 0
1192      Yes (0.00s cpu, solution 2)
1193
1194",
1195	see_also:[reference/1, setval/2, getval/2, setarg / 3, arg/3]]).
1196
1197
1198:- comment(setval / 2, [
1199	summary:"Sets the value of a non-logical variable, array element, or reference to the value Value.",
1200	amode:(setval(++,?) is det),
1201	desc:html("\
1202   If ElemSpec is the name of a visible non-logical variable, its
1203   value gets set to a copy of the term value.  If there was no
1204   variable visible from the caller module, a local non-logical
1205   variable is created and its value is set.  The value of a
1206   non-logical variable can be overwritten any number of times with
1207   any data type, including a free variable. Values of non-logical
1208   variables are copies of the original term and persist across failures.
1209<P>
1210   If ElemSpec is a compound term, it must specify a visible array element:
1211   all its argument must be non negative integers smaller than the bounds
1212   specified with array/1 or array/2.
1213   If the array has been created with array/2, then Value is restricted
1214   to the type given in the declaration; otherwise Value can have any type,
1215   including a free variable.  Its value can be overwritten any number of times.
1216   Values of non-logical arrays are copies of the original term and persist
1217   across failures.
1218<P>
1219   If ElemSpec is the name of a visible reference, its value will be set
1220   to the term value.  Unlike for non-logical variables, the value of a
1221   reference is the original term, not a copy. Setting the value of a
1222   reference is undone on backtracking, i.e. the value of the reference
1223   reverts to what it was before being changed.
1224"),
1225	args:["ElemSpec" : "Atom (non-logical variable or reference) or fully instantiated compound term with positive integer arguments (array element specification).",
1226	    "Value" : "Prolog term."],
1227	exceptions:[4 : "ElemSpec is not ground", 4 : "ElemSpec is of an array of type integer, float or byte and Value is not instantiated", 5 : "the type of Value is not of the declared type of ElemSpec.", 5 : "ElemSpec is a structure whose arguments are not all integers.", 5 : "ElemSpec is neither an atom nor a ground structure.", 6 : "Array index in ElemSpec is out of bounds.", 41:"ElemSpec is an element of an array which does not exist."],
1228	eg:"
1229Success:
1230      local(array(a(4,3))),
1231          setval(a(0,0), 2),
1232          setval(a(1,2), \"string\"),
1233          % overwrite a(0,0) (= 2) with a free variable
1234          setval(a(0,0), X).
1235      local(array(a(4), float)),
1236          setval(a(0), 2.0),
1237          setval(a(3), -19.6).
1238      setval(i, 4).
1239      setval(j, 4),
1240           setval(j, \"string data\").
1241
1242Error:
1243      setval(A, 2.0).            (Error 4).
1244      setval(a(V), 2.0).         (Error 4).
1245      setval(a(1.0), 2).         (Error 5).
1246      setval(\"b(0)\", 2.0).       (Error 5).
1247      local(array(a(4))),
1248          setval(a(-2), 2).      (Error 6).
1249      local(array(a(9), integer)),
1250          setval(a(9), 4).       (Error 6).
1251      setval(no_array(1), 2.0).  (Error 41).
1252
1253
1254
1255",
1256	see_also:[decval / 1, erase_array / 1, incval / 1, array / 1, array / 2, variable / 1, getval / 2]]).
1257
1258:- comment(test_and_setval / 3, [
1259	summary:"Test whether a non-logical variable has value Old and if so, set it to New.",
1260	amode:(test_and_setval(+,?,?) is semidet),
1261	desc:html("\
1262   VarName must be the name of a non-logical variable (not an array
1263   element and not a reference).  If the current value of this
1264   variable is not identical to Old, the predicate fails.  If it is
1265   identical, the variable's value gets changed to the value New. 
1266   Test and set is done as an atomic operation.
1267"),
1268	args:["VarName" : "An atom", "Old" : "A term", "New":"A term"],
1269	fail_if:"Fails it the current value of the variable is not identical to Old",
1270	exceptions:[4 : "VarName is not ground",
1271	    5 : "VarName not an atom",
1272	    5 : "VarName is the name of a reference",
1273	    41: "VarName is not the name of a non-logical variable."],
1274	eg:"
1275Success:
1276     ?- setval(k, 3), test_and_setval(k, 3, 5).
1277
1278     wait_for_lock :-
1279	    ( test_and_setval(lock, 0, 1) ->
1280		true
1281	    ;
1282	        wait_for_lock
1283	    ).
1284
1285Fail:
1286      setval(k, 1), test_and_setval(k, 3, 5).
1287",
1288	see_also:[decval / 1, incval / 1, variable / 1, setval/2, getval / 2]]).
1289
1290
1291
1292
1293:- comment(store/1, [
1294    summary:"Create a named store object which can store indexed data across failures",
1295    desc:html("\
1296    	This creates a 'store' object which provides indexed access to
1297	key-value pairs, and whose contents are unaffected by backtracking.
1298<P>
1299	A store is a persistent (w.r.t. backtracking) hash table. It can
1300	store arbitrary ECLiPSe terms under arbitrary ground keys.
1301<P>
1302	Stores can be referred to either by handle or by name. Whenever
1303	possible, handles should be used, because this naturally leads to
1304	robust, reentrant code, and avoids the danger of memory leaks.
1305	See store_create/1 for how to create stores with a handle.
1306<P>
1307	Named stores are identified by a functor. This is usually simply
1308	an atom, but in general it can be name/arity pair.
1309<P>
1310	When named stores are used, the visibility of the store name is
1311	local to the module where it was created. A named store never
1312	disappears, therefore, in order to free the associated memory,
1313	its contents should be erased when no longer needed.
1314<P>
1315	Duplicate store declarations are silently ignored.
1316    "),
1317    template:"local store(++Name)",
1318    amode:(store(++) is det),
1319    args:["Name":"An atom, or an atom/integer structure"],
1320    exceptions:[
1321	4 : "Name is uninstantiated",
1322	5 : "Name is neither an atom nor an atom/integer structure"],
1323    eg:"
1324
1325    % A store with the simple, atomic name 'phone_numbers'
1326
1327    :- local store(phone_numbers).
1328
1329    main1 :-
1330	store_set(phone_numbers, name(peter,panther), data(1234,mobile)),
1331	store_set(phone_numbers, name(tom,tiger), data(4567,home)),
1332	stored_keys_and_values(phone_numbers, Contents),
1333	writeln(Contents).
1334
1335
1336    % A store identified by the functor foo/3
1337
1338    :- local store(foo/3).
1339
1340    main2 :-
1341	store_set(foo(_,_,_), key_1, value_1),
1342	store_set(foo(_,_,_), key_2, value_2),
1343	stored_keys_and_values(foo(_,_,_), Contents),
1344	writeln(Contents).
1345    ",
1346    see_also:[current_store/1, store_create/1, (local)/1, store_set/3, store_get/3, store_delete/2,
1347    	store_contains/2, stored_keys/2, stored_keys_and_values/2,
1348	store_erase/1, store_count/2]
1349    ]).
1350
1351
1352:- comment(store_create/1, [
1353    summary:"Create an anonymous store object which can store indexed data across failures",
1354    desc:html("\
1355    	This creates a 'store' object which provides indexed access to
1356	key-value pairs, and whose contents are unaffected by backtracking.
1357<P>
1358	A store is a persistent (w.r.t. backtracking) hash table. It can
1359	store arbitrary ECLiPSe terms under arbitrary ground keys.
1360<P>
1361	Stores can be referred to either by handle or by name. Whenever
1362	possible, handles should be used, because this naturally leads to
1363	robust, reentrant code, and avoids the danger of memory leaks.
1364	A store disappears when the system backtracks over its creation,
1365	when the store handle gets garbage collected, or when it is
1366	explicitly destroyed.
1367<P>
1368	When named stores are used, the visibility of the store name is
1369	local to the module where it was created. A named store never
1370	disappears, therefore, in order to free the associated memory,
1371	its contents should be erased when no longer needed.
1372    "),
1373    amode:(store_create(-) is det),
1374    args:["StoreHandle":"A free variable"],
1375    exceptions:[5 : "StoreHandle is not a variable"],
1376    eg:"
1377
1378% Creating and using an 'anonymous store'
1379
1380    main2 :-
1381	store_create(Handle),
1382	store_set(Handle, name(peter,panther), data(1234,mobile)),
1383	store_set(Handle, name(tom,tiger), data(4567,home)),
1384	stored_keys_and_values(Handle, Contents),
1385	writeln(Contents).
1386
1387
1388% Creating and using a 'named store'
1389
1390    :- local store(phone_numbers).
1391
1392    main1 :-
1393	store_set(phone_numbers, name(peter,panther), data(1234,mobile)),
1394	store_set(phone_numbers, name(tom,tiger), data(4567,home)),
1395	stored_keys_and_values(phone_numbers, Contents),
1396	writeln(Contents).
1397    ",
1398    see_also:[store/1, (local)/1, store_set/3, store_get/3, store_delete/2,
1399    	store_contains/2, stored_keys/2, stored_keys_and_values/2,
1400	store_erase/1, store_count/2]
1401    ]).
1402
1403
1404:- comment(store_erase/1, [
1405    summary:"Erase the contents of the specified store object",
1406    desc:html("\
1407    	This erases the contents of the store object and frees the associated
1408	memory. The store object itself remains valid and is equivalent to a
1409	newly created store.
1410<P>
1411	Note that anonymous stores (which are referred to by handle rather
1412	than name) are automatically erased and destroyed when their handle
1413	gets garbage collected, or when failing across their creation point.
1414<P>
1415	On the other hand, named stores should be explicitly erased,
1416	otherwise their contents will continue to occupy memory.
1417<P>
1418	Calling store_erase/1 is equivalent to deleting every entry in
1419	the store via store_delete/2.
1420<P>
1421	Note: If StoreHandle is not a handle, then it must be an atom or a
1422	compound term, and the store is identified by this term's toplevel
1423	functor together with the context module.
1424	.
1425    "),
1426    amode:(store_erase(+) is det),
1427    args:["StoreHandle":"A store handle or store name"],
1428    exceptions:[
1429	4 : "StoreHandle is uninstantiated",
1430	5 : "StoreHandle is neither atom nor compound term nor store handle",
1431	45 : "StoreHandle is not the name of a store"],
1432    eg:"
1433
1434    ?- store_create(Handle),
1435       store_set(Handle, key, value),
1436       stored_keys_and_values(Handle, Data1),
1437       store_count(Handle, N1),
1438       store_erase(Handle),
1439       stored_keys_and_values(Handle, Data2),
1440       store_count(Handle, N2).
1441
1442    Handle = 'STORE'(16'002f4da0)
1443    Data1 = [key - value]
1444    N1 = 1
1445    Data2 = []
1446    N2 = 0
1447    Yes (0.00s cpu)
1448    ",
1449    see_also:[store/1, (local)/1, store_set/3, store_get/3, store_delete/2,
1450    	store_contains/2, stored_keys/2, stored_keys_and_values/2,
1451	store_create/1, store_count/2]
1452    ]).
1453
1454:- comment(store_count/2, [
1455    summary:"Retrieve the number of entries in a store object",
1456    desc:html("\
1457    	This returns the count of the number of entries in a store object.
1458    	For an empty store, 0 (zero) is returned.
1459<P>
1460	Note: If StoreHandle is not a handle, then it must be an atom or a
1461	compound term, and the store is identified by this term's toplevel
1462	functor together with the context module.
1463    "),
1464    amode:(store_count(+,-) is det),
1465    args:["StoreHandle":"A store handle or store name",
1466    	"Count":"Variable or integer"],
1467    exceptions:[
1468	4 : "StoreHandle is uninstantiated",
1469	5 : "StoreHandle is neither atom nor compound term nor store handle",
1470	45 : "StoreHandle is not the name of a store"],
1471    eg:"
1472
1473    ?- store_create(Handle),
1474       store_count(Handle, N1),
1475       store_set(Handle, tom, 12345),
1476       store_count(Handle, N2),
1477       store_set(Handle, dick, 42376),
1478       store_count(Handle, N3),
1479       store_set(Handle, harry, 84223),
1480       store_count(Handle, N4),
1481       store_delete(Handle, dick),
1482       store_count(Handle, N5),
1483       store_erase(Handle),
1484       store_count(Handle, N6).
1485
1486    Handle = 'STORE'(16'002f4ef8)
1487    N1 = 0
1488    N2 = 1
1489    N3 = 2
1490    N4 = 3
1491    N5 = 2
1492    N6 = 0
1493    Yes (0.00s cpu)
1494    ",
1495    see_also:[store/1, (local)/1, store_set/3, store_get/3, store_delete/2,
1496    	store_contains/2, stored_keys/2, stored_keys_and_values/2,
1497	store_create/1, store_count/2]
1498    ]).
1499
1500:- comment(store_set/3, [
1501    summary:"Make an entry into a store object",
1502    desc:html("\
1503	This stores an arbitrary ECLiPSe term under a given key into
1504	the given store object. If an entry for this key already exists,
1505	it will be replaced by the new entry. 
1506<P>
1507	The key can be arbitrarily complex, but must be a ground term.
1508	The value can be an arbitrary term, and may contain uninstantiated
1509	variables. Note that values are copied when being stored or
1510	retrieved, therefore a retrieved nonground value will contain
1511	fresh variables rather than the original ones (this is similar
1512	to the behaviour of bags, shelves and global variables).
1513<P>
1514	The complexity of the store operation is linear in both the size
1515	of the key and the value, since both are being copied. For indexing
1516	purposes, a hash value is computed from the key, and the full depth
1517	of the key is taken into account.
1518<P>
1519	Note: If StoreHandle is not a handle, then it must be an atom or a
1520	compound term, and the store is identified by this term's toplevel
1521	functor together with the context module.
1522<P>
1523    "),
1524    amode:(store_set(+,++,?) is det),
1525    args:["StoreHandle":"A store handle or store name",
1526    	"Key":"A ground term",
1527    	"Value":"An arbitrary term"],
1528    exceptions:[
1529	4 : "StoreHandle is uninstantiated",
1530	4 : "Key is not ground",
1531	5 : "StoreHandle is neither atom nor compound term nor store handle",
1532	45 : "StoreHandle is not the name of a store"],
1533    eg:"
1534
1535    ?- store_create(Handle),
1536       store_set(Handle, tom, 12345),
1537       store_set(Handle, name(dick,tracy), phone(42376,home)),
1538       store_set(Handle, numbers:prime, [2,3,5,7|_More]),
1539       stored_keys_and_values(Handle, Data).
1540
1541    Handle = 'STORE'(16'003130e8)
1542    Data = [(numbers : prime) - [2, 3, 5, 7|_123],
1543            tom - 12345,
1544	    name(dick, tracy) - phone(42376, home)]
1545    Yes (0.00s cpu)
1546    ",
1547    see_also:[store/1, (local)/1, store_erase/1, store_get/3, store_delete/2,
1548    	store_contains/2, stored_keys/2, stored_keys_and_values/2,
1549	store_create/1, store_count/2, store_inc/2]
1550    ]).
1551
1552
1553:- comment(store_get/3, [
1554    summary:"Look up an entry in a store object",
1555    desc:html("\
1556	This looks up an entry under a given key in a given store object.
1557	If an entry for this key exists, the corresponding value is returned,
1558	otherwise the predicate fails.
1559<P>
1560	The key can be arbitrarily complex, but must be a ground term.
1561	The value can be an arbitrary term, and may contain uninstantiated
1562	variables. Note that values are copied when being stored or
1563	retrieved, therefore a retrieved nonground value will contain
1564	fresh variables rather than the original ones (this is similar
1565	to the behaviour of bags, shelves and global variables).
1566<P>
1567	The complexity of the retrieval operation is linear in both the size
1568	of the key and the value, since the value is being copied and the key
1569	needs to be compared. For indexing purposes, a hash value is computed
1570	from the key, and the full depth of the key is taken into account.
1571<P>
1572	Note: If StoreHandle is not a handle, then it must be an atom or a
1573	compound term, and the store is identified by this term's toplevel
1574	functor together with the context module.
1575<P>
1576    "),
1577    amode:(store_get(+,++,-) is semidet),
1578    args:["StoreHandle":"A store handle or store name",
1579    	"Key":"A ground term",
1580    	"Value":"A variable or arbitrary term"],
1581    fail_if:"The store does not contain an entry for Key",
1582    exceptions:[
1583	4 : "StoreHandle is uninstantiated",
1584	4 : "Key is not ground",
1585	5 : "StoreHandle is neither atom nor compound term nor store handle",
1586	45 : "StoreHandle is not the name of a store"],
1587    eg:"
1588
1589    ?- store_create(Handle),
1590       store_set(Handle, tom, 12345),
1591       store_set(Handle, name(dick,tracy), phone(42376,home)),
1592       store_set(Handle, numbers:prime, [2,3,5,7|_More]),
1593       store_get(Handle, tom, Value1),
1594       store_get(Handle, name(dick,tracy), Value2),
1595       store_get(Handle, numbers:prime, Value3).
1596
1597    Handle = 'STORE'(16'001b3c50)
1598    Value1 = 12345
1599    Value2 = phone(42376, home)
1600    Value3 = [2, 3, 5, 7|_More]
1601    Yes (0.00s cpu)
1602
1603
1604    ?- store_create(Handle),
1605       store_set(Handle, tom, 12345),
1606       store_get(Handle, harry, Value).
1607
1608    No (0.00s cpu)
1609    ",
1610    see_also:[store/1, (local)/1, store_erase/1, store_set/3, store_delete/2,
1611    	store_contains/2, stored_keys/2, stored_keys_and_values/2,
1612	store_create/1, store_count/2, store_inc/2]
1613    ]).
1614
1615:- comment(store_contains/2, [
1616    summary:"Check for an entry in a store object",
1617    desc:html("\
1618	This checks whether a given store object contains an entry for a
1619	given key.  If so, the predicate succeeds, otherwise it fails.
1620<P>
1621	The key can be arbitrarily complex, but must be a ground term.
1622<P>
1623	The complexity of this  operation is linear in the size
1624	of the key, since the key needs to be compared. For indexing purposes,
1625	a hash value is computed from the key, and the full depth of the key
1626	is taken into account.
1627<P>
1628	Note: If StoreHandle is not a handle, then it must be an atom or a
1629	compound term, and the store is identified by this term's toplevel
1630	functor together with the context module.
1631<P>
1632    "),
1633    amode:(store_contains(+,++) is semidet),
1634    args:["StoreHandle":"A store handle or store name",
1635    	"Key":"A ground term"],
1636    fail_if:"The store does not contain an entry for Key",
1637    exceptions:[
1638	4 : "StoreHandle is uninstantiated",
1639	4 : "Key is not ground",
1640	5 : "StoreHandle is neither atom nor compound term nor store handle",
1641	45 : "StoreHandle is not the name of a store"],
1642    eg:"
1643
1644    ?- store_create(Handle),
1645       store_set(Handle, tom, 12345),
1646       store_contains(Handle, tom).
1647
1648    Yes (0.00s cpu)
1649
1650
1651    ?- store_create(Handle),
1652       store_set(Handle, tom, 12345),
1653       store_contains(Handle, harry).
1654
1655    No (0.00s cpu)
1656    ",
1657    see_also:[store/1, (local)/1, store_erase/1, store_set/3, store_delete/2,
1658    	store_get/3, stored_keys/2, stored_keys_and_values/2,
1659	store_create/1, store_count/2]
1660    ]).
1661
1662:- comment(store_delete/2, [
1663    summary:"Delete an entry in a store object",
1664    desc:html("\
1665	This deletes any entry for a given key in a given store object.
1666	If the store does not contain such an entry, the predicate
1667	silently succeeds anyway.
1668<P>
1669	The key can be arbitrarily complex, but must be a ground term.
1670<P>
1671	The complexity of this operation is linear in the size
1672	of the key, since the key needs to be compared. For indexing purposes,
1673	a hash value is computed from the key, and the full depth of the key
1674	is taken into account.
1675<P>
1676	Note: If StoreHandle is not a handle, then it must be an atom or a
1677	compound term, and the store is identified by this term's toplevel
1678	functor together with the context module.
1679<P>
1680    "),
1681    amode:(store_delete(+,++) is det),
1682    args:["StoreHandle":"A store handle or store name",
1683    	"Key":"A ground term"],
1684    exceptions:[
1685	4 : "StoreHandle is uninstantiated",
1686	4 : "Key is not ground",
1687	5 : "StoreHandle is neither atom nor compound term nor store handle",
1688	45 : "StoreHandle is not the name of a store"],
1689    eg:"
1690
1691    ?- store_create(Handle),
1692       store_set(Handle, tom, 12345),
1693       stored_keys_and_values(Handle, Before),
1694       store_delete(Handle, tom),
1695       stored_keys_and_values(Handle, After).
1696
1697    Handle = 'STORE'(16'001b3d40)
1698    Before = [tom - 12345]
1699    After = []
1700    Yes (0.00s cpu)
1701
1702    ?- store_create(Handle),
1703       store_set(Handle, tom, 12345),
1704       store_delete(Handle, tom),
1705       store_delete(Handle, tom).
1706
1707    Yes (0.00s cpu)
1708    ",
1709    see_also:[store/1, (local)/1, store_erase/1, store_set/3, store_contains/2,
1710    	store_get/3, stored_keys/2, stored_keys_and_values/2,
1711	store_create/1, store_count/2]
1712    ]).
1713
1714:- comment(stored_keys/2, [
1715    summary:"Retrieve all keys stored in a store object",
1716    desc:html("\
1717	This retrieves a list of all keys under which entries are stored
1718	in the given store object. If the store is empty, the empty list
1719	is returned.
1720<P>
1721	The order of the keys in the returned list is undefined.
1722<P>
1723	The complexity of this operation is linear in the size of all keys,
1724	since they need to be copied.
1725<P>
1726	Note: If StoreHandle is not a handle, then it must be an atom or a
1727	compound term, and the store is identified by this term's toplevel
1728	functor together with the context module.
1729    "),
1730    amode:(stored_keys(+,-) is det),
1731    args:["StoreHandle":"A store handle or store name",
1732    	"Keys":"A variable or list"],
1733    exceptions:[
1734	4 : "StoreHandle is uninstantiated",
1735	5 : "StoreHandle is neither atom nor compound term nor store handle",
1736	45 : "StoreHandle is not the name of a store"],
1737    eg:"
1738
1739    ?- store_create(Handle),
1740       store_set(Handle, tom, 12345),
1741       store_set(Handle, name(dick,tracy), phone(42376,home)),
1742       store_set(Handle, numbers:prime, [2,3,5,7|_More]),
1743       stored_keys(Handle, Keys).
1744
1745    Handle = 'STORE'(16'003130e8)
1746    Keys = [numbers:prime, tom, name(dick, tracy)]
1747    Yes (0.00s cpu)
1748    ",
1749    see_also:[store/1, (local)/1, store_erase/1, store_set/3, store_contains/2,
1750    	store_get/3, store_delete/2, stored_keys_and_values/2,
1751	store_create/1, store_count/2]
1752    ]).
1753
1754:- comment(stored_keys_and_values/2, [
1755    summary:"Retrieve all data stored in a store object",
1756    desc:html("\
1757	This retrieves a list of all key/value pairs which are stored
1758	in the given store object. If the store is empty, the empty list
1759	is returned. Otherwise, a list of Key - Value terms is returned.
1760<P>
1761	The order of the returned list is undefined.
1762<P>
1763	The complexity of this operation is linear in the size of all keys
1764	and values, since they need to be copied.
1765<P>
1766	Note: If StoreHandle is not a handle, then it must be an atom or a
1767	compound term, and the store is identified by this term's toplevel
1768	functor together with the context module.
1769<P>
1770    "),
1771    amode:(stored_keys_and_values(+,-) is det),
1772    args:["StoreHandle":"A store handle or store name",
1773    	"KeysValues":"A variable or list"],
1774    exceptions:[
1775	4 : "StoreHandle is uninstantiated",
1776	5 : "StoreHandle is neither atom nor compound term nor store handle",
1777	45 : "StoreHandle is not the name of a store"],
1778    eg:"
1779
1780    ?- store_create(Handle),
1781       store_set(Handle, tom, 12345),
1782       store_set(Handle, name(dick,tracy), phone(42376,home)),
1783       store_set(Handle, numbers:prime, [2,3,5,7|_More]),
1784       stored_keys_and_values(Handle, Data).
1785
1786    Handle = 'STORE'(16'003130e8)
1787    Data = [(numbers : prime) - [2, 3, 5, 7|_More],
1788            tom - 12345,
1789	    name(dick, tracy) - phone(42376, home)]
1790    Yes (0.00s cpu)
1791
1792    ?- store_create(Handle),
1793       stored_keys_and_values(Handle, Data).
1794
1795    Handle = 'STORE'(16'003130e8)
1796    Data = []
1797    Yes (0.00s cpu)
1798    ",
1799    see_also:[store/1, (local)/1, store_erase/1, store_set/3, store_contains/2,
1800    	store_get/3, store_delete/2, stored_keys/2,
1801	store_create/1, store_count/2]
1802    ]).
1803
1804:- comment(store_inc/2, [
1805    summary:"Increment an integral entry within a store object",
1806    desc:html("\
1807	This looks up an entry under a given key in a given store object, and
1808	if such an entry exists, and is of integer type, it is incremented by
1809	one.  If no entry exists, an entry with integer value 1 is created.
1810<P>
1811	This predicate is a shorthand for:
1812<PRE>
1813	store_inc(Handle, Key) :-
1814	    ( store_get(Handle, Key, C0) ->
1815		C1 is C0 + 1,
1816		store_set(Handle, Key, C1)
1817	    ;
1818		store_set(Handle, Key, 1)
1819	    ).
1820</PRE>
1821	Note: If StoreHandle is not a handle, then it must be an atom or a
1822	compound term, and the store is identified by this term's toplevel
1823	functor together with the context module.
1824    "),
1825    amode:(store_inc(+,++) is det),
1826    args:["StoreHandle":"A store handle or store name",
1827    	"Key":"A ground term"],
1828    exceptions:[
1829	4 : "StoreHandle is uninstantiated",
1830	4 : "Key is not a ground term",
1831	5 : "StoreHandle is neither atom nor compound term nor store handle",
1832	45 : "StoreHandle is not the name of a store"],
1833    eg:"
1834    ?- store_create(Handle),
1835       store_set(Handle, count, 7),
1836       store_inc(Handle, count),
1837       store_get(Handle, count, N).
1838    Handle = 'STORE'(16'00334e20)
1839    N1 = 8
1840    Yes (0.00s cpu)
1841
1842    ?- store_create(Handle),
1843       store_inc(Handle, foo),
1844       store_get(Handle, foo, N).
1845    Handle = 'STORE'(16'00334e20)
1846    N = 1
1847    Yes (0.00s cpu)
1848    ",
1849    see_also:[store/1, (local)/1, store_set/3, store_get/3, store_delete/2,
1850    	store_contains/2, stored_keys/2, stored_keys_and_values/2,
1851	store_create/1, store_count/2]
1852    ]).
1853
1854:- comment(current_store/1, [
1855    summary:"StoreName is a visible store name",
1856    desc:html("\
1857	Used to check whether StoreName is the name of a visible store,
1858	or to enumerate all visible store names in the context module. 
1859<P>
1860	Note that this predicate will only accept/generate store names
1861	that have been created with local/1, store/1, not anonymous
1862	store handles created via store_create/1.
1863</PRE>
1864	Note: StoreHandle gets unified with an atom or a compound term,
1865	and the store is identified by this term's toplevel functor
1866	together with the context module.
1867    "),
1868    amode:(current_store(+) is semidet),
1869    amode:(current_store(-) is nondet),
1870    args:["StoreHandle":"A variable or a store name (atom or compound)"],
1871    fail_if:"StoreName is not a visible store name",
1872    exceptions:[
1873	5 : "StoreHandle is neither atom nor compound term nor variable"],
1874    eg:"
1875    :- local store(shed).
1876    :- local store(warehouse/3).
1877
1878    ?- current_store(shed).
1879    Yes (0.00s cpu)
1880
1881    ?- current_store(heap).
1882    No (0.00s cpu)
1883
1884    ?- current_store(X).
1885    X = shed
1886    More (0.00s cpu) ? ;
1887
1888    X = warehouse(_184, _185, _186)
1889    More (0.00s cpu) ? ;
1890
1891    No (0.00s cpu)
1892    ",
1893    see_also:[store/1, (local)/1]
1894    ]).