mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-07 11:45:41 -05:00
- 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
190 lines
4.7 KiB
OCaml
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;
|
|
}
|