751 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
		
		
			
		
	
	
			751 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| 
								 | 
							
								/*  $Id: chr_runtime.pl,v 1.1 2005-10-28 17:41:30 vsc Exp $
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Part of CHR (Constraint Handling Rules)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Author:        Christian Holzbaur and Tom Schrijvers
							 | 
						||
| 
								 | 
							
								    E-mail:        christian@ai.univie.ac.at
							 | 
						||
| 
								 | 
							
										   Tom.Schrijvers@cs.kuleuven.ac.be
							 | 
						||
| 
								 | 
							
								    WWW:           http://www.swi-prolog.org
							 | 
						||
| 
								 | 
							
								    Copyright (C): 2003-2004, K.U. Leuven
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    This program is free software; you can redistribute it and/or
							 | 
						||
| 
								 | 
							
								    modify it under the terms of the GNU General Public License
							 | 
						||
| 
								 | 
							
								    as published by the Free Software Foundation; either version 2
							 | 
						||
| 
								 | 
							
								    of the License, or (at your option) any later version.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    This program is distributed in the hope that it will be useful,
							 | 
						||
| 
								 | 
							
								    but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						||
| 
								 | 
							
								    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
							 | 
						||
| 
								 | 
							
								    GNU General Public License for more details.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    You should have received a copy of the GNU Lesser General Public
							 | 
						||
| 
								 | 
							
								    License along with this library; if not, write to the Free Software
							 | 
						||
| 
								 | 
							
								    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    As a special exception, if you link this library with other files,
							 | 
						||
| 
								 | 
							
								    compiled with a Free Software compiler, to produce an executable, this
							 | 
						||
| 
								 | 
							
								    library does not by itself cause the resulting executable to be covered
							 | 
						||
| 
								 | 
							
								    by the GNU General Public License. This exception does not however
							 | 
						||
| 
								 | 
							
								    invalidate any other reasons why the executable file might be covered by
							 | 
						||
| 
								 | 
							
								    the GNU General Public License.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Distributed with SWI-Prolog under the above conditions with
							 | 
						||
| 
								 | 
							
								    permission from the authors.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								%%       _                             _   _                
							 | 
						||
| 
								 | 
							
								%%   ___| |__  _ __   _ __ _   _ _ __ | |_(_)_ __ ___   ___ 
							 | 
						||
| 
								 | 
							
								%%  / __| '_ \| '__| | '__| | | | '_ \| __| | '_ ` _ \ / _ \
							 | 
						||
| 
								 | 
							
								%% | (__| | | | |    | |  | |_| | | | | |_| | | | | | |  __/
							 | 
						||
| 
								 | 
							
								%%  \___|_| |_|_|    |_|   \__,_|_| |_|\__|_|_| |_| |_|\___|
							 | 
						||
| 
								 | 
							
								%%
							 | 
						||
| 
								 | 
							
								%% hProlog CHR runtime:
							 | 
						||
| 
								 | 
							
								%%
							 | 
						||
| 
								 | 
							
								%% 	* based on the SICStus CHR runtime by Christian Holzbaur
							 | 
						||
| 
								 | 
							
								%% 
							 | 
						||
| 
								 | 
							
								%%          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								%%          %  Constraint Handling Rules		      version 2.2 %
							 | 
						||
| 
								 | 
							
								%%          %								  %
							 | 
						||
| 
								 | 
							
								%%          %  (c) Copyright 1996-98					  %
							 | 
						||
| 
								 | 
							
								%%          %  LMU, Muenchen						  %
							 | 
						||
| 
								 | 
							
								%% 	    %								  %
							 | 
						||
| 
								 | 
							
								%%          %  File:   chr.pl						  %
							 | 
						||
| 
								 | 
							
								%%          %  Author: Christian Holzbaur	christian@ai.univie.ac.at %
							 | 
						||
| 
								 | 
							
								%%          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								%% 
							 | 
						||
| 
								 | 
							
								%%	
							 | 
						||
| 
								 | 
							
								%%	* modified by Tom Schrijvers, K.U.Leuven, Tom.Schrijvers@cs.kuleuven.ac.be
							 | 
						||
| 
								 | 
							
								%%		- ported to hProlog
							 | 
						||
| 
								 | 
							
								%%		- modified for eager suspension removal
							 | 
						||
| 
								 | 
							
								%%
							 | 
						||
| 
								 | 
							
								%%      * First working version: 6 June 2003
							 | 
						||
| 
								 | 
							
								%%
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								%% SWI-Prolog changes
							 | 
						||
| 
								 | 
							
								%% 
							 | 
						||
| 
								 | 
							
								%% 	* Added initialization directives for saved-states
							 | 
						||
| 
								 | 
							
								%%	* Renamed merge/3 --> sbag_merge/3 (name conflict)
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:- module(chr_runtime,
							 | 
						||
| 
								 | 
							
									  [ 'chr sbag_del_element'/3,
							 | 
						||
| 
								 | 
							
									    'chr sbag_member'/2,
							 | 
						||
| 
								 | 
							
									    'chr merge_attributes'/3,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    'chr run_suspensions'/1,
							 | 
						||
| 
								 | 
							
									    'chr run_suspensions_loop'/1,
							 | 
						||
| 
								 | 
							
									    
							 | 
						||
| 
								 | 
							
									    'chr run_suspensions_d'/1,
							 | 
						||
| 
								 | 
							
									    'chr run_suspensions_loop_d'/1,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    'chr insert_constraint_internal'/5,
							 | 
						||
| 
								 | 
							
									    'chr remove_constraint_internal'/2,
							 | 
						||
| 
								 | 
							
									    'chr allocate_constraint'/4,
							 | 
						||
| 
								 | 
							
									    'chr activate_constraint'/3,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    'chr global_term_ref_1'/1,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    'chr via_1'/2,
							 | 
						||
| 
								 | 
							
									    'chr via_2'/3,
							 | 
						||
| 
								 | 
							
									    'chr via'/2,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    'chr lock'/1,
							 | 
						||
| 
								 | 
							
									    'chr unlock'/1,
							 | 
						||
| 
								 | 
							
									    'chr not_locked'/1,
							 | 
						||
| 
								 | 
							
								            'chr none_locked'/1,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    'chr update_mutable'/2,
							 | 
						||
| 
								 | 
							
									    'chr get_mutable'/2,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    'chr novel_production'/2,
							 | 
						||
| 
								 | 
							
									    'chr extend_history'/2,
							 | 
						||
| 
								 | 
							
									    'chr empty_history'/1,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    'chr gen_id'/1,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    'chr debug_event'/1,
							 | 
						||
| 
								 | 
							
									    'chr debug command'/2,	% Char, Command
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    'chr chr_indexed_variables'/2,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    chr_trace/0,
							 | 
						||
| 
								 | 
							
									    chr_notrace/0,
							 | 
						||
| 
								 | 
							
									    chr_leash/1
							 | 
						||
| 
								 | 
							
									  ]).
							 | 
						||
| 
								 | 
							
								:- set_prolog_flag(generate_debug_info, false).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								                                                       
							 | 
						||
| 
								 | 
							
								:- use_module(library(assoc)).
							 | 
						||
| 
								 | 
							
								:- use_module(hprolog).
							 | 
						||
| 
								 | 
							
								%:- use_module(library(lists)).
							 | 
						||
| 
								 | 
							
								:- include(chr_op).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%   I N I T I A L I S A T I O N
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								chr_init :-
							 | 
						||
| 
								 | 
							
									nb_setval(id,0),
							 | 
						||
| 
								 | 
							
									nb_setval(chr_global,_),
							 | 
						||
| 
								 | 
							
									nb_setval(chr_debug,mutable(off)),
							 | 
						||
| 
								 | 
							
									nb_setval(chr_debug_history,mutable([],0)).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:- initialization chr_init.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								show_store(Mod) :-
							 | 
						||
| 
								 | 
							
									(
							 | 
						||
| 
								 | 
							
										Mod:'$enumerate_suspensions'(Susp),
							 | 
						||
| 
								 | 
							
										arg(6,Susp,C),
							 | 
						||
| 
								 | 
							
										writeln(C),
							 | 
						||
| 
								 | 
							
										fail
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
										true
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								'chr merge_attributes'( As, Bs, Cs) :-
							 | 
						||
| 
								 | 
							
									sbag_union(As,Bs,Cs).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								'chr run_suspensions'( Slots) :-
							 | 
						||
| 
								 | 
							
									    run_suspensions( Slots).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								'chr run_suspensions_loop'([]).
							 | 
						||
| 
								 | 
							
								'chr run_suspensions_loop'([L|Ls]) :-
							 | 
						||
| 
								 | 
							
									run_suspensions(L),
							 | 
						||
| 
								 | 
							
									'chr run_suspensions_loop'(Ls).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								run_suspensions([]).
							 | 
						||
| 
								 | 
							
								run_suspensions([S|Next] ) :-
							 | 
						||
| 
								 | 
							
									arg( 2, S, Mref),
							 | 
						||
| 
								 | 
							
									Mref = mutable(Status), % get_mutable( Status, Mref), % XXX Inlined
							 | 
						||
| 
								 | 
							
									( Status==active ->
							 | 
						||
| 
								 | 
							
									    update_mutable( triggered, Mref),
							 | 
						||
| 
								 | 
							
									    arg( 4, S, Gref),
							 | 
						||
| 
								 | 
							
									    Gref = mutable(Gen), % get_mutable( Gen, Gref), % XXX Inlined
							 | 
						||
| 
								 | 
							
									    Generation is Gen+1,
							 | 
						||
| 
								 | 
							
									    update_mutable( Generation, Gref),
							 | 
						||
| 
								 | 
							
									    arg( 3, S, Goal),
							 | 
						||
| 
								 | 
							
									    call( Goal),
							 | 
						||
| 
								 | 
							
									    					% get_mutable( Post, Mref), % XXX Inlined
							 | 
						||
| 
								 | 
							
									    ( Mref = mutable(triggered) ->	% Post==triggered ->
							 | 
						||
| 
								 | 
							
										update_mutable( removed, Mref)
							 | 
						||
| 
								 | 
							
									    ;
							 | 
						||
| 
								 | 
							
										true
							 | 
						||
| 
								 | 
							
									    )
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									    true
							 | 
						||
| 
								 | 
							
									),
							 | 
						||
| 
								 | 
							
									run_suspensions( Next).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								'chr run_suspensions_d'( Slots) :-
							 | 
						||
| 
								 | 
							
									    run_suspensions_d( Slots).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								'chr run_suspensions_loop_d'([]).
							 | 
						||
| 
								 | 
							
								'chr run_suspensions_loop_d'([L|Ls]) :-
							 | 
						||
| 
								 | 
							
									run_suspensions_d(L),
							 | 
						||
| 
								 | 
							
									'chr run_suspensions_loop_d'(Ls).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								run_suspensions_d([]).
							 | 
						||
| 
								 | 
							
								run_suspensions_d([S|Next] ) :-
							 | 
						||
| 
								 | 
							
									arg( 2, S, Mref),
							 | 
						||
| 
								 | 
							
									Mref = mutable(Status), % get_mutable( Status, Mref), % XXX Inlined
							 | 
						||
| 
								 | 
							
									( Status==active ->
							 | 
						||
| 
								 | 
							
									    update_mutable( triggered, Mref),
							 | 
						||
| 
								 | 
							
									    arg( 4, S, Gref),
							 | 
						||
| 
								 | 
							
									    Gref = mutable(Gen), % get_mutable( Gen, Gref), % XXX Inlined
							 | 
						||
| 
								 | 
							
									    Generation is Gen+1,
							 | 
						||
| 
								 | 
							
									    update_mutable( Generation, Gref),
							 | 
						||
| 
								 | 
							
									    arg( 3, S, Goal),
							 | 
						||
| 
								 | 
							
									    ( 
							 | 
						||
| 
								 | 
							
										'chr debug_event'(wake(S)),
							 | 
						||
| 
								 | 
							
									        call( Goal)
							 | 
						||
| 
								 | 
							
									    ;
							 | 
						||
| 
								 | 
							
										'chr debug_event'(fail(S)), !,
							 | 
						||
| 
								 | 
							
										fail
							 | 
						||
| 
								 | 
							
									    ),
							 | 
						||
| 
								 | 
							
									    (
							 | 
						||
| 
								 | 
							
										'chr debug_event'(exit(S))
							 | 
						||
| 
								 | 
							
									    ;
							 | 
						||
| 
								 | 
							
										'chr debug_event'(redo(S)),
							 | 
						||
| 
								 | 
							
										fail
							 | 
						||
| 
								 | 
							
									    ),	
							 | 
						||
| 
								 | 
							
									    					% get_mutable( Post, Mref), % XXX Inlined
							 | 
						||
| 
								 | 
							
									    ( Mref = mutable(triggered) ->	% Post==triggered ->
							 | 
						||
| 
								 | 
							
										update_mutable( removed, Mref)
							 | 
						||
| 
								 | 
							
									    ;
							 | 
						||
| 
								 | 
							
										true
							 | 
						||
| 
								 | 
							
									    )
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									    true
							 | 
						||
| 
								 | 
							
									),
							 | 
						||
| 
								 | 
							
									run_suspensions_d( Next).
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								locked:attr_unify_hook(_,_) :- fail.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								'chr lock'(T) :- 
							 | 
						||
| 
								 | 
							
									lock(T).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								'chr unlock'(T) :-
							 | 
						||
| 
								 | 
							
									unlock(T).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								'chr not_locked'(T) :-
							 | 
						||
| 
								 | 
							
									not_locked(T).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								lock(T) :-
							 | 
						||
| 
								 | 
							
									( var(T)
							 | 
						||
| 
								 | 
							
									-> put_attr(T, locked, x)
							 | 
						||
| 
								 | 
							
								        ;  term_variables(T,L),
							 | 
						||
| 
								 | 
							
								           lockv(L)
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								lockv([]).
							 | 
						||
| 
								 | 
							
								lockv([T|R]) :- put_attr( T, locked, x), lockv(R).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								unlock(T) :-
							 | 
						||
| 
								 | 
							
									( var(T)
							 | 
						||
| 
								 | 
							
									-> del_attr(T, locked)
							 | 
						||
| 
								 | 
							
									;  term_variables(T,L),
							 | 
						||
| 
								 | 
							
								           unlockv(L)
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								unlockv([]).
							 | 
						||
| 
								 | 
							
								unlockv([T|R]) :- del_attr( T, locked), unlockv(R).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								'chr none_locked'( []).
							 | 
						||
| 
								 | 
							
								'chr none_locked'( [V|Vs]) :-
							 | 
						||
| 
								 | 
							
									not_locked( V),
							 | 
						||
| 
								 | 
							
									'chr none_locked'( Vs).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								not_locked( V) :- 
							 | 
						||
| 
								 | 
							
									( var( V) ->
							 | 
						||
| 
								 | 
							
								  		( get_attr( V, locked, _) ->
							 | 
						||
| 
								 | 
							
											fail
							 | 
						||
| 
								 | 
							
										;
							 | 
						||
| 
								 | 
							
											true
							 | 
						||
| 
								 | 
							
										)
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
										true
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% Eager removal from all chains.
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								'chr remove_constraint_internal'( Susp, Agenda) :-
							 | 
						||
| 
								 | 
							
									arg( 2, Susp, Mref),
							 | 
						||
| 
								 | 
							
									Mref = mutable(State), % get_mutable( State, Mref), % XXX Inlined
							 | 
						||
| 
								 | 
							
									update_mutable( removed, Mref),		% mark in any case
							 | 
						||
| 
								 | 
							
									( compound(State) ->			% passive/1
							 | 
						||
| 
								 | 
							
									    Agenda = []
							 | 
						||
| 
								 | 
							
									; State==removed ->
							 | 
						||
| 
								 | 
							
									    Agenda = []
							 | 
						||
| 
								 | 
							
									%; State==triggered ->
							 | 
						||
| 
								 | 
							
									%     Agenda = []
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
								            Susp =.. [_,_,_,_,_,_,_|Args],
							 | 
						||
| 
								 | 
							
									    term_variables( Args, Vars),
							 | 
						||
| 
								 | 
							
									    global_term_ref_1( Global),
							 | 
						||
| 
								 | 
							
									    Agenda = [Global|Vars]
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								'chr via_1'(X,V) :-
							 | 
						||
| 
								 | 
							
									( var(X) ->
							 | 
						||
| 
								 | 
							
										X = V
							 | 
						||
| 
								 | 
							
									; atomic(X) ->
							 | 
						||
| 
								 | 
							
										global_term_ref_1(V)
							 | 
						||
| 
								 | 
							
									; nonground(X,V) ->
							 | 
						||
| 
								 | 
							
										true
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
										global_term_ref_1(V)
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								% 'chr via_1'( X, V) :- var(X), !, X=V.
							 | 
						||
| 
								 | 
							
								% 'chr via_1'( T, V) :- compound(T), nonground( T, V), ! .
							 | 
						||
| 
								 | 
							
								% 'chr via_1'( _, V) :- global_term_ref_1( V).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								'chr via_2'(X,Y,V) :- 
							 | 
						||
| 
								 | 
							
									( var(X) -> 
							 | 
						||
| 
								 | 
							
										X = V
							 | 
						||
| 
								 | 
							
									; var(Y) ->
							 | 
						||
| 
								 | 
							
										Y = V
							 | 
						||
| 
								 | 
							
									; compound(X), nonground(X,V) ->
							 | 
						||
| 
								 | 
							
										true
							 | 
						||
| 
								 | 
							
									; compound(Y), nonground(Y,V) ->
							 | 
						||
| 
								 | 
							
										true
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
										global_term_ref_1(V)
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								% 'chr via_2'( X, _, V) :- var(X), !, X=V.
							 | 
						||
| 
								 | 
							
								% 'chr via_2'( _, Y, V) :- var(Y), !, Y=V.
							 | 
						||
| 
								 | 
							
								% 'chr via_2'( T, _, V) :- compound(T), nonground( T, V), ! .
							 | 
						||
| 
								 | 
							
								% 'chr via_2'( _, T, V) :- compound(T), nonground( T, V), ! .
							 | 
						||
| 
								 | 
							
								% 'chr via_2'( _, _, V) :- global_term_ref_1( V).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% The second arg is a witness.
							 | 
						||
| 
								 | 
							
								% The formulation with term_variables/2 is
							 | 
						||
| 
								 | 
							
								% cycle safe, but it finds a list of all vars.
							 | 
						||
| 
								 | 
							
								% We need only one, and no list in particular.
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								'chr via'(L,V) :-
							 | 
						||
| 
								 | 
							
									( nonground(L,V) ->
							 | 
						||
| 
								 | 
							
										true
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
										global_term_ref_1(V)
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								nonground( Term, V) :-
							 | 
						||
| 
								 | 
							
									term_variables( Term, Vs),
							 | 
						||
| 
								 | 
							
									Vs = [V|_].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								'chr novel_production'( Self, Tuple) :-
							 | 
						||
| 
								 | 
							
									arg( 5, Self, Ref),
							 | 
						||
| 
								 | 
							
									Ref = mutable(History), % get_mutable( History, Ref), % XXX Inlined
							 | 
						||
| 
								 | 
							
									( get_assoc( Tuple, History, _) ->
							 | 
						||
| 
								 | 
							
									    fail
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									    true
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% Not folded with novel_production/2 because guard checking
							 | 
						||
| 
								 | 
							
								% goes in between the two calls.
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								'chr extend_history'( Self, Tuple) :-
							 | 
						||
| 
								 | 
							
									arg( 5, Self, Ref),
							 | 
						||
| 
								 | 
							
									Ref = mutable(History), % get_mutable( History, Ref), % XXX Inlined
							 | 
						||
| 
								 | 
							
									put_assoc( Tuple, History, x, NewHistory),
							 | 
						||
| 
								 | 
							
									update_mutable( NewHistory, Ref).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								constraint_generation( Susp, State, Generation) :-
							 | 
						||
| 
								 | 
							
									arg( 2, Susp, Mref),
							 | 
						||
| 
								 | 
							
									Mref = mutable(State), % get_mutable( State, Mref), % XXX Inlined
							 | 
						||
| 
								 | 
							
									arg( 4, Susp, Gref),
							 | 
						||
| 
								 | 
							
									Gref = mutable(Generation). % get_mutable( Generation, Gref). 	% not incremented meanwhile % XXX Inlined
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								'chr allocate_constraint'( Closure, Self, F, Args) :-
							 | 
						||
| 
								 | 
							
									'chr empty_history'( History),
							 | 
						||
| 
								 | 
							
									create_mutable( passive(Args), Mref),
							 | 
						||
| 
								 | 
							
									create_mutable( 0, Gref),
							 | 
						||
| 
								 | 
							
									create_mutable( History, Href),
							 | 
						||
| 
								 | 
							
									'chr gen_id'( Id),
							 | 
						||
| 
								 | 
							
									Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% 'chr activate_constraint'( -, +, -).
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% The transition gc->active should be rare
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								'chr activate_constraint'( Vars, Susp, Generation) :-
							 | 
						||
| 
								 | 
							
									arg( 2, Susp, Mref),
							 | 
						||
| 
								 | 
							
									Mref = mutable(State), % get_mutable( State, Mref),  % XXX Inlined
							 | 
						||
| 
								 | 
							
									update_mutable( active, Mref),
							 | 
						||
| 
								 | 
							
									( nonvar(Generation) ->			% aih
							 | 
						||
| 
								 | 
							
									    true
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									    arg( 4, Susp, Gref),
							 | 
						||
| 
								 | 
							
									    Gref = mutable(Gen), % get_mutable( Gen, Gref), % XXX Inlined
							 | 
						||
| 
								 | 
							
									    Generation is Gen+1,
							 | 
						||
| 
								 | 
							
									    update_mutable( Generation, Gref)
							 | 
						||
| 
								 | 
							
									),
							 | 
						||
| 
								 | 
							
									( compound(State) ->			% passive/1
							 | 
						||
| 
								 | 
							
									    term_variables( State, Vs),
							 | 
						||
| 
								 | 
							
									    'chr none_locked'( Vs),
							 | 
						||
| 
								 | 
							
									    global_term_ref_1( Global),
							 | 
						||
| 
								 | 
							
									    Vars = [Global|Vs]
							 | 
						||
| 
								 | 
							
									; State==removed ->			% the price for eager removal ...
							 | 
						||
| 
								 | 
							
									    Susp =.. [_,_,_,_,_,_,_|Args],
							 | 
						||
| 
								 | 
							
									    term_variables( Args, Vs),
							 | 
						||
| 
								 | 
							
									    global_term_ref_1( Global),
							 | 
						||
| 
								 | 
							
									    Vars = [Global|Vs]
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									    Vars = []
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								'chr insert_constraint_internal'( [Global|Vars], Self, Closure, F, Args) :-
							 | 
						||
| 
								 | 
							
									term_variables( Args, Vars),
							 | 
						||
| 
								 | 
							
									'chr none_locked'( Vars),
							 | 
						||
| 
								 | 
							
									global_term_ref_1( Global),
							 | 
						||
| 
								 | 
							
									'chr empty_history'( History),
							 | 
						||
| 
								 | 
							
									create_mutable( active, Mref),
							 | 
						||
| 
								 | 
							
									create_mutable( 0, Gref),
							 | 
						||
| 
								 | 
							
									create_mutable( History, Href),
							 | 
						||
| 
								 | 
							
									'chr gen_id'( Id),
							 | 
						||
| 
								 | 
							
									Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								insert_constraint_internal( [Global|Vars], Self, Term, Closure, F, Args) :-
							 | 
						||
| 
								 | 
							
									term_variables( Term, Vars),
							 | 
						||
| 
								 | 
							
									'chr none_locked'( Vars),
							 | 
						||
| 
								 | 
							
									global_term_ref_1( Global),
							 | 
						||
| 
								 | 
							
									'chr empty_history'( History),
							 | 
						||
| 
								 | 
							
									create_mutable( active, Mref),
							 | 
						||
| 
								 | 
							
									create_mutable( 0, Gref),
							 | 
						||
| 
								 | 
							
									create_mutable( History, Href),
							 | 
						||
| 
								 | 
							
									'chr gen_id'( Id),
							 | 
						||
| 
								 | 
							
									Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								change_state( Susp, State) :-
							 | 
						||
| 
								 | 
							
									arg( 2, Susp, Mref),
							 | 
						||
| 
								 | 
							
									update_mutable( State, Mref).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								'chr empty_history'( E) :- empty_assoc( E).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								'chr gen_id'( Id) :-
							 | 
						||
| 
								 | 
							
									incval( id, Id).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								incval(id,Id) :-
							 | 
						||
| 
								 | 
							
									nb_getval(id,Id),
							 | 
						||
| 
								 | 
							
									NextId is Id + 1,
							 | 
						||
| 
								 | 
							
									nb_setval(id,NextId).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								create_mutable(V,mutable(V)).
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								'chr get_mutable'(V, mutable(V)).  
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								'chr update_mutable'(V,M) :-
							 | 
						||
| 
								 | 
							
									setarg(1,M,V).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								get_mutable(V, mutable(V)).  
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								update_mutable(V,M) :-
							 | 
						||
| 
								 | 
							
									setarg(1,M,V).
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								'chr global_term_ref_1'(X) :-
							 | 
						||
| 
								 | 
							
									global_term_ref_1(X).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								global_term_ref_1(X) :-
							 | 
						||
| 
								 | 
							
									nb_getval(chr_global,X).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								'chr sbag_member'( Element, [Head|Tail]) :-
							 | 
						||
| 
								 | 
							
								      sbag_member( Element, Tail, Head).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								% auxiliary to avoid choicepoint for last element
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								sbag_member( E, _,	     E).
							 | 
						||
| 
								 | 
							
								sbag_member( E, [Head|Tail], _) :-
							 | 
						||
| 
								 | 
							
									sbag_member( E, Tail, Head).
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								'chr sbag_del_element'( [],	  _,	[]).
							 | 
						||
| 
								 | 
							
								'chr sbag_del_element'( [X|Xs], Elem, Set2) :-
							 | 
						||
| 
								 | 
							
									( X==Elem ->
							 | 
						||
| 
								 | 
							
									    Set2 = Xs
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									    Set2 = [X|Xss],
							 | 
						||
| 
								 | 
							
									    'chr sbag_del_element'( Xs, Elem, Xss)
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								sbag_union( A, B, C) :-
							 | 
						||
| 
								 | 
							
									sbag_merge( A, B, C).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								sbag_merge([],Ys,Ys).
							 | 
						||
| 
								 | 
							
								sbag_merge([X | Xs],YL,R) :-
							 | 
						||
| 
								 | 
							
								  ( YL = [Y | Ys] ->
							 | 
						||
| 
								 | 
							
								      arg(1,X,XId),
							 | 
						||
| 
								 | 
							
								      arg(1,Y,YId),	
							 | 
						||
| 
								 | 
							
								       ( XId < YId ->
							 | 
						||
| 
								 | 
							
								           R = [X | T],
							 | 
						||
| 
								 | 
							
								           sbag_merge(Xs,YL,T)
							 | 
						||
| 
								 | 
							
								       ; XId > YId ->
							 | 
						||
| 
								 | 
							
								           R = [Y | T],
							 | 
						||
| 
								 | 
							
								           sbag_merge([X|Xs],Ys,T)
							 | 
						||
| 
								 | 
							
								       ;
							 | 
						||
| 
								 | 
							
								           R = [X | T],
							 | 
						||
| 
								 | 
							
								           sbag_merge(Xs,Ys,T)
							 | 
						||
| 
								 | 
							
								       )    
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								       R = [X | Xs]
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:- multifile
							 | 
						||
| 
								 | 
							
									chr:debug_event/2,		% +State, +Event
							 | 
						||
| 
								 | 
							
									chr:debug_interact/3.		% +Event, +Depth, -Command
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								'chr debug_event'(Event) :-
							 | 
						||
| 
								 | 
							
									nb_getval(chr_debug,mutable(State)),
							 | 
						||
| 
								 | 
							
									( State == off ->
							 | 
						||
| 
								 | 
							
										true
							 | 
						||
| 
								 | 
							
									; chr:debug_event(State, Event) ->
							 | 
						||
| 
								 | 
							
										true
							 | 
						||
| 
								 | 
							
									; 	debug_event(State,Event)
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								chr_trace :-
							 | 
						||
| 
								 | 
							
									nb_setval(chr_debug,mutable(trace)).
							 | 
						||
| 
								 | 
							
								chr_notrace :-
							 | 
						||
| 
								 | 
							
									nb_setval(chr_debug,mutable(off)).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%	chr_leash(+Spec)
							 | 
						||
| 
								 | 
							
								%	
							 | 
						||
| 
								 | 
							
								%	Define the set of ports at which we prompt for user interaction
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								chr_leash(Spec) :-
							 | 
						||
| 
								 | 
							
									leashed_ports(Spec, Ports),
							 | 
						||
| 
								 | 
							
									nb_setval(chr_leash,mutable(Ports)).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								leashed_ports(none, []).
							 | 
						||
| 
								 | 
							
								leashed_ports(off,  []).
							 | 
						||
| 
								 | 
							
								leashed_ports(all,  [call, exit, redo, fail, wake, try, apply, insert, remove]).
							 | 
						||
| 
								 | 
							
								leashed_ports(default, [call,exit,fail,wake,apply]).
							 | 
						||
| 
								 | 
							
								leashed_ports(One, Ports) :-
							 | 
						||
| 
								 | 
							
									atom(One), One \== [], !,
							 | 
						||
| 
								 | 
							
									leashed_ports([One], Ports).
							 | 
						||
| 
								 | 
							
								leashed_ports(Set, Ports) :-
							 | 
						||
| 
								 | 
							
									sort(Set, Ports),		% make unique
							 | 
						||
| 
								 | 
							
									leashed_ports(all, All),
							 | 
						||
| 
								 | 
							
									valid_ports(Ports, All).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								valid_ports([], _).
							 | 
						||
| 
								 | 
							
								valid_ports([H|T], Valid) :-
							 | 
						||
| 
								 | 
							
									(   memberchk(H, Valid)
							 | 
						||
| 
								 | 
							
									->  true
							 | 
						||
| 
								 | 
							
									;   throw(error(domain_error(chr_port, H), _))
							 | 
						||
| 
								 | 
							
									),
							 | 
						||
| 
								 | 
							
									valid_ports(T, Valid).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:- initialization
							 | 
						||
| 
								 | 
							
								   leashed_ports(default, Ports),
							 | 
						||
| 
								 | 
							
								   nb_setval(chr_leash, mutable(Ports)).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%	debug_event(+State, +Event)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%debug_event(trace, Event) :-
							 | 
						||
| 
								 | 
							
								%	functor(Event, Name, Arity),
							 | 
						||
| 
								 | 
							
								%	writeln(Name/Arity), fail.
							 | 
						||
| 
								 | 
							
								debug_event(trace,Event) :- 
							 | 
						||
| 
								 | 
							
									Event = call(_), !,
							 | 
						||
| 
								 | 
							
									get_debug_history(History,Depth),
							 | 
						||
| 
								 | 
							
									NDepth is Depth + 1,
							 | 
						||
| 
								 | 
							
									chr_debug_interact(Event,NDepth), 
							 | 
						||
| 
								 | 
							
									set_debug_history([Event|History],NDepth).
							 | 
						||
| 
								 | 
							
								debug_event(trace,Event) :- 
							 | 
						||
| 
								 | 
							
									Event = wake(_), !,
							 | 
						||
| 
								 | 
							
									get_debug_history(History,Depth),
							 | 
						||
| 
								 | 
							
									NDepth is Depth + 1,
							 | 
						||
| 
								 | 
							
									chr_debug_interact(Event,NDepth), 
							 | 
						||
| 
								 | 
							
									set_debug_history([Event|History],NDepth).
							 | 
						||
| 
								 | 
							
								debug_event(trace,Event) :-
							 | 
						||
| 
								 | 
							
									Event = redo(_), !,
							 | 
						||
| 
								 | 
							
									get_debug_history(_History, Depth),
							 | 
						||
| 
								 | 
							
									chr_debug_interact(Event, Depth).
							 | 
						||
| 
								 | 
							
								debug_event(trace,Event) :- 
							 | 
						||
| 
								 | 
							
									Event = exit(_),!,
							 | 
						||
| 
								 | 
							
									get_debug_history([_|History],Depth),
							 | 
						||
| 
								 | 
							
									chr_debug_interact(Event,Depth),
							 | 
						||
| 
								 | 
							
									NDepth is Depth - 1,
							 | 
						||
| 
								 | 
							
									set_debug_history(History,NDepth). 
							 | 
						||
| 
								 | 
							
								debug_event(trace,Event) :- 
							 | 
						||
| 
								 | 
							
									Event = fail(_),!,
							 | 
						||
| 
								 | 
							
									get_debug_history(_,Depth),
							 | 
						||
| 
								 | 
							
									chr_debug_interact(Event,Depth). 
							 | 
						||
| 
								 | 
							
								debug_event(trace, Event) :-
							 | 
						||
| 
								 | 
							
									Event = remove(_), !,
							 | 
						||
| 
								 | 
							
									get_debug_history(_,Depth),
							 | 
						||
| 
								 | 
							
									chr_debug_interact(Event, Depth).
							 | 
						||
| 
								 | 
							
								debug_event(trace, Event) :-
							 | 
						||
| 
								 | 
							
									Event = insert(_), !,
							 | 
						||
| 
								 | 
							
									get_debug_history(_,Depth),
							 | 
						||
| 
								 | 
							
									chr_debug_interact(Event, Depth).
							 | 
						||
| 
								 | 
							
								debug_event(trace, Event) :-
							 | 
						||
| 
								 | 
							
									Event = try(_,_,_,_), !,
							 | 
						||
| 
								 | 
							
									get_debug_history(_,Depth),
							 | 
						||
| 
								 | 
							
									chr_debug_interact(Event, Depth).
							 | 
						||
| 
								 | 
							
								debug_event(trace, Event) :- 
							 | 
						||
| 
								 | 
							
									Event = apply(_,_,_,_), !,
							 | 
						||
| 
								 | 
							
									get_debug_history(_,Depth),
							 | 
						||
| 
								 | 
							
									chr_debug_interact(Event,Depth). 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								debug_event(skip(_,_),Event) :- 
							 | 
						||
| 
								 | 
							
									Event = call(_), !,
							 | 
						||
| 
								 | 
							
									get_debug_history(History,Depth),
							 | 
						||
| 
								 | 
							
									NDepth is Depth + 1,
							 | 
						||
| 
								 | 
							
									set_debug_history([Event|History],NDepth).
							 | 
						||
| 
								 | 
							
								debug_event(skip(_,_),Event) :- 
							 | 
						||
| 
								 | 
							
									Event = wake(_), !,
							 | 
						||
| 
								 | 
							
									get_debug_history(History,Depth),
							 | 
						||
| 
								 | 
							
									NDepth is Depth + 1,
							 | 
						||
| 
								 | 
							
									set_debug_history([Event|History],NDepth).
							 | 
						||
| 
								 | 
							
								debug_event(skip(SkipSusp,SkipDepth),Event) :- 
							 | 
						||
| 
								 | 
							
									Event = exit(Susp),!,
							 | 
						||
| 
								 | 
							
									get_debug_history([_|History],Depth),
							 | 
						||
| 
								 | 
							
									( SkipDepth == Depth,
							 | 
						||
| 
								 | 
							
									  SkipSusp == Susp -> 
							 | 
						||
| 
								 | 
							
										set_chr_debug(trace),
							 | 
						||
| 
								 | 
							
										chr_debug_interact(Event,Depth)
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
										true
							 | 
						||
| 
								 | 
							
									),
							 | 
						||
| 
								 | 
							
									NDepth is Depth - 1,
							 | 
						||
| 
								 | 
							
									set_debug_history(History,NDepth). 
							 | 
						||
| 
								 | 
							
								debug_event(skip(_,_),_) :- !,
							 | 
						||
| 
								 | 
							
									true.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%	chr_debug_interact(+Event, +Depth)
							 | 
						||
| 
								 | 
							
								%	
							 | 
						||
| 
								 | 
							
								%	Interact with the user on Event that took place at Depth.  First
							 | 
						||
| 
								 | 
							
								%	calls chr:debug_interact(+Event, +Depth, -Command) hook. If this
							 | 
						||
| 
								 | 
							
								%	fails the event is printed and the system prompts for a command.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								chr_debug_interact(Event, Depth) :-
							 | 
						||
| 
								 | 
							
									chr:debug_interact(Event, Depth, Command), !,
							 | 
						||
| 
								 | 
							
									handle_debug_command(Command,Event,Depth).
							 | 
						||
| 
								 | 
							
								chr_debug_interact(Event, Depth) :-
							 | 
						||
| 
								 | 
							
									print_event(Event, Depth),
							 | 
						||
| 
								 | 
							
									(   leashed(Event)
							 | 
						||
| 
								 | 
							
									->  ask_continue(Command)
							 | 
						||
| 
								 | 
							
									;   Command = creep
							 | 
						||
| 
								 | 
							
									),
							 | 
						||
| 
								 | 
							
									handle_debug_command(Command,Event,Depth).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								leashed(Event) :-
							 | 
						||
| 
								 | 
							
									functor(Event, Port, _),
							 | 
						||
| 
								 | 
							
									nb_getval(chr_leash, mutable(Ports)),
							 | 
						||
| 
								 | 
							
									memberchk(Port, Ports).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ask_continue(Command) :-
							 | 
						||
| 
								 | 
							
									print_message(debug, chr(prompt)),
							 | 
						||
| 
								 | 
							
									get_single_char(CharCode),
							 | 
						||
| 
								 | 
							
									(   CharCode == -1
							 | 
						||
| 
								 | 
							
									->  Char = end_of_file
							 | 
						||
| 
								 | 
							
									;   char_code(Char, CharCode)
							 | 
						||
| 
								 | 
							
									),
							 | 
						||
| 
								 | 
							
									(   debug_command(Char, Command)
							 | 
						||
| 
								 | 
							
									->  print_message(debug, chr(command(Command)))
							 | 
						||
| 
								 | 
							
									;   print_message(help, chr(invalid_command)),
							 | 
						||
| 
								 | 
							
									    ask_continue(Command)
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								'chr debug command'(Char, Command) :-
							 | 
						||
| 
								 | 
							
									debug_command(Char, Command).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								debug_command(c, creep).
							 | 
						||
| 
								 | 
							
								debug_command(' ', creep).
							 | 
						||
| 
								 | 
							
								debug_command('\r', creep).
							 | 
						||
| 
								 | 
							
								debug_command(s, skip).
							 | 
						||
| 
								 | 
							
								debug_command(g, ancestors).
							 | 
						||
| 
								 | 
							
								debug_command(n, nodebug).
							 | 
						||
| 
								 | 
							
								debug_command(a, abort).
							 | 
						||
| 
								 | 
							
								debug_command(f, fail).
							 | 
						||
| 
								 | 
							
								debug_command(b, break).
							 | 
						||
| 
								 | 
							
								debug_command(?, help).
							 | 
						||
| 
								 | 
							
								debug_command(h, help).
							 | 
						||
| 
								 | 
							
								debug_command(end_of_file, exit).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								handle_debug_command(creep,_,_) :- !.
							 | 
						||
| 
								 | 
							
								handle_debug_command(skip, Event, Depth) :- !,
							 | 
						||
| 
								 | 
							
									Event =.. [Type|Rest],
							 | 
						||
| 
								 | 
							
									( Type \== call,
							 | 
						||
| 
								 | 
							
									  Type \== wake ->
							 | 
						||
| 
								 | 
							
										handle_debug_command('c',Event,Depth)
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
										Rest = [Susp],
							 | 
						||
| 
								 | 
							
										set_chr_debug(skip(Susp,Depth))
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								handle_debug_command(ancestors,Event,Depth) :- !,
							 | 
						||
| 
								 | 
							
									print_chr_debug_history,
							 | 
						||
| 
								 | 
							
									chr_debug_interact(Event,Depth).	
							 | 
						||
| 
								 | 
							
								handle_debug_command(nodebug,_,_) :- !,
							 | 
						||
| 
								 | 
							
									chr_notrace.
							 | 
						||
| 
								 | 
							
								handle_debug_command(abort,_,_) :- !,
							 | 
						||
| 
								 | 
							
									abort.
							 | 
						||
| 
								 | 
							
								handle_debug_command(exit,_,_) :- !,
							 | 
						||
| 
								 | 
							
									halt.
							 | 
						||
| 
								 | 
							
								handle_debug_command(fail,_,_) :- !,
							 | 
						||
| 
								 | 
							
									fail.
							 | 
						||
| 
								 | 
							
								handle_debug_command(break,Event,Depth) :- !,
							 | 
						||
| 
								 | 
							
									break,
							 | 
						||
| 
								 | 
							
									chr_debug_interact(Event,Depth).
							 | 
						||
| 
								 | 
							
								handle_debug_command(help,Event,Depth) :- !,
							 | 
						||
| 
								 | 
							
									print_message(help, chr(debug_options)),
							 | 
						||
| 
								 | 
							
									chr_debug_interact(Event,Depth).	
							 | 
						||
| 
								 | 
							
								handle_debug_command(Cmd, _, _) :- 
							 | 
						||
| 
								 | 
							
									throw(error(domain_error(chr_debug_command, Cmd), _)).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								print_chr_debug_history :-
							 | 
						||
| 
								 | 
							
									get_debug_history(History,Depth),
							 | 
						||
| 
								 | 
							
									print_message(debug, chr(ancestors(History, Depth))).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								print_event(Event, Depth) :-
							 | 
						||
| 
								 | 
							
									print_message(debug, chr(event(Event, Depth))).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%	{set,get}_debug_history(Ancestors, Depth)
							 | 
						||
| 
								 | 
							
								%	
							 | 
						||
| 
								 | 
							
								%	Set/get the list of ancestors and the depth of the current goal.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								get_debug_history(History,Depth) :-
							 | 
						||
| 
								 | 
							
									nb_getval(chr_debug_history,mutable(History,Depth)).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								set_debug_history(History,Depth) :-
							 | 
						||
| 
								 | 
							
									nb_getval(chr_debug_history,Mutable),
							 | 
						||
| 
								 | 
							
									setarg(1,Mutable,History),
							 | 
						||
| 
								 | 
							
									setarg(2,Mutable,Depth).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								set_chr_debug(State) :-
							 | 
						||
| 
								 | 
							
									nb_getval(chr_debug,Mutable),
							 | 
						||
| 
								 | 
							
									setarg(1,Mutable,State).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								'chr chr_indexed_variables'(Susp,Vars) :-
							 | 
						||
| 
								 | 
							
								        Susp =.. [_,_,_,_,_,_,_|Args],
							 | 
						||
| 
								 | 
							
									term_variables(Args,Vars).
							 |