* make CHR load its private stuff silently
[chr.git] / chr_runtime.pl
blobb6d2bdc0a849cb7e63e66200e3de210e4de7ca2a
1 /* $Id$
3 Part of CHR (Constraint Handling Rules)
5 Author: Christian Holzbaur and Tom Schrijvers
6 E-mail: christian@ai.univie.ac.at
7 Tom.Schrijvers@cs.kuleuven.be
8 WWW: http://www.swi-prolog.org
9 Copyright (C): 2003-2004, K.U. Leuven
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 as published by the Free Software Foundation; either version 2
14 of the License, or (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 As a special exception, if you link this library with other files,
26 compiled with a Free Software compiler, to produce an executable, this
27 library does not by itself cause the resulting executable to be covered
28 by the GNU General Public License. This exception does not however
29 invalidate any other reasons why the executable file might be covered by
30 the GNU General Public License.
32 Distributed with SWI-Prolog under the above conditions with
33 permission from the authors.
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38 %% _ _ _
39 %% ___| |__ _ __ _ __ _ _ _ __ | |_(_)_ __ ___ ___
40 %% / __| '_ \| '__| | '__| | | | '_ \| __| | '_ ` _ \ / _ \
41 %% | (__| | | | | | | | |_| | | | | |_| | | | | | | __/
42 %% \___|_| |_|_| |_| \__,_|_| |_|\__|_|_| |_| |_|\___|
44 %% hProlog CHR runtime:
46 %% * based on the SICStus CHR runtime by Christian Holzbaur
47 %%
48 %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
49 %% % Constraint Handling Rules version 2.2 %
50 %% % %
51 %% % (c) Copyright 1996-98 %
52 %% % LMU, Muenchen %
53 %% % %
54 %% % File: chr.pl %
55 %% % Author: Christian Holzbaur christian@ai.univie.ac.at %
56 %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57 %%
58 %%
59 %% * modified by Tom Schrijvers, K.U.Leuven, Tom.Schrijvers@cs.kuleuven.be
60 %% - ported to hProlog
61 %% - modified for eager suspension removal
63 %% * First working version: 6 June 2003
65 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
66 %% SWI-Prolog changes
67 %%
68 %% * Added initialization directives for saved-states
69 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71 :- module(chr_runtime,
72 [ 'chr sbag_del_element'/3,
73 'chr sbag_member'/2,
74 'chr merge_attributes'/3,
76 'chr run_suspensions'/1,
77 'chr run_suspensions_loop'/1,
79 'chr run_suspensions_d'/1,
80 'chr run_suspensions_loop_d'/1,
82 'chr insert_constraint_internal'/5,
83 'chr remove_constraint_internal'/2,
84 'chr allocate_constraint'/4,
85 'chr activate_constraint'/3,
87 'chr default_store'/1,
89 'chr via_1'/2,
90 'chr via_2'/3,
91 'chr via'/2,
92 'chr newvia_1'/2,
93 'chr newvia_2'/3,
94 'chr newvia'/2,
96 'chr lock'/1,
97 'chr unlock'/1,
98 'chr not_locked'/1,
99 'chr none_locked'/1,
101 'chr update_mutable'/2,
102 'chr get_mutable'/2,
103 'chr create_mutable'/2,
105 'chr novel_production'/2,
106 'chr extend_history'/2,
107 'chr empty_history'/1,
109 'chr gen_id'/1,
111 'chr debug_event'/1,
112 'chr debug command'/2, % Char, Command
114 'chr chr_indexed_variables'/2,
116 chr_show_store/1, % +Module
117 find_chr_constraint/1,
119 chr_trace/0,
120 chr_notrace/0,
121 chr_leash/1
124 %% SWI begin
125 :- set_prolog_flag(generate_debug_info, false).
126 %% SWI end
128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
130 :- use_module(hprolog).
131 :- include(chr_op).
133 %% SICStus begin
134 %% :- use_module(library(lists),[memberchk/2]).
135 %% :- use_module(library(terms),[term_variables/2]).
136 %% :- use_module(hpattvars).
137 %% :- use_module(b_globval).
138 %% SICStus end
141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143 % I N I T I A L I S A T I O N
145 %% SWI begin
146 :- dynamic user:exception/3.
147 :- multifile user:exception/3.
149 user:exception(undefined_global_variable, Name, retry) :-
150 chr_runtime_global_variable(Name),
151 chr_init.
153 chr_runtime_global_variable(chr_id).
154 chr_runtime_global_variable(chr_global).
155 chr_runtime_global_variable(chr_debug).
156 chr_runtime_global_variable(chr_debug_history).
158 chr_init :-
159 nb_setval(chr_id,0),
160 nb_setval(chr_global,_),
161 nb_setval(chr_debug,mutable(off)), % XXX
162 nb_setval(chr_debug_history,mutable([],0)). % XXX
163 %% SWI end
165 %% SICStus begin
166 %% chr_init :-
167 %% nb_setval(chr_id,0).
168 %% SICStus end
170 :- initialization chr_init.
173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
174 % Contents of former chr_debug.pl
176 % chr_show_store(+Module)
178 % Prints all suspended constraints of module Mod to the standard
179 % output.
181 chr_show_store(Mod) :-
183 Mod:'$enumerate_constraints'(Constraint),
184 print(Constraint),nl, % allows use of portray to control printing
186 fail
188 true
191 find_chr_constraint(Constraint) :-
192 chr:'$chr_module'(Mod),
193 Mod:'$enumerate_constraints'(Constraint).
195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196 % Inlining of some goals is good for performance
197 % That's the reason for the next section
198 % There must be correspondence with the predicates as implemented in chr_mutable.pl
199 % so that user:goal_expansion(G,G). also works (but do not add such a rule)
200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
202 %% SWI begin
203 :- multifile user:goal_expansion/2.
204 :- dynamic user:goal_expansion/2.
206 user:goal_expansion('chr get_mutable'(Val,Var), Var=mutable(Val)).
207 user:goal_expansion('chr update_mutable'(Val,Var), setarg(1,Var,Val)).
208 user:goal_expansion('chr create_mutable'(Val,Var), Var=mutable(Val)).
209 user:goal_expansion('chr default_store'(X), nb_getval(chr_global,X)).
210 %% SWI end
212 % goal_expansion seems too different in SICStus 4 for me to cater for in a
213 % decent way at this moment - so I stick with the old way to do this
214 % so that it doesn't get lost, the code from Mats for SICStus 4 is included in comments
217 %% Mats begin
218 %% goal_expansion('chr get_mutable'(Val,Var), Lay, _M, get_mutable(Val,Var), Lay).
219 %% goal_expansion('chr update_mutable'(Val,Var), Lay, _M, update_mutable(Val,Var), Lay).
220 %% goal_expansion('chr create_mutable'(Val,Var), Lay, _M, create_mutable(Val,Var), Lay).
221 %% goal_expansion('chr default_store'(A), Lay, _M, global_term_ref_1(A), Lay).
222 %% Mats begin
225 %% SICStus begin
226 %% :- multifile user:goal_expansion/2.
227 %% :- dynamic user:goal_expansion/2.
229 %% user:goal_expansion('chr get_mutable'(Val,Var), get_mutable(Val,Var)).
230 %% user:goal_expansion('chr update_mutable'(Val,Var), update_mutable(Val,Var)).
231 %% user:goal_expansion('chr create_mutable'(Val,Var), create_mutable(Val,Var)).
232 %% user:goal_expansion('chr default_store'(A), global_term_ref_1(A)).
233 %% SICStus end
236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
237 'chr run_suspensions'( Slots) :-
238 run_suspensions( Slots).
240 'chr run_suspensions_loop'([]).
241 'chr run_suspensions_loop'([L|Ls]) :-
242 run_suspensions(L),
243 'chr run_suspensions_loop'(Ls).
245 run_suspensions([]).
246 run_suspensions([S|Next] ) :-
247 arg( 2, S, Mref), % ARGXXX
248 'chr get_mutable'( Status, Mref),
249 ( Status==active ->
250 'chr update_mutable'( triggered, Mref),
251 arg( 4, S, Gref), % ARGXXX
252 'chr get_mutable'( Gen, Gref),
253 Generation is Gen+1,
254 'chr update_mutable'( Generation, Gref),
255 arg( 3, S, Goal), % ARGXXX
256 call( Goal),
257 'chr get_mutable'( Post, Mref),
258 ( Post==triggered ->
259 'chr update_mutable'( active, Mref) % catching constraints that did not do anything
261 true
264 true
266 run_suspensions( Next).
268 'chr run_suspensions_d'( Slots) :-
269 run_suspensions_d( Slots).
271 'chr run_suspensions_loop_d'([]).
272 'chr run_suspensions_loop_d'([L|Ls]) :-
273 run_suspensions_d(L),
274 'chr run_suspensions_loop_d'(Ls).
276 run_suspensions_d([]).
277 run_suspensions_d([S|Next] ) :-
278 arg( 2, S, Mref), % ARGXXX
279 'chr get_mutable'( Status, Mref),
280 ( Status==active ->
281 'chr update_mutable'( triggered, Mref),
282 arg( 4, S, Gref), % ARGXXX
283 'chr get_mutable'( Gen, Gref),
284 Generation is Gen+1,
285 'chr update_mutable'( Generation, Gref),
286 arg( 3, S, Goal), % ARGXXX
288 'chr debug_event'(wake(S)),
289 call( Goal)
291 'chr debug_event'(fail(S)), !,
292 fail
295 'chr debug_event'(exit(S))
297 'chr debug_event'(redo(S)),
298 fail
300 'chr get_mutable'( Post, Mref),
301 ( Post==triggered ->
302 'chr update_mutable'( active, Mref) % catching constraints that did not do anything
304 true
307 true
309 run_suspensions_d( Next).
310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311 locked:attr_unify_hook(_,_) :- fail.
313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
314 'chr lock'(T) :-
315 ( var(T)
316 -> put_attr(T, locked, x)
317 ; term_variables(T,L),
318 lockv(L)
321 lockv([]).
322 lockv([T|R]) :- put_attr( T, locked, x), lockv(R).
324 'chr unlock'(T) :-
325 ( var(T)
326 -> del_attr(T, locked)
327 ; term_variables(T,L),
328 unlockv(L)
331 unlockv([]).
332 unlockv([T|R]) :- del_attr( T, locked), unlockv(R).
334 'chr none_locked'( []).
335 'chr none_locked'( [V|Vs]) :-
336 ( get_attr(V, locked, _) ->
337 fail
339 'chr none_locked'(Vs)
342 'chr not_locked'(V) :-
343 ( var( V) ->
344 ( get_attr( V, locked, _) ->
345 fail
347 true
350 true
353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
355 % Eager removal from all chains.
357 'chr remove_constraint_internal'( Susp, Agenda) :-
358 arg( 2, Susp, Mref), % ARGXXX
359 'chr get_mutable'( State, Mref),
360 'chr update_mutable'( removed, Mref), % mark in any case
361 ( compound(State) -> % passive/1
362 Agenda = []
363 ; State==removed ->
364 Agenda = []
365 %; State==triggered ->
366 % Agenda = []
368 Susp =.. [_,_,_,_,_,_,_|Args],
369 term_variables( Args, Vars),
370 'chr default_store'( Global),
371 Agenda = [Global|Vars]
374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375 'chr newvia_1'(X,V) :-
376 ( var(X) ->
377 X = V
379 nonground(X,V)
382 'chr newvia_2'(X,Y,V) :-
383 ( var(X) ->
384 X = V
385 ; var(Y) ->
386 Y = V
387 ; compound(X), nonground(X,V) ->
388 true
390 compound(Y), nonground(Y,V)
394 % The second arg is a witness.
395 % The formulation with term_variables/2 is
396 % cycle safe, but it finds a list of all vars.
397 % We need only one, and no list in particular.
399 'chr newvia'(L,V) :- nonground(L,V).
400 %~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
402 'chr via_1'(X,V) :-
403 ( var(X) ->
404 X = V
405 ; atomic(X) ->
406 'chr default_store'(V)
407 ; nonground(X,V) ->
408 true
410 'chr default_store'(V)
413 'chr via_2'(X,Y,V) :-
414 ( var(X) ->
415 X = V
416 ; var(Y) ->
417 Y = V
418 ; compound(X), nonground(X,V) ->
419 true
420 ; compound(Y), nonground(Y,V) ->
421 true
423 'chr default_store'(V)
427 % The second arg is a witness.
428 % The formulation with term_variables/2 is
429 % cycle safe, but it finds a list of all vars.
430 % We need only one, and no list in particular.
432 'chr via'(L,V) :-
433 ( nonground(L,V) ->
434 true
436 'chr default_store'(V)
439 nonground( Term, V) :-
440 term_variables( Term, Vs),
441 Vs = [V|_].
443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
444 'chr novel_production'( Self, Tuple) :-
445 arg( 5, Self, Ref), % ARGXXX
446 'chr get_mutable'( History, Ref),
447 ( get_ds( Tuple, History, _) ->
448 fail
450 true
454 % Not folded with novel_production/2 because guard checking
455 % goes in between the two calls.
457 'chr extend_history'( Self, Tuple) :-
458 arg( 5, Self, Ref), % ARGXXX
459 'chr get_mutable'( History, Ref),
460 put_ds( Tuple, History, x, NewHistory),
461 'chr update_mutable'( NewHistory, Ref).
463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
464 constraint_generation( Susp, State, Generation) :-
465 arg( 2, Susp, Mref), % ARGXXX
466 'chr get_mutable'( State, Mref),
467 arg( 4, Susp, Gref), % ARGXXX
468 'chr get_mutable'( Generation, Gref). % not incremented meanwhile
470 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
471 'chr allocate_constraint'( Closure, Self, F, Args) :-
472 Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args], % SUSPXXX
473 'chr create_mutable'(0, Gref),
474 'chr empty_history'(History),
475 'chr create_mutable'(History, Href),
476 'chr create_mutable'(passive(Args), Mref),
477 'chr gen_id'( Id).
480 % 'chr activate_constraint'( -, +, -).
482 % The transition gc->active should be rare
484 'chr activate_constraint'( Vars, Susp, Generation) :-
485 arg( 2, Susp, Mref), % ARGXXX
486 'chr get_mutable'( State, Mref),
487 'chr update_mutable'( active, Mref),
488 ( nonvar(Generation) -> % aih
489 true
491 arg( 4, Susp, Gref), % ARGXXX
492 'chr get_mutable'( Gen, Gref),
493 Generation is Gen+1,
494 'chr update_mutable'( Generation, Gref)
496 ( compound(State) -> % passive/1
497 term_variables( State, Vs),
498 'chr none_locked'( Vs),
499 Vars = [Global|Vs],
500 'chr default_store'(Global)
501 ; State == removed -> % the price for eager removal ...
502 Susp =.. [_,_,_,_,_,_,_|Args],
503 term_variables( Args, Vs),
504 Vars = [Global|Vs],
505 'chr default_store'(Global)
507 Vars = []
510 'chr insert_constraint_internal'([Global|Vars], Self, Closure, F, Args) :-
511 'chr default_store'(Global),
512 term_variables(Args,Vars),
513 'chr none_locked'(Vars),
514 Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args], % SUSPXXX
515 'chr create_mutable'(active, Mref),
516 'chr create_mutable'(0, Gref),
517 'chr empty_history'(History),
518 'chr create_mutable'(History, Href),
519 'chr gen_id'(Id).
521 insert_constraint_internal([Global|Vars], Self, Term, Closure, F, Args) :-
522 'chr default_store'(Global),
523 term_variables( Term, Vars),
524 'chr none_locked'( Vars),
525 'chr empty_history'( History),
526 'chr create_mutable'( active, Mref),
527 'chr create_mutable'( 0, Gref),
528 'chr create_mutable'( History, Href),
529 'chr gen_id'( Id),
530 Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args]. % SUSPXXX
532 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533 'chr empty_history'( E) :- empty_ds( E).
535 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
536 'chr gen_id'( Id) :-
537 nb_getval(chr_id,Id),
538 NextId is Id + 1,
539 nb_setval(chr_id,NextId).
541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
543 %% SWI begin
544 'chr create_mutable'(V,mutable(V)).
545 'chr get_mutable'(V,mutable(V)).
546 'chr update_mutable'(V,M) :- setarg(1,M,V).
547 %% SWI end
549 %% SICStus begin
550 %% 'chr create_mutable'(Val, Mut) :- create_mutable(Val, Mut).
551 %% 'chr get_mutable'(Val, Mut) :- get_mutable(Val, Mut).
552 %% 'chr update_mutable'(Val, Mut) :- update_mutable(Val, Mut).
553 %% SICStus end
556 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
557 %% SWI begin
558 'chr default_store'(X) :- nb_getval(chr_global,X).
559 %% SWI end
561 %% SICStus begin
562 %% 'chr default_store'(A) :- global_term_ref_1(A).
563 %% SICStus end
565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567 %'chr sbag_member'( Head, [Head]) :- !.
568 %'chr sbag_member'( Head, [Head|Tail]).
569 %'chr sbag_member'( Elem, [_|Tail]) :-
570 % 'chr sbag_member'( Elem, Tail).
572 'chr sbag_member'( Element, [Head|Tail]) :-
573 sbag_member( Element, Tail, Head).
575 % auxiliary to avoid choicepoint for last element
576 % does it really avoid the choicepoint? -jon
577 sbag_member( E, _, E).
578 sbag_member( E, [Head|Tail], _) :-
579 sbag_member( E, Tail, Head).
581 'chr sbag_del_element'( [], _, []).
582 'chr sbag_del_element'( [X|Xs], Elem, Set2) :-
583 ( X==Elem ->
584 Set2 = Xs
586 Set2 = [X|Xss],
587 'chr sbag_del_element'( Xs, Elem, Xss)
590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
591 'chr merge_attributes'([],Ys,Ys).
592 'chr merge_attributes'([X | Xs],YL,R) :-
593 ( YL = [Y | Ys] ->
594 arg(1,X,XId), % ARGXXX
595 arg(1,Y,YId), % ARGXXX
596 ( XId < YId ->
597 R = [X | T],
598 'chr merge_attributes'(Xs,YL,T)
599 ; XId > YId ->
600 R = [Y | T],
601 'chr merge_attributes'([X|Xs],Ys,T)
603 R = [X | T],
604 'chr merge_attributes'(Xs,Ys,T)
607 R = [X | Xs]
610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
612 :- multifile
613 chr:debug_event/2, % +State, +Event
614 chr:debug_interact/3. % +Event, +Depth, -Command
616 'chr debug_event'(Event) :-
617 nb_getval(chr_debug,mutable(State)), % XXX
618 ( State == off ->
619 true
620 ; chr:debug_event(State, Event) ->
621 true
622 ; debug_event(State,Event)
625 chr_trace :-
626 nb_setval(chr_debug,mutable(trace)).
627 chr_notrace :-
628 nb_setval(chr_debug,mutable(off)).
630 % chr_leash(+Spec)
632 % Define the set of ports at which we prompt for user interaction
634 chr_leash(Spec) :-
635 leashed_ports(Spec, Ports),
636 nb_setval(chr_leash,mutable(Ports)).
638 leashed_ports(none, []).
639 leashed_ports(off, []).
640 leashed_ports(all, [call, exit, redo, fail, wake, try, apply, insert, remove]).
641 leashed_ports(default, [call,exit,fail,wake,apply]).
642 leashed_ports(One, Ports) :-
643 atom(One), One \== [], !,
644 leashed_ports([One], Ports).
645 leashed_ports(Set, Ports) :-
646 sort(Set, Ports), % make unique
647 leashed_ports(all, All),
648 valid_ports(Ports, All).
650 valid_ports([], _).
651 valid_ports([H|T], Valid) :-
652 ( memberchk(H, Valid)
653 -> true
654 ; throw(error(domain_error(chr_port, H), _))
656 valid_ports(T, Valid).
659 :- initialization
660 leashed_ports(default, Ports),
661 nb_setval(chr_leash, mutable(Ports)).
663 % debug_event(+State, +Event)
666 %debug_event(trace, Event) :-
667 % functor(Event, Name, Arity),
668 % writeln(Name/Arity), fail.
669 debug_event(trace,Event) :-
670 Event = call(_), !,
671 get_debug_history(History,Depth),
672 NDepth is Depth + 1,
673 chr_debug_interact(Event,NDepth),
674 set_debug_history([Event|History],NDepth).
675 debug_event(trace,Event) :-
676 Event = wake(_), !,
677 get_debug_history(History,Depth),
678 NDepth is Depth + 1,
679 chr_debug_interact(Event,NDepth),
680 set_debug_history([Event|History],NDepth).
681 debug_event(trace,Event) :-
682 Event = redo(_), !,
683 get_debug_history(_History, Depth),
684 chr_debug_interact(Event, Depth).
685 debug_event(trace,Event) :-
686 Event = exit(_),!,
687 get_debug_history([_|History],Depth),
688 chr_debug_interact(Event,Depth),
689 NDepth is Depth - 1,
690 set_debug_history(History,NDepth).
691 debug_event(trace,Event) :-
692 Event = fail(_),!,
693 get_debug_history(_,Depth),
694 chr_debug_interact(Event,Depth).
695 debug_event(trace, Event) :-
696 Event = remove(_), !,
697 get_debug_history(_,Depth),
698 chr_debug_interact(Event, Depth).
699 debug_event(trace, Event) :-
700 Event = insert(_), !,
701 get_debug_history(_,Depth),
702 chr_debug_interact(Event, Depth).
703 debug_event(trace, Event) :-
704 Event = try(_,_,_,_), !,
705 get_debug_history(_,Depth),
706 chr_debug_interact(Event, Depth).
707 debug_event(trace, Event) :-
708 Event = apply(_,_,_,_), !,
709 get_debug_history(_,Depth),
710 chr_debug_interact(Event,Depth).
712 debug_event(skip(_,_),Event) :-
713 Event = call(_), !,
714 get_debug_history(History,Depth),
715 NDepth is Depth + 1,
716 set_debug_history([Event|History],NDepth).
717 debug_event(skip(_,_),Event) :-
718 Event = wake(_), !,
719 get_debug_history(History,Depth),
720 NDepth is Depth + 1,
721 set_debug_history([Event|History],NDepth).
722 debug_event(skip(SkipSusp,SkipDepth),Event) :-
723 Event = exit(Susp),!,
724 get_debug_history([_|History],Depth),
725 ( SkipDepth == Depth,
726 SkipSusp == Susp ->
727 set_chr_debug(trace),
728 chr_debug_interact(Event,Depth)
730 true
732 NDepth is Depth - 1,
733 set_debug_history(History,NDepth).
734 debug_event(skip(_,_),_) :- !,
735 true.
737 % chr_debug_interact(+Event, +Depth)
739 % Interact with the user on Event that took place at Depth. First
740 % calls chr:debug_interact(+Event, +Depth, -Command) hook. If this
741 % fails the event is printed and the system prompts for a command.
743 chr_debug_interact(Event, Depth) :-
744 chr:debug_interact(Event, Depth, Command), !,
745 handle_debug_command(Command,Event,Depth).
746 chr_debug_interact(Event, Depth) :-
747 print_event(Event, Depth),
748 ( leashed(Event)
749 -> ask_continue(Command)
750 ; Command = creep
752 handle_debug_command(Command,Event,Depth).
754 leashed(Event) :-
755 functor(Event, Port, _),
756 nb_getval(chr_leash, mutable(Ports)),
757 memberchk(Port, Ports).
759 ask_continue(Command) :-
760 print_message(debug, chr(prompt)),
761 get_single_char(CharCode),
762 ( CharCode == -1
763 -> Char = end_of_file
764 ; char_code(Char, CharCode)
766 ( debug_command(Char, Command)
767 -> print_message(debug, chr(command(Command)))
768 ; print_message(help, chr(invalid_command)),
769 ask_continue(Command)
773 'chr debug command'(Char, Command) :-
774 debug_command(Char, Command).
776 debug_command(c, creep).
777 debug_command(' ', creep).
778 debug_command('\r', creep).
779 debug_command(s, skip).
780 debug_command(g, ancestors).
781 debug_command(n, nodebug).
782 debug_command(a, abort).
783 debug_command(f, fail).
784 debug_command(b, break).
785 debug_command(?, help).
786 debug_command(h, help).
787 debug_command(end_of_file, exit).
790 handle_debug_command(creep,_,_) :- !.
791 handle_debug_command(skip, Event, Depth) :- !,
792 Event =.. [Type|Rest],
793 ( Type \== call,
794 Type \== wake ->
795 handle_debug_command('c',Event,Depth)
797 Rest = [Susp],
798 set_chr_debug(skip(Susp,Depth))
801 handle_debug_command(ancestors,Event,Depth) :- !,
802 print_chr_debug_history,
803 chr_debug_interact(Event,Depth).
804 handle_debug_command(nodebug,_,_) :- !,
805 chr_notrace.
806 handle_debug_command(abort,_,_) :- !,
807 abort.
808 handle_debug_command(exit,_,_) :- !,
809 halt.
810 handle_debug_command(fail,_,_) :- !,
811 fail.
812 handle_debug_command(break,Event,Depth) :- !,
813 break,
814 chr_debug_interact(Event,Depth).
815 handle_debug_command(help,Event,Depth) :- !,
816 print_message(help, chr(debug_options)),
817 chr_debug_interact(Event,Depth).
818 handle_debug_command(Cmd, _, _) :-
819 throw(error(domain_error(chr_debug_command, Cmd), _)).
821 print_chr_debug_history :-
822 get_debug_history(History,Depth),
823 print_message(debug, chr(ancestors(History, Depth))).
825 print_event(Event, Depth) :-
826 print_message(debug, chr(event(Event, Depth))).
828 % {set,get}_debug_history(Ancestors, Depth)
830 % Set/get the list of ancestors and the depth of the current goal.
832 get_debug_history(History,Depth) :-
833 nb_getval(chr_debug_history,mutable(History,Depth)).
835 set_debug_history(History,Depth) :-
836 nb_getval(chr_debug_history,Mutable),
837 setarg(1,Mutable,History),
838 setarg(2,Mutable,Depth).
840 set_chr_debug(State) :-
841 nb_getval(chr_debug,Mutable),
842 setarg(1,Mutable,State).
844 'chr chr_indexed_variables'(Susp,Vars) :-
845 Susp =.. [_,_,_,_,_,_,_|Args],
846 term_variables(Args,Vars).