mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-10 05:03:59 -05:00
interface variables are terms claimed by >= 2 theories. Theories now have a unique ID attributed at their creation.
85 lines
2.5 KiB
OCaml
85 lines
2.5 KiB
OCaml
open Sidekick_core
|
|
module T = Term
|
|
|
|
type t = {
|
|
tst: Term.store;
|
|
processed: T.Set.t T.Tbl.t; (** type -> set of terms *)
|
|
unprocessed: T.t Vec.t;
|
|
new_lits: Lit.t Vec.t;
|
|
claims: Theory_id.Set.t T.Tbl.t; (** term -> theories claiming it *)
|
|
n_terms: int Stat.counter;
|
|
n_lits: int Stat.counter;
|
|
}
|
|
|
|
let create ?(stat = Stat.global) tst : t =
|
|
{
|
|
tst;
|
|
processed = T.Tbl.create 8;
|
|
unprocessed = Vec.create ();
|
|
claims = T.Tbl.create 8;
|
|
new_lits = Vec.create ();
|
|
n_terms = Stat.mk_int stat "smt.thcomb.terms";
|
|
n_lits = Stat.mk_int stat "smt.thcomb.intf-lits";
|
|
}
|
|
|
|
let processed_ (self : t) t : bool =
|
|
let ty = T.ty t in
|
|
match T.Tbl.find_opt self.processed ty with
|
|
| None -> false
|
|
| Some set -> T.Set.mem t set
|
|
|
|
let add_term_needing_combination (self : t) (t : T.t) : unit =
|
|
if not (processed_ self t) then (
|
|
Log.debugf 50 (fun k ->
|
|
k "(@[th.comb.add-term-needing-comb@ `%a`@ :ty `%a`@])" T.pp t T.pp
|
|
(T.ty t));
|
|
Vec.push self.unprocessed t
|
|
)
|
|
|
|
let claim_term (self : t) ~th_id (t : T.t) : unit =
|
|
(* booleans don't need theory combination *)
|
|
if T.is_bool (T.ty t) then
|
|
()
|
|
else (
|
|
Log.debugf 50 (fun k ->
|
|
k "(@[th.comb.claim :th-id %a@ `%a`@])" Theory_id.pp th_id T.pp t);
|
|
let set =
|
|
try T.Tbl.find self.claims t with Not_found -> Theory_id.Set.empty
|
|
in
|
|
let set' = Theory_id.Set.add th_id set in
|
|
if Theory_id.Set.(not (equal set set')) then (
|
|
T.Tbl.replace self.claims t set';
|
|
(* first time we have 2 theories, means we need combination *)
|
|
if Theory_id.Set.cardinal set' = 2 then
|
|
add_term_needing_combination self t
|
|
)
|
|
)
|
|
|
|
let pop_new_lits (self : t) : Lit.t list =
|
|
(* first, process new terms, if any *)
|
|
while not (Vec.is_empty self.unprocessed) do
|
|
let t = Vec.pop_exn self.unprocessed in
|
|
let ty = T.ty t in
|
|
let set_for_ty =
|
|
try T.Tbl.find self.processed ty with Not_found -> T.Set.empty
|
|
in
|
|
if not (T.Set.mem t set_for_ty) then (
|
|
Stat.incr self.n_terms;
|
|
|
|
(* now create [t=u] for each [u] in [set_for_ty] *)
|
|
T.Set.iter
|
|
(fun u ->
|
|
let lit = Lit.make_eq self.tst t u in
|
|
Stat.incr self.n_lits;
|
|
Vec.push self.new_lits lit)
|
|
set_for_ty;
|
|
|
|
(* add [t] to the set of processed terms *)
|
|
let new_set_for_ty = T.Set.add t set_for_ty in
|
|
T.Tbl.replace self.processed ty new_set_for_ty
|
|
)
|
|
done;
|
|
|
|
let lits = Vec.to_list self.new_lits in
|
|
Vec.clear self.new_lits;
|
|
lits
|