sidekick/src/smt/Term.ml
Simon Cruanes 50fe488dcb refactor types for terms and congruence closure
- terms are extensible
- explanations have a custom case, shaped as a term
- remove distinction repr/node in Equiv_class, for simplicity
- make propositional connectives n-ary
2018-01-30 21:55:37 -06:00

190 lines
4.7 KiB
OCaml

open Solver_types
type t = term
let[@inline] id t = t.term_id
let[@inline] ty t = t.term_ty
let[@inline] cell t = t.term_cell
let equal = term_equal_
let hash = term_hash_
let compare a b = CCInt.compare a.term_id b.term_id
type state = {
tbl : term Term_cell.Tbl.t;
mutable n: int;
true_ : t lazy_t;
false_ : t lazy_t;
}
let mk_real_ st c : t =
let term_ty = Term_cell.ty c in
let t = {
term_id= st.n;
term_ty;
term_cell=c;
} in
st.n <- 1 + st.n;
Term_cell.Tbl.add st.tbl c t;
t
let[@inline] make st (c:t term_cell) : t =
try Term_cell.Tbl.find st.tbl c
with Not_found -> mk_real_ st c
let[@inline] true_ st = Lazy.force st.true_
let[@inline] false_ st = Lazy.force st.false_
let create ?(size=1024) () : state =
let rec st ={
n=2;
tbl=Term_cell.Tbl.create size;
true_ = lazy (make st Term_cell.true_);
false_ = lazy (make st (Term_cell.not_ (true_ st)));
} in
ignore (Lazy.force st.true_);
ignore (Lazy.force st.false_); (* not true *)
st
let[@inline] all_terms st = Term_cell.Tbl.values st.tbl
let app_cst st f a =
let cell = Term_cell.app_cst f a in
make st cell
let const st c = app_cst st c IArray.empty
let case st u m = make st (Term_cell.case u m)
let if_ st a b c = make st (Term_cell.if_ a b c)
let not_ st t = make st (Term_cell.not_ t)
let and_l st = function
| [] -> true_ st
| [t] -> t
| l -> make st (Term_cell.and_ l)
let or_l st = function
| [] -> false_ st
| [t] -> t
| l -> make st (Term_cell.or_ l)
let and_ st a b = and_l st [a;b]
let or_ st a b = and_l st [a;b]
let imply st a b = match a with [] -> b | _ -> make st (Term_cell.imply a b)
let eq st a b = make st (Term_cell.eq a b)
let neq st a b = not_ st (eq st a b)
let builtin st b = make st (Term_cell.builtin b)
(* "eager" and, evaluating [a] first *)
let and_eager st a b = if_ st a b (false_ st)
let cstor_test st cstor t = make st (Term_cell.cstor_test cstor t)
let cstor_proj st cstor i t = make st (Term_cell.cstor_proj cstor i t)
(* might need to tranfer the negation from [t] to [sign] *)
let abs t : t * bool = match t.term_cell with
| Builtin (B_not t) -> t, false
| _ -> t, true
let fold_map_builtin
(f:'a -> term -> 'a * term) (acc:'a) (b:t builtin): 'a * t builtin =
let fold_binary acc a b =
let acc, a = f acc a in
let acc, b = f acc b in
acc, a, b
in
match b with
| B_not t ->
let acc, t' = f acc t in
acc, B_not t'
| B_and l ->
let acc, l = CCList.fold_map f acc l in
acc, B_and l
| B_or l ->
let acc, l = CCList.fold_map f acc l in
acc, B_or l
| B_eq (a,b) ->
let acc, a, b = fold_binary acc a b in
acc, B_eq (a, b)
| B_imply (a,b) ->
let acc, a = CCList.fold_map f acc a in
let acc, b = f acc b in
acc, B_imply (a, b)
let is_const t = match t.term_cell with
| App_cst (_, a) -> IArray.is_empty a
| _ -> false
let map_builtin f b =
let (), b = fold_map_builtin (fun () t -> (), f t) () b in
b
let builtin_to_seq b yield = match b with
| B_not t -> yield t
| B_or l | B_and l -> List.iter yield l
| B_imply (a,b) -> List.iter yield a; yield b
| B_eq (a,b) -> yield a; yield b
module As_key = struct
type t = term
let compare = compare
let equal = equal
let hash = hash
end
module Map = CCMap.Make(As_key)
module Tbl = CCHashtbl.Make(As_key)
let to_seq t yield =
let rec aux t =
yield t;
match t.term_cell with
| True -> ()
| App_cst (_,a) -> IArray.iter aux a
| If (a,b,c) -> aux a; aux b; aux c
| Case (t, m) ->
aux t;
ID.Map.iter (fun _ rhs -> aux rhs) m
| Builtin b -> builtin_to_seq b aux
| Custom {view;tc} -> tc.tc_t_sub view aux
in
aux t
(* return [Some] iff the term is an undefined constant *)
let as_cst_undef (t:term): (cst * Ty.t) option =
match t.term_cell with
| App_cst (c, a) when IArray.is_empty a ->
Cst.as_undefined c
| _ -> None
(* return [Some (cstor,ty,args)] if the term is a constructor
applied to some arguments *)
let as_cstor_app (t:term): (cst * data_cstor * term IArray.t) option =
match t.term_cell with
| App_cst ({cst_kind=Cst_cstor (lazy cstor); _} as c, a) ->
Some (c,cstor,a)
| _ -> None
(* typical view for unification/equality *)
type unif_form =
| Unif_cst of cst * Ty.t
| Unif_cstor of cst * data_cstor * term IArray.t
| Unif_none
let as_unif (t:term): unif_form = match t.term_cell with
| App_cst ({cst_kind=Cst_undef ty; _} as c, a) when IArray.is_empty a ->
Unif_cst (c,ty)
| App_cst ({cst_kind=Cst_cstor (lazy cstor); _} as c, a) ->
Unif_cstor (c,cstor,a)
| _ -> Unif_none
let pp = Solver_types.pp_term
let dummy : t = {
term_id= -1;
term_ty=Ty.prop;
term_cell=True;
}