diff options
Diffstat (limited to 'contrib/jprover/jterm.ml')
-rw-r--r-- | contrib/jprover/jterm.ml | 872 |
1 files changed, 872 insertions, 0 deletions
diff --git a/contrib/jprover/jterm.ml b/contrib/jprover/jterm.ml new file mode 100644 index 00000000..7fc923a5 --- /dev/null +++ b/contrib/jprover/jterm.ml @@ -0,0 +1,872 @@ +open Printf +open Opname +open List + +(* Definitions of [jterm]: *) +type param = param' + and operator = operator' + and term = term' + and bound_term = bound_term' + and param' = + | Number of int + | String of string + | Token of string + | Var of string + | ParamList of param list + and operator' = { op_name : opname; op_params : param list } + and term' = { term_op : operator; term_terms : bound_term list } + and bound_term' = { bvars : string list; bterm : term } +;; + +(* Debugging tools: *) +(*i*) +let mbreak s = Format.print_flush (); print_string ("-break at: "^s); + Format.print_flush (); let _ = input_char stdin in () +(*i*) + +type error_msg = + | TermMatchError of term * string + | StringError of string + +exception RefineError of string * error_msg + +let ref_raise = function + | RefineError(s,e) -> raise (RefineError(s,e)) + | _ -> raise (RefineError ("Jterm", StringError "unexpected error")) + +(* Printing utilities: *) + +let fprint_str ostream s = + let _ = fprintf ostream "%s." s in ostream + +let fprint_str_list ostream sl = + ignore (List.fold_left fprint_str ostream sl); + Format.print_flush () + +let fprint_opname ostream = function + { opname_token= tk; opname_name = sl } -> + fprint_str_list ostream sl + +let rec fprint_param ostream = function + | Number n -> fprintf ostream " %d " n + | String s -> fprint_str_list ostream [s] + | Token t -> fprint_str_list ostream [t] + | Var v -> fprint_str_list ostream [v] + | ParamList ps -> fprint_param_list ostream ps +and fprint_param_list ostream = function + | [] -> () + | param::r -> fprint_param ostream param; + fprint_param_list ostream r +;; + +let print_strs = fprint_str_list stdout + + +(* Interface to [Jall.ml]: *) +(* It is extracted from Meta-Prl's standard implementation. *) +(*c begin of the extraction *) + +type term_subst = (string * term) list +let mk_term op bterms = { term_op = op; term_terms = bterms } +let make_term x = x (* external [make_term : term' -> term] = "%identity" *) +let dest_term x = x (* external [dest_term : term -> term'] = "%identity" *) +let mk_op name params = + { op_name = name; op_params = params } + +let make_op x = x (* external [make_op : operator' -> operator] = "%identity" *) +let dest_op x = x (* external [dest_op : operator -> operator'] = "%identity" *) +let mk_bterm bvars term = { bvars = bvars; bterm = term } +let make_bterm x = x (* external [make_bterm : bound_term' -> bound_term] = "%identity" *) +let dest_bterm x = x (* external [dest_bterm : bound_term -> bound_term'] = "%identity" *) +let make_param x = x (* external [make_param : param' -> param] = "%identity" *) +let dest_param x = x (* external [dest_param : param -> param'] = "%identity" *) + +(* + * Operator names. + *) +let opname_of_term = function + { term_op = { op_name = name } } -> + name + +(* + * Get the subterms. + * None of the subterms should be bound. + *) +let subterms_of_term t = + List.map (fun { bterm = t } -> t) t.term_terms + +let subterm_count { term_terms = terms } = + List.length terms + +let subterm_arities { term_terms = terms } = + List.map (fun { bvars = vars } -> List.length vars) terms + +(* + * Manifest terms are injected into the "perv" module. + *) +let xperv = make_opname ["Perv"] +let sequent_opname = mk_opname "sequent" xperv + +(* + * Variables. + *) + +let var_opname = make_opname ["var"] + +(* + * See if a term is a variable. + *) +let is_var_term = function + | { term_op = { op_name = opname; op_params = [Var v] }; + term_terms = [] + } when Opname.eq opname var_opname -> true + | _ -> + false + +(* + * Destructor for a variable. + *) +let dest_var = function + | { term_op = { op_name = opname; op_params = [Var v] }; + term_terms = [] + } when Opname.eq opname var_opname -> v + | t -> + ref_raise(RefineError ("dest_var", TermMatchError (t, "not a variable"))) +(* + * Make a variable. + *) +let mk_var_term v = + { term_op = { op_name = var_opname; op_params = [Var v] }; + term_terms = [] + } + +(* + * Simple terms + *) +(* + * "Simple" terms have no parameters and no binding variables. + *) +let is_simple_term_opname name = function + | { term_op = { op_name = name'; op_params = [] }; + term_terms = bterms + } when Opname.eq name' name -> + let rec aux = function + | { bvars = []; bterm = _ }::t -> aux t + | _::t -> false + | [] -> true + in + aux bterms + | _ -> false + +let mk_any_term op terms = + let aux t = + { bvars = []; bterm = t } + in + { term_op = op; term_terms = List.map aux terms } + +let mk_simple_term name terms = + mk_any_term { op_name = name; op_params = [] } terms + +let dest_simple_term = function + | ({ term_op = { op_name = name; op_params = [] }; + term_terms = bterms + } : term) as t -> + let aux = function + | { bvars = []; bterm = t } -> + t + | _ -> + ref_raise(RefineError ("dest_simple_term", TermMatchError (t, "binding vars exist"))) + in + name, List.map aux bterms + | t -> + ref_raise(RefineError ("dest_simple_term", TermMatchError (t, "params exist"))) + +let dest_simple_term_opname name = function + | ({ term_op = { op_name = name'; op_params = [] }; + term_terms = bterms + } : term) as t -> + if Opname.eq name name' then + let aux = function + | { bvars = []; bterm = t } -> t + | _ -> ref_raise(RefineError ("dest_simple_term_opname", TermMatchError (t, "binding vars exist"))) + in + List.map aux bterms + else + ref_raise(RefineError ("dest_simple_term_opname", TermMatchError (t, "opname mismatch"))) + | t -> + ref_raise(RefineError ("dest_simple_term_opname", TermMatchError (t, "params exist"))) + +(* + * Bound terms. + *) +let mk_simple_bterm bterm = + { bvars = []; bterm = bterm } + +let dest_simple_bterm = function + | { bvars = []; bterm = bterm } -> + bterm + | _ -> + ref_raise(RefineError ("dest_simple_bterm", StringError ("bterm is not simple"))) + +(* Copy from [term_op_std.ml]: *) +(*i modified for Jprover, as a patch... i*) +let mk_string_term opname s = + { term_op = { op_name = opname; op_params = [String s] }; term_terms = [] } + +(*i let mk_string_term opname s = + let new_opname={opname_token=opname.opname_token; opname_name=(List.tl opname.opname_name)@[s]} in + { term_op = { op_name = new_opname; op_params = [String (List.hd opname.opname_name)] }; term_terms = [] } +i*) + +(* Copy from [term_subst_std.ml]: *) + +let rec free_vars_term gvars bvars = function + | { term_op = { op_name = opname; op_params = [Var v] }; term_terms = bterms } when Opname.eq opname var_opname -> + (* This is a variable *) + let gvars' = + if List.mem v bvars or List.mem v gvars then + gvars + else + v::gvars + in + free_vars_bterms gvars' bvars bterms + | { term_terms = bterms } -> + free_vars_bterms gvars bvars bterms + and free_vars_bterms gvars bvars = function + | { bvars = vars; bterm = term}::l -> + let bvars' = vars @ bvars in + let gvars' = free_vars_term gvars bvars' term in + free_vars_bterms gvars' bvars l + | [] -> + gvars + +let free_vars_list = free_vars_term [] [] + + +(* Termop: *) + +let is_no_subterms_term opname = function + | { term_op = { op_name = opname'; op_params = [] }; + term_terms = [] + } -> + Opname.eq opname' opname + | _ -> + false + +(* + * Terms with one subterm. + *) +let is_dep0_term opname = function + | { term_op = { op_name = opname'; op_params = [] }; + term_terms = [{ bvars = [] }] + } -> Opname.eq opname' opname + | _ -> false + +let mk_dep0_term opname t = + { term_op = { op_name = opname; op_params = [] }; + term_terms = [{ bvars = []; bterm = t }] + } + +let dest_dep0_term opname = function + | { term_op = { op_name = opname'; op_params = [] }; + term_terms = [{ bvars = []; bterm = t }] + } when Opname.eq opname' opname -> t + | t -> ref_raise(RefineError ("dest_dep0_term", TermMatchError (t, "not a dep0 term"))) + +(* + * Terms with two subterms. + *) +let is_dep0_dep0_term opname = function + | { term_op = { op_name = opname'; op_params = [] }; + term_terms = [{ bvars = [] }; { bvars = [] }] + } -> Opname.eq opname' opname + | _ -> false + +let mk_dep0_dep0_term opname = fun + t1 t2 -> + { term_op = { op_name = opname; op_params = [] }; + term_terms = [{ bvars = []; bterm = t1 }; + { bvars = []; bterm = t2 }] + } + +let dest_dep0_dep0_term opname = function + | { term_op = { op_name = opname'; op_params = [] }; + term_terms = [{ bvars = []; bterm = t1 }; + { bvars = []; bterm = t2 }] + } when Opname.eq opname' opname -> t1, t2 + | t -> ref_raise(RefineError ("dest_dep0_dep0_term", TermMatchError (t, "bad arity"))) + +(* + * Bound term. + *) + +let is_dep0_dep1_term opname = function + | { term_op = { op_name = opname'; op_params = [] }; + term_terms = [{ bvars = [] }; { bvars = [_] }] + } when Opname.eq opname' opname -> true + | _ -> false + +let is_dep0_dep1_any_term = function + | { term_op = { op_params = [] }; + term_terms = [{ bvars = [] }; { bvars = [_] }] + } -> true + | _ -> false + +let mk_dep0_dep1_term opname = fun + v t1 t2 -> { term_op = { op_name = opname; op_params = [] }; + term_terms = [{ bvars = []; bterm = t1 }; + { bvars = [v]; bterm = t2 }] + } + +let dest_dep0_dep1_term opname = function + | { term_op = { op_name = opname'; op_params = [] }; + term_terms = [{ bvars = []; bterm = t1 }; + { bvars = [v]; bterm = t2 }] + } when Opname.eq opname' opname -> v, t1, t2 + | t -> ref_raise(RefineError ("dest_dep0_dep1_term", TermMatchError (t, "bad arity"))) + +let rec smap f = function + | [] -> [] + | (hd::tl) as l -> + let hd' = f hd in + let tl' = smap f tl in + if (hd==hd')&&(tl==tl') then l else hd'::tl' + +let rec try_check_assoc v v' = function + | [] -> raise Not_found + | (v1,v2)::tl -> + begin match v=v1, v'=v2 with + | true, true -> true + | false, false -> try_check_assoc v v' tl + | _ -> false + end + +let rec zip_list l l1 l2 = match (l1,l2) with + | (h1::t1), (h2::t2) -> + zip_list ((h1,h2)::l) t1 t2 + | [], [] -> + l + | _ -> raise (Failure "Term.zip_list") + +let rec assoc_in_range eq y = function + | (_, y')::tl -> + (eq y y') || (assoc_in_range eq y tl) + | [] -> + false + +let rec check_assoc v v' = function + | [] -> v=v' + | (v1,v2)::tl -> + begin match v=v1, v'=v2 with + | true, true -> true + | false, false -> check_assoc v v' tl + | _ -> false + end + +let rec zip a b = match (a,b) with + | (h1::t1), (h2::t2) -> + (h1, h2) :: zip t1 t2 + | [], [] -> + [] + | + _ -> raise (Failure "Term.zip") + +let rec for_all2 f l1 l2 = + match (l1,l2) with + | h1::t1, h2::t2 -> for_all2 f t1 t2 & f h1 h2 + | [], [] -> true + | _ -> false + +let newname v i = + v ^ "_" ^ (string_of_int i) + +let rec new_var v avoid i = + let v' = newname v i in + if avoid v' + then new_var v avoid (succ i) + else v' + +let vnewname v avoid = new_var v avoid 1 + +let rev_mem a b = List.mem b a + +let rec find_index_aux v i = function + | h::t -> + if h = v then + i + else + find_index_aux v (i + 1) t + | [] -> + raise Not_found + +let find_index v l = find_index_aux v 0 l + +let rec remove_elements l1 l2 = + match l1, l2 with + | flag::ft, h::t -> + if flag then + remove_elements ft t + else + h :: remove_elements ft t + | _, l -> + l + +let rec subtract l1 l2 = + match l1 with + | h::t -> + if List.mem h l2 then + subtract t l2 + else + h :: subtract t l2 + | [] -> + [] + +let rec fv_mem fv v = + match fv with + | [] -> false + | h::t -> + List.mem v h || fv_mem t v + +let rec new_vars fv = function + | [] -> [] + | v::t -> + (* Rename the first one, then add it to free vars *) + let v' = vnewname v (fv_mem fv) in + v'::(new_vars ([v']::fv) t) + +let rec fsubtract l = function + | [] -> l + | h::t -> + fsubtract (subtract l h) t + +let add_renames_fv r l = + let rec aux = function + | [] -> l + | v::t -> [v]::(aux t) + in + aux r + +let add_renames_terms r l = + let rec aux = function + | [] -> l + | v::t -> (mk_var_term v)::(aux t) + in + aux r + +(* + * First order simultaneous substitution. + *) +let rec subst_term terms fv vars = function + | { term_op = { op_name = opname; op_params = [Var(v)] }; term_terms = [] } as t + when Opname.eq opname var_opname-> + (* Var case *) + begin + try List.nth terms (find_index v vars) with + Not_found -> + t + end + | { term_op = op; term_terms = bterms } -> + (* Other term *) + { term_op = op; term_terms = subst_bterms terms fv vars bterms } + +and subst_bterms terms fv vars bterms = + (* When subst through bterms, catch binding occurrences *) + let rec subst_bterm = function + | { bvars = []; bterm = term } -> + (* Optimize the common case *) + { bvars = []; bterm = subst_term terms fv vars term } + + | { bvars = bvars; bterm = term } -> + (* First subtract bound instances *) + let flags = List.map (function v -> List.mem v bvars) vars in + let vars' = remove_elements flags vars in + let fv' = remove_elements flags fv in + let terms' = remove_elements flags terms in + + (* If any of the binding variables are free, rename them *) + let renames = subtract bvars (fsubtract bvars fv') in + if renames <> [] then + let fv'' = (free_vars_list term)::fv' in + let renames' = new_vars fv'' renames in + { bvars = subst_bvars renames' renames bvars; + bterm = subst_term + (add_renames_terms renames' terms') + (add_renames_fv renames' fv') + (renames @ vars') + term + } + else + { bvars = bvars; + bterm = subst_term terms' fv' vars' term + } + in + List.map subst_bterm bterms + +and subst_bvars renames' renames bvars = + let subst_bvar v = + try List.nth renames' (find_index v renames) with + Not_found -> v + in + List.map subst_bvar bvars + +let subst term vars terms = + subst_term terms (List.map free_vars_list terms) vars term + +(*i bug!!! in the [term_std] module + let subst1 t var term = + let fv = free_vars_list term in + if List.mem var fv then + subst_term [term] [fv] [var] t + else + t +The following is the correct implementation +i*) + +let subst1 t var term = +if List.mem var (free_vars_list t) then + subst_term [term] [free_vars_list term] [var] t +else + t + +let apply_subst t s = + let vs,ts = List.split s in + subst t vs ts + +let rec equal_params p1 p2 = + match p1, p2 with + | Number n1, Number n2 -> + n1 = n2 + | ParamList pl1, ParamList pl2 -> + List.for_all2 equal_params pl1 pl2 + | _ -> + p1 = p2 + +let rec equal_term vars t t' = + match t, t' with + | { term_op = { op_name = opname1; op_params = [Var v] }; + term_terms = [] + }, + { term_op = { op_name = opname2; op_params = [Var v'] }; + term_terms = [] + } when Opname.eq opname1 var_opname & Opname.eq opname2 var_opname -> + check_assoc v v' vars + | { term_op = { op_name = name1; op_params = params1 }; term_terms = bterms1 }, + { term_op = { op_name = name2; op_params = params2 }; term_terms = bterms2 } -> + (Opname.eq name1 name2) + & (for_all2 equal_params params1 params2) + & (equal_bterms vars bterms1 bterms2) +and equal_bterms vars bterms1 bterms2 = + let equal_bterm = fun + { bvars = bvars1; bterm = term1 } + { bvars = bvars2; bterm = term2 } -> + equal_term (zip_list vars bvars1 bvars2) term1 term2 + in + for_all2 equal_bterm bterms1 bterms2 + + +let alpha_equal t1 t2 = + try equal_term [] t1 t2 with Failure _ -> false + +let var_subst t t' v = + let { term_op = { op_name = opname } } = t' in + let vt = mk_var_term v in + let rec subst_term = function + { term_op = { op_name = opname'; op_params = params }; + term_terms = bterms + } as t -> + (* Check if this is the same *) + if Opname.eq opname' opname & alpha_equal t t' then + vt + else + { term_op = { op_name = opname'; op_params = params }; + term_terms = List.map subst_bterm bterms + } + + and subst_bterm { bvars = vars; bterm = term } = + if List.mem v vars then + let av = vars @ (free_vars_list term) in + let v' = vnewname v (fun v -> List.mem v av) in + let rename var = if var = v then v' else var in + let term = subst1 term v (mk_var_term v') in + { bvars = smap rename vars; bterm = subst_term term } + else + { bvars = vars; bterm = subst_term term } + in + subst_term t + +let xnil_opname = mk_opname "nil" xperv +let xnil_term = mk_simple_term xnil_opname [] +let is_xnil_term = is_no_subterms_term xnil_opname + +(*c End of the extraction from Meta-Prl *) + +(* Huang's modification: *) +let all_opname = make_opname ["quantifier";"all"] +let is_all_term = is_dep0_dep1_term all_opname +let dest_all = dest_dep0_dep1_term all_opname +let mk_all_term = mk_dep0_dep1_term all_opname + +let exists_opname = make_opname ["quantifier";"exst"] +let is_exists_term = is_dep0_dep1_term exists_opname +let dest_exists = dest_dep0_dep1_term exists_opname +let mk_exists_term = mk_dep0_dep1_term exists_opname + +let or_opname = make_opname ["connective";"or"] +let is_or_term = is_dep0_dep0_term or_opname +let dest_or = dest_dep0_dep0_term or_opname +let mk_or_term = mk_dep0_dep0_term or_opname + +let and_opname = make_opname ["connective";"and"] +let is_and_term = is_dep0_dep0_term and_opname +let dest_and = dest_dep0_dep0_term and_opname +let mk_and_term = mk_dep0_dep0_term and_opname + +let cor_opname = make_opname ["connective";"cor"] +let is_cor_term = is_dep0_dep0_term cor_opname +let dest_cor = dest_dep0_dep0_term cor_opname +let mk_cor_term = mk_dep0_dep0_term cor_opname + +let cand_opname = make_opname ["connective";"cand"] +let is_cand_term = is_dep0_dep0_term cand_opname +let dest_cand = dest_dep0_dep0_term cand_opname +let mk_cand_term = mk_dep0_dep0_term cand_opname + +let implies_opname = make_opname ["connective";"=>"] +let is_implies_term = is_dep0_dep0_term implies_opname +let dest_implies = dest_dep0_dep0_term implies_opname +let mk_implies_term = mk_dep0_dep0_term implies_opname + +let iff_opname = make_opname ["connective";"iff"] +let is_iff_term = is_dep0_dep0_term iff_opname +let dest_iff = dest_dep0_dep0_term iff_opname +let mk_iff_term = mk_dep0_dep0_term iff_opname + +let not_opname = make_opname ["connective";"not"] +let is_not_term = is_dep0_term not_opname +let dest_not = dest_dep0_term not_opname +let mk_not_term = mk_dep0_term not_opname + +let var_ = mk_var_term +let fun_opname = make_opname ["function"] +let fun_ f ts = mk_any_term {op_name = fun_opname; op_params = [String f] } ts + +let is_fun_term = function + | { term_op = { op_name = opname; op_params = [String f] }} + when Opname.eq opname fun_opname -> true + | _ -> + false + +let dest_fun = function + | { term_op = { op_name = opname; op_params = [String f] }; term_terms = ts} + when Opname.eq opname fun_opname -> (f, List.map (fun { bterm = t } -> t) ts) + | t -> + ref_raise(RefineError ("dest_fun", TermMatchError (t, "not a function symbol"))) + +let const_ c = fun_ c [] +let is_const_term = function + | { term_op = { op_name = opname; op_params = [String f] }; term_terms = [] } + when Opname.eq opname fun_opname -> true + | _ -> + false + +let dest_const t = + let (n, ts) = dest_fun t in n + +let pred_opname = make_opname ["predicate"] +let pred_ p ts = mk_any_term {op_name = pred_opname; op_params = [String p] } ts + +let not_ = mk_not_term +let and_ = mk_and_term +let or_ = mk_or_term +let imp_ = mk_implies_term +let cand_ = mk_cand_term +let cor_ = mk_cor_term +let iff_ = mk_iff_term +let nil_term = {term_op={op_name=nil_opname; op_params=[]}; term_terms=[] } +let forall v t = mk_all_term v nil_term t +let exists v t= mk_exists_term v nil_term t +let rec wbin op = function + | [] -> raise (Failure "Term.wbin") + | [t] -> t + | t::r -> op t (wbin op r) + +let wand_ = wbin and_ +let wor_ = wbin or_ +let wimp_ = wbin imp_ + +(*i let true_opname = make_opname ["bool";"true"] +let is_true_term = is_no_subterms_term true_opname +let true_ = mk_simple_term true_opname [] +let false_ = not_ true_ + +let is_false_term t = + if is_not_term t then + let t1 = dest_not t in + is_true_term t1 + else + false +i*) + +let dummy_false_ = mk_simple_term (make_opname ["bool";"false"]) [] +let dummy_true_ = mk_simple_term (make_opname ["bool";"true"]) [] +let false_ = and_ (dummy_false_) (not_ dummy_false_) +let true_ = not_ (and_ (dummy_true_) (not_ dummy_true_)) + +let is_false_term t = + if (alpha_equal t false_) then true + else false + +let is_true_term t = + if (alpha_equal t true_) then true + else false + +(* Print a term [t] via the [ostream]: *) +let rec fprint_term ostream t prec = + let l_print op_prec = + if (prec > op_prec) then fprintf ostream "(" in + let r_print op_prec = + if (prec > op_prec) then fprintf ostream ")" in + if is_false_term t then (* false *) + fprint_str_list ostream ["False"] + else if is_true_term t then (* true *) + fprint_str_list ostream ["True"] + else if is_all_term t then (* for all *) + let v, t1, t2 = dest_all t in + fprint_str_list ostream ["A."^v]; + fprint_term ostream t2 4 + else if is_exists_term t then (* exists *) + let v, t1, t2 = dest_exists t in + fprint_str_list ostream ["E."^v]; + fprint_term ostream t2 4 (* implication *) + else if is_implies_term t then + let t1, t2 = dest_implies t in + l_print 0; + fprint_term ostream t1 1; + fprint_str_list ostream ["=>"]; + fprint_term ostream t2 0; + r_print 0 + else if is_and_term t then (* logical and *) + let t1, t2 = dest_and t in + l_print 3; + fprint_term ostream t1 3; + fprint_str_list ostream ["&"]; + fprint_term ostream t2 3; + r_print 3 + else if is_or_term t then (* logical or *) + let t1, t2 = dest_or t in + l_print 2; + fprint_term ostream t1 2; + fprint_str_list ostream ["|"]; + fprint_term ostream t2 2; + r_print 2 + else if is_not_term t then (* logical not *) + let t2 = dest_not t in + fprint_str_list ostream ["~"]; + fprint_term ostream t2 4 (* nil term *) + else if is_xnil_term t then + fprint_str_list ostream ["NIL"] + else match t with (* other cases *) + { term_op = { op_name = opname; op_params = opparm }; term_terms = bterms} -> + if (Opname.eq opname pred_opname) || (Opname.eq opname fun_opname) then + begin + fprint_param_list ostream opparm; + if bterms != [] then + begin + fprintf ostream "("; + fprint_bterm_list ostream prec bterms; + fprintf ostream ")"; + end + end else + begin + fprintf ostream "["; +(* fprint_opname ostream opname; + fprintf ostream ": "; *) + fprint_param_list ostream opparm; + if bterms != [] then + begin + fprintf ostream "("; + fprint_bterm_list ostream prec bterms; + fprintf ostream ")"; + end; + fprintf ostream "]" + end +and fprint_bterm_list ostream prec = function + | [] -> () + | {bvars=bv; bterm=bt}::r -> + fprint_str_list ostream bv; + fprint_term ostream bt prec; + if (r<>[]) then fprint_str_list ostream [","]; + fprint_bterm_list ostream prec r +;; + + +let print_term ostream t = + Format.print_flush (); + fprint_term ostream t 0; + Format.print_flush () + +let print_error_msg = function + | RefineError(s,e) -> print_string ("(module "^s^") "); + begin + match e with + | TermMatchError(t,s) -> print_term stdout t; print_string (s^"\n") + | StringError s -> print_string (s^"\n") + end + | ue -> print_string "Unexpected error for Jp.\n"; + raise ue + + +(* Naive implementation for [jterm] substitution, unification, etc.: *) +let substitute subst term = + apply_subst term subst + +(* A naive unification algorithm: *) +let compsubst subst1 subst2 = + (List.map (fun (v, t) -> (v, substitute subst1 t)) subst2) @ subst1 +;; + +let rec extract_terms = function + | [] -> [] + | h::r -> let {bvars=_; bterm=bt}=h in bt::extract_terms r + +(* Occurs check: *) +let occurs v t = + let rec occur_rec t = + if is_var_term t then v=dest_var t + else let { term_op = _ ; term_terms = bterms} = t in + let sons = extract_terms bterms in + List.exists occur_rec sons + in + occur_rec t + +(* The naive unification algorithm: *) +let rec unify2 (term1,term2) = + if is_var_term term1 then + if equal_term [] term1 term2 then [] + else let v1 = dest_var term1 in + if occurs v1 term2 then raise (RefineError ("unify1", StringError ("1"))) + else [v1,term2] + else if is_var_term term2 then + let v2 = dest_var term2 in + if occurs v2 term1 then raise (RefineError ("unify2", StringError ("2"))) + else [v2,term1] + else + let { term_op = { op_name = opname1; op_params = params1 }; + term_terms = bterms1 + } = term1 + in + let { term_op = { op_name = opname2; op_params = params2 }; + term_terms = bterms2 + } = term2 + in + if Opname.eq opname1 opname2 & params1 = params2 then + let sons1 = extract_terms bterms1 + and sons2 = extract_terms bterms2 in + List.fold_left2 + (fun s t1 t2 -> compsubst + (unify2 (substitute s t1, substitute s t2)) s) + [] sons1 sons2 + else raise (RefineError ("unify3", StringError ("3"))) + +let unify term1 term2 = unify2 (term1, term2) +let unify_mm term1 term2 _ = unify2 (term1, term2) |