%
% module filtering empty-slots from a CSP expression
%
:- module(filter_empty_slot,[filter_empty_slot/3]).

:- use_module('../../prolog/util/prolog_detect').
:- prolog_detect:prolog(Prolog),
	(	(	Prolog=sicstus,
			use_module(library(lists))
		);
		Prolog=swi;
		Prolog=eclipse;
		(	write('*** unsupported Prolog system***'),
			nl,
			fail
		)
	).
:- use_module('../../prolog/util/cif_util').


%
% filter_empty_slot/3
%
% remove empty-slots from a CIF expression
% (including group/2)
%
% filter_empty_slot(+Cif,+Empty_slots,-Filtered)
%
% Cif		=	the CIF for filtering
% Empty_slots	=	a list of empty-slot templates
% Filtered	=	the filtered CIF
%

filter_empty_slot(Cif,Empty_slots,Filtered) :-
	filter_can_unify(Cif,Empty_slots,Filtered).


%
% filter_can_unify/3
%
% filter any term which can unify with some templates
%
% filter_can_unify(+Orig,+Templates,-Filtered)
%
% Orig		=	the original expression
% Templates	=	a list of template (w/ uninstantiated vars)
% Filtered	=	the filtered expression
%

%
% nothing to filter
%
filter_can_unify(Cif,[],Cif) :-
	!.

%
% an empty-list
%
filter_can_unify([],_,[]) :-
	!.

%
% a group/2
%
filter_can_unify(Cif,Templates,Filtered) :-
	Cif=group(Vars,In_group),
	!,
	filter_can_unify(In_group,Templates,In_group_filtered),
	Filtered=group(Vars,In_group_filtered).


%
% if head of list can unify w/ a template
% remove it from the result
%
filter_can_unify([C|Cs],Templates,Filtered) :-
	member(E,Templates),			%there is an empty-slot
	can_unify(C,E),				%which can unify with C
	!,
	filter_can_unify(Cs,Templates,Filtered).

%
% otherwise, recursively work on each element
% (NOTE: if C cannot unify w/ any template, it will be returned as F)
%
filter_can_unify([C|Cs],Templates,[F|Fs]) :-
	!,
	filter_can_unify(C,Templates,F),
	filter_can_unify(Cs,Templates,Fs).

%
% any other term
%
filter_can_unify(Cif,Templates,Filtered) :-
	functor(Cif,_,Arity),
	Arity>0,
	Cif =.. [Functor|Args],
	!,
	filter_can_unify(Functor,Templates,Filtered_functor),
	filter_can_unify(Args,Templates,Filtered_args),
	Filtered =.. [Filtered_functor|Filtered_args].

%
% C cannot unify with any template
%
filter_can_unify(C,_,C) :-
	!.


%
% can_unify/2
%
% test unifiability of 2 terms but not unifying them
%
can_unify(A,B) :-
	copy_term(A,A_clone),   %make a copy of A
	copy_term(B,B_clone),   %make a copy of A
	A_clone=B_clone.        %unifying the copy with B

