%
% this module generates ECLiPSe codes for a fused list of CIF
% it doesn't, however, interacts with ECLiPSe
% All interactions are left to the CPE-M
%

%:- module(eclipse_gen,[generate_eclipse_code/3]).

:- use_module('../../prolog/util/is_daplex_variable').
:- use_module('../../prolog/util/cif_util').


%
% ECLiPSe operator definitions
%

:- op(800,xfx,infers).
:- op(700,xfx,#=).
:- op(700,xfx,#<).
:- op(700,xfx,#>).
:- op(700,xfx,#<=).
:- op(700,xfx,#>=).
:- op(700,xfx,#\=).
:- op(900,fx,~).
:- op(500,xfx,::).
:- op(400,xfx,..).


%
% print generated code
%

dump_code([]).

dump_code([(Head:-Body)|Cs]) :-
	!,
	write(Head),
	write(' :-'),
	nl,
	dump_body(Body),
	dump_code(Cs).

dump_code([C|Cs]) :-
	write(C),
	write('.'),
	nl,
	dump_code(Cs).

dump_body((C,Cs)) :-
	!,
	write('        '),
	write(C),
	write(','),
	nl,
	dump_body(Cs).

dump_body(C) :-
	write('        '),
	write(C),
	write('.'),
	nl.

/*
dump_body(C) :-
	dump_body(1,C).

dump_body(0,C) :-
	C=(X,Y),
	dump_code(N,X),
	write(','),
	nl,
	dump_body(Y).

dump_body(N,C) :-
	N > 0,
	write('    '),
	M is N-1,
	dump_body(M,C).
*/



%========================================================================
%
% generate_eclipse_code/3
%
% given a list of groups & links, generate the corresponding ECLiPSe code
%
% generate_eclipse_code(Groups,Links,Codes)
%
% Groups	=	list of group/2 for code generation
% Links		=	list of var unification links in var1:var2 format
% Codes		=	the generated ECLiPSe code
%
%========================================================================

generate_eclipse_code(Groups,_,Codes) :-
	find_var_types(Groups,Var_types),					%find all vars w/ type
	generate_declare_clause(Var_types,Shared,Declare),			%generate the domain declaration calls
	generate_posting_clause(Groups,Shared,Post),				%generate ECLiPSe codes for CIF groups
%	generate_link_clause(Links,Shared,Link),				%and the links
	Invoke=(	solve(Vars) :-	(	declare_vars(Vars),
						post_constraints(Vars),
					%	post_links(Vars),
						label_vars(Vars)
					)
		),
%	my_append([Invoke,Declare,Post,Link],Codes).				%concate all clauses together
	my_append([Invoke,Declare,Post],Codes).				%concate all clauses together
/*
%	my_append([Invoke,Declare],Post,Codes).					%put them all into a list
	my_append([Invoke,Declare],Post,Temp),					%put them all into a list
	my_append(Temp,Link,Codes).
*/



%==============================================================
%
% generate_declare_clause/3
%
% given a list of groups
% find all vars and return them as a daplex:prolog pair list
% and generate predicate calls for domain formation
%
% generate_declare_clause(+Var_types,+Shared,-Clause)
%
% Var_types	=	a list of Daplex:Type pairs
% Shared	=	the shared var of Daplex:Prolog var
% Clause	=	the returned clause for var declaration
%
%==============================================================

generate_declare_clause(Var_types,Shared,Clause) :-
	Head=declare_vars(Shared),				%the head of the clause
	Body=(	All_vars=Var_types,				%the body
		declare_vars(All_vars,Shared)			%call declare_vars/2 in "eclipse_stdlib"
		),
	Clause=(Head :- Body).


%====================================================================
%
% generate_posting_clause/3
%
% generate clauses to post constraints and the clause that calls them
%
% generate_posting_clause(+Groups,+Shared,-Clauses)
%
% Groups	=	list of groups in group/2
% Shared	=	the shared var containing Daplex:Prolog pairs
% Clauses	=	a list of generated clause to post constraints
%			including the top level posting clause
%			and all other
%
%====================================================================

generate_posting_clause(Groups,Shared,Clauses) :-
	initialize_counter(posting_clause),				%init the "posting_clause" counter to 1
	generate_posting_clause(Groups,Shared,Post_clauses,Calls),	%generate clauses to post constraints
	Calling_clause=(post_constraints(Shared) :- Calls),		%the predicate calls to post these constraints
	Clauses=[Calling_clause|Post_clauses].				%put in the calling clause too


%
% generate_posting_clause/4
%
% given a list of groups, generate clauses to post constraints
% also returning the require predicate calls
%
% generate_posting_clause(+Groups,+Shared,-Clauses,-Calls)
%
% Groups	=	a group in group/2
% Shared	=	the shared var of daplex:prolog pairs
% Clauses	=	the generated clauses from these groups
% Calls		=	the call to invoke these clauses
%

%
% a singleton list
%
% *** to fix a bug discovered by Stuart, 13/08/01
%
generate_posting_clause([G],Shared,Clause,Call) :-
	!,
	generate_cif_code(G,Shared,Body),				%generate code of G as the body
	generate_counter(posting_clause,Count),
%	functor(Head,post_constraint,2),
%	arg(1,Head,Count),
%	arg(2,Head,Shared),
	Head=post_constraint(Count,Shared),
	Clause=[(Head :- Body)],
	Call=Head.							%the way to invoke this clause

%
% a list of groups
%
% *** to fix a bug discovered by Stuart, 13/08/01
%
generate_posting_clause([G|Gs],Shared,[Clause|Clauses],(Call,Calls)) :-
	generate_cif_code(G,Shared,Body),				%generate code of G as the body
%	generate_counter(posting_clause,'post_constraint_',Functor),	%get clause's functor
%	functor(Head,Functor,1),					%construct term
%	arg(1,Head,Shared),
	generate_counter(posting_clause,Count),
	Head=post_constraint(Count,Shared),
	Clause=(Head :- Body),
	Call=Head,							%the way to invoke this clause
	generate_posting_clause(Gs,Shared,Clauses,Calls).		%proceed w/ remaining groups





%
% given a CIF/a list of CIF construct, generate the corresponding ECLiPSe code
%

%
% group/2
%
generate_cif_code(group(_,Cif),Shared,Code) :-
	generate_cif_code(Cif,Shared,Code).		%take the CIF and generate code for it


%
% an empty list
%
% NOTE:	We shouldn't hit an empty list but in case we do,
%	just return a "true".
%
generate_cif_code([],_,true) :-
	!.

%
% a singleton list of groups
% NOTE:	we don't want to generate anything for an empty list
%	so we stop when hitting a singleton list
%
generate_cif_code([G],Shared,Code) :-
	!,
	generate_cif_code(G,Shared,Code).			%get the construct and gen the code for it

%
% a list of group
%
generate_cif_code([C|Cs],Shared,Code) :-
	!,
	generate_cif_code(C,Shared,C_code),			%gen code for 1st CIF
	generate_cif_code(Cs,Shared,Cs_code),			%gen code for the rest
	Code=(C_code,Cs_code).


%:::::::::::::::::::::::::::::::::::::::::::::::::::
% generate ECLiPSe code for different CIF constructs
%:::::::::::::::::::::::::::::::::::::::::::::::::::

%
% for most construct, we generate the "constraint" version by default
%

/*
%
% restrict_subquery/3 with some/1
%
generate_cif_code(C,Shared,Code) :-
	C=restrict_subquery(some(Vs),G,P),
	!,
	V_code=(find_prolog_var(Vs,Shared,Prolog)),		%find Prolog vars from Shared daplex:prolog list
	generate_testing_code(G,Shared,G_code),
	generate_constraint_code(P,Shared,P_code),
	Code=(	V_code,
		exist(Prolog,G_code,P_code)
	).
%	Code=(if_then_else(G_code,P_code,true)).

%
% restrict_subquery/3 with all/1
%
generate_cif_code(C,Shared,Code) :-
	C=restrict_subquery(all(Vs),G,P),
	!,
	V_code=(find_prolog_var(Vs,Shared,Prolog)),		%find Prolog vars from Shared daplex:prolog list
	generate_testing_code(G,Shared,G_code),
	negate_cif(P,Negated_p),
%	write(Negated_p),
%	nl,
	generate_constraint_code(Negated_p,Shared,Negated_p_code),
	Code=(	V_code,
		all_violate(Prolog,G_code,Negated_p_code)
	).
%	Code=(if_then_else(G_code,P_code,true)).
*/

%
% all others
%

%
% by default, generate the constraint version code
%
generate_cif_code(C,Shared,Code) :-
	generate_constraint_code(C,Shared,Code).


%:::::::::::::::::::::::::::::::::::::::::::::::
% generate constraint codes (active constraints)
%:::::::::::::::::::::::::::::::::::::::::::::::

%
% a singleton list
%
generate_constraint_code([C],Shared,Code) :-
	generate_constraint_code(C,Shared,Code).

%
% a list of CIF
%
generate_constraint_code([C|Cs],Shared,(Code,Codes)) :-
	generate_constraint_code(C,Shared,Code),
	generate_constraint_code(Cs,Shared,Codes).

%
% restrict_subquery/3 with some/1
%
generate_constraint_code(C,Shared,Code) :-
	C=restrict_subquery(some(Vs),G,P),
	!,
	V_code=(find_prolog_var(Vs,Shared,Prolog_vars)),				%code to find Prolog vars
	split_can_unify(G,[generate(_,_),generate(_,_,_,_,_)],Base_gen_cif,Test_cif),	%find the basic-gen & test
	(	(	Test_cif=[],							%no testing condition
			!,
			generate_constraint_code(G,Shared,G_code),			%gen G code
			generate_constraint_code(P,Shared,P_code),			%gen P code
			Code=(	V_code,
				Gen=G_code,
				Pred=P_code,
				exist(Prolog_vars,Gen,Pred)
			)
		);
		(	generate_constraint_code(Base_gen_cif,Shared,Base_code),	%gen the basic G code
			generate_constraint_code(Test_cif,Shared,Test_code),		%gen the testing condition code
			generate_constraint_code(P,Shared,Then_code),			%gen P code
			find_vars(Test,Test_vars),					%find vars involved in the test
			Code=(	V_code,
				%
				% construct if_then_else here
				%
				find_prolog_var(Test_vars,Shared,Test_prolog_vars),	%bind Prolog vars
				Test=Test_code,						%the testing code
				Then=Then_code,						%the THEN code
				If_then_else_code=if_then_else(active,Test_prolog_vars,Test,Then,true),
				%
				% construct existential quantifier
				%
				Gen=Base_code,
				Pred=If_then_else_code,
				exist(Prolog_vars,Gen,Pred)
			)
		)
	).

/*
	C=restrict_subquery(some(Vs),G,P),
	!,
	V_code=(find_prolog_var(Vs,Shared,Prolog)),		%find Prolog vars from Shared daplex:prolog list
	generate_testing_code(G,Shared,G_code),
	generate_constraint_code(P,Shared,P_code),
	Code=(	V_code,
		Gen=G_code,
		Pred=P_code,
		exist(Prolog,Gen,Pred)
	).
*/


%
% restrict_subquery/3 with all/1
%
generate_constraint_code(C,Shared,Code) :-
	C=restrict_subquery(all(Vs),G,P),
	!,
	V_code=(find_prolog_var(Vs,Shared,Prolog_vars)),			%code to find Prolog vars
	split_can_unify(G,[generate(_,_),generate(_,_,_,_,_)],Base_gen_cif,Test_cif),	%find the basic-gen & test
	(	(	Test_cif=[],						%no testing condition
			!,
			generate_constraint_code(G,Shared,G_code),		%gen G code
			generate_constraint_code(P,Shared,P_code),		%gen P code
			Code=(	V_code,
				Gen=G_code,
				Pred=P_code,
				forall(Prolog_vars,Gen,Pred)
			)
		);
		(
			marker,
			generate_constraint_code(Base_gen_cif,Shared,Base_code),	%gen the basic G code
			generate_constraint_code(Test_cif,Shared,Test_code),		%gen the testing condition code
			generate_constraint_code(P,Shared,Then_code),			%gen P code
			find_vars(Test_cif,Test_vars),					%find vars involved in the test
			Code=(	V_code,
				%
				% construct if_then_else here
				%
				find_prolog_var(Test_vars,Shared,Test_prolog_vars),	%bind Prolog vars
				Test=Test_code,						%the testing code
				Then=Then_code,						%the THEN code
				If_then_else_code=if_then_else(active,Test_prolog_vars,Test,Then,true),
				%
				% construct existential quantifier
				%
				Gen=Base_code,
				Pred=If_then_else_code,
				forall(Prolog_vars,Gen,Pred)
			)
		)
	).





/*
	V_code=(find_prolog_var(Vs,Shared,Prolog)),		%find Prolog vars from Shared daplex:prolog list
	generate_testing_code(G,Shared,G_code),
%	write(Negated_p),
%	nl,
	generate_constraint_code(P,Shared,P_code),
	Code=(	V_code,
		Gen=G_code,
		Pred=P_code,
		forall(Prolog,Gen,Pred)
	).
*/
/*
	C=restrict_subquery(all(Vs),G,P),
	!,
	V_code=(find_prolog_var(Vs,Shared,Prolog)),		%find Prolog vars from Shared daplex:prolog list
	generate_testing_code(G,Shared,G_code),
	negate_cif(P,Negated_p),
%	write(Negated_p),
%	nl,
	generate_constraint_code(Negated_p,Shared,Negated_p_code),
	Code=(	V_code,
		Gen=G_code,
		Pred=Negated_p_code,
		all_violate(Prolog,Gen,Pred)
	).
*/

%
% generate/2
%
generate_constraint_code(C,Shared,Code) :-
	C=generate(Class,Var),
	!,
	Code=(	find_prolog_var(Var,Shared,Prolog),	%find Prolog var from Shared daplex:prolog list
		set_domain(Var,Class,Prolog)		%set its domain to class
		).

%
% generate/5
%
generate_constraint_code(C,Shared,Code) :-
	C=generate(Fname,Arg_types,Args,Type,Result),
	!,
	Code=(	find_prolog_var([Result|Args],Shared,[Prolog_result|Prolog_args]),
		fnval(Fname,Arg_types,Prolog_args,Type,Prolog_result) infers most
	).

%
% expr/3, binary comparison version
% both are Daplex var
%
generate_constraint_code(C,Shared,Code) :-
	C=expr(Op,Lhs,Rhs),
	Daplex_ops=[=,<,>,=<,>=,<>],			%a Daplex operator
	nth0(Index,Daplex_ops,Op),
	is_daplex_variable(Lhs),
	is_daplex_variable(Rhs),
	!,
	Eclipse_ops=[#=,#<,>#,#<=,#>=,#\=],			%map it into ECLiPSe's constraint operator
	nth0(Index,Eclipse_ops,Eclipse_op),
	functor(Compare_term,Eclipse_op,2),			%constructing the term
	arg(1,Compare_term,Lhs_prolog),
	arg(2,Compare_term,Rhs_prolog),
	Code=(	find_prolog_var(Lhs,Shared,Lhs_prolog),
		find_prolog_var(Rhs,Shared,Rhs_prolog),
		Compare_term
		).

generate_constraint_code(C,Shared,Code) :-
	C=expr(Op,Lhs,Rhs),
	Daplex_ops=[=,<,>,=<,>=,<>],			%a Daplex operator
	nth0(Index,Daplex_ops,Op),
	is_daplex_variable(Lhs),
	!,
	Eclipse_ops=[#=,#<,>#,#<=,#>=,#\=],			%map it into ECLiPSe's constraint operator
	nth0(Index,Eclipse_ops,Eclipse_op),
	functor(Compare_term,Eclipse_op,2),			%constructing the term
	arg(1,Compare_term,Lhs_prolog),
	arg(2,Compare_term,Rhs),
	Code=(	find_prolog_var(Lhs,Shared,Lhs_prolog),
		Compare_term
		).

generate_constraint_code(C,Shared,Code) :-
	C=expr(Op,Lhs,Rhs),
	Daplex_ops=[=,<,>,=<,>=,<>],			%a Daplex operator
	nth0(Index,Daplex_ops,Op),
	is_daplex_variable(Rhs),
	!,
	Eclipse_ops=[#=,#<,>#,#<=,#>=,#\=],			%map it into ECLiPSe's constraint operator
	nth0(Index,Eclipse_ops,Eclipse_op),
	functor(Compare_term,Eclipse_op,2),			%constructing the term
	arg(1,Compare_term,Lhs),
	arg(2,Compare_term,Rhs_prolog),
	Code=(	find_prolog_var(Rhs,Shared,Rhs_prolog),
		Compare_term
		).

generate_constraint_code(C,_,Code) :-
	C=expr(Op,Lhs,Rhs),
	Daplex_ops=[=,<,>,=<,>=,<>],			%a Daplex operator
	nth0(Index,Daplex_ops,Op),
	!,
	Eclipse_ops=[#=,#<,>#,#<=,#>=,#\=],			%map it into ECLiPSe's constraint operator
	nth0(Index,Eclipse_ops,Eclipse_op),
	functor(Compare_term,Eclipse_op,2),			%constructing the term
	arg(1,Compare_term,Lhs),
	arg(2,Compare_term,Rhs),
	Code=Compare_term.

/*
%
% expr/3, arithmetic operator version
%
generate_constraint_code(C,Shared,Code) :-
	C=expr(Op,Lhs,Rhs),
	!,
	Daplex_ops=[+,-,*,/],				%a Daplex operator
	Eclipse_opes=[+,-,*,/],
	nth0(Index,Daplex_ops,Op),
	nth0(Index,Eclipse_ops,Eclipse_op),
*/

%
% expression/3
%
generate_constraint_code(C,Shared,Code) :-
	C=expression(_,_,Expr),
	!,
	generate_constraint_code(Expr,Shared,Code).

%
% relative/3
%
generate_constraint_code(C,Shared,Code) :-
	C=relative(Class,From_var,To_var),
	!,
	Code=(	find_prolog_var(From_var,Shared,From),
		find_prolog_var(To_var,Shared,To),
		cast(Class,From,To) infers most
	).

%
% generate_subquery/5 w/ explicit/1
%
generate_constraint_code(C,Shared,Code) :-
	C=generate_subquery(Class,Var,explicit(Set_icode),_,_),	%generate_subquery/5 w/ explicit/3
	!,
	get_explicit_set(Set_icode,Set),
	Code=(	find_prolog_var(Var,Shared,Prolog_var),
		explicit_set(Prolog_var,Class,Set)
	).



%:::::::::::::::::::::::::::::::::::::::::::::
% generate testing codes (passive constraints)
%:::::::::::::::::::::::::::::::::::::::::::::

%
% a singleton list
%
generate_testing_code([C],Shared,Code) :-
	generate_testing_code(C,Shared,Code).

%
% a list of CIF
%
generate_testing_code([C|Cs],Shared,(Code,Codes)) :-
	generate_testing_code(C,Shared,Code),
	generate_testing_code(Cs,Shared,Codes).



generate_testing_code(C,Shared,Code) :-
	C=restrict_subquery(_,_,_),
	!,
	generate_constraint_code(C,Shared,Code).


%
% generate/2
%
% currently, it is the same as the constraint version
%
generate_testing_code(C,Shared,Code) :-
	C=generate(_,_),
	!,
	generate_constraint_code(C,Shared,Code).

%
% generate/5
%
generate_testing_code(C,Shared,Code) :-
	C=generate(_,_,_,_,_),
	!,
	generate_constraint_code(C,Shared,Code).

%
% expr/3
%
generate_testing_code(C,Shared,Code) :-
	C=expr(Op,Lhs,Rhs),
	Daplex_ops=[=,<,>,=<,>=,<>],			%a Daplex operator
	nth0(Index,Daplex_ops,Op),
	is_daplex_variable(Lhs),			%both sides are Daplex vars
	is_daplex_variable(Rhs),
	!,
	Eclipse_ops=[=,<,>,=<,>=,\=],			%map it into ECLiPSe's comparison operator
	nth0(Index,Eclipse_ops,Eclipse_op),
	functor(Compare_term,Eclipse_op,2),			%constructing the term
	arg(1,Compare_term,Lhs_prolog),
	arg(2,Compare_term,Rhs_prolog),
	Code=(	find_prolog_var(Lhs,Shared,Lhs_prolog),
		find_prolog_var(Rhs,Shared,Rhs_prolog),
		Compare_term
		).

generate_testing_code(C,Shared,Code) :-
	C=expr(Op,Lhs,Rhs),
	Daplex_ops=[=,<,>,=<,>=,<>],			%a Daplex operator
	nth0(Index,Daplex_ops,Op),
	is_daplex_variable(Lhs),			%only LHS is a Daplex var
	!,
	Eclipse_ops=[=,<,>,=<,>=,\=],			%map it into ECLiPSe's comparison operator
	nth0(Index,Eclipse_ops,Eclipse_op),
	functor(Compare_term,Eclipse_op,2),			%constructing the term
	arg(1,Compare_term,Lhs_prolog),
	arg(2,Compare_term,Rhs),
	Code=(	find_prolog_var(Lhs,Shared,Lhs_prolog),
		Compare_term
		).

generate_testing_code(C,Shared,Code) :-
	C=expr(Op,Lhs,Rhs),
	Daplex_ops=[=,<,>,=<,>=,<>],			%a Daplex operator
	nth0(Index,Daplex_ops,Op),
	is_daplex_variable(Rhs),			%only the RHS is a Daplex var
	!,
	Eclipse_ops=[=,<,>,=<,>=,\=],			%map it into ECLiPSe's comparison operator
	nth0(Index,Eclipse_ops,Eclipse_op),
	functor(Compare_term,Eclipse_op,2),		%constructing the term
	arg(1,Compare_term,Lhs),
	arg(2,Compare_term,Rhs_prolog),
	Code=(	find_prolog_var(Rhs,Shared,Rhs_prolog),
		Compare_term
		).

generate_testing_code(C,_,Code) :-
	C=expr(Op,Lhs,Rhs),
	Daplex_ops=[=,<,>,=<,>=,<>],			%a Daplex operator
	nth0(Index,Daplex_ops,Op),
	!,
	Eclipse_ops=[=,<,>,=<,>=,\=],			%map it into ECLiPSe's comparison operator
	nth0(Index,Eclipse_ops,Eclipse_op),
	functor(Compare_term,Eclipse_op,2),		%constructing the term
	arg(1,Compare_term,Lhs),
	arg(2,Compare_term,Rhs),
	Code=Compare_term.


%
% expression/3
%
generate_testing_code(C,Shared,Code) :-
	C=expression(_,_,Expr),
	!,
	generate_testing_code(Expr,Shared,Code).


%
% relative/3
%
generate_testing_code(C,Shared,Code) :-
	C=relative(Class,From_var,To_var),
	!,
	Code=(	find_prolog_var(From_var,Shared,From),
		find_prolog_var(To_var,Shared,To),
		cast(Class,From,To)
	).

%
% generate_subquery/5 w/ explicit/3
%
generate_testing_code(C,Shared,Code) :-
	C=generate_subquery(_,_,explicit(_),_,_),	%generate_subquery/5 w/ explicit/3
	!,
	generate_constraint_code(C,Shared,Code).


%:::::::::::::::::::::::::::::::::::::::::::::::
% generate ECLiPSe code for variable unification
%:::::::::::::::::::::::::::::::::::::::::::::::

generate_link_clause([],Shared,Clause) :-
	Clause=(post_links(Shared) :- true),
	!.

generate_link_clause(Links,Shared,Clause) :-
	Clause=(	(post_links(Shared) :-
				Links_var=Links,
				post_links(Shared,Links_var)		%call the runtime predicate post_links/2
			)
		).

/*
	copy_term(Links,Links_copy),
	generate_link_code(Links_copy,Shared,Code),
	Clause=(post_links(Shared) :- Code).

generate_link_code([],_,true) :-
	!.

generate_link_code([Daplex:Linking_var|Rest],Shared,Code) :-
	nonvar(Linking_var),				%Linking_var is already instantiated
	!,
	member(Linking_var:Prolog_var1,Shared),
	member(Daplex:Prolog_var2,Shared),		%find the corresponding FD var from Shared
	generate_link_code(Rest,Shared,Codes),
	Code=(Prolog_var1=Prolog_var2,Codes).

generate_link_code([Daplex:Linking_var|Rest],Shared,Code) :-
	var(Linking_var),
	!,
	Daplex=Linking_var,			%instantiate Linking_var
	generate_link_code(Rest,Shared,Code).
*/


/*
generate_link_code([],_,true) :-
	!.

generate_link_code([Var1:Var2],Var_pairs,Code) :-
	member(Var1:Prolog_var1,Var_pairs),
	member(Var2:Prolog_var2,Var_pairs),
	Code=(Prolog_var1=Prolog_var2),
	!.

generate_link_code([Var1:Var2|Rest],Var_pairs,Code) :-
	generate_link_code(Rest,Var_pairs,Part2),
	member(Var1:Prolog_var1,Var_pairs),
	member(Var2:Prolog_var2,Var_pairs),
	Code=(Prolog_var1=Prolog_var2,Part2).
*/

%
% give a list of Daplex vars, generate a Daplex:Prolog pair
%
generate_var_pair([],[]) :-
	!.

generate_var_pair([Var|Vars],[Pair|Pairs]) :-
	generate_var_pair(Var,Pair),
	generate_var_pair(Vars,Pairs).

generate_var_pair(Var,Var:_) :-
	is_daplex_variable(Var),
	!.

generate_var_pair(Var:_,Var:_) :-
	is_daplex_variable(Var).



%
% given an explicit set
% return the set as a list
%
get_explicit_set([],[]) :-
	!.

get_explicit_set([E|Es],[Value|Xs]) :-
	E=[expression(_,_,expr(Value))],	%in expression/3 w/ expr/1
	!,
	get_explicit_set(Es,Xs).

get_explicit_set([Something|Es],Xs) :-
	!,
	format("WARNING: get_explicit_set cannot figure out~q~n",[Something]),
	get_explicit_set(Es,Xs).



%
% split_can_unify/4
%
% split a CIF into 2 parts
% 1 contains constructs which can unify w/ Terms
% and the other one cannot
%
split_can_unify([],_,[],[]).

split_can_unify([C|Cs],Term,[C|Can],Cannot) :-
	can_unify(C,Term),
	!,
	split_can_unify(Cs,Term,Can,Cannot).

split_can_unify([C|Cs],Terms,[C|Can],Cannot) :-
	member(M,Terms),
	can_unify(C,M),
	!,
split_can_unify(Cs,Terms,Can,Cannot).

split_can_unify([C|Cs],Terms,Can,[C|Cannot]) :-
	split_can_unify(Cs,Terms,Can,Cannot).

%
% 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
marker.

