/tmp/mosstmp/csu01130/unify.sml

(* 
	1: input is in the form of term list list
	2: in this input each term list represents an expression
	3: output gives two lists . first is the list gives us disa	      greement set if complete unification takes place then it 		 comes out to be []
	4: 2nd list gives us unifier
	5: when an illegel input occurs then first list is empty 	      & 2nd list contains VAR"illegel"
						*)	
signature UNIFY =
sig 
	datatype Term = VAR of string
		| CONST of string
		| OPR1 of string * Term
		| OPR2 of string * Term * Term
		| OPR3 of string * Term * Term * Term
	val unify : Term list list -> Term list * (Term*Term) list
end;

structure unify : UNIFY =
struct


datatype Term = VAR of string
		| CONST of string
		| OPR1 of string * Term
		| OPR2 of string * Term * Term
		| OPR3 of string * Term * Term * Term

fun     dis_coll([]) = []
|	dis_coll(xs) = hd(hd(xs))::dis_coll(tl(xs));	
	

fun 	get_element(VAR(x)) = [x]
|	get_element(CONST(x)) = [x]
|	get_element(OPR1(x,y)) = get_element(y)
|	get_element(OPR2(x,y,z)) = get_element(y)@get_element(z)
|	get_element(OPR3(a,x,y,z)) = get_element(x)@get_element(y)@get_element(z);

fun     cr_level(OPR1(x,y)) = [y]
|	cr_level(OPR2(x,y,z)) = [y,z]
|	cr_level(OPR3(a,b,c,d)) = [b,c,d]
|	cr_level(_) = [];
 
fun     member(x,[]) = false
|       member(x,ys) = if x=hd(ys) then true else member(x,tl(ys));

fun 	com(VAR(x),VAR(y)) = true
|	com(VAR(x),CONST(y)) = true
|	com(CONST(x),VAR(y)) = true
|	com(VAR(x),xs) = if member(x,get_element(xs)) then false else true
|  	com(xs,VAR(x)) = if member(x,get_element(xs)) then false else true
other|	com(OPR1(a,b),OPR1(c,d)) = (a=c)
|	com(OPR2(a,b,c),OPR2(d,e,f)) = (a=d)
|	com(OPR3(a,b,c,d),OPR3(e,f,g,h)) = (a=e)
|	com(x,y) = (x=y);


fun 	get_type(VAR(x)) = "VAR"
|	get_type(CONST(x)) = "CONST"
|	get_type(OPR1(x,y)) = "OPR1"
|	get_type(OPR2(a,b,c)) = "OPR2"
|	get_type(OPR3(a,b,c,d)) = "OPR3";

fun 	c_type([]) = false
|	c_type(x) = get_type(hd(x))=get_type(hd(tl(x))) andalso c_type(tl(x)); 	


fun   	ch_sametype([]) = true
|	ch_sametype(xs) = if tl(xs) = [] then true
	else get_type(hd(xs))=get_type(hd(tl(xs))) andalso ch_sametype(tl(xs));	

fun 	ch_equality([]) = true
|	ch_equality(xs) = if tl(xs)=[] then true 
			else hd(xs)=hd(tl(xs)) andalso ch_equality(tl(xs))

fun 	ch_con(x,[]) = true
|	ch_con(x,xs) = if tl(xs)=[] then com(x,hd(xs)) 
		else com(x,hd(tl(xs))) andalso ch_con(x,tl(xs)) andalso 
			ch_con(hd(tl(xs)),tl(xs));

fun 	set_subdset([],_) = []
|	set_subdset(xs,i) = if get_type(List.nth(xs,i))="VAR" then 
		List.nth(xs,i)::List.take(xs,i)@List.drop(xs,i+1)
			else set_subdset(xs,i+1);

fun 	set_dset([]) = []
|	set_dset(xs) = if ch_con(hd(xs),xs) then xs
			else if c_type(xs) then xs
			else  set_subdset(xs,0);

