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, "Dynamic Predicates").
24:- comment(summary, "Built-ins to create and manipulate dynamic procedures").
25:- comment(categories, ["Built-In Predicates"]).
26
27:- tool(assert / 1).
28:- tool(asserta / 1).
29:- tool(assertz / 1).
30:- tool(clause / 1).
31:- tool(clause / 2).
32:- tool(is_dynamic / 1).
33:- tool((dynamic) / 1).
34:- tool((listing) / 0).
35:- tool((listing) / 1).
36:- tool(retract / 1).
37:- tool(retractall / 1).
38
39:- comment((dynamic) / 1, [
40	summary:"Declares the procedures specified by SpecList as dynamic.
41
42",
43	template:"dynamic ++SpecList",
44	amode:(dynamic(++) is det),
45	desc:html("   Declare the procedures specified by SpecList as dynamic procedures.
46   This has to be done before the procedure is defined.
47
48<P>
49   To change a static procedure to a dynamic one it must first be
50   abolished.
51
52<P>
53   If the procedure was already dynamic Error 64 is raised.  The default
54   error handler erases all existing clauses and succeeds.  This is useful
55   for recompiling files with dynamic declarations, but it can be redefined
56   if desired.
57
58<P>
59"),
60	args:["SpecList" : "Sequence of expressions of the form Atom/Integer."],
61	exceptions:[4 : "SpecList is not instantiated.", 5 : "SpecList is instantiated, but not to a sequence of    expressions of the form Atom/Integer.", 64 : "SpecList is already dynamic.", 65 : "SpecList is already defined."],
62	eg:"
63Success:
64     [eclipse]: pred(a/1).
65     no.
66     [eclipse]: dynamic a/1.
67     yes.
68     [eclipse]: pred(a/1).
69     in eclipse: dynamic prolog local debugged stopped traceable
70     yes.
71     [eclipse]: a(X).
72     no (more) solution.
73Error:
74     dynamic X.                 (Error 4).
75     dynamic a.                 (Error 5).
76     dynamic a/1, a/1.          (Error 64). % succeeds
77     get_flag(p/0,type,user),
78     dynamic p/0.               (Error 65).
79
80
81
82",
83	see_also:[is_dynamic / 1]]).
84
85:- comment(is_dynamic / 1, [
86	summary:"Succeeds if the procedure specified by PredSpec has been declared as
87dynamic.
88
89",
90	amode:(is_dynamic(++) is semidet),
91	desc:html("   Used to test whether the procedure specified by PredSpec was declared as
92   dynamic.
93
94<P>
95"),
96	args:["PredSpec" : "Expression of the form Atom/Integer."],
97	fail_if:"Fails if the procedure specified by PredSpec has not been declared as\n   dynamic.",
98	exceptions:[4 : "PredSpec is not instantiated.", 5 : "PredSpec is instantiated, but not to an expression of the    form Atom/Integer.", 60 : "PredSpec is an undefined procedure."],
99	eg:"
100Success:
101      [eclipse]: assert(p).
102      yes.
103      [eclipse]: is_dynamic(p/0).
104      yes.
105
106Error:
107     is_dynamic(X).                (Error 4).
108     is_dynamic(a).                (Error 5).
109     is_dynamic(y/0).              (Error 60).
110
111
112
113",
114	see_also:[(abolish) / 1, (dynamic) / 1]]).
115
116:- comment((listing) / 0, [
117	summary:"Outputs the definition of all dynamic predicates in the database.
118
119",
120	amode:((listing) is det),
121	desc:html("   Outputs each of the dynamic predicates currently contained on the
122   database.  ie.  all predicates created using assert/1 or asserta/1 or
123   compiled as dynamic predicates.
124
125<P>
126   The order in which the predicates are listed is undefined.
127
128<P>
129   The individual clauses are output in indented format using
130   writeclause/2.
131
132<P>
133   No static predicates are output.
134
135<P>
136"),
137	args:[],
138	eg:"
139Success:
140    [eclipse]: [user].
141     :- dynamic x/0, y/1.
142     x :- true.
143     y(X) :- write(X).
144     user compiled 0 bytes in 0.07 seconds
145    yes.
146    [eclipse]: assert(man(adam)), assert(woman(eve)),
147    > assert((likes(X,Y):-man(X),woman(Y))).
148    X = _g102
149    Y = _g98
150    yes.
151    [eclipse]: listing.
152    x .
153    y(_g68):-
154            write(_g68) .
155    likes(_g68, _g70):-
156            man(_g68),
157            woman(_g70) .
158    woman(eve) .
159    man(adam) .
160    yes.
161
162
163
164",
165	see_also:[assert / 1, clause / 2, (listing) / 1, writeclause / 1]]).
166
167:- comment((listing) / 1, [
168	summary:"Outputs the definition of all dynamic predicates indicated by SpecList.
169
170",
171	template:"listing ++SpecList",
172	amode:(listing(++) is det),
173	desc:html("   Outputs the definition of all dynamic predicates defined by SpecList to
174   the standard output.  An expression in SpecList may be a single
175   predicate in the form name/arity in which case only the clauses for
176   name/arity are printed.  Alternatively the format name is accepted in
177   which case all the predicates of any arity associated with name are
178   output.
179
180<P>
181   The individual clauses are output in indented format using
182   writeclause/2.
183
184<P>
185   No static predicates are output.
186
187<P>
188"),
189	args:["SpecList" : "Sequence of expressions of the form Atom/Integer or just                Atom."],
190	exceptions:[4 : "An expression in SpecList is not instantiated.", 5 : "An expression in SpecList is not of the form Atom/Integer or    Atom.", 63 : "An expression in SpecList is not a dynamic procedure."],
191	eg:"
192Success:
193    [eclipse]: [user], assert(woman(eve)).
194     :- dynamic p/0.
195     p.
196     user compiled 0 bytes in 0.00 seconds
197    yes.
198    [eclipse]: listing p/0, woman/1.
199    p .
200    woman(eve) .
201    yes.
202
203Error:
204    listing X.                  (Error 4).
205    listing a/a.                (Error 5).
206    listing z/3.                (Error 63).
207
208
209
210",
211	see_also:[assert / 1, clause / 1, clause / 2, (listing) / 0, writeclause / 1]]).
212
213
214:- comment(assertz / 1, [
215	summary:"Add specified clause at the end of the dynamic procedure to the database",
216	amode:(assertz(+) is det),
217	desc:html("\
218   Adds the specified clause for a dynamic procedure to the database.]
219   The clause is added AFTER any existing clauses for the procedure.
220   This is an alias for assert/1.
221<P>
222   The procedure must be declared to be dynamic using the dynamic/1
223   built-in.  If the procedure is undefined an exception is raised.
224   However, the default error handler for this exception simply declares
225   the procedure dynamic and asserts the clause.
226<P>
227   The asserted clause is NOT removed from the database on backtracking
228   through the call to assertz/1.
229<P>
230   assertz/1 satisfies the logical update semantics.  Asserting a clause to
231   a procedure will not, in any way, affect previous calls to it when
232   backtracking.
233<P>
234   No clause transformation is performed on Clause. Use expand_clause/2 to
235   explicitly expand the clause before calling this predicate if clause
236   expansion is rquired.
237<P>
238"),
239	args:["Clause" : "Atom or compound term"],
240	exceptions:[4 : "Clause is a free variable.",
241	    4 : "The head of Clause is a free variable.",
242	    5 : "Clause is not a valid Prolog clause.",
243	    63 : "The procedure is not dynamic.",
244	    70 : "The procedure is undefined.  However, the default error handler for this exception simply declares the procedure dynamic and    asserts the clause, if the error was caused by an assert."
245	],
246	eg:"   Success:
247    ?- assertz(city(london)), assertz(city(munich)), assertz(city(paris)).
248    yes.
249    ?- listing.
250    city(london).
251    city(munich).
252    city(paris).
253    yes.
254
255    ?- assertz((likes(X,Y) :- man(X), woman(Y))).
256    yes.
257    ?- listing.
258    likes(_186, _187) :-
259        man(_186),
260        woman(_187).
261    yes.
262
263
264   Error:
265    assertz(X).                        - gives error 4.
266    assertz(\"the man\").                - gives error 5.
267    assertz(1).                        - gives error 5.
268    assertz((my_static(X):-write(X))). - gives error 63.
269                                        if my_static/1 is not
270                                        dynamic.
271   Logical semantics :
272
273   If the following clauses are in the database :
274p :- assertz(p), fail.
275p :- fail.
276
277q :- fail.
278q :- assertz(q), fail.
279
280   The queries p.  and q.  will both fail.
281",
282	see_also:[(dynamic) / 1, asserta / 1, assert/1, retract / 1, compile_term / 1]]).
283
284
285:- comment(assert / 1, [
286	summary:"Add specified clause at the end of the dynamic procedure to the database",
287	amode:(assert(+) is det),
288	desc:html("\
289   Adds the specified clause for a dynamic procedure to the database.]
290   The clause is added AFTER any existing clauses for the procedure.
291   This is an alias for assertz/1.
292<P>
293   The procedure must be declared to be dynamic using the dynamic/1
294   built-in.  If the procedure is undefined an exception is raised.
295   However, the default error handler for this exception simply declares
296   the procedure dynamic and asserts the clause.
297<P>
298   The asserted clause is NOT removed from the database on backtracking
299   through the call to assert/1.
300<P>
301   assert/1 satisfies the logical update semantics.  Asserting a clause to
302   a procedure will not, in any way, affect previous calls to it when
303   backtracking.
304<P>
305   No clause transformation is performed on Clause. Use expand_clause/2 to
306   explicitly expand the clause before calling this predicate if clause
307   expansion is rquired.
308<P>
309"),
310	args:["Clause" : "Atom or compound term"],
311	exceptions:[4 : "Clause is a free variable.",
312	    4 : "The head of Clause is a free variable.",
313	    5 : "Clause is not a valid Prolog clause.",
314	    63 : "The procedure is not dynamic.",
315	    70 : "The procedure is undefined.  However, the default error handler for this exception simply declares the procedure dynamic and    asserts the clause, if the error was caused by an assert."
316	],
317	eg:"   Success:
318    ?- assert(city(london)), assert(city(munich)), assert(city(paris)).
319    yes.
320    ?- listing.
321    city(london).
322    city(munich).
323    city(paris).
324    yes.
325
326    ?- assert((likes(X,Y) :- man(X), woman(Y))).
327    yes.
328    ?- listing.
329    likes(_186, _187) :-
330        man(_186),
331        woman(_187).
332    yes.
333
334
335   Error:
336    assert(X).                        - gives error 4.
337    assert(\"the man\").                - gives error 5.
338    assert(1).                        - gives error 5.
339    assert((my_static(X):-write(X))). - gives error 63.
340                                        if my_static/1 is not
341                                        dynamic.
342   Logical semantics :
343
344   If the following clauses are in the database :
345p :- assert(p), fail.
346p :- fail.
347
348q :- fail.
349q :- assert(q), fail.
350
351   The queries p.  and q.  will both fail.
352",
353	see_also:[(dynamic) / 1, asserta / 1, assertz/1, retract / 1, compile_term / 1]]).
354
355
356:- comment(asserta / 1, [
357	summary:"Add specified clause for a dynamic procedure to the database before any existing clauses",
358	amode:(asserta(+) is det),
359	desc:html("\
360   Adds the specified clause for a dynamic procedure to the database.]
361   The clause is added BEFORE any existing clauses for the procedure.
362<P>
363   The procedure must be declared to be dynamic using the dynamic/1
364   built-in.  If the procedure is undefined an exception is raised.
365   However, the default error handler for this exception simply declares
366   the procedure dynamic and asserts the clause.
367<P>
368   The asserted clause is NOT removed from the database on backtracking
369   through the call to asserta/1.
370<P>
371   asserta/1 satisfies the logical update semantics.  Asserting a clause to
372   a procedure will not, in any way, affect previous calls to it when
373   backtracking.
374<P>
375   No clause transformation is performed on Clause. Use expand_clause/2 to
376   explicitly expand the clause before calling this predicate if clause
377   expansion is rquired.
378<P>
379"),
380	args:["Clause" : "Atom or compound term"],
381	exceptions:[4 : "Clause is a free variable.",
382	    4 : "The head of Clause is a free variable.",
383	    5 : "Clause is not a valid Prolog clause.",
384	    63 : "The procedure is not dynamic.",
385	    70 : "The procedure is undefined.  However, the default error handler for this exception simply declares the procedure dynamic and    asserts the clause, if the error was caused by an assert."
386	],
387	eg:"   Success:
388    ?- asserta(city(london)), asserta(city(munich)), asserta(city(paris)).
389    yes.
390    ?- listing.
391    city(paris).
392    city(munich).
393    city(london).
394    yes.
395
396    ?- asserta((likes(X,Y) :- man(X), woman(Y))).
397    yes.
398    ?- listing.
399    likes(_186, _187) :-
400        man(_186),
401        woman(_187).
402    yes.
403
404
405   Error:
406    asserta(X).                        - gives error 4.
407    asserta(\"the man\").                - gives error 5.
408    asserta(1).                        - gives error 5.
409    asserta((my_static(X):-write(X))). - gives error 63.
410                                        if my_static/1 is not
411                                        dynamic.
412   Logical semantics :
413
414   If the following clauses are in the database :
415p :- asserta(p), fail.
416p :- fail.
417
418q :- fail.
419q :- asserta(q), fail.
420
421   The queries p.  and q.  will both fail.
422",
423	see_also:[(dynamic) / 1, assert / 1, assertz/1, retract / 1, compile_term / 1]]).
424
425
426
427:- comment(clause / 1, [
428	summary:"Succeeds if Clause unifies with a clause of a dynamic procedure.
429
430",
431	amode:(clause(+) is nondet),
432	desc:html("   Finds a dynamic clause whose head unifies with the head of Clause and
433   unifies the body of the clause with the body of Clause.  The head of
434   Clause must be sufficiently instantiated so that the predicate (head) of
435   the clause can be determined.  The functor of the head of Clause must be
436   that of a procedure previously declared as dynamic using dynamic/1.
437
438<P>
439   This goal may be resatisfied if there are several clauses which match
440   the first argument.  In the first solution the argument will be unified
441   with the first such clause.  Subsequent solutions will unify the
442   argument to the other clauses in the same order in which they are listed
443   by listing/0, 1.
444
445<P>
446   clause/1 satisfies the logical update semantics.  When clause/1 is first
447   called, it makes a virtual copy of the clauses that match and, on
448   backtracking, unifies its argument with them.  Any modifications made to
449   the procedure after clause/1 has started executing do not, in any way,
450   affect the solutions produced.  A subsequent call, however makes and
451   uses a new, virtual, copy of the modified database.
452
453<P>
454   No clause transformation is performed on Clause. Use expand_clause/2 to
455   explicitly expand the clause before calling this predicate if clause
456   expansion is rquired.
457<P>
458"),
459	args:["Clause" : "Atom or compound term"],
460	fail_if:"Fails if no dynamic clause unifies with Clause",
461	exceptions:[4 : "Clause is not instantiated", 4 : "The head of Clause is a free variable.", 63 : "Procedure is not dynamic", 70 : "Procedure is undefined"],
462	see_also:[clause/2]]).
463
464:- comment(clause / 2, [
465	summary:"Succeeds if Head :- Body  is an existing dynamic clause.
466
467",
468	amode:(clause(+,-) is nondet),
469	desc:html("   Identical to clause((Head :- Body)).
470
471<P>
472"),
473	args:["Head" : "Atom or compound term.", "Body" : "Atom, variable or compound term."],
474	fail_if:"Fails if no dynamic clause head unifies with Head",
475	see_also:[clause / 1]]).
476
477:- comment(retract / 1, [
478	summary:"Succeeds if a clause that unifies with Clause can be removed from the
479database.
480
481",
482	amode:(retract(+) is nondet),
483	desc:html("   Removes the first clause that matches the argument from the database.
484   On backtracking, successive clauses that match are removed.  The clauses
485   are not reasserted when backtracking occurs through retract/1.
486
487<P>
488   The functor of the head of Clause must be that of a predicate declared
489   as dynamic, otherwise an error occurs.  If no clause matches, it fails.
490
491<P>
492   retract/1 satisfies the logical update semantics.  When retract/1 is
493   first called, it makes a virtual copy of the clauses that match and, on
494   backtracking, unifies its argument with them and removes them from the
495   database.  Any modifications made to the procedure after retract/1 has
496   started executing do not, in any way, affect its behaviour.  A
497   subsequent call, however, makes and uses a new, virtual, copy of the
498   modified database.
499
500<P>
501   No clause transformation is performed on Clause. Use expand_clause/2 to
502   explicitly expand the clause before calling this predicate if clause
503   expansion is rquired.
504
505<P>
506"),
507	args:["Clause" : "Atom or compound term"],
508	fail_if:"Fails if no dynamic clause unifies with Clause",
509	exceptions:[4 : "Clause is not instantiated", 4 : "The head of Clause is a free variable.", 5 : "Clause or the head of Clause is not a callable term.", 63 : "Procedure is not dynamic", 70 : "Procedure is undefined"],
510	eg:"
511Success:
512    [eclipse]: assert(city(munich)), assert(city(london)),
513    assert((p :- write(hi), write(there))).
514
515    yes.
516    [eclipse]: retract(city(X)).
517
518    X = munich     More? (;)
519    yes.
520    [eclipse]: retract(city(X) :- Body).
521
522    X = london
523    Body = true
524    yes.
525    [eclipse]: retract(p :- Body).
526
527    Body = write(hi) , write(there)
528    yes.
529Fail:
530    assert(fact),retract(fact),retract(fact).
531
532Error:
533    retract(X).                            (Error 4).
534    retract(\"x\").                          (Error 5).
535    retract(listing).                      (Error 63).
536    retract(undef).                        (Error 70).
537
538
539
540",
541	see_also:[assert / 1, (dynamic) / 1, (listing) / 1]]).
542
543:- comment(retractall / 1, [
544	summary:"Removes from the database all clauses whose heads match Head",
545	amode:(retractall(+) is det),
546	desc:html("   Retracts from the database all clauses whose heads match the argument.
547   The argument must be sufficiently instantiated otherwise an error is
548   signalled.  retractall/1 never fails.  The clauses are not reasserted
549   when backtracking through the call of retractall/1.
550
551<P>
552   The functor and the arity of Head must be that of a predicate declared
553   as dynamic (or implicitly declared as dynamic by asserting).
554
555<P>
556   retractall/1 satisfies the logical update semantics.  Using it to
557   retract all the clauses of a predicate will not, in any way, affect
558   previous calls to the predicate, i.e. they will still see all the clauses
559   that existed at call time.
560
561<P>
562"),
563	args:["Head" : "Atom, variable or compound term."],
564	exceptions:[4 : "Head is not instantiated", 5 : "Head is not a callable term", 63 : "Procedure is not dynamic", 70 : "Procedure is undefined"],
565	eg:"
566Success:
567    [eclipse]: assert(city(munich)), assert(city(london)).
568    yes.
569    [eclipse]: retractall(city(_)).
570    yes.
571    [eclipse]: city(X).
572    no (more) solution.
573    [eclipse]: retractall(city(_)).
574    yes.
575Error:
576    retractall(X).                  (Error 4).
577    retractall(\"x\").                (Error 5).
578
579
580   % if h/0 is defined, but not as dynamic..
581    retractall(h).                  (Error 63).
582
583    retractall(z/0).                (Error 70).
584
585
586
587",
588	see_also:[(dynamic) / 1, assert / 1, retract / 1]]).
589
590