* Avoud autoload
[chr.git] / chr_runtime.pl
blobaf47a3696d726134fb164a85b544e02912327e4e
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.ac.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.ac.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 %% * Renamed merge/3 --> sbag_merge/3 (name conflict)
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72 :- module(chr_runtime,
73 [ 'chr sbag_del_element'/3,
74 'chr sbag_member'/2,
75 'chr merge_attributes'/3,
77 'chr run_suspensions'/1,
78 'chr run_suspensions_loop'/1,
80 'chr run_suspensions_d'/1,
81 'chr run_suspensions_loop_d'/1,
83 'chr insert_constraint_internal'/5,
84 'chr remove_constraint_internal'/2,
85 'chr allocate_constraint'/4,
86 'chr activate_constraint'/3,
88 'chr global_term_ref_1'/1,
90 'chr via_1'/2,
91 'chr via_2'/3,
92 'chr via'/2,
94 'chr lock'/1,
95 'chr unlock'/1,
96 'chr not_locked'/1,
97 'chr none_locked'/1,
99 'chr update_mutable'/2,
100 'chr get_mutable'/2,
102 'chr novel_production'/2,
103 'chr extend_history'/2,
104 'chr empty_history'/1,
106 'chr gen_id'/1,
108 'chr debug_event'/1,
109 'chr debug command'/2, % Char, Command
111 'chr chr_indexed_variables'/2,
113 chr_trace/0,
114 chr_notrace/0,
115 chr_leash/1
117 :- set_prolog_flag(generate_debug_info, false).
119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121 :- use_module(library(assoc)).
122 :- use_module(hprolog).
123 :- use_module(library(lists)).
124 :- include(chr_op).
126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
128 % I N I T I A L I S A T I O N
130 chr_init :-
131 nb_setval(id,0),
132 nb_setval(chr_global,_),
133 nb_setval(chr_debug,mutable(off)),
134 nb_setval(chr_debug_history,mutable([],0)).
136 :- initialization chr_init.
138 show_store(Mod) :-
140 Mod:'$enumerate_suspensions'(Susp),
141 arg(6,Susp,C),
142 writeln(C),
143 fail
145 true
148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149 'chr merge_attributes'( As, Bs, Cs) :-
150 sbag_union(As,Bs,Cs).
152 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
153 'chr run_suspensions'( Slots) :-
154 run_suspensions( Slots).
156 'chr run_suspensions_loop'([]).
157 'chr run_suspensions_loop'([L|Ls]) :-
158 run_suspensions(L),
159 'chr run_suspensions_loop'(Ls).
161 run_suspensions([]).
162 run_suspensions([S|Next] ) :-
163 arg( 2, S, Mref),
164 Mref = mutable(Status), % get_mutable( Status, Mref), % XXX Inlined
165 ( Status==active ->
166 update_mutable( triggered, Mref),
167 arg( 4, S, Gref),
168 Gref = mutable(Gen), % get_mutable( Gen, Gref), % XXX Inlined
169 Generation is Gen+1,
170 update_mutable( Generation, Gref),
171 arg( 3, S, Goal),
172 call( Goal),
173 % get_mutable( Post, Mref), % XXX Inlined
174 ( Mref = mutable(triggered) -> % Post==triggered ->
175 update_mutable( removed, Mref)
177 true
180 true
182 run_suspensions( Next).
184 'chr run_suspensions_d'( Slots) :-
185 run_suspensions_d( Slots).
187 'chr run_suspensions_loop_d'([]).
188 'chr run_suspensions_loop_d'([L|Ls]) :-
189 run_suspensions_d(L),
190 'chr run_suspensions_loop_d'(Ls).
192 run_suspensions_d([]).
193 run_suspensions_d([S|Next] ) :-
194 arg( 2, S, Mref),
195 Mref = mutable(Status), % get_mutable( Status, Mref), % XXX Inlined
196 ( Status==active ->
197 update_mutable( triggered, Mref),
198 arg( 4, S, Gref),
199 Gref = mutable(Gen), % get_mutable( Gen, Gref), % XXX Inlined
200 Generation is Gen+1,
201 update_mutable( Generation, Gref),
202 arg( 3, S, Goal),
204 'chr debug_event'(wake(S)),
205 call( Goal)
207 'chr debug_event'(fail(S)), !,
208 fail
211 'chr debug_event'(exit(S))
213 'chr debug_event'(redo(S)),
214 fail
216 % get_mutable( Post, Mref), % XXX Inlined
217 ( Mref = mutable(triggered) -> % Post==triggered ->
218 update_mutable( removed, Mref)
220 true
223 true
225 run_suspensions_d( Next).
226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227 locked:attr_unify_hook(_,_) :- fail.
229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
230 'chr lock'(T) :-
231 lock(T).
233 'chr unlock'(T) :-
234 unlock(T).
236 'chr not_locked'(T) :-
237 not_locked(T).
239 lock(T) :-
240 ( var(T)
241 -> put_attr(T, locked, x)
242 ; term_variables(T,L),
243 lockv(L)
246 lockv([]).
247 lockv([T|R]) :- put_attr( T, locked, x), lockv(R).
249 unlock(T) :-
250 ( var(T)
251 -> del_attr(T, locked)
252 ; term_variables(T,L),
253 unlockv(L)
256 unlockv([]).
257 unlockv([T|R]) :- del_attr( T, locked), unlockv(R).
259 'chr none_locked'( []).
260 'chr none_locked'( [V|Vs]) :-
261 not_locked( V),
262 'chr none_locked'( Vs).
264 not_locked( V) :-
265 ( var( V) ->
266 ( get_attr( V, locked, _) ->
267 fail
269 true
272 true
275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
277 % Eager removal from all chains.
279 'chr remove_constraint_internal'( Susp, Agenda) :-
280 arg( 2, Susp, Mref),
281 Mref = mutable(State), % get_mutable( State, Mref), % XXX Inlined
282 update_mutable( removed, Mref), % mark in any case
283 ( compound(State) -> % passive/1
284 Agenda = []
285 ; State==removed ->
286 Agenda = []
287 %; State==triggered ->
288 % Agenda = []
290 Susp =.. [_,_,_,_,_,_,_|Args],
291 term_variables( Args, Vars),
292 global_term_ref_1( Global),
293 Agenda = [Global|Vars]
296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
297 'chr via_1'(X,V) :-
298 ( var(X) ->
299 X = V
300 ; atomic(X) ->
301 global_term_ref_1(V)
302 ; nonground(X,V) ->
303 true
305 global_term_ref_1(V)
307 % 'chr via_1'( X, V) :- var(X), !, X=V.
308 % 'chr via_1'( T, V) :- compound(T), nonground( T, V), ! .
309 % 'chr via_1'( _, V) :- global_term_ref_1( V).
311 'chr via_2'(X,Y,V) :-
312 ( var(X) ->
313 X = V
314 ; var(Y) ->
315 Y = V
316 ; compound(X), nonground(X,V) ->
317 true
318 ; compound(Y), nonground(Y,V) ->
319 true
321 global_term_ref_1(V)
323 % 'chr via_2'( X, _, V) :- var(X), !, X=V.
324 % 'chr via_2'( _, Y, V) :- var(Y), !, Y=V.
325 % 'chr via_2'( T, _, V) :- compound(T), nonground( T, V), ! .
326 % 'chr via_2'( _, T, V) :- compound(T), nonground( T, V), ! .
327 % 'chr via_2'( _, _, V) :- global_term_ref_1( V).
330 % The second arg is a witness.
331 % The formulation with term_variables/2 is
332 % cycle safe, but it finds a list of all vars.
333 % We need only one, and no list in particular.
335 'chr via'(L,V) :-
336 ( nonground(L,V) ->
337 true
339 global_term_ref_1(V)
342 nonground( Term, V) :-
343 term_variables( Term, Vs),
344 Vs = [V|_].
346 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
347 'chr novel_production'( Self, Tuple) :-
348 arg( 5, Self, Ref),
349 Ref = mutable(History), % get_mutable( History, Ref), % XXX Inlined
350 ( get_assoc( Tuple, History, _) ->
351 fail
353 true
357 % Not folded with novel_production/2 because guard checking
358 % goes in between the two calls.
360 'chr extend_history'( Self, Tuple) :-
361 arg( 5, Self, Ref),
362 Ref = mutable(History), % get_mutable( History, Ref), % XXX Inlined
363 put_assoc( Tuple, History, x, NewHistory),
364 update_mutable( NewHistory, Ref).
366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367 constraint_generation( Susp, State, Generation) :-
368 arg( 2, Susp, Mref),
369 Mref = mutable(State), % get_mutable( State, Mref), % XXX Inlined
370 arg( 4, Susp, Gref),
371 Gref = mutable(Generation). % get_mutable( Generation, Gref). % not incremented meanwhile % XXX Inlined
373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
374 'chr allocate_constraint'( Closure, Self, F, Args) :-
375 'chr empty_history'( History),
376 create_mutable( passive(Args), Mref),
377 create_mutable( 0, Gref),
378 create_mutable( History, Href),
379 'chr gen_id'( Id),
380 Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args].
383 % 'chr activate_constraint'( -, +, -).
385 % The transition gc->active should be rare
387 'chr activate_constraint'( Vars, Susp, Generation) :-
388 arg( 2, Susp, Mref),
389 Mref = mutable(State), % get_mutable( State, Mref), % XXX Inlined
390 update_mutable( active, Mref),
391 ( nonvar(Generation) -> % aih
392 true
394 arg( 4, Susp, Gref),
395 Gref = mutable(Gen), % get_mutable( Gen, Gref), % XXX Inlined
396 Generation is Gen+1,
397 update_mutable( Generation, Gref)
399 ( compound(State) -> % passive/1
400 term_variables( State, Vs),
401 'chr none_locked'( Vs),
402 global_term_ref_1( Global),
403 Vars = [Global|Vs]
404 ; State==removed -> % the price for eager removal ...
405 Susp =.. [_,_,_,_,_,_,_|Args],
406 term_variables( Args, Vs),
407 global_term_ref_1( Global),
408 Vars = [Global|Vs]
410 Vars = []
413 'chr insert_constraint_internal'( [Global|Vars], Self, Closure, F, Args) :-
414 term_variables( Args, Vars),
415 'chr none_locked'( Vars),
416 global_term_ref_1( Global),
417 'chr empty_history'( History),
418 create_mutable( active, Mref),
419 create_mutable( 0, Gref),
420 create_mutable( History, Href),
421 'chr gen_id'( Id),
422 Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args].
424 insert_constraint_internal( [Global|Vars], Self, Term, Closure, F, Args) :-
425 term_variables( Term, Vars),
426 'chr none_locked'( Vars),
427 global_term_ref_1( Global),
428 'chr empty_history'( History),
429 create_mutable( active, Mref),
430 create_mutable( 0, Gref),
431 create_mutable( History, Href),
432 'chr gen_id'( Id),
433 Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args].
435 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
436 change_state( Susp, State) :-
437 arg( 2, Susp, Mref),
438 update_mutable( State, Mref).
440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441 'chr empty_history'( E) :- empty_assoc( E).
443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
444 'chr gen_id'( Id) :-
445 incval( id, Id).
447 incval(id,Id) :-
448 nb_getval(id,Id),
449 NextId is Id + 1,
450 nb_setval(id,NextId).
452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
453 create_mutable(V,mutable(V)).
455 'chr get_mutable'(V, mutable(V)).
457 'chr update_mutable'(V,M) :-
458 setarg(1,M,V).
460 get_mutable(V, mutable(V)).
462 update_mutable(V,M) :-
463 setarg(1,M,V).
465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
466 'chr global_term_ref_1'(X) :-
467 global_term_ref_1(X).
469 global_term_ref_1(X) :-
470 nb_getval(chr_global,X).
472 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
474 'chr sbag_member'( Element, [Head|Tail]) :-
475 sbag_member( Element, Tail, Head).
477 % auxiliary to avoid choicepoint for last element
479 sbag_member( E, _, E).
480 sbag_member( E, [Head|Tail], _) :-
481 sbag_member( E, Tail, Head).
483 'chr sbag_del_element'( [], _, []).
484 'chr sbag_del_element'( [X|Xs], Elem, Set2) :-
485 ( X==Elem ->
486 Set2 = Xs
488 Set2 = [X|Xss],
489 'chr sbag_del_element'( Xs, Elem, Xss)
492 sbag_union( A, B, C) :-
493 sbag_merge( A, B, C).
495 sbag_merge([],Ys,Ys).
496 sbag_merge([X | Xs],YL,R) :-
497 ( YL = [Y | Ys] ->
498 arg(1,X,XId),
499 arg(1,Y,YId),
500 ( XId < YId ->
501 R = [X | T],
502 sbag_merge(Xs,YL,T)
503 ; XId > YId ->
504 R = [Y | T],
505 sbag_merge([X|Xs],Ys,T)
507 R = [X | T],
508 sbag_merge(Xs,Ys,T)
511 R = [X | Xs]
514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
516 :- multifile
517 chr:debug_event/2, % +State, +Event
518 chr:debug_interact/3. % +Event, +Depth, -Command
520 'chr debug_event'(Event) :-
521 nb_getval(chr_debug,mutable(State)),
522 ( State == off ->
523 true
524 ; chr:debug_event(State, Event) ->
525 true
526 ; debug_event(State,Event)
529 chr_trace :-
530 nb_setval(chr_debug,mutable(trace)).
531 chr_notrace :-
532 nb_setval(chr_debug,mutable(off)).
534 % chr_leash(+Spec)
536 % Define the set of ports at which we prompt for user interaction
538 chr_leash(Spec) :-
539 leashed_ports(Spec, Ports),
540 nb_setval(chr_leash,mutable(Ports)).
542 leashed_ports(none, []).
543 leashed_ports(off, []).
544 leashed_ports(all, [call, exit, redo, fail, wake, try, apply, insert, remove]).
545 leashed_ports(default, [call,exit,fail,wake,apply]).
546 leashed_ports(One, Ports) :-
547 atom(One), One \== [], !,
548 leashed_ports([One], Ports).
549 leashed_ports(Set, Ports) :-
550 sort(Set, Ports), % make unique
551 leashed_ports(all, All),
552 valid_ports(Ports, All).
554 valid_ports([], _).
555 valid_ports([H|T], Valid) :-
556 ( memberchk(H, Valid)
557 -> true
558 ; throw(error(domain_error(chr_port, H), _))
560 valid_ports(T, Valid).
563 :- initialization
564 leashed_ports(default, Ports),
565 nb_setval(chr_leash, mutable(Ports)).
567 % debug_event(+State, +Event)
570 %debug_event(trace, Event) :-
571 % functor(Event, Name, Arity),
572 % writeln(Name/Arity), fail.
573 debug_event(trace,Event) :-
574 Event = call(_), !,
575 get_debug_history(History,Depth),
576 NDepth is Depth + 1,
577 chr_debug_interact(Event,NDepth),
578 set_debug_history([Event|History],NDepth).
579 debug_event(trace,Event) :-
580 Event = wake(_), !,
581 get_debug_history(History,Depth),
582 NDepth is Depth + 1,
583 chr_debug_interact(Event,NDepth),
584 set_debug_history([Event|History],NDepth).
585 debug_event(trace,Event) :-
586 Event = redo(_), !,
587 get_debug_history(_History, Depth),
588 chr_debug_interact(Event, Depth).
589 debug_event(trace,Event) :-
590 Event = exit(_),!,
591 get_debug_history([_|History],Depth),
592 chr_debug_interact(Event,Depth),
593 NDepth is Depth - 1,
594 set_debug_history(History,NDepth).
595 debug_event(trace,Event) :-
596 Event = fail(_),!,
597 get_debug_history(_,Depth),
598 chr_debug_interact(Event,Depth).
599 debug_event(trace, Event) :-
600 Event = remove(_), !,
601 get_debug_history(_,Depth),
602 chr_debug_interact(Event, Depth).
603 debug_event(trace, Event) :-
604 Event = insert(_), !,
605 get_debug_history(_,Depth),
606 chr_debug_interact(Event, Depth).
607 debug_event(trace, Event) :-
608 Event = try(_,_,_,_), !,
609 get_debug_history(_,Depth),
610 chr_debug_interact(Event, Depth).
611 debug_event(trace, Event) :-
612 Event = apply(_,_,_,_), !,
613 get_debug_history(_,Depth),
614 chr_debug_interact(Event,Depth).
616 debug_event(skip(_,_),Event) :-
617 Event = call(_), !,
618 get_debug_history(History,Depth),
619 NDepth is Depth + 1,
620 set_debug_history([Event|History],NDepth).
621 debug_event(skip(_,_),Event) :-
622 Event = wake(_), !,
623 get_debug_history(History,Depth),
624 NDepth is Depth + 1,
625 set_debug_history([Event|History],NDepth).
626 debug_event(skip(SkipSusp,SkipDepth),Event) :-
627 Event = exit(Susp),!,
628 get_debug_history([_|History],Depth),
629 ( SkipDepth == Depth,
630 SkipSusp == Susp ->
631 set_chr_debug(trace),
632 chr_debug_interact(Event,Depth)
634 true
636 NDepth is Depth - 1,
637 set_debug_history(History,NDepth).
638 debug_event(skip(_,_),_) :- !,
639 true.
641 % chr_debug_interact(+Event, +Depth)
643 % Interact with the user on Event that took place at Depth. First
644 % calls chr:debug_interact(+Event, +Depth, -Command) hook. If this
645 % fails the event is printed and the system prompts for a command.
647 chr_debug_interact(Event, Depth) :-
648 chr:debug_interact(Event, Depth, Command), !,
649 handle_debug_command(Command,Event,Depth).
650 chr_debug_interact(Event, Depth) :-
651 print_event(Event, Depth),
652 ( leashed(Event)
653 -> ask_continue(Command)
654 ; Command = creep
656 handle_debug_command(Command,Event,Depth).
658 leashed(Event) :-
659 functor(Event, Port, _),
660 nb_getval(chr_leash, mutable(Ports)),
661 memberchk(Port, Ports).
663 ask_continue(Command) :-
664 print_message(debug, chr(prompt)),
665 get_single_char(CharCode),
666 ( CharCode == -1
667 -> Char = end_of_file
668 ; char_code(Char, CharCode)
670 ( debug_command(Char, Command)
671 -> print_message(debug, chr(command(Command)))
672 ; print_message(help, chr(invalid_command)),
673 ask_continue(Command)
677 'chr debug command'(Char, Command) :-
678 debug_command(Char, Command).
680 debug_command(c, creep).
681 debug_command(' ', creep).
682 debug_command('\r', creep).
683 debug_command(s, skip).
684 debug_command(g, ancestors).
685 debug_command(n, nodebug).
686 debug_command(a, abort).
687 debug_command(f, fail).
688 debug_command(b, break).
689 debug_command(?, help).
690 debug_command(h, help).
691 debug_command(end_of_file, exit).
694 handle_debug_command(creep,_,_) :- !.
695 handle_debug_command(skip, Event, Depth) :- !,
696 Event =.. [Type|Rest],
697 ( Type \== call,
698 Type \== wake ->
699 handle_debug_command('c',Event,Depth)
701 Rest = [Susp],
702 set_chr_debug(skip(Susp,Depth))
705 handle_debug_command(ancestors,Event,Depth) :- !,
706 print_chr_debug_history,
707 chr_debug_interact(Event,Depth).
708 handle_debug_command(nodebug,_,_) :- !,
709 chr_notrace.
710 handle_debug_command(abort,_,_) :- !,
711 abort.
712 handle_debug_command(exit,_,_) :- !,
713 halt.
714 handle_debug_command(fail,_,_) :- !,
715 fail.
716 handle_debug_command(break,Event,Depth) :- !,
717 break,
718 chr_debug_interact(Event,Depth).
719 handle_debug_command(help,Event,Depth) :- !,
720 print_message(help, chr(debug_options)),
721 chr_debug_interact(Event,Depth).
722 handle_debug_command(Cmd, _, _) :-
723 throw(error(domain_error(chr_debug_command, Cmd), _)).
725 print_chr_debug_history :-
726 get_debug_history(History,Depth),
727 print_message(debug, chr(ancestors(History, Depth))).
729 print_event(Event, Depth) :-
730 print_message(debug, chr(event(Event, Depth))).
732 % {set,get}_debug_history(Ancestors, Depth)
734 % Set/get the list of ancestors and the depth of the current goal.
736 get_debug_history(History,Depth) :-
737 nb_getval(chr_debug_history,mutable(History,Depth)).
739 set_debug_history(History,Depth) :-
740 nb_getval(chr_debug_history,Mutable),
741 setarg(1,Mutable,History),
742 setarg(2,Mutable,Depth).
744 set_chr_debug(State) :-
745 nb_getval(chr_debug,Mutable),
746 setarg(1,Mutable,State).
748 'chr chr_indexed_variables'(Susp,Vars) :-
749 Susp =.. [_,_,_,_,_,_,_|Args],
750 term_variables(Args,Vars).