fun 	replace_term(VAR(x),z,d) = if VAR(x)=z then d else VAR(x)
|	replace_term(CONST(x),z,d) = CONST(x)
|	replace_term(OPR1(a,b),z,d) = OPR1(a,replace_term(b,z,d))
|	replace_term(OPR2(a,b,c),z,d) = OPR2(a,replace_term(b,z,d),replace_term(c,z,d))
|	replace_term(OPR3(a,b,c,e),z,d) = OPR3(a,replace_term(b,z,d),replace_term(c,z,d),replace_term(e,z,d));		

fun 	replace_list([],z,d) = []
|	replace_list(xs,z,d) = replace_term(hd(xs),z,d)::replace_list(tl(xs),z,d);

fun 	replace([],z,d) = []
|	replace(xs,z,d) = replace_list(hd(xs),z,d)::replace(tl(xs),z,d);

fun	var_substitude([],z) = []
|	var_substitude(xs,z) = if tl(z)=[] then xs else 
			var_substitude(replace(xs,hd(tl(z)),hd(z)),List.take(z,1)@List.drop(z,2));

				 
fun 	substitude([],z) = []
|	substitude(xs,z) = if length(z)=2 then replace(xs,hd(z),hd(tl(z)))
				else if get_type(hd(tl(z)))="VAR" then  
			var_substitude(xs,z) else replace(xs,hd(z),hd(tl(z)));

fun  	var_mgu([],ys) = ys 
|	var_mgu(z,ys) = if tl(z)=[] then ys 
			else (hd(tl(z)),hd(z))::var_mgu(tl(z),ys); 		

fun 	create_mgu([],ys) = ys
|	create_mgu(z,ys) = if length(z)=2 then ys@[(hd(tl(z)),hd(z))]
			else if get_type(hd(tl(z)))="VAR" then var_mgu(z,ys)				else ys@[(hd(tl(z)),hd(z))];



fun	reduce_ip([]) = []
|	reduce_ip(xs) = if tl(xs)=[] then [tl(hd(xs))] 
			else tl(hd(xs))::reduce_ip(tl(xs));
				   	
fun 	low_level([]) = []
|	low_level(xs) = if (get_type(hd(hd(xs)))="VAR")=false 
			then cr_level(hd(hd(xs)))::low_level(tl(xs))
			else [];

fun 	ch_f([]) = true
|	ch_f(xs) = if tl(xs)=[] then true else com(hd(hd(xs)),hd(hd(tl(xs)))) 
			andalso ch_f(tl(xs));
			
fun 	find_d([]) = []
|	find_d(xs) = if ch_con(hd(dis_coll(xs)),dis_coll(xs))=false
			 then dis_coll(xs)
			else
			if ch_sametype(dis_coll(xs)) 
                      andalso (get_type(hd(hd(xs)))="VAR")=false 
	 andalso (get_type(hd(hd(xs)))="CONST")=false andalso ch_f(xs)
			then find_d(low_level(xs))
	else if set_dset(dis_coll(xs))=[] orelse ch_equality(dis_coll(xs))
			 then find_d(reduce_ip(xs))
			else dis_coll(xs);

fun rdl([],_) = []
|   rdl(xs,i) = if (i=length(xs)) then xs else
                 if member(List.nth(xs,i),List.drop(xs,i+1)) 
                      	then rdl((List.take(xs,i)@List.drop(xs,i+1)),i)
		     else rdl(xs,i+1);  



fun	unify_hd([],ys) = ([],ys)
|	unify_hd(xs,ys) = if length(xs)=1 then ([],ys)

			else	if ch_con(hd(find_d(xs)),find_d(xs))= false 
				then (find_d(xs),ys)
       else unify_hd(rdl(substitude(xs,find_d(xs)),0),create_mgu(find_d(xs),ys));

fun 	ch_ill([]) = true
|	ch_ill(xs) = if length(xs) =1 then true else 
	length(hd(xs))=length(hd(tl(xs))) andalso ch_ill(tl(xs));

fun	unify([]) = ([],[(VAR"illegel",VAR"illegel")])
|	unify(xs) = if ch_ill(xs) then unify_hd(rdl(xs,0),[])
			else ([],[(VAR"illegel",VAR"illegel")]);

end;