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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
39 %% ___
| |__ _ __ _ __ _ _ _ __
| |_
(_
)_ __ ___ ___
40 %% / __| '_ \| '__| | '__| | | | '_ \| __| | '_ ` _ \ / _ \
41 %% | (__
| | | | | | | | |_
| | | | | |_
| | | | | | | __
/
42 %% \___
|_
| |_
|_
| |_
| \__
,_
|_
| |_
|\__
|_
|_
| |_
| |_
|\___
|
44 %% hProlog CHR runtime
:
46 %% * based on the SICStus CHR runtime by Christian Holzbaur
48 %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
49 %% % Constraint Handling Rules version
2.2 %
51 %% % (c
) Copyright
1996-98 %
55 %% % Author
: Christian Holzbaur christian
@ai.univie
.ac
.at
%
56 %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
68 %% * Added initialization directives
for saved
-states
69 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71 :- module
(chr_runtime
,
72 [ 'chr sbag_del_element'/3,
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,
102 'chr unerror_lock'/1,
103 'chr not_error_locked'/1,
104 'chr none_error_locked'/1,
106 'chr update_mutable'/2,
108 'chr create_mutable'/2,
110 'chr novel_production'/2,
111 'chr extend_history'/2,
112 'chr empty_history'/1,
117 'chr debug command'/2, % Char
, Command
119 'chr chr_indexed_variables'/2,
121 'chr all_suspensions'/3,
122 'chr new_merge_attributes'/3,
123 'chr normalize_attr'/2,
127 chr_show_store
/1, % +Module
128 find_chr_constraint
/1,
136 :- set_prolog_flag
(generate_debug_info
, false
).
139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141 :- use_module
(hprolog
).
145 %% :- use_module
(hpattvars
).
146 %% :- use_module
(b_globval
).
150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
152 % I N I T I A L I S A T I O N
155 :- dynamic user
:exception
/3.
156 :- multifile user
:exception
/3.
158 user
:exception
(undefined_global_variable
, Name
, retry
) :-
159 chr_runtime_global_variable
(Name
),
162 chr_runtime_global_variable
(chr_id
).
163 chr_runtime_global_variable
(chr_global
).
164 chr_runtime_global_variable
(chr_debug
).
165 chr_runtime_global_variable
(chr_debug_history
).
169 nb_setval
(chr_global
,_
),
170 nb_setval
(chr_debug
,mutable
(off
)), % XXX
171 nb_setval
(chr_debug_history
,mutable
([],0)). % XXX
176 %% nb_setval
(chr_id
,0).
179 :- initialization chr_init
.
182 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
183 % Contents of former chr_debug
.pl
185 % chr_show_store
(+Module
)
187 % Prints all suspended constraints of module Mod to the standard
190 chr_show_store
(Mod
) :-
192 Mod
:'$enumerate_constraints'(Constraint
),
193 print(Constraint
),nl
, % allows
use of portray to control printing
199 find_chr_constraint
(Constraint
) :-
200 chr:'$chr_module'(Mod
),
201 Mod
:'$enumerate_constraints'(Constraint
).
203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204 % Inlining of some goals is good
for performance
205 % That
's the reason for the next section
206 % There must be correspondence with the predicates as implemented in chr_mutable.pl
207 % so that user:goal_expansion(G,G). also works (but do not add such a rule)
208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
211 :- multifile user:goal_expansion/2.
212 :- dynamic user:goal_expansion/2.
214 user:goal_expansion('chr get_mutable
'(Val,Var), Var=mutable(Val)).
215 user:goal_expansion('chr update_mutable
'(Val,Var), setarg(1,Var,Val)).
216 user:goal_expansion('chr create_mutable
'(Val,Var), Var=mutable(Val)).
217 user:goal_expansion('chr default_store
'(X), nb_getval(chr_global,X)).
220 % goal_expansion seems too different in SICStus 4 for me to cater for in a
221 % decent way at this moment - so I stick with the old way to do this
222 % so that it doesn't get lost
, the code from Mats
for SICStus
4 is included
in comments
226 %% goal_expansion
('chr get_mutable'(Val
,Var
), Lay
, _M
, get_mutable
(Val
,Var
), Lay
).
227 %% goal_expansion
('chr update_mutable'(Val
,Var
), Lay
, _M
, update_mutable
(Val
,Var
), Lay
).
228 %% goal_expansion
('chr create_mutable'(Val
,Var
), Lay
, _M
, create_mutable
(Val
,Var
), Lay
).
229 %% goal_expansion
('chr default_store'(A
), Lay
, _M
, global_term_ref_1
(A
), Lay
).
234 %% :- multifile user
:goal_expansion
/2.
235 %% :- dynamic user
:goal_expansion
/2.
237 %% user
:goal_expansion
('chr get_mutable'(Val
,Var
), get_mutable
(Val
,Var
)).
238 %% user
:goal_expansion
('chr update_mutable'(Val
,Var
), update_mutable
(Val
,Var
)).
239 %% user
:goal_expansion
('chr create_mutable'(Val
,Var
), create_mutable
(Val
,Var
)).
240 %% user
:goal_expansion
('chr default_store'(A
), global_term_ref_1
(A
)).
244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
245 'chr run_suspensions'( Slots
) :-
246 run_suspensions
( Slots
).
248 'chr run_suspensions_loop'([]).
249 'chr run_suspensions_loop'([L
|Ls
]) :-
251 'chr run_suspensions_loop'(Ls
).
254 run_suspensions
([S
|Next
] ) :-
255 arg
( 2, S
, Mref
), % ARGXXX
256 'chr get_mutable'( Status
, Mref
),
258 'chr update_mutable'( triggered
, Mref
),
259 arg
( 4, S
, Gref
), % ARGXXX
260 'chr get_mutable'( Gen
, Gref
),
262 'chr update_mutable'( Generation
, Gref
),
263 arg
( 3, S
, Goal
), % ARGXXX
265 'chr get_mutable'( Post
, Mref
),
267 'chr update_mutable'( active
, Mref
) % catching constraints that did
not do anything
274 run_suspensions
( Next
).
276 'chr run_suspensions_d'( Slots
) :-
277 run_suspensions_d
( Slots
).
279 'chr run_suspensions_loop_d'([]).
280 'chr run_suspensions_loop_d'([L
|Ls
]) :-
281 run_suspensions_d
(L
),
282 'chr run_suspensions_loop_d'(Ls
).
284 run_suspensions_d
([]).
285 run_suspensions_d
([S
|Next
] ) :-
286 arg
( 2, S
, Mref
), % ARGXXX
287 'chr get_mutable'( Status
, Mref
),
289 'chr update_mutable'( triggered
, Mref
),
290 arg
( 4, S
, Gref
), % ARGXXX
291 'chr get_mutable'( Gen
, Gref
),
293 'chr update_mutable'( Generation
, Gref
),
294 arg
( 3, S
, Goal
), % ARGXXX
296 'chr debug_event'(wake
(S
)),
299 'chr debug_event'(fail
(S
)), !,
303 'chr debug_event'(exit(S
))
305 'chr debug_event'(redo(S
)),
308 'chr get_mutable'( Post
, Mref
),
310 'chr update_mutable'( active
, Mref
) % catching constraints that did
not do anything
317 run_suspensions_d
( Next
).
318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
321 % locking of variables
in guards
323 %= IMPLEMENTATION
1: SILENT FAILURE
============================================
325 %- attribute handler
-----------------------------------------------------------
326 % intercepts unification of locked variable unification
328 locked
:attr_unify_hook
(_
,_
) :- fail
.
330 %- locking
& unlocking
---------------------------------------------------------
333 -> put_attr
(T
, locked
, x
)
334 ; term_variables
(T
,L
),
339 lockv
([T
|R
]) :- put_attr
( T
, locked
, x
), lockv
(R
).
343 -> del_attr
(T
, locked
)
344 ; term_variables
(T
,L
),
349 unlockv
([T
|R
]) :- del_attr
( T
, locked
), unlockv
(R
).
351 %- checking
for locks
----------------------------------------------------------
353 'chr none_locked'( []).
354 'chr none_locked'( [V
|Vs
]) :-
355 ( get_attr
(V
, locked
, _
) ->
358 'chr none_locked'(Vs
)
361 'chr not_locked'(V
) :-
363 ( get_attr
( V
, locked
, _
) ->
372 %= IMPLEMENTATION
2: EXPLICT EXCEPTION
=========================================
374 %- LOCK ERROR MESSAGE
----------------------------------------------------------
376 throw
(error
(instantation_error
(Term
),context
(_
,'CHR Runtime Error: unification in guard not allowed!'))).
378 %- attribute handler
-----------------------------------------------------------
379 % intercepts unification of locked variable unification
381 error_locked
:attr_unify_hook
(_
,Term
) :- lock_error
(Term
).
383 %- locking
& unlocking
---------------------------------------------------------
384 'chr error_lock'(T
) :-
386 -> put_attr
(T
, error_locked
, x
)
387 ; term_variables
(T
,L
),
392 error_lockv
([T
|R
]) :- put_attr
( T
, error_locked
, x
), error_lockv
(R
).
394 'chr unerror_lock'(T
) :-
396 -> del_attr
(T
, error_locked
)
397 ; term_variables
(T
,L
),
402 unerror_lockv
([T
|R
]) :- del_attr
( T
, error_locked
), unerror_lockv
(R
).
404 %- checking
for locks
----------------------------------------------------------
406 'chr none_error_locked'( []).
407 'chr none_error_locked'( [V
|Vs
]) :-
408 ( get_attr
(V
, error_locked
, _
) ->
411 'chr none_error_locked'(Vs
)
414 'chr not_error_locked'(V
) :-
416 ( get_attr
( V
, error_locked
, _
) ->
425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
427 % Eager removal from all chains
.
429 'chr remove_constraint_internal'( Susp
, Agenda
) :-
430 arg
( 2, Susp
, Mref
), % ARGXXX
431 'chr get_mutable'( State
, Mref
),
432 'chr update_mutable'( removed
, Mref
), % mark
in any case
433 ( compound
(State
) -> % passive
/1
437 %; State
==triggered
->
440 Susp
=.. [_
,_
,_
,_
,_
,_
,_
|Args
],
441 term_variables
( Args
, Vars
),
442 'chr default_store'( Global
),
443 Agenda
= [Global
|Vars
]
446 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
447 'chr newvia_1'(X
,V
) :-
454 'chr newvia_2'(X
,Y
,V
) :-
459 ; compound
(X
), nonground
(X
,V
) ->
462 compound
(Y
), nonground
(Y
,V
)
466 % The second arg is a witness
.
467 % The formulation with term_variables
/2 is
468 % cycle safe
, but it finds a list of all vars
.
469 % We need only one
, and no list
in particular
.
471 'chr newvia'(L
,V
) :- nonground
(L
,V
).
472 %~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
478 'chr default_store'(V
)
482 'chr default_store'(V
)
485 'chr via_2'(X
,Y
,V
) :-
490 ; compound
(X
), nonground
(X
,V
) ->
492 ; compound
(Y
), nonground
(Y
,V
) ->
495 'chr default_store'(V
)
499 % The second arg is a witness
.
500 % The formulation with term_variables
/2 is
501 % cycle safe
, but it finds a list of all vars
.
502 % We need only one
, and no list
in particular
.
508 'chr default_store'(V
)
511 nonground
( Term
, V
) :-
512 term_variables
( Term
, Vs
),
515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
516 'chr novel_production'( Self
, Tuple
) :-
517 arg
( 5, Self
, Ref
), % ARGXXX
518 'chr get_mutable'( History
, Ref
),
519 ( get_ds
( Tuple
, History
, _
) ->
526 % Not folded with novel_production
/2 because guard checking
527 % goes
in between the two calls
.
529 'chr extend_history'( Self
, Tuple
) :-
530 arg
( 5, Self
, Ref
), % ARGXXX
531 'chr get_mutable'( History
, Ref
),
532 put_ds
( Tuple
, History
, x
, NewHistory
),
533 'chr update_mutable'( NewHistory
, Ref
).
535 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
536 constraint_generation
( Susp
, State
, Generation
) :-
537 arg
( 2, Susp
, Mref
), % ARGXXX
538 'chr get_mutable'( State
, Mref
),
539 arg
( 4, Susp
, Gref
), % ARGXXX
540 'chr get_mutable'( Generation
, Gref
). % not incremented meanwhile
542 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
543 'chr allocate_constraint'( Closure
, Self
, F
, Args
) :-
544 Self
=.. [suspension
,Id
,Mref
,Closure
,Gref
,Href
,F
|Args
], % SUSPXXX
545 'chr create_mutable'(0, Gref
),
546 'chr empty_history'(History
),
547 'chr create_mutable'(History
, Href
),
548 'chr create_mutable'(passive
(Args
), Mref
),
552 % 'chr activate_constraint'( -, +, -).
554 % The transition gc
->active should be rare
556 'chr activate_constraint'( Vars
, Susp
, Generation
) :-
557 arg
( 2, Susp
, Mref
), % ARGXXX
558 'chr get_mutable'( State
, Mref
),
559 'chr update_mutable'( active
, Mref
),
560 ( nonvar
(Generation
) -> % aih
563 arg
( 4, Susp
, Gref
), % ARGXXX
564 'chr get_mutable'( Gen
, Gref
),
566 'chr update_mutable'( Generation
, Gref
)
568 ( compound
(State
) -> % passive
/1
569 term_variables
( State
, Vs
),
570 'chr none_locked'( Vs
),
572 'chr default_store'(Global
)
573 ; State
== removed
-> % the price
for eager removal
...
574 Susp
=.. [_
,_
,_
,_
,_
,_
,_
|Args
],
575 term_variables
( Args
, Vs
),
577 'chr default_store'(Global
)
582 'chr insert_constraint_internal'([Global
|Vars
], Self
, Closure
, F
, Args
) :-
583 'chr default_store'(Global
),
584 term_variables
(Args
,Vars
),
585 'chr none_locked'(Vars
),
586 Self
=.. [suspension
,Id
,Mref
,Closure
,Gref
,Href
,F
|Args
], % SUSPXXX
587 'chr create_mutable'(active
, Mref
),
588 'chr create_mutable'(0, Gref
),
589 'chr empty_history'(History
),
590 'chr create_mutable'(History
, Href
),
593 insert_constraint_internal
([Global
|Vars
], Self
, Term
, Closure
, F
, Args
) :-
594 'chr default_store'(Global
),
595 term_variables
( Term
, Vars
),
596 'chr none_locked'( Vars
),
597 'chr empty_history'( History
),
598 'chr create_mutable'( active
, Mref
),
599 'chr create_mutable'( 0, Gref
),
600 'chr create_mutable'( History
, Href
),
602 Self
=.. [suspension
,Id
,Mref
,Closure
,Gref
,Href
,F
|Args
]. % SUSPXXX
604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
605 'chr empty_history'( E
) :- empty_ds
( E
).
607 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
609 nb_getval
(chr_id
,Id
),
611 nb_setval
(chr_id
,NextId
).
613 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616 'chr create_mutable'(V
,mutable
(V
)).
617 'chr get_mutable'(V
,mutable
(V
)).
618 'chr update_mutable'(V
,M
) :- setarg
(1,M
,V
).
622 %% 'chr create_mutable'(Val
, Mut
) :- create_mutable
(Val
, Mut
).
623 %% 'chr get_mutable'(Val
, Mut
) :- get_mutable
(Val
, Mut
).
624 %% 'chr update_mutable'(Val
, Mut
) :- update_mutable
(Val
, Mut
).
628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
630 'chr default_store'(X
) :- nb_getval
(chr_global
,X
).
634 %% 'chr default_store'(A
) :- global_term_ref_1
(A
).
637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
639 'chr sbag_member'( Element
, [Head
|Tail
]) :-
640 sbag_member
( Element
, Tail
, Head
).
642 % auxiliary to avoid choicepoint
for last element
643 % does it really avoid the choicepoint?
-jon
644 sbag_member
( E
, _
, E
).
645 sbag_member
( E
, [Head
|Tail
], _
) :-
646 sbag_member
( E
, Tail
, Head
).
648 'chr sbag_del_element'( [], _
, []).
649 'chr sbag_del_element'( [X
|Xs
], Elem
, Set2
) :-
654 'chr sbag_del_element'( Xs
, Elem
, Xss
)
657 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
658 'chr merge_attributes'([],Ys
,Ys
).
659 'chr merge_attributes'([X
| Xs
],YL
,R
) :-
661 arg
(1,X
,XId
), % ARGXXX
662 arg
(1,Y
,YId
), % ARGXXX
665 'chr merge_attributes'(Xs
,YL
,T
)
668 'chr merge_attributes'([X
|Xs
],Ys
,T
)
671 'chr merge_attributes'(Xs
,Ys
,T
)
677 'chr new_merge_attributes'([],A2
,A
) :-
679 'chr new_merge_attributes'([E1
|AT1
],A2
,A
) :-
681 'chr new_merge_attributes'(E1
,E2
,AT1
,AT2
,A
)
686 'chr new_merge_attributes'(Pos1
-L1
,Pos2
-L2
,AT1
,AT2
,A
) :-
689 'chr new_merge_attributes'(AT1
,[Pos2
-L2
|AT2
],AT
)
692 'chr new_merge_attributes'([Pos1
-L1
|AT1
],AT2
,AT
)
694 'chr merge_attributes'(L1
,L2
,L
),
696 'chr new_merge_attributes'(AT1
,AT2
,AT
)
699 'chr all_suspensions'([],_
,_
).
700 'chr all_suspensions'([Susps
|SuspsList
],Pos
,Attr
) :-
701 all_suspensions
(Attr
,Susps
,SuspsList
,Pos
).
703 all_suspensions
([],[],SuspsList
,Pos
) :-
704 all_suspensions
([],[],SuspsList
,Pos
). % all empty lists
705 all_suspensions
([APos
-ASusps
|RAttr
],Susps
,SuspsList
,Pos
) :-
709 'chr all_suspensions'(SuspsList
,NPos
,RAttr
)
712 'chr all_suspensions'(SuspsList
,NPos
,[APos
-ASusps
|RAttr
])
715 'chr normalize_attr'([],[]).
716 'chr normalize_attr'([Pos
-L
|R
],[Pos
-NL
|NR
]) :-
718 'chr normalize_attr'(R
,NR
).
720 'chr select'([E
|T
],F
,R
) :-
728 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
731 chr:debug_event
/2, % +State
, +Event
732 chr:debug_interact
/3. % +Event
, +Depth
, -Command
734 'chr debug_event'(Event
) :-
735 nb_getval
(chr_debug
,mutable
(State
)), % XXX
738 ; chr:debug_event
(State
, Event
) ->
740 ; debug_event
(State
,Event
)
744 nb_setval
(chr_debug
,mutable
(trace
)).
746 nb_setval
(chr_debug
,mutable
(off
)).
750 % Define the set of ports at which we prompt
for user interaction
753 leashed_ports
(Spec
, Ports
),
754 nb_setval
(chr_leash
,mutable
(Ports
)).
756 leashed_ports
(none
, []).
757 leashed_ports
(off
, []).
758 leashed_ports
(all
, [call
, exit, redo, fail
, wake
, try
, apply
, insert
, remove
]).
759 leashed_ports
(default, [call
,exit,fail
,wake
,apply
]).
760 leashed_ports
(One
, Ports
) :-
761 atom
(One
), One \
== [], !,
762 leashed_ports
([One
], Ports
).
763 leashed_ports
(Set
, Ports
) :-
764 sort(Set
, Ports
), % make unique
765 leashed_ports
(all
, All
),
766 valid_ports
(Ports
, All
).
769 valid_ports
([H
|T
], Valid
) :-
770 ( memberchk
(H
, Valid
)
772 ; throw
(error
(domain_error
(chr_port
, H
), _
))
774 valid_ports
(T
, Valid
).
776 user
:exception
(undefined_global_variable
, Name
, retry
) :-
777 chr_runtime_debug_global_variable
(Name
),
780 chr_runtime_debug_global_variable
(chr_leash
).
783 leashed_ports
(default, Ports
),
784 nb_setval
(chr_leash
, mutable
(Ports
)).
786 :- initialization chr_debug_init
.
788 % debug_event
(+State
, +Event
)
791 %debug_event(trace
, Event
) :-
792 % functor
(Event
, Name
, Arity
),
793 % writeln
(Name
/Arity
), fail
.
794 debug_event
(trace
,Event
) :-
796 get_debug_history
(History
,Depth
),
798 chr_debug_interact
(Event
,NDepth
),
799 set_debug_history
([Event
|History
],NDepth
).
800 debug_event
(trace
,Event
) :-
802 get_debug_history
(History
,Depth
),
804 chr_debug_interact
(Event
,NDepth
),
805 set_debug_history
([Event
|History
],NDepth
).
806 debug_event
(trace
,Event
) :-
808 get_debug_history
(_History
, Depth
),
809 chr_debug_interact
(Event
, Depth
).
810 debug_event
(trace
,Event
) :-
812 get_debug_history
([_
|History
],Depth
),
813 chr_debug_interact
(Event
,Depth
),
815 set_debug_history
(History
,NDepth
).
816 debug_event
(trace
,Event
) :-
818 get_debug_history
(_
,Depth
),
819 chr_debug_interact
(Event
,Depth
).
820 debug_event
(trace
, Event
) :-
821 Event
= remove
(_
), !,
822 get_debug_history
(_
,Depth
),
823 chr_debug_interact
(Event
, Depth
).
824 debug_event
(trace
, Event
) :-
825 Event
= insert
(_
), !,
826 get_debug_history
(_
,Depth
),
827 chr_debug_interact
(Event
, Depth
).
828 debug_event
(trace
, Event
) :-
829 Event
= try
(_
,_
,_
,_
), !,
830 get_debug_history
(_
,Depth
),
831 chr_debug_interact
(Event
, Depth
).
832 debug_event
(trace
, Event
) :-
833 Event
= apply
(_
,_
,_
,_
), !,
834 get_debug_history
(_
,Depth
),
835 chr_debug_interact
(Event
,Depth
).
837 debug_event
(skip
(_
,_
),Event
) :-
839 get_debug_history
(History
,Depth
),
841 set_debug_history
([Event
|History
],NDepth
).
842 debug_event
(skip
(_
,_
),Event
) :-
844 get_debug_history
(History
,Depth
),
846 set_debug_history
([Event
|History
],NDepth
).
847 debug_event
(skip
(SkipSusp
,SkipDepth
),Event
) :-
848 Event
= exit(Susp
),!,
849 get_debug_history
([_
|History
],Depth
),
850 ( SkipDepth
== Depth
,
852 set_chr_debug
(trace
),
853 chr_debug_interact
(Event
,Depth
)
858 set_debug_history
(History
,NDepth
).
859 debug_event
(skip
(_
,_
),_
) :- !,
862 % chr_debug_interact
(+Event
, +Depth
)
864 % Interact with the user on Event that took place at Depth
. First
865 % calls
chr:debug_interact
(+Event
, +Depth
, -Command
) hook
. If this
866 % fails the event is printed
and the
system prompts
for a command
.
868 chr_debug_interact
(Event
, Depth
) :-
869 chr:debug_interact
(Event
, Depth
, Command
), !,
870 handle_debug_command
(Command
,Event
,Depth
).
871 chr_debug_interact
(Event
, Depth
) :-
872 print_event
(Event
, Depth
),
874 -> ask_continue
(Command
)
877 handle_debug_command
(Command
,Event
,Depth
).
880 functor
(Event
, Port
, _
),
881 nb_getval
(chr_leash
, mutable
(Ports
)),
882 memberchk
(Port
, Ports
).
884 ask_continue
(Command
) :-
885 print_message
(debug
, chr(prompt
)),
886 get_single_char
(CharCode
),
888 -> Char
= end_of_file
889 ; char_code
(Char
, CharCode
)
891 ( debug_command
(Char
, Command
)
892 -> print_message
(debug
, chr(command
(Command
)))
893 ; print_message
(help
, chr(invalid_command
)),
894 ask_continue
(Command
)
898 'chr debug command'(Char
, Command
) :-
899 debug_command
(Char
, Command
).
901 debug_command
(c
, creep
).
902 debug_command
(' ', creep
).
903 debug_command
('\r', creep
).
904 debug_command
(s
, skip
).
905 debug_command
(g
, ancestors
).
906 debug_command
(n
, nodebug
).
907 debug_command
(a
, abort
).
908 debug_command
(f
, fail
).
909 debug_command
(b
, break).
910 debug_command
(?
, help
).
911 debug_command
(h
, help
).
912 debug_command
(end_of_file
, exit).
915 handle_debug_command
(creep
,_
,_
) :- !.
916 handle_debug_command
(skip
, Event
, Depth
) :- !,
917 Event
=.. [Type
|Rest
],
920 handle_debug_command
('c',Event
,Depth
)
923 set_chr_debug
(skip
(Susp
,Depth
))
926 handle_debug_command
(ancestors
,Event
,Depth
) :- !,
927 print_chr_debug_history
,
928 chr_debug_interact
(Event
,Depth
).
929 handle_debug_command
(nodebug
,_
,_
) :- !,
931 handle_debug_command
(abort
,_
,_
) :- !,
933 handle_debug_command
(exit,_
,_
) :- !,
935 handle_debug_command
(fail
,_
,_
) :- !,
937 handle_debug_command
(break,Event
,Depth
) :- !,
939 chr_debug_interact
(Event
,Depth
).
940 handle_debug_command
(help
,Event
,Depth
) :- !,
941 print_message
(help
, chr(debug_options
)),
942 chr_debug_interact
(Event
,Depth
).
943 handle_debug_command
(Cmd
, _
, _
) :-
944 throw
(error
(domain_error
(chr_debug_command
, Cmd
), _
)).
946 print_chr_debug_history
:-
947 get_debug_history
(History
,Depth
),
948 print_message
(debug
, chr(ancestors
(History
, Depth
))).
950 print_event
(Event
, Depth
) :-
951 print_message
(debug
, chr(event
(Event
, Depth
))).
953 % {set
,get
}_debug_history
(Ancestors
, Depth
)
955 % Set
/get the list of ancestors
and the depth of the current goal
.
957 get_debug_history
(History
,Depth
) :-
958 nb_getval
(chr_debug_history
,mutable
(History
,Depth
)).
960 set_debug_history
(History
,Depth
) :-
961 nb_getval
(chr_debug_history
,Mutable
),
962 setarg
(1,Mutable
,History
),
963 setarg
(2,Mutable
,Depth
).
965 set_chr_debug
(State
) :-
966 nb_getval
(chr_debug
,Mutable
),
967 setarg
(1,Mutable
,State
).
969 'chr chr_indexed_variables'(Susp
,Vars
) :-
970 Susp
=.. [_
,_
,_
,_
,_
,_
,_
|Args
],
971 term_variables
(Args
,Vars
).