* Fix paths to runtex
[chr.git] / chr_runtime.pl
blobe051e615303215dc5b06f523cfd523ae6eea8c0a
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(hpattvars).
135 %% :- use_module(b_globval).
136 %% SICStus end
139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141 % I N I T I A L I S A T I O N
143 %% SWI begin
144 :- dynamic user:exception/3.
145 :- multifile user:exception/3.
147 user:exception(undefined_global_variable, Name, retry) :-
148 chr_runtime_global_variable(Name),
149 chr_init.
151 chr_runtime_global_variable(chr_id).
152 chr_runtime_global_variable(chr_global).
153 chr_runtime_global_variable(chr_debug).
154 chr_runtime_global_variable(chr_debug_history).
156 chr_init :-
157 nb_setval(chr_id,0),
158 nb_setval(chr_global,_),
159 nb_setval(chr_debug,mutable(off)), % XXX
160 nb_setval(chr_debug_history,mutable([],0)). % XXX
161 %% SWI end
163 %% SICStus begin
164 %% chr_init :-
165 %% nb_setval(chr_id,0).
166 %% SICStus end
168 :- initialization chr_init.
171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172 % Contents of former chr_debug.pl
174 % chr_show_store(+Module)
176 % Prints all suspended constraints of module Mod to the standard
177 % output.
179 chr_show_store(Mod) :-
181 Mod:'$enumerate_constraints'(Constraint),
182 print(Constraint),nl, % allows use of portray to control printing
183 fail
185 true
188 find_chr_constraint(Constraint) :-
189 chr:'$chr_module'(Mod),
190 Mod:'$enumerate_constraints'(Constraint).
192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
193 % Inlining of some goals is good for performance
194 % That's the reason for the next section
195 % There must be correspondence with the predicates as implemented in chr_mutable.pl
196 % so that user:goal_expansion(G,G). also works (but do not add such a rule)
197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
199 %% SWI begin
200 :- multifile user:goal_expansion/2.
201 :- dynamic user:goal_expansion/2.
203 user:goal_expansion('chr get_mutable'(Val,Var), Var=mutable(Val)).
204 user:goal_expansion('chr update_mutable'(Val,Var), setarg(1,Var,Val)).
205 user:goal_expansion('chr create_mutable'(Val,Var), Var=mutable(Val)).
206 user:goal_expansion('chr default_store'(X), nb_getval(chr_global,X)).
207 %% SWI end
209 % goal_expansion seems too different in SICStus 4 for me to cater for in a
210 % decent way at this moment - so I stick with the old way to do this
211 % so that it doesn't get lost, the code from Mats for SICStus 4 is included in comments
214 %% Mats begin
215 %% goal_expansion('chr get_mutable'(Val,Var), Lay, _M, get_mutable(Val,Var), Lay).
216 %% goal_expansion('chr update_mutable'(Val,Var), Lay, _M, update_mutable(Val,Var), Lay).
217 %% goal_expansion('chr create_mutable'(Val,Var), Lay, _M, create_mutable(Val,Var), Lay).
218 %% goal_expansion('chr default_store'(A), Lay, _M, global_term_ref_1(A), Lay).
219 %% Mats begin
222 %% SICStus begin
223 %% :- multifile user:goal_expansion/2.
224 %% :- dynamic user:goal_expansion/2.
226 %% user:goal_expansion('chr get_mutable'(Val,Var), get_mutable(Val,Var)).
227 %% user:goal_expansion('chr update_mutable'(Val,Var), update_mutable(Val,Var)).
228 %% user:goal_expansion('chr create_mutable'(Val,Var), create_mutable(Val,Var)).
229 %% user:goal_expansion('chr default_store'(A), global_term_ref_1(A)).
230 %% SICStus end
233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234 'chr run_suspensions'( Slots) :-
235 run_suspensions( Slots).
237 'chr run_suspensions_loop'([]).
238 'chr run_suspensions_loop'([L|Ls]) :-
239 run_suspensions(L),
240 'chr run_suspensions_loop'(Ls).
242 run_suspensions([]).
243 run_suspensions([S|Next] ) :-
244 arg( 2, S, Mref), % ARGXXX
245 'chr get_mutable'( Status, Mref),
246 ( Status==active ->
247 'chr update_mutable'( triggered, Mref),
248 arg( 4, S, Gref), % ARGXXX
249 'chr get_mutable'( Gen, Gref),
250 Generation is Gen+1,
251 'chr update_mutable'( Generation, Gref),
252 arg( 3, S, Goal), % ARGXXX
253 call( Goal),
254 'chr get_mutable'( Post, Mref),
255 ( Post==triggered ->
256 'chr update_mutable'( active, Mref) % catching constraints that did not do anything
258 true
261 true
263 run_suspensions( Next).
265 'chr run_suspensions_d'( Slots) :-
266 run_suspensions_d( Slots).
268 'chr run_suspensions_loop_d'([]).
269 'chr run_suspensions_loop_d'([L|Ls]) :-
270 run_suspensions_d(L),
271 'chr run_suspensions_loop_d'(Ls).
273 run_suspensions_d([]).
274 run_suspensions_d([S|Next] ) :-
275 arg( 2, S, Mref), % ARGXXX
276 'chr get_mutable'( Status, Mref),
277 ( Status==active ->
278 'chr update_mutable'( triggered, Mref),
279 arg( 4, S, Gref), % ARGXXX
280 'chr get_mutable'( Gen, Gref),
281 Generation is Gen+1,
282 'chr update_mutable'( Generation, Gref),
283 arg( 3, S, Goal), % ARGXXX
285 'chr debug_event'(wake(S)),
286 call( Goal)
288 'chr debug_event'(fail(S)), !,
289 fail
292 'chr debug_event'(exit(S))
294 'chr debug_event'(redo(S)),
295 fail
297 'chr get_mutable'( Post, Mref),
298 ( Post==triggered ->
299 'chr update_mutable'( active, Mref) % catching constraints that did not do anything
301 true
304 true
306 run_suspensions_d( Next).
307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
308 locked:attr_unify_hook(_,_) :- fail.
310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311 'chr lock'(T) :-
312 ( var(T)
313 -> put_attr(T, locked, x)
314 ; term_variables(T,L),
315 lockv(L)
318 lockv([]).
319 lockv([T|R]) :- put_attr( T, locked, x), lockv(R).
321 'chr unlock'(T) :-
322 ( var(T)
323 -> del_attr(T, locked)
324 ; term_variables(T,L),
325 unlockv(L)
328 unlockv([]).
329 unlockv([T|R]) :- del_attr( T, locked), unlockv(R).
331 'chr none_locked'( []).
332 'chr none_locked'( [V|Vs]) :-
333 ( get_attr(V, locked, _) ->
334 fail
336 'chr none_locked'(Vs)
339 'chr not_locked'(V) :-
340 ( var( V) ->
341 ( get_attr( V, locked, _) ->
342 fail
344 true
347 true
350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
352 % Eager removal from all chains.
354 'chr remove_constraint_internal'( Susp, Agenda) :-
355 arg( 2, Susp, Mref), % ARGXXX
356 'chr get_mutable'( State, Mref),
357 'chr update_mutable'( removed, Mref), % mark in any case
358 ( compound(State) -> % passive/1
359 Agenda = []
360 ; State==removed ->
361 Agenda = []
362 %; State==triggered ->
363 % Agenda = []
365 Susp =.. [_,_,_,_,_,_,_|Args],
366 term_variables( Args, Vars),
367 'chr default_store'( Global),
368 Agenda = [Global|Vars]
371 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
372 'chr newvia_1'(X,V) :-
373 ( var(X) ->
374 X = V
376 nonground(X,V)
379 'chr newvia_2'(X,Y,V) :-
380 ( var(X) ->
381 X = V
382 ; var(Y) ->
383 Y = V
384 ; compound(X), nonground(X,V) ->
385 true
387 compound(Y), nonground(Y,V)
391 % The second arg is a witness.
392 % The formulation with term_variables/2 is
393 % cycle safe, but it finds a list of all vars.
394 % We need only one, and no list in particular.
396 'chr newvia'(L,V) :- nonground(L,V).
397 %~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
399 'chr via_1'(X,V) :-
400 ( var(X) ->
401 X = V
402 ; atomic(X) ->
403 'chr default_store'(V)
404 ; nonground(X,V) ->
405 true
407 'chr default_store'(V)
410 'chr via_2'(X,Y,V) :-
411 ( var(X) ->
412 X = V
413 ; var(Y) ->
414 Y = V
415 ; compound(X), nonground(X,V) ->
416 true
417 ; compound(Y), nonground(Y,V) ->
418 true
420 'chr default_store'(V)
424 % The second arg is a witness.
425 % The formulation with term_variables/2 is
426 % cycle safe, but it finds a list of all vars.
427 % We need only one, and no list in particular.
429 'chr via'(L,V) :-
430 ( nonground(L,V) ->
431 true
433 'chr default_store'(V)
436 nonground( Term, V) :-
437 term_variables( Term, Vs),
438 Vs = [V|_].
440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441 'chr novel_production'( Self, Tuple) :-
442 arg( 5, Self, Ref), % ARGXXX
443 'chr get_mutable'( History, Ref),
444 ( get_ds( Tuple, History, _) ->
445 fail
447 true
451 % Not folded with novel_production/2 because guard checking
452 % goes in between the two calls.
454 'chr extend_history'( Self, Tuple) :-
455 arg( 5, Self, Ref), % ARGXXX
456 'chr get_mutable'( History, Ref),
457 put_ds( Tuple, History, x, NewHistory),
458 'chr update_mutable'( NewHistory, Ref).
460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
461 constraint_generation( Susp, State, Generation) :-
462 arg( 2, Susp, Mref), % ARGXXX
463 'chr get_mutable'( State, Mref),
464 arg( 4, Susp, Gref), % ARGXXX
465 'chr get_mutable'( Generation, Gref). % not incremented meanwhile
467 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
468 'chr allocate_constraint'( Closure, Self, F, Args) :-
469 Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args], % SUSPXXX
470 'chr create_mutable'(0, Gref),
471 'chr empty_history'(History),
472 'chr create_mutable'(History, Href),
473 'chr create_mutable'(passive(Args), Mref),
474 'chr gen_id'( Id).
477 % 'chr activate_constraint'( -, +, -).
479 % The transition gc->active should be rare
481 'chr activate_constraint'( Vars, Susp, Generation) :-
482 arg( 2, Susp, Mref), % ARGXXX
483 'chr get_mutable'( State, Mref),
484 'chr update_mutable'( active, Mref),
485 ( nonvar(Generation) -> % aih
486 true
488 arg( 4, Susp, Gref), % ARGXXX
489 'chr get_mutable'( Gen, Gref),
490 Generation is Gen+1,
491 'chr update_mutable'( Generation, Gref)
493 ( compound(State) -> % passive/1
494 term_variables( State, Vs),
495 'chr none_locked'( Vs),
496 Vars = [Global|Vs],
497 'chr default_store'(Global)
498 ; State == removed -> % the price for eager removal ...
499 Susp =.. [_,_,_,_,_,_,_|Args],
500 term_variables( Args, Vs),
501 Vars = [Global|Vs],
502 'chr default_store'(Global)
504 Vars = []
507 'chr insert_constraint_internal'([Global|Vars], Self, Closure, F, Args) :-
508 'chr default_store'(Global),
509 term_variables(Args,Vars),
510 'chr none_locked'(Vars),
511 Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args], % SUSPXXX
512 'chr create_mutable'(active, Mref),
513 'chr create_mutable'(0, Gref),
514 'chr empty_history'(History),
515 'chr create_mutable'(History, Href),
516 'chr gen_id'(Id).
518 insert_constraint_internal([Global|Vars], Self, Term, Closure, F, Args) :-
519 'chr default_store'(Global),
520 term_variables( Term, Vars),
521 'chr none_locked'( Vars),
522 'chr empty_history'( History),
523 'chr create_mutable'( active, Mref),
524 'chr create_mutable'( 0, Gref),
525 'chr create_mutable'( History, Href),
526 'chr gen_id'( Id),
527 Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args]. % SUSPXXX
529 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
530 'chr empty_history'( E) :- empty_ds( E).
532 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533 'chr gen_id'( Id) :-
534 nb_getval(chr_id,Id),
535 NextId is Id + 1,
536 nb_setval(chr_id,NextId).
538 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
540 %% SWI begin
541 'chr create_mutable'(V,mutable(V)).
542 'chr get_mutable'(V,mutable(V)).
543 'chr update_mutable'(V,M) :- setarg(1,M,V).
544 %% SWI end
546 %% SICStus begin
547 %% 'chr create_mutable'(Val, Mut) :- create_mutable(Val, Mut).
548 %% 'chr get_mutable'(Val, Mut) :- get_mutable(Val, Mut).
549 %% 'chr update_mutable'(Val, Mut) :- update_mutable(Val, Mut).
550 %% SICStus end
553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
554 %% SWI begin
555 'chr default_store'(X) :- nb_getval(chr_global,X).
556 %% SWI end
558 %% SICStus begin
559 %% 'chr default_store'(A) :- global_term_ref_1(A).
560 %% SICStus end
562 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
564 'chr sbag_member'( Element, [Head|Tail]) :-
565 sbag_member( Element, Tail, Head).
567 % auxiliary to avoid choicepoint for last element
568 % does it really avoid the choicepoint? -jon
569 sbag_member( E, _, E).
570 sbag_member( E, [Head|Tail], _) :-
571 sbag_member( E, Tail, Head).
573 'chr sbag_del_element'( [], _, []).
574 'chr sbag_del_element'( [X|Xs], Elem, Set2) :-
575 ( X==Elem ->
576 Set2 = Xs
578 Set2 = [X|Xss],
579 'chr sbag_del_element'( Xs, Elem, Xss)
582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
583 'chr merge_attributes'([],Ys,Ys).
584 'chr merge_attributes'([X | Xs],YL,R) :-
585 ( YL = [Y | Ys] ->
586 arg(1,X,XId), % ARGXXX
587 arg(1,Y,YId), % ARGXXX
588 ( XId < YId ->
589 R = [X | T],
590 'chr merge_attributes'(Xs,YL,T)
591 ; XId > YId ->
592 R = [Y | T],
593 'chr merge_attributes'([X|Xs],Ys,T)
595 R = [X | T],
596 'chr merge_attributes'(Xs,Ys,T)
599 R = [X | Xs]
602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
604 :- multifile
605 chr:debug_event/2, % +State, +Event
606 chr:debug_interact/3. % +Event, +Depth, -Command
608 'chr debug_event'(Event) :-
609 nb_getval(chr_debug,mutable(State)), % XXX
610 ( State == off ->
611 true
612 ; chr:debug_event(State, Event) ->
613 true
614 ; debug_event(State,Event)
617 chr_trace :-
618 nb_setval(chr_debug,mutable(trace)).
619 chr_notrace :-
620 nb_setval(chr_debug,mutable(off)).
622 % chr_leash(+Spec)
624 % Define the set of ports at which we prompt for user interaction
626 chr_leash(Spec) :-
627 leashed_ports(Spec, Ports),
628 nb_setval(chr_leash,mutable(Ports)).
630 leashed_ports(none, []).
631 leashed_ports(off, []).
632 leashed_ports(all, [call, exit, redo, fail, wake, try, apply, insert, remove]).
633 leashed_ports(default, [call,exit,fail,wake,apply]).
634 leashed_ports(One, Ports) :-
635 atom(One), One \== [], !,
636 leashed_ports([One], Ports).
637 leashed_ports(Set, Ports) :-
638 sort(Set, Ports), % make unique
639 leashed_ports(all, All),
640 valid_ports(Ports, All).
642 valid_ports([], _).
643 valid_ports([H|T], Valid) :-
644 ( memberchk(H, Valid)
645 -> true
646 ; throw(error(domain_error(chr_port, H), _))
648 valid_ports(T, Valid).
651 :- initialization
652 leashed_ports(default, Ports),
653 nb_setval(chr_leash, mutable(Ports)).
655 % debug_event(+State, +Event)
658 %debug_event(trace, Event) :-
659 % functor(Event, Name, Arity),
660 % writeln(Name/Arity), fail.
661 debug_event(trace,Event) :-
662 Event = call(_), !,
663 get_debug_history(History,Depth),
664 NDepth is Depth + 1,
665 chr_debug_interact(Event,NDepth),
666 set_debug_history([Event|History],NDepth).
667 debug_event(trace,Event) :-
668 Event = wake(_), !,
669 get_debug_history(History,Depth),
670 NDepth is Depth + 1,
671 chr_debug_interact(Event,NDepth),
672 set_debug_history([Event|History],NDepth).
673 debug_event(trace,Event) :-
674 Event = redo(_), !,
675 get_debug_history(_History, Depth),
676 chr_debug_interact(Event, Depth).
677 debug_event(trace,Event) :-
678 Event = exit(_),!,
679 get_debug_history([_|History],Depth),
680 chr_debug_interact(Event,Depth),
681 NDepth is Depth - 1,
682 set_debug_history(History,NDepth).
683 debug_event(trace,Event) :-
684 Event = fail(_),!,
685 get_debug_history(_,Depth),
686 chr_debug_interact(Event,Depth).
687 debug_event(trace, Event) :-
688 Event = remove(_), !,
689 get_debug_history(_,Depth),
690 chr_debug_interact(Event, Depth).
691 debug_event(trace, Event) :-
692 Event = insert(_), !,
693 get_debug_history(_,Depth),
694 chr_debug_interact(Event, Depth).
695 debug_event(trace, Event) :-
696 Event = try(_,_,_,_), !,
697 get_debug_history(_,Depth),
698 chr_debug_interact(Event, Depth).
699 debug_event(trace, Event) :-
700 Event = apply(_,_,_,_), !,
701 get_debug_history(_,Depth),
702 chr_debug_interact(Event,Depth).
704 debug_event(skip(_,_),Event) :-
705 Event = call(_), !,
706 get_debug_history(History,Depth),
707 NDepth is Depth + 1,
708 set_debug_history([Event|History],NDepth).
709 debug_event(skip(_,_),Event) :-
710 Event = wake(_), !,
711 get_debug_history(History,Depth),
712 NDepth is Depth + 1,
713 set_debug_history([Event|History],NDepth).
714 debug_event(skip(SkipSusp,SkipDepth),Event) :-
715 Event = exit(Susp),!,
716 get_debug_history([_|History],Depth),
717 ( SkipDepth == Depth,
718 SkipSusp == Susp ->
719 set_chr_debug(trace),
720 chr_debug_interact(Event,Depth)
722 true
724 NDepth is Depth - 1,
725 set_debug_history(History,NDepth).
726 debug_event(skip(_,_),_) :- !,
727 true.
729 % chr_debug_interact(+Event, +Depth)
731 % Interact with the user on Event that took place at Depth. First
732 % calls chr:debug_interact(+Event, +Depth, -Command) hook. If this
733 % fails the event is printed and the system prompts for a command.
735 chr_debug_interact(Event, Depth) :-
736 chr:debug_interact(Event, Depth, Command), !,
737 handle_debug_command(Command,Event,Depth).
738 chr_debug_interact(Event, Depth) :-
739 print_event(Event, Depth),
740 ( leashed(Event)
741 -> ask_continue(Command)
742 ; Command = creep
744 handle_debug_command(Command,Event,Depth).
746 leashed(Event) :-
747 functor(Event, Port, _),
748 nb_getval(chr_leash, mutable(Ports)),
749 memberchk(Port, Ports).
751 ask_continue(Command) :-
752 print_message(debug, chr(prompt)),
753 get_single_char(CharCode),
754 ( CharCode == -1
755 -> Char = end_of_file
756 ; char_code(Char, CharCode)
758 ( debug_command(Char, Command)
759 -> print_message(debug, chr(command(Command)))
760 ; print_message(help, chr(invalid_command)),
761 ask_continue(Command)
765 'chr debug command'(Char, Command) :-
766 debug_command(Char, Command).
768 debug_command(c, creep).
769 debug_command(' ', creep).
770 debug_command('\r', creep).
771 debug_command(s, skip).
772 debug_command(g, ancestors).
773 debug_command(n, nodebug).
774 debug_command(a, abort).
775 debug_command(f, fail).
776 debug_command(b, break).
777 debug_command(?, help).
778 debug_command(h, help).
779 debug_command(end_of_file, exit).
782 handle_debug_command(creep,_,_) :- !.
783 handle_debug_command(skip, Event, Depth) :- !,
784 Event =.. [Type|Rest],
785 ( Type \== call,
786 Type \== wake ->
787 handle_debug_command('c',Event,Depth)
789 Rest = [Susp],
790 set_chr_debug(skip(Susp,Depth))
793 handle_debug_command(ancestors,Event,Depth) :- !,
794 print_chr_debug_history,
795 chr_debug_interact(Event,Depth).
796 handle_debug_command(nodebug,_,_) :- !,
797 chr_notrace.
798 handle_debug_command(abort,_,_) :- !,
799 abort.
800 handle_debug_command(exit,_,_) :- !,
801 halt.
802 handle_debug_command(fail,_,_) :- !,
803 fail.
804 handle_debug_command(break,Event,Depth) :- !,
805 break,
806 chr_debug_interact(Event,Depth).
807 handle_debug_command(help,Event,Depth) :- !,
808 print_message(help, chr(debug_options)),
809 chr_debug_interact(Event,Depth).
810 handle_debug_command(Cmd, _, _) :-
811 throw(error(domain_error(chr_debug_command, Cmd), _)).
813 print_chr_debug_history :-
814 get_debug_history(History,Depth),
815 print_message(debug, chr(ancestors(History, Depth))).
817 print_event(Event, Depth) :-
818 print_message(debug, chr(event(Event, Depth))).
820 % {set,get}_debug_history(Ancestors, Depth)
822 % Set/get the list of ancestors and the depth of the current goal.
824 get_debug_history(History,Depth) :-
825 nb_getval(chr_debug_history,mutable(History,Depth)).
827 set_debug_history(History,Depth) :-
828 nb_getval(chr_debug_history,Mutable),
829 setarg(1,Mutable,History),
830 setarg(2,Mutable,Depth).
832 set_chr_debug(State) :-
833 nb_getval(chr_debug,Mutable),
834 setarg(1,Mutable,State).
836 'chr chr_indexed_variables'(Susp,Vars) :-
837 Susp =.. [_,_,_,_,_,_,_|Args],
838 term_variables(Args,Vars).