smt_scope/parsers/z3/
inst.rs1#[cfg(feature = "mem_dbg")]
2use mem_dbg::{MemDbg, MemSize};
3
4use crate::{
5 items::{ENodeIdx, Fingerprint, InstIdx, Instantiation, Match, MatchIdx, TermIdx},
6 parsers::z3::stack::Stack,
7 Error, FxHashMap, Result, TiVec,
8};
9
10use super::bugs::InstanceBody;
11
12#[derive(Debug)]
13pub struct InstData<'a> {
14 pub iidx: InstIdx,
15 pub inst: &'a Instantiation,
16 pub midx: MatchIdx,
17 pub match_: &'a Match,
18}
19
20#[cfg_attr(feature = "mem_dbg", derive(MemSize, MemDbg))]
21#[derive(Debug, Default)]
22pub struct Insts {
23 fingerprint_to_match: FxHashMap<Fingerprint, (MatchIdx, Option<InstIdx>)>,
25 pub(crate) matches: TiVec<MatchIdx, Match>,
26 pub(crate) insts: TiVec<InstIdx, Instantiation>,
27
28 inst_stack: Vec<ActiveInst>,
29
30 has_theory_solving_inst: bool,
31}
32
33impl Insts {
34 pub(super) fn new_match(
35 &mut self,
36 fingerprint: Fingerprint,
37 match_: Match,
38 ) -> Result<MatchIdx> {
39 self.has_theory_solving_inst |= match_.kind.quant_idx().is_none();
40
41 self.matches.raw.try_reserve(1)?;
42 let idx = self.matches.push_and_get_key(match_);
43 self.fingerprint_to_match.try_reserve(1)?;
45 self.fingerprint_to_match.insert(fingerprint, (idx, None));
46 Ok(idx)
47 }
48
49 pub fn get_match(&self, fingerprint: Fingerprint) -> Option<MatchIdx> {
50 self.fingerprint_to_match
51 .get(&fingerprint)
52 .map(|(idx, _)| *idx)
53 }
54 pub(super) fn new_inst(
55 &mut self,
56 fingerprint: Fingerprint,
57 inst: Instantiation,
58 body: Option<InstanceBody>,
59 stack: &Stack,
60 can_duplicate: bool,
61 ) -> Result<InstIdx> {
62 let (match_idx, inst_idx) = self
63 .fingerprint_to_match
64 .get_mut(&fingerprint)
65 .unwrap_or_else(|| panic!("{:x}", fingerprint.0));
66 let midx = *match_idx;
67 self.insts.raw.try_reserve(1)?;
68 let iidx = self.insts.push_and_get_key(inst);
69 debug_assert!(
72 stack.is_alive(self.matches[midx].frame)
73 && (can_duplicate
74 || !inst_idx.is_some_and(|i| stack.is_alive(self.insts[i].frame))),
75 "duplicate instantiation of fingerprint {fingerprint}",
76 );
77 *inst_idx = Some(iidx);
78
79 self.inst_stack.try_reserve(1)?;
80 self.inst_stack.push(ActiveInst::new(iidx, body));
81 Ok(iidx)
82 }
83 pub fn end_inst(&mut self) -> Result<()> {
84 let active = self.inst_stack.pop().ok_or(Error::UnmatchedEndOfInstance)?;
85 self[active.idx].yields_terms = active.yields.into();
86 Ok(())
87 }
88
89 pub(super) fn active_inst(&mut self) -> Option<&mut ActiveInst> {
90 self.inst_stack.last_mut()
91 }
92
93 pub fn has_theory_solving_inst(&self) -> bool {
94 self.has_theory_solving_inst
95 }
96
97 pub fn instantiations(&self) -> impl Iterator<Item = InstData<'_>> {
98 self.insts
99 .iter_enumerated()
100 .map(move |(iidx, inst)| self.get_inst_inner(iidx, inst))
101 }
102
103 pub fn get_inst(&self, iidx: InstIdx) -> InstData<'_> {
104 let inst = &self.insts[iidx];
105 self.get_inst_inner(iidx, inst)
106 }
107
108 fn get_inst_inner<'a>(&'a self, iidx: InstIdx, inst: &'a Instantiation) -> InstData<'a> {
109 let match_ = &self.matches[inst.match_];
110 InstData {
111 iidx,
112 inst,
113 midx: inst.match_,
114 match_,
115 }
116 }
117}
118
119#[cfg_attr(feature = "mem_dbg", derive(MemSize, MemDbg))]
120#[derive(Debug)]
121pub(super) struct ActiveInst {
122 pub(super) idx: InstIdx,
123 pub(super) body: Option<InstanceBody>,
124 pub(super) yields: Vec<ENodeIdx>,
125}
126
127impl ActiveInst {
128 fn new(idx: InstIdx, body: Option<InstanceBody>) -> Self {
129 Self {
130 idx,
131 body,
132 yields: Vec::new(),
133 }
134 }
135
136 pub(super) fn req_eqs(&self, term: TermIdx) -> impl Iterator<Item = (ENodeIdx, ENodeIdx)> + '_ {
137 self.body
138 .iter()
139 .flat_map(move |body| {
140 body.req_eqs
141 .get(&term)
142 .into_iter()
143 .flat_map(|eqs| eqs.iter())
144 })
145 .copied()
146 }
147}
148
149impl std::ops::Index<InstIdx> for Insts {
150 type Output = Instantiation;
151 fn index(&self, idx: InstIdx) -> &Self::Output {
152 &self.insts[idx]
153 }
154}
155impl std::ops::IndexMut<InstIdx> for Insts {
156 fn index_mut(&mut self, idx: InstIdx) -> &mut Self::Output {
157 &mut self.insts[idx]
158 }
159}
160
161impl std::ops::Index<MatchIdx> for Insts {
162 type Output = Match;
163 fn index(&self, idx: MatchIdx) -> &Self::Output {
164 &self.matches[idx]
165 }
166}