YAP 7.1.0
control.yap
Go to the documentation of this file.
1/*************************************************************************
2* *
3* YAP Prolog *
4* *
5* Yap Prolog was developed at NCCUP - Universidade do Porto *
6* *
7* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8* *
9**************************************************************************
10* *
11* File: control.yap *
12* Last rev: 20/08/09 *
13* mods: *
14* comments: control predicates available in yap *
15* *
16*************************************************************************/
17
18/**
19 * @file control.yap
20 * @author VITOR SANTOS COSTA <vsc@VITORs-MBP.lan>
21 * @date Thu Nov 19 10:26:35 2015
22 *
23 * @brief Control Predicates
24 *
25 *
26*/
27
28:- system_module( '$_control', [at_halt/1,
30 break/0,
31 call/2,
32 call/3,
33 call/4,
34 call/5,
35 call/6,
36 call/7,
37 call/8,
38 call/9,
39 call/10,
40 call/11,
41 call/12,
43 call_cleanup/3,
45 garbage_collect/0,
46 garbage_collect_atoms/0,
47 gc/0,
50 halt/0,
51 halt/1,
52 if/3,
55 nogc/0,
56 notrace/1,
57 once/1,
58 prolog_current_frame/1,
60 setup_call_catcher_cleanup/4,
62 version/0,
63 version/1], ['$run_atom_goal'/1,
64 '$set_toplevel_hook'/1]).
65
66:- '$call'/4'$disable_debugging'/0'$do_live'/0'$enable_debugging'/0'$system_catch'/4'$version'/0use_system_module( '$_boot', [,
67 ,
68 ,
69 ,
70 ,
71 ]).
72
73:- '$init_debugger'/0use_system_module( '$_debug', []).
74
75:- '$do_error'/2use_system_module( '$_errors', []).
76
77:- '$getval_exception'/3use_system_module( '$_utils', []).
78
79:- freeze_goal/2use_system_module( '$coroutining', []).
80
81/**
82
83
84@addtogroup YAPControl
85
86%% @{
87
88*/
89
90'$comma'(PA,A,PB,B) :-
91 '$exec'(PA,A),
92 '$exec'(PB,B).
93
94/** @pred forall(: _Cond_,: _Action_)
95
96
97For all alternative bindings of _Cond_ _Action_ can be
98proven. The example verifies that all arithmetic statements in the list
99 _L_ are correct. It does not say which is wrong if one proves wrong.
100
101```{.prolog}
102?- forall(member(Result = Formula, [2 = 1 + 1, 4 = 2 * 2]),
103 Result =:= Formula).
104```
105
106
107*/
108/** @pred forall(+ _Cond_,+ _Action_)
109
110
111
112
113For all alternative bindings of _Cond_ _Action_ can be proven.
114The next example verifies that all arithmetic statements in the list
115 _L_ are correct. It does not say which is wrong if one proves wrong.
116
117```
118?- forall(member(Result = Formula, [2 = 1 + 1, 4 = 2 * 2]),
119 Result =:= Formula).
120```
121
122
123
124*/
125forall(Cond, Action) :- \+((Cond, \+(Action))).
126
127/** @pred ignore(: _Goal_)
128
129
130Calls _Goal_ as once/1, but succeeds, regardless of whether
131`Goal` succeeded or not. Defined as:
132
133```{.prolog}
134ignore(Goal) :-
135 Goal, !.
136ignore(_).
137```
138
139
140*/
141ignore(Goal) :- (Goal->true;true).
142
143notrace(G) :-
144 strip_module(G, M, G1),
146 '$debug_stop'( State ),
147 '$call'(G1, CP, G, M),
149 (CP == CP2 -> ! ; '$debug_state'( NState ), ( true ; '$debug_restart'(NState), '$debug_restart' ) ),
150 '$debug_restart'( State )
151 ;
152 '$debug_restart'( State ),
153 '$debug_restart'
154 ).
155
156/** @pred if(? _G_,? _H_,? _I_)
157
158Call goal _H_ once per each solution of goal _H_. If goal
159 _H_ has no solutions, call goal _I_.
160
161The built-in `if/3` is similar to `->/3`, with the difference
162that it will backtrack over the test goal. Consider the following
163small data-base:
164
165```{.prolog}
166a(1). b(a). c(x).
167a(2). b(b). c(y).
168```
169
170Execution of an `if/3` query will proceed as follows:
171
172```{.prolog}
173 ?- if(a(X),b(Y),c(Z)).
174
175X = 1,
176Y = a ? ;
177
178X = 1,
179Y = b ? ;
180
181X = 2,
182Y = a ? ;
183
184X = 2,
185Y = b ? ;
186
187no
188```
189
190The system will backtrack over the two solutions for `a/1` and the
191two solutions for `b/1`, generating four solutions.
192
193Cuts are allowed inside the first goal _G_, but they will only prune
194over _G_.
195
196If you want _G_ to be deterministic you should use if-then-else, as
197it is both more efficient and more portable.
198
199*/
200if(X,Y,Z) :-
201 CP0 is '$last_choice_pt',
202 (
203 CP1 is '$last_choice_pt',
204 '$call'(X,CP1,if(X,Y,Z),M),
205 '$execute'(X),
206 '$clean_ifcp'(CP0,CP1),
207 '$call'(Y,CP0,if(X,Y,Z),M)
208 ;
209 '$call'(Z,CP0,if(X,Y,Z),M)
210 ).
211
212/** @pred call(+ _Closure_,...,? _Ai_,...) is iso
213
214
215Meta-call where _Closure_ is a closure that is converted into a goal by
216appending the _Ai_ additional arguments. The number of arguments varies
217between 0 and 10.
218
219
220*/
221
222/** @pred call_cleanup(: _Goal_, : _CleanUpGoal_)
223
224This is similar to call_cleanup/1 but with an additional
225 _CleanUpGoal_ which gets called after _Goal_ is finished.
226
227*/
228call_cleanup(Goal, Cleanup) :-
229'$gated_call'( false , Goal,_Catcher, Cleanup) .
230
231call_cleanup(Goal, Catcher, Cleanup) :-
232'$gated_call'( false , Goal, Catcher, Cleanup) .
233
234/** @pred setup_call_cleanup(: _Setup_,: _Goal_, : _CleanUpGoal_)
235
236
237Calls `(Setup, Goal)`. For each sucessful execution of _Setup_,
238calling _Goal_, the cleanup handler _Cleanup_ is guaranteed to be
239called exactly once. This will happen after _Goal_ completes, either
240through failure, deterministic success, commit, or an exception.
241_Setup_ will contain the goals that need to be protected from
242asynchronous interrupts such as the ones received from
243`call_with_time_limit/2` or thread_signal/2. In most uses, _Setup_
244will perform temporary side-effects required by _Goal_ that are
245finally undone by _Cleanup_.
246
247*/
248
249setup_call_cleanup(Setup,Goal, Cleanup) :-
250 setup_call_catcher_cleanup(Setup, Goal, _Catcher, Cleanup).
251
252setup_call_catcher_cleanup(Setup, Goal, Catcher, Cleanup) :-
253 '$setup_call_catcher_cleanup'(Setup),
254 call_cleanup(Goal, Catcher, Cleanup).
255
256
257/** @pred call_with_args(+ _Name_,...,? _Ai_,...)
258
259
260Meta-call where _Name_ is the name of the procedure to be called and
261the _Ai_ are the arguments. The number of arguments varies between 0
262and 10. New code should use `call/N` for better portability.
263
264If _Name_ is a complex term, then call_with_args/n behaves as
265call/n:
266
267```{.prolog}
268call(p(X1,...,Xm), Y1,...,Yn) :- p(X1,...,Xm,Y1,...,Yn).
269```
270
271
272*/
273
274%%% Some "dirty" predicates
275
276% Only efective if yap compiled with -DDEBUG
277% this predicate shows the code produced by the compiler
278'$show_code' :- /** @pred grow_heap(+ _Size_)
279Increase heap size _Size_ kilobytes.
280
281
282*/
283grow_heap(X) :- '$grow_heap'(X).
284/** @pred grow_stack(+ _Size_)
285
286
287Increase stack size _Size_ kilobytes
288
289
290 */
291grow_stack(X) :- '$grow_stack'(X).
292
293/** @pred gc
294
295
296The goal `gc` enables garbage collection. The same as
297`yap_flag(gc,on)`.
298
299
300*/
301'$grow_stack' :-
302 yap_flag(gc,true).
303/** @pred nogc
304
305
306The goal `nogc` disables garbage collection. The same as
307`yap_flag(gc,off)`.
308
309
310*/
311yap_flag :-
312 yap_flag(gc,false).
313
314
315/** @pred garbage_collect_atoms
316
317
318The goal `garbage_collect` forces a garbage collection of the atoms
319in the data-base. Currently, only atoms are recovered.
320
321
322*/
323yap_flag :-
324 '$atom_gc'.
325
326'$force_environment_for_gc'.
327
328'$good_list_of_character_codes'(V) :- var(V), var.
329'$good_list_of_character_codes'([]).
330'$good_list_of_character_codes'([X|L]) :-
331 '$good_character_code'(X),
332 '$good_list_of_character_codes'(L).
333
334'$good_character_code'(X) :- var(X), var.
335'$good_character_code'(X) :- integer(X), X > -2, X < 256.
336
337/** @pred prolog_initialization( _G_)
338
339
340Add a goal to be executed on system initialization. This is compatible
341with SICStus Prolog's initialization/1.
342
343
344*/
345prolog_initialization(G) :- var(G), var,
346 '$do_error'(instantiation_error,initialization(G)).
347prolog_initialization(T) :- must_be_callable(T), must_be_callable,
348 '$assert_init'(T).
350 '$do_error'(type_error(callable,T),initialization(T)).
351
352'$assert_init'(T) :- recordz('$startup_goal',T,_), recordz.
353'$assert_init'(_).
354
355/** @pred version
356
357Write YAP's boot message.
358
359
360*/
361'$assert_init' :-
362 '$version_specs'(Specs),
363 print_message(informational, version(Specs)).
364
365
366
367/** @pred version(- _Message_)
368
369Add a message to be written when yap boots or after aborting. It is not
370possible to remove messages.
371
372
373*/
374version(V) :- var(V), var,
375 '$do_error'(instantiation_error,version(V)).
376version(T) :- atom(T), atom, '$assert_version'(T).
377version(T) :-
378 '$do_error'(type_error(atom,T),version(T)).
379
380'$assert_version'(T) :- recordz('$version',T,_), recordz.
381'$assert_version'(_).
382
383'$set_toplevel_hook'(_) :-
384 recorded('$toplevel_hooks',_,R),
385 erase(R),
386 erase.
387'$set_toplevel_hook'(H) :-
388 recorda('$toplevel_hooks',H,_),
389 recorda.
390'$set_toplevel_hook'(_).
391
392%% @{
393
394%% @addtogroup Global_Variables
395
396/** @pred nb_getval(+ _Name_, - _Value_)
397
398
399The nb_getval/2 predicate is a synonym for b_getval/2,
400introduced for compatibility and symmetry. As most scenarios will use
401a particular global variable either using non-backtrackable or
402backtrackable assignment, using nb_getval/2 can be used to
403document that the variable is used non-backtrackable.
404
405
406*/
407/** @pred nb_getval(+ _Name_,- _Value_)
408
409
410The nb_getval/2 predicate is a synonym for b_getval/2, introduced for
411compatibility and symmetry. As most scenarios will use a particular
412global variable either using non-backtrackable or backtrackable
413assignment, using nb_getval/2 can be used to document that the
414variable is used non-backtrackable.
415
416
417*/
418nb_getval(GlobalVariable, Val) :-
419 '__NB_getval__'(GlobalVariable, Val, Error),
420 (var(Error)
421 ->
422 var
423 ;
424 '$getval_exception'(GlobalVariable, Val, nb_getval(GlobalVariable, Val)) ->
425 nb_getval(GlobalVariable, Val)
426 ;
427 '$do_error'(existence_error(variable, GlobalVariable),nb_getval(GlobalVariable, Val))
428 ).
429
430
431/** @pred b_getval(+ _Name_, - _Value_)
432
433
434Get the value associated with the global variable _Name_ and unify
435it with _Value_. Note that this unification may further
436instantiate the value of the global variable. If this is undesirable
437the normal precautions (double negation or copy_term/2) must be
438taken. The b_getval/2 predicate generates errors if _Name_ is not
439an atom or the requested variable does not exist.
440
441Notice that for compatibility with other systems _Name_ <em>must</em> be already associated with a term: otherwise the system will generate an error.
442
443
444*/
445/** @pred b_getval(+ _Name_,- _Value_)
446
447
448Get the value associated with the global variable _Name_ and unify
449it with _Value_. Note that this unification may further instantiate
450the value of the global variable. If this is undesirable the normal
451precautions (double negation or copy_term/2) must be taken. The
452b_getval/2 predicate generates errors if _Name_ is not an atom or
453the requested variable does not exist.
454
455
456*/
457b_getval(GlobalVariable, Val) :-
458 '__NB_getval__'(GlobalVariable, Val, Error),
459 (var(Error)
460 ->
461 var
462 ;
463 '$getval_exception'(GlobalVariable, Val, b_getval(GlobalVariable, Val)) ->
464 '$getval_exception'
465 ;
466 '$do_error'(existence_error(variable, GlobalVariable),b_getval(GlobalVariable, Val))
467 ).
468
469
470%% @}
471
472%% @{
473
474%% @addtogroup YAPControl
475
476/* This is the break predicate,
477 it saves the importante data about current streams and
478 debugger state */
479
480'$debug_state'(state(Creep, SPYTarget,SpyOn,Trace,Debugging, Debug, SPY_GN, GList, GDList)) :-
481 '$init_debugger',
482 '$get_debugger_state'(Creep, SPYTarget,SpyOn,Trace,Debugging),
483 current_prolog_flag(debug, Debug),
484 nb_getval('$spy_gn',SPY_GN),
485 b_getval('$spy_glist',GList),
486 b_getval('$spy_gdlist',GDList).
487
488
489'$debug_stop' :-
490 '$set_debugger_state'(trace,off),
491 set_prolog_flag(debug, false),
492 b_setval('$spy_gn',0),
493 b_setval('$spy_glist',[]),
494 b_setval('$spy_gdlist',[]),
495 '$disable_debugging'.
496
497 '$debug_restart'(state(Creep, SPYTarget,SpyOn,Trace,Debugging, Debug, SPY_GN, GList, GDList)) :-
498 b_setval('$spy_glist',GList),
499 b_setval('$spy_gdlist',GDList),
500 b_setval('$spy_gn',SPY_GN),
501 '$set_debugger_state'(Creep, SPYTarget,SpyOn,Trace,Debugging),
502 set_prolog_flag(debug, Debug),
503 '$enable_debugging'.
504
505/** @pred break
506
507
508Suspends the execution of the current goal and creates a new execution
509level similar to the top level, displaying the following message:
510
511```{.prolog}
512 [ Break (level <number>) ]
513```
514telling the depth of the break level just entered. To return to the
515previous level just type the end-of-file character or call the
516end_of_file predicate. This predicate is especially useful during
517debugging.
518
519
520*/
521set_prolog_flag :-
522 '$debug_state'(DState),
523 '$break'( true ),
524 current_output(OutStream), current_input(InpStream),
525 current_prolog_flag(break_level, BL ),
526 NBL is BL+1,
527 set_prolog_flag(break_level, NBL ),
528 format(user_error, '% Break (level ~w)~n', [NBL]),
529 format,
530 format,
531 set_value('$live','$true'),
532 '$debug_restart'(DState),
533 set_input(InpStream),
534 set_output(OutStream),
535 set_prolog_flag(break_level, BL ),
536 '$break'( false ).
537
538
539at_halt(G) :-
540 recorda('$halt', G, _),
541 recorda.
542at_halt(_).
543
544/** @pred halt is iso
545
546Halts Prolog, and exits to the calling application. In YAP,
547halt/0 returns the exit code `0`.
548*/
549at_halt :-
550 print_message(informational, halt),
551 print_message.
552print_message :-
553 halt(0).
554
555/** @pred halt(+ _I_) is iso
556
557Halts Prolog, and exits to 1the calling application returning the code
558given by the integer _I_.
559
560*/
561halt(_) :-
562 recorded('$halt', G, _),
563 catch(once(G), Error, user:'$Error'(Error)),
564 catch.
565halt(X) :-
566 '$sync_mmapped_arrays',
567 set_value('$live','$false'),
568 '$halt'(X).
569
570prolog_current_frame(Env) :-
571 Env is '$env'.
572
573'$run_atom_goal'(GA) :-
574 '$current_module'(Module),
575 atom_to_term(GA, G, _),
576 catch(once(Module:G), Error,user:'$Error'(Error)).
577
578/**
579
580@pred call_in_module( +M:G )
581
582 This predicate ensures that both deterministic and non-deterministic execution of the goal $G$ takes place in the context of goal _G_?
583**/
584
585yap_hacks:call_in_module(M:G) :-
586 gated_call(
587 '$module_boundary'(call, M0, M),
588 call(G),
589 Event,
590 '$module_boundary'(Event,M0,M)
591 ).
592
593
594
595'$module_boundary'(call, M0, M) :-
596 current_source_module(M0, M).
597'$module_boundary'(answer, M0, _) :-
598 current_source_module(_M, M0).
599'$module_boundary'(exit, M0, _) :-
600 current_source_module(_M, M0).
601'$module_boundary'(redo, M0, _M) :-
602 current_source_module(_, M0).
603'$module_boundary'(fail, M0, _M) :-
604 current_source_module(_, M0).
605'$module_boundary'(!, _, _).
606'$module_boundary'(external_exception(_), _, _).
607'$module_boundary'(exception(_), M0, _M) :-
608 current_source_module(_, M0).
609
610/**
611@}
612*/
613
catch( : Goal,+ Exception,+ Action)
current_input(+ S)
current_output(+ S)
must_be_callable( ?_Goal_ )
set_input(+ S)
set_output(+ S)
yap_flag( ?Param, ?Value)
erase(+ R)
recordz(+ K, T,- R)
b_getval(+ Name, - Value)
call(+ Closure,...,? Ai,...)
call_cleanup(: Goal, : CleanUpGoal)
call_in_module( +M:G )
forall(: Cond,: Action)
grow_heap(+ Size)
Definition: control.yap:278
grow_stack(+ Size)
halt(+ I)
if(? G,? H,? I)
ignore(: Goal)
nb_getval(+ Name, - Value)
once( 0:G)
prolog_initialization( G)
setup_call_cleanup(: Setup,: Goal, : CleanUpGoal)
version(- Message)
current_prolog_flag(? Flag,- Value)
set_prolog_flag(+ Flag,+ Value)
print_message(+ Severity, +Term)
set_value(+ A,+ C)
atom( T)
current_choice_point( -CP )
integer( T)
var( T)