1
(****************** Term manipulations *****************)
6
| Term of string * term list;;
8
let rec vars = function
10
| Term (_, l) -> vars_of_list l
11
and vars_of_list = function
13
| t :: r -> union (vars t) (vars_of_list r)
16
let substitute subst =
17
let rec subst_rec = function
18
| Term (oper, sons) -> Term (oper, List.map subst_rec sons)
19
| Var (n) as t -> try List.assoc n subst with Not_found -> t in
24
let rec change_rec l n =
26
| h :: t -> if n = 1 then f h :: t else h :: change_rec t (n - 1)
27
| _ -> failwith "change" in
31
(* Term replacement replace m u n => m[u<-n] *)
33
let rec reprec = function
35
| Term (oper, sons), (n :: u) ->
36
Term (oper, change (fun p -> reprec (p, u)) sons n)
37
| _ -> failwith "replace" in
41
(* matching = - : (term -> term -> subst) *)
42
let matching term1 term2 =
43
let rec match_rec subst t1 t2 =
46
if List.mem_assoc v subst then
47
if m = List.assoc v subst then subst else failwith "matching"
50
| Term (op1, sons1), Term (op2, sons2) ->
51
if op1 = op2 then List.fold_left2 match_rec subst sons1 sons2
52
else failwith "matching"
54
failwith "matching" in
55
match_rec [] term1 term2
58
(* A naive unification algorithm *)
60
let compsubst subst1 subst2 =
61
(List.map (fun (v, t) -> (v, substitute subst1 t)) subst2) @ subst1
65
let rec occur_rec = function
67
| Term (_, sons) -> List.exists occur_rec sons in
71
let rec unify = function
72
| (Var n1 as term1), term2 ->
73
if term1 = term2 then []
74
else if occurs n1 term2 then failwith "unify1"
77
if occurs n2 term1 then failwith "unify2"
79
| Term (op1, sons1), Term (op2, sons2) ->
81
List.fold_left2 (fun s t1 t2 -> compsubst (unify (substitute s t1,
84
else failwith "unify3"
87
(* We need to print terms with variables independently from input terms
88
obtained by parsing. We give arbitrary names v1,v2,... to their variables. *)
90
let infixes = ["+";"*";"-";"/"];;
92
let rec pretty_term = function
94
print_string "v"; print_int n
95
| Term (oper, sons) ->
96
if List.mem oper infixes then
99
pretty_close s1; print_string oper; pretty_close s2
101
failwith "pretty_term : infix arity <> 2"
106
| t::lt -> print_string "(";
108
List.iter (fun t -> print_string ","; pretty_term t) lt;
110
and pretty_close = function
111
| Term (oper, _) as m ->
112
if List.mem oper infixes then
113
(print_string "("; pretty_term m; print_string ")")