experimental dynamic attribute terms
[chr.git] / chr_runtime.pl
blob594e5fe842dff03223f82f555b4550b2793ecf3a
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 all_suspensions'/3,
117 'chr new_merge_attributes'/3,
118 'chr normalize_attr'/2,
120 chr_show_store/1, % +Module
121 find_chr_constraint/1,
123 chr_trace/0,
124 chr_notrace/0,
125 chr_leash/1
128 %% SWI begin
129 :- set_prolog_flag(generate_debug_info, false).
130 %% SWI end
132 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
134 :- use_module(hprolog).
135 :- include(chr_op).
137 %% SICStus begin
138 %% :- use_module(hpattvars).
139 %% :- use_module(b_globval).
140 %% SICStus end
143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
145 % I N I T I A L I S A T I O N
147 %% SWI begin
148 :- dynamic user:exception/3.
149 :- multifile user:exception/3.
151 user:exception(undefined_global_variable, Name, retry) :-
152 chr_runtime_global_variable(Name),
153 chr_init.
155 chr_runtime_global_variable(chr_id).
156 chr_runtime_global_variable(chr_global).
157 chr_runtime_global_variable(chr_debug).
158 chr_runtime_global_variable(chr_debug_history).
160 chr_init :-
161 nb_setval(chr_id,0),
162 nb_setval(chr_global,_),
163 nb_setval(chr_debug,mutable(off)), % XXX
164 nb_setval(chr_debug_history,mutable([],0)). % XXX
165 %% SWI end
167 %% SICStus begin
168 %% chr_init :-
169 %% nb_setval(chr_id,0).
170 %% SICStus end
172 :- initialization chr_init.
175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
176 % Contents of former chr_debug.pl
178 % chr_show_store(+Module)
180 % Prints all suspended constraints of module Mod to the standard
181 % output.
183 chr_show_store(Mod) :-
185 Mod:'$enumerate_constraints'(Constraint),
186 print(Constraint),nl, % allows use of portray to control printing
187 fail
189 true
192 find_chr_constraint(Constraint) :-
193 chr:'$chr_module'(Mod),
194 Mod:'$enumerate_constraints'(Constraint).
196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
197 % Inlining of some goals is good for performance
198 % That's the reason for the next section
199 % There must be correspondence with the predicates as implemented in chr_mutable.pl
200 % so that user:goal_expansion(G,G). also works (but do not add such a rule)
201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
203 %% SWI begin
204 :- multifile user:goal_expansion/2.
205 :- dynamic user:goal_expansion/2.
207 user:goal_expansion('chr get_mutable'(Val,Var), Var=mutable(Val)).
208 user:goal_expansion('chr update_mutable'(Val,Var), setarg(1,Var,Val)).
209 user:goal_expansion('chr create_mutable'(Val,Var), Var=mutable(Val)).
210 user:goal_expansion('chr default_store'(X), nb_getval(chr_global,X)).
211 %% SWI end
213 % goal_expansion seems too different in SICStus 4 for me to cater for in a
214 % decent way at this moment - so I stick with the old way to do this
215 % so that it doesn't get lost, the code from Mats for SICStus 4 is included in comments
218 %% Mats begin
219 %% goal_expansion('chr get_mutable'(Val,Var), Lay, _M, get_mutable(Val,Var), Lay).
220 %% goal_expansion('chr update_mutable'(Val,Var), Lay, _M, update_mutable(Val,Var), Lay).
221 %% goal_expansion('chr create_mutable'(Val,Var), Lay, _M, create_mutable(Val,Var), Lay).
222 %% goal_expansion('chr default_store'(A), Lay, _M, global_term_ref_1(A), Lay).
223 %% Mats begin
226 %% SICStus begin
227 %% :- multifile user:goal_expansion/2.
228 %% :- dynamic user:goal_expansion/2.
230 %% user:goal_expansion('chr get_mutable'(Val,Var), get_mutable(Val,Var)).
231 %% user:goal_expansion('chr update_mutable'(Val,Var), update_mutable(Val,Var)).
232 %% user:goal_expansion('chr create_mutable'(Val,Var), create_mutable(Val,Var)).
233 %% user:goal_expansion('chr default_store'(A), global_term_ref_1(A)).
234 %% SICStus end
237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238 'chr run_suspensions'( Slots) :-
239 run_suspensions( Slots).
241 'chr run_suspensions_loop'([]).
242 'chr run_suspensions_loop'([L|Ls]) :-
243 run_suspensions(L),
244 'chr run_suspensions_loop'(Ls).
246 run_suspensions([]).
247 run_suspensions([S|Next] ) :-
248 arg( 2, S, Mref), % ARGXXX
249 'chr get_mutable'( Status, Mref),
250 ( Status==active ->
251 'chr update_mutable'( triggered, Mref),
252 arg( 4, S, Gref), % ARGXXX
253 'chr get_mutable'( Gen, Gref),
254 Generation is Gen+1,
255 'chr update_mutable'( Generation, Gref),
256 arg( 3, S, Goal), % ARGXXX
257 call( Goal),
258 'chr get_mutable'( Post, Mref),
259 ( Post==triggered ->
260 'chr update_mutable'( active, Mref) % catching constraints that did not do anything
262 true
265 true
267 run_suspensions( Next).
269 'chr run_suspensions_d'( Slots) :-
270 run_suspensions_d( Slots).
272 'chr run_suspensions_loop_d'([]).
273 'chr run_suspensions_loop_d'([L|Ls]) :-
274 run_suspensions_d(L),
275 'chr run_suspensions_loop_d'(Ls).
277 run_suspensions_d([]).
278 run_suspensions_d([S|Next] ) :-
279 arg( 2, S, Mref), % ARGXXX
280 'chr get_mutable'( Status, Mref),
281 ( Status==active ->
282 'chr update_mutable'( triggered, Mref),
283 arg( 4, S, Gref), % ARGXXX
284 'chr get_mutable'( Gen, Gref),
285 Generation is Gen+1,
286 'chr update_mutable'( Generation, Gref),
287 arg( 3, S, Goal), % ARGXXX
289 'chr debug_event'(wake(S)),
290 call( Goal)
292 'chr debug_event'(fail(S)), !,
293 fail
296 'chr debug_event'(exit(S))
298 'chr debug_event'(redo(S)),
299 fail
301 'chr get_mutable'( Post, Mref),
302 ( Post==triggered ->
303 'chr update_mutable'( active, Mref) % catching constraints that did not do anything
305 true
308 true
310 run_suspensions_d( Next).
311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
312 locked:attr_unify_hook(_,_) :- fail.
314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315 'chr lock'(T) :-
316 ( var(T)
317 -> put_attr(T, locked, x)
318 ; term_variables(T,L),
319 lockv(L)
322 lockv([]).
323 lockv([T|R]) :- put_attr( T, locked, x), lockv(R).
325 'chr unlock'(T) :-
326 ( var(T)
327 -> del_attr(T, locked)
328 ; term_variables(T,L),
329 unlockv(L)
332 unlockv([]).
333 unlockv([T|R]) :- del_attr( T, locked), unlockv(R).
335 'chr none_locked'( []).
336 'chr none_locked'( [V|Vs]) :-
337 ( get_attr(V, locked, _) ->
338 fail
340 'chr none_locked'(Vs)
343 'chr not_locked'(V) :-
344 ( var( V) ->
345 ( get_attr( V, locked, _) ->
346 fail
348 true
351 true
354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
356 % Eager removal from all chains.
358 'chr remove_constraint_internal'( Susp, Agenda) :-
359 arg( 2, Susp, Mref), % ARGXXX
360 'chr get_mutable'( State, Mref),
361 'chr update_mutable'( removed, Mref), % mark in any case
362 ( compound(State) -> % passive/1
363 Agenda = []
364 ; State==removed ->
365 Agenda = []
366 %; State==triggered ->
367 % Agenda = []
369 Susp =.. [_,_,_,_,_,_,_|Args],
370 term_variables( Args, Vars),
371 'chr default_store'( Global),
372 Agenda = [Global|Vars]
375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376 'chr newvia_1'(X,V) :-
377 ( var(X) ->
378 X = V
380 nonground(X,V)
383 'chr newvia_2'(X,Y,V) :-
384 ( var(X) ->
385 X = V
386 ; var(Y) ->
387 Y = V
388 ; compound(X), nonground(X,V) ->
389 true
391 compound(Y), nonground(Y,V)
395 % The second arg is a witness.
396 % The formulation with term_variables/2 is
397 % cycle safe, but it finds a list of all vars.
398 % We need only one, and no list in particular.
400 'chr newvia'(L,V) :- nonground(L,V).
401 %~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
403 'chr via_1'(X,V) :-
404 ( var(X) ->
405 X = V
406 ; atomic(X) ->
407 'chr default_store'(V)
408 ; nonground(X,V) ->
409 true
411 'chr default_store'(V)
414 'chr via_2'(X,Y,V) :-
415 ( var(X) ->
416 X = V
417 ; var(Y) ->
418 Y = V
419 ; compound(X), nonground(X,V) ->
420 true
421 ; compound(Y), nonground(Y,V) ->
422 true
424 'chr default_store'(V)
428 % The second arg is a witness.
429 % The formulation with term_variables/2 is
430 % cycle safe, but it finds a list of all vars.
431 % We need only one, and no list in particular.
433 'chr via'(L,V) :-
434 ( nonground(L,V) ->
435 true
437 'chr default_store'(V)
440 nonground( Term, V) :-
441 term_variables( Term, Vs),
442 Vs = [V|_].
444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
445 'chr novel_production'( Self, Tuple) :-
446 arg( 5, Self, Ref), % ARGXXX
447 'chr get_mutable'( History, Ref),
448 ( get_ds( Tuple, History, _) ->
449 fail
451 true
455 % Not folded with novel_production/2 because guard checking
456 % goes in between the two calls.
458 'chr extend_history'( Self, Tuple) :-
459 arg( 5, Self, Ref), % ARGXXX
460 'chr get_mutable'( History, Ref),
461 put_ds( Tuple, History, x, NewHistory),
462 'chr update_mutable'( NewHistory, Ref).
464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
465 constraint_generation( Susp, State, Generation) :-
466 arg( 2, Susp, Mref), % ARGXXX
467 'chr get_mutable'( State, Mref),
468 arg( 4, Susp, Gref), % ARGXXX
469 'chr get_mutable'( Generation, Gref). % not incremented meanwhile
471 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
472 'chr allocate_constraint'( Closure, Self, F, Args) :-
473 Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args], % SUSPXXX
474 'chr create_mutable'(0, Gref),
475 'chr empty_history'(History),
476 'chr create_mutable'(History, Href),
477 'chr create_mutable'(passive(Args), Mref),
478 'chr gen_id'( Id).
481 % 'chr activate_constraint'( -, +, -).
483 % The transition gc->active should be rare
485 'chr activate_constraint'( Vars, Susp, Generation) :-
486 arg( 2, Susp, Mref), % ARGXXX
487 'chr get_mutable'( State, Mref),
488 'chr update_mutable'( active, Mref),
489 ( nonvar(Generation) -> % aih
490 true
492 arg( 4, Susp, Gref), % ARGXXX
493 'chr get_mutable'( Gen, Gref),
494 Generation is Gen+1,
495 'chr update_mutable'( Generation, Gref)
497 ( compound(State) -> % passive/1
498 term_variables( State, Vs),
499 'chr none_locked'( Vs),
500 Vars = [Global|Vs],
501 'chr default_store'(Global)
502 ; State == removed -> % the price for eager removal ...
503 Susp =.. [_,_,_,_,_,_,_|Args],
504 term_variables( Args, Vs),
505 Vars = [Global|Vs],
506 'chr default_store'(Global)
508 Vars = []
511 'chr insert_constraint_internal'([Global|Vars], Self, Closure, F, Args) :-
512 'chr default_store'(Global),
513 term_variables(Args,Vars),
514 'chr none_locked'(Vars),
515 Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args], % SUSPXXX
516 'chr create_mutable'(active, Mref),
517 'chr create_mutable'(0, Gref),
518 'chr empty_history'(History),
519 'chr create_mutable'(History, Href),
520 'chr gen_id'(Id).
522 insert_constraint_internal([Global|Vars], Self, Term, Closure, F, Args) :-
523 'chr default_store'(Global),
524 term_variables( Term, Vars),
525 'chr none_locked'( Vars),
526 'chr empty_history'( History),
527 'chr create_mutable'( active, Mref),
528 'chr create_mutable'( 0, Gref),
529 'chr create_mutable'( History, Href),
530 'chr gen_id'( Id),
531 Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args]. % SUSPXXX
533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
534 'chr empty_history'( E) :- empty_ds( E).
536 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
537 'chr gen_id'( Id) :-
538 nb_getval(chr_id,Id),
539 NextId is Id + 1,
540 nb_setval(chr_id,NextId).
542 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
544 %% SWI begin
545 'chr create_mutable'(V,mutable(V)).
546 'chr get_mutable'(V,mutable(V)).
547 'chr update_mutable'(V,M) :- setarg(1,M,V).
548 %% SWI end
550 %% SICStus begin
551 %% 'chr create_mutable'(Val, Mut) :- create_mutable(Val, Mut).
552 %% 'chr get_mutable'(Val, Mut) :- get_mutable(Val, Mut).
553 %% 'chr update_mutable'(Val, Mut) :- update_mutable(Val, Mut).
554 %% SICStus end
557 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
558 %% SWI begin
559 'chr default_store'(X) :- nb_getval(chr_global,X).
560 %% SWI end
562 %% SICStus begin
563 %% 'chr default_store'(A) :- global_term_ref_1(A).
564 %% SICStus end
566 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
568 'chr sbag_member'( Element, [Head|Tail]) :-
569 sbag_member( Element, Tail, Head).
571 % auxiliary to avoid choicepoint for last element
572 % does it really avoid the choicepoint? -jon
573 sbag_member( E, _, E).
574 sbag_member( E, [Head|Tail], _) :-
575 sbag_member( E, Tail, Head).
577 'chr sbag_del_element'( [], _, []).
578 'chr sbag_del_element'( [X|Xs], Elem, Set2) :-
579 ( X==Elem ->
580 Set2 = Xs
582 Set2 = [X|Xss],
583 'chr sbag_del_element'( Xs, Elem, Xss)
586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
587 'chr merge_attributes'([],Ys,Ys).
588 'chr merge_attributes'([X | Xs],YL,R) :-
589 ( YL = [Y | Ys] ->
590 arg(1,X,XId), % ARGXXX
591 arg(1,Y,YId), % ARGXXX
592 ( XId < YId ->
593 R = [X | T],
594 'chr merge_attributes'(Xs,YL,T)
595 ; XId > YId ->
596 R = [Y | T],
597 'chr merge_attributes'([X|Xs],Ys,T)
599 R = [X | T],
600 'chr merge_attributes'(Xs,Ys,T)
603 R = [X | Xs]
606 'chr new_merge_attributes'([],A2,A) :-
607 A = A2.
608 'chr new_merge_attributes'([E1|AT1],A2,A) :-
609 ( A2 = [E2|AT2] ->
610 'chr new_merge_attributes'(E1,E2,AT1,AT2,A)
612 A = [E1|AT1]
615 'chr new_merge_attributes'(Pos1-L1,Pos2-L2,AT1,AT2,A) :-
616 ( Pos1 < Pos2 ->
617 A = [Pos1-L1|AT],
618 'chr new_merge_attributes'(AT1,[Pos2-L2|AT2],AT)
619 ; Pos1 > Pos2 ->
620 A = [Pos2-L2|AT],
621 'chr new_merge_attributes'([Pos1-L1|AT1],AT2,AT)
623 'chr merge_attributes'(L1,L2,L),
624 A = [Pos1-L|AT],
625 'chr new_merge_attributes'(AT1,AT2,AT)
628 'chr all_suspensions'([],_,_).
629 'chr all_suspensions'([Susps|SuspsList],Pos,Attr) :-
630 all_suspensions(Attr,Susps,SuspsList,Pos).
632 all_suspensions([],[],SuspsList,Pos) :-
633 all_suspensions([],[],SuspsList,Pos). % all empty lists
634 all_suspensions([APos-ASusps|RAttr],Susps,SuspsList,Pos) :-
635 NPos is Pos + 1,
636 ( Pos == APos ->
637 Susps = ASusps,
638 'chr all_suspensions'(SuspsList,NPos,RAttr)
640 Susps = [],
641 'chr all_suspensions'(SuspsList,NPos,[APos-ASusps|RAttr])
644 'chr normalize_attr'([],[]).
645 'chr normalize_attr'([Pos-L|R],[Pos-NL|NR]) :-
646 sort(L,NL),
647 'chr normalize_attr'(R,NR).
649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651 :- multifile
652 chr:debug_event/2, % +State, +Event
653 chr:debug_interact/3. % +Event, +Depth, -Command
655 'chr debug_event'(Event) :-
656 nb_getval(chr_debug,mutable(State)), % XXX
657 ( State == off ->
658 true
659 ; chr:debug_event(State, Event) ->
660 true
661 ; debug_event(State,Event)
664 chr_trace :-
665 nb_setval(chr_debug,mutable(trace)).
666 chr_notrace :-
667 nb_setval(chr_debug,mutable(off)).
669 % chr_leash(+Spec)
671 % Define the set of ports at which we prompt for user interaction
673 chr_leash(Spec) :-
674 leashed_ports(Spec, Ports),
675 nb_setval(chr_leash,mutable(Ports)).
677 leashed_ports(none, []).
678 leashed_ports(off, []).
679 leashed_ports(all, [call, exit, redo, fail, wake, try, apply, insert, remove]).
680 leashed_ports(default, [call,exit,fail,wake,apply]).
681 leashed_ports(One, Ports) :-
682 atom(One), One \== [], !,
683 leashed_ports([One], Ports).
684 leashed_ports(Set, Ports) :-
685 sort(Set, Ports), % make unique
686 leashed_ports(all, All),
687 valid_ports(Ports, All).
689 valid_ports([], _).
690 valid_ports([H|T], Valid) :-
691 ( memberchk(H, Valid)
692 -> true
693 ; throw(error(domain_error(chr_port, H), _))
695 valid_ports(T, Valid).
697 user:exception(undefined_global_variable, Name, retry) :-
698 chr_runtime_debug_global_variable(Name),
699 chr_debug_init.
701 chr_runtime_debug_global_variable(chr_leash).
703 chr_debug_init :-
704 leashed_ports(default, Ports),
705 nb_setval(chr_leash, mutable(Ports)).
707 :- initialization chr_debug_init.
709 % debug_event(+State, +Event)
712 %debug_event(trace, Event) :-
713 % functor(Event, Name, Arity),
714 % writeln(Name/Arity), fail.
715 debug_event(trace,Event) :-
716 Event = call(_), !,
717 get_debug_history(History,Depth),
718 NDepth is Depth + 1,
719 chr_debug_interact(Event,NDepth),
720 set_debug_history([Event|History],NDepth).
721 debug_event(trace,Event) :-
722 Event = wake(_), !,
723 get_debug_history(History,Depth),
724 NDepth is Depth + 1,
725 chr_debug_interact(Event,NDepth),
726 set_debug_history([Event|History],NDepth).
727 debug_event(trace,Event) :-
728 Event = redo(_), !,
729 get_debug_history(_History, Depth),
730 chr_debug_interact(Event, Depth).
731 debug_event(trace,Event) :-
732 Event = exit(_),!,
733 get_debug_history([_|History],Depth),
734 chr_debug_interact(Event,Depth),
735 NDepth is Depth - 1,
736 set_debug_history(History,NDepth).
737 debug_event(trace,Event) :-
738 Event = fail(_),!,
739 get_debug_history(_,Depth),
740 chr_debug_interact(Event,Depth).
741 debug_event(trace, Event) :-
742 Event = remove(_), !,
743 get_debug_history(_,Depth),
744 chr_debug_interact(Event, Depth).
745 debug_event(trace, Event) :-
746 Event = insert(_), !,
747 get_debug_history(_,Depth),
748 chr_debug_interact(Event, Depth).
749 debug_event(trace, Event) :-
750 Event = try(_,_,_,_), !,
751 get_debug_history(_,Depth),
752 chr_debug_interact(Event, Depth).
753 debug_event(trace, Event) :-
754 Event = apply(_,_,_,_), !,
755 get_debug_history(_,Depth),
756 chr_debug_interact(Event,Depth).
758 debug_event(skip(_,_),Event) :-
759 Event = call(_), !,
760 get_debug_history(History,Depth),
761 NDepth is Depth + 1,
762 set_debug_history([Event|History],NDepth).
763 debug_event(skip(_,_),Event) :-
764 Event = wake(_), !,
765 get_debug_history(History,Depth),
766 NDepth is Depth + 1,
767 set_debug_history([Event|History],NDepth).
768 debug_event(skip(SkipSusp,SkipDepth),Event) :-
769 Event = exit(Susp),!,
770 get_debug_history([_|History],Depth),
771 ( SkipDepth == Depth,
772 SkipSusp == Susp ->
773 set_chr_debug(trace),
774 chr_debug_interact(Event,Depth)
776 true
778 NDepth is Depth - 1,
779 set_debug_history(History,NDepth).
780 debug_event(skip(_,_),_) :- !,
781 true.
783 % chr_debug_interact(+Event, +Depth)
785 % Interact with the user on Event that took place at Depth. First
786 % calls chr:debug_interact(+Event, +Depth, -Command) hook. If this
787 % fails the event is printed and the system prompts for a command.
789 chr_debug_interact(Event, Depth) :-
790 chr:debug_interact(Event, Depth, Command), !,
791 handle_debug_command(Command,Event,Depth).
792 chr_debug_interact(Event, Depth) :-
793 print_event(Event, Depth),
794 ( leashed(Event)
795 -> ask_continue(Command)
796 ; Command = creep
798 handle_debug_command(Command,Event,Depth).
800 leashed(Event) :-
801 functor(Event, Port, _),
802 nb_getval(chr_leash, mutable(Ports)),
803 memberchk(Port, Ports).
805 ask_continue(Command) :-
806 print_message(debug, chr(prompt)),
807 get_single_char(CharCode),
808 ( CharCode == -1
809 -> Char = end_of_file
810 ; char_code(Char, CharCode)
812 ( debug_command(Char, Command)
813 -> print_message(debug, chr(command(Command)))
814 ; print_message(help, chr(invalid_command)),
815 ask_continue(Command)
819 'chr debug command'(Char, Command) :-
820 debug_command(Char, Command).
822 debug_command(c, creep).
823 debug_command(' ', creep).
824 debug_command('\r', creep).
825 debug_command(s, skip).
826 debug_command(g, ancestors).
827 debug_command(n, nodebug).
828 debug_command(a, abort).
829 debug_command(f, fail).
830 debug_command(b, break).
831 debug_command(?, help).
832 debug_command(h, help).
833 debug_command(end_of_file, exit).
836 handle_debug_command(creep,_,_) :- !.
837 handle_debug_command(skip, Event, Depth) :- !,
838 Event =.. [Type|Rest],
839 ( Type \== call,
840 Type \== wake ->
841 handle_debug_command('c',Event,Depth)
843 Rest = [Susp],
844 set_chr_debug(skip(Susp,Depth))
847 handle_debug_command(ancestors,Event,Depth) :- !,
848 print_chr_debug_history,
849 chr_debug_interact(Event,Depth).
850 handle_debug_command(nodebug,_,_) :- !,
851 chr_notrace.
852 handle_debug_command(abort,_,_) :- !,
853 abort.
854 handle_debug_command(exit,_,_) :- !,
855 halt.
856 handle_debug_command(fail,_,_) :- !,
857 fail.
858 handle_debug_command(break,Event,Depth) :- !,
859 break,
860 chr_debug_interact(Event,Depth).
861 handle_debug_command(help,Event,Depth) :- !,
862 print_message(help, chr(debug_options)),
863 chr_debug_interact(Event,Depth).
864 handle_debug_command(Cmd, _, _) :-
865 throw(error(domain_error(chr_debug_command, Cmd), _)).
867 print_chr_debug_history :-
868 get_debug_history(History,Depth),
869 print_message(debug, chr(ancestors(History, Depth))).
871 print_event(Event, Depth) :-
872 print_message(debug, chr(event(Event, Depth))).
874 % {set,get}_debug_history(Ancestors, Depth)
876 % Set/get the list of ancestors and the depth of the current goal.
878 get_debug_history(History,Depth) :-
879 nb_getval(chr_debug_history,mutable(History,Depth)).
881 set_debug_history(History,Depth) :-
882 nb_getval(chr_debug_history,Mutable),
883 setarg(1,Mutable,History),
884 setarg(2,Mutable,Depth).
886 set_chr_debug(State) :-
887 nb_getval(chr_debug,Mutable),
888 setarg(1,Mutable,State).
890 'chr chr_indexed_variables'(Susp,Vars) :-
891 Susp =.. [_,_,_,_,_,_,_|Args],
892 term_variables(Args,Vars).