type t = | Relation of string * Term.t list | Equal of Term.t * Term.t | Bottom | Neg of t | Conj of t * t | Disj of t * t | Impl of t * t | Iff of t * t | Forall of t | Exists of t let rec match_term t phi psi = match (phi, psi) with | Relation (r1, ts1), Relation (r2, ts2) -> if r1 = r2 && List.length ts1 = List.length ts2 then List.map2 (Term.match_term t) ts1 ts2 |> List.fold_left Term.merge_result None else MatchErr | Equal (t1, s1), Equal (t2, s2) -> Term.(merge_result (match_term t t1 t2) (match_term t s1 s2)) | Bottom, Bottom -> None | Neg phi, Neg psi -> match_term t phi psi | Conj (phi1, psi1), Conj (phi2, psi2) -> Term.merge_result (match_term t phi1 phi2) (match_term t psi1 psi2) | Disj (phi1, psi1), Disj (phi2, psi2) -> Term.merge_result (match_term t phi1 phi2) (match_term t psi1 psi2) | Impl (phi1, psi1), Impl (phi2, psi2) -> Term.merge_result (match_term t phi1 phi2) (match_term t psi1 psi2) | Iff (phi1, psi1), Iff (phi2, psi2) -> Term.merge_result (match_term t phi1 phi2) (match_term t psi1 psi2) | Forall phi, Forall psi -> match_term (Term.inc_var t) phi psi | Exists phi, Exists psi -> match_term (Term.inc_var t) phi psi | _ -> MatchErr let rec occurs t = function | Relation (_, ts) -> List.exists (Term.occurs t) ts | Equal (t1, t2) -> Term.occurs t t1 || Term.occurs t t2 | Bottom -> false | Neg phi -> occurs t phi | Conj (phi, psi) -> occurs t phi || occurs t psi | Disj (phi, psi) -> occurs t phi || occurs t psi | Impl (phi, psi) -> occurs t phi || occurs t psi | Iff (phi, psi) -> occurs t phi || occurs t psi | Forall phi -> occurs (Term.inc_var t) phi | Exists phi -> occurs (Term.inc_var t) phi