1use super::expr::ExprId;
4use super::name::NameId;
5use std::rc::Rc;
6
7#[derive(Copy, Clone, PartialEq, Eq, Debug)]
8pub enum Hint {
9 Opaque,
10 Abbrev,
11 Regular(u32),
12}
13
14impl Hint {
15 pub fn lt(self, other: Hint) -> bool {
17 match (self, other) {
18 (_, Hint::Opaque) => false,
19 (Hint::Abbrev, _) => false,
20 (Hint::Opaque, _) => true,
21 (_, Hint::Abbrev) => true,
22 (Hint::Regular(a), Hint::Regular(b)) => a < b,
23 }
24 }
25}
26
27#[derive(Copy, Clone, PartialEq, Eq, Debug)]
28pub enum Safety {
29 Safe,
30 Unsafe,
31 Partial,
32}
33
34#[derive(Copy, Clone, PartialEq, Eq, Debug)]
35pub enum QuotKind {
36 Type,
37 Ctor,
38 Lift,
39 Ind,
40}
41
42#[derive(Clone, Debug, PartialEq)]
43pub struct RecRule {
44 pub ctor: NameId,
45 pub nfields: u32,
46 pub rhs: ExprId,
47}
48
49#[derive(Clone, Debug, PartialEq)]
50pub struct InductiveInfo {
51 pub num_params: u32,
52 pub num_indices: u32,
53 pub all: Rc<[NameId]>,
54 pub ctors: Rc<[NameId]>,
55 pub num_nested: u32,
56 pub is_rec: bool,
57 pub is_reflexive: bool,
58 pub is_unsafe: bool,
59 pub rec: NameId,
61}
62
63#[derive(Clone, Debug, PartialEq)]
64pub struct CtorInfo {
65 pub induct: NameId,
66 pub cidx: u32,
67 pub num_params: u32,
68 pub num_fields: u32,
69 pub is_unsafe: bool,
70}
71
72#[derive(Clone, Debug, PartialEq)]
73pub struct RecInfo {
74 pub all: Rc<[NameId]>,
75 pub num_params: u32,
76 pub num_indices: u32,
77 pub num_motives: u32,
78 pub num_minors: u32,
79 pub rules: Rc<[RecRule]>,
80 pub k: bool,
81 pub is_unsafe: bool,
82 pub major_induct: NameId,
85}
86
87impl RecInfo {
88 pub fn major_idx(&self) -> usize {
89 (self.num_params + self.num_motives + self.num_minors + self.num_indices) as usize
90 }
91 pub fn first_index_idx(&self) -> usize {
92 (self.num_params + self.num_motives + self.num_minors) as usize
93 }
94}
95
96#[derive(Clone, Debug, PartialEq)]
97pub enum Kind {
98 Axiom {
99 is_unsafe: bool,
100 },
101 Defn {
102 value: ExprId,
103 hint: Hint,
104 safety: Safety,
105 },
106 Thm {
107 value: ExprId,
108 },
109 Opaque {
110 value: ExprId,
111 is_unsafe: bool,
112 },
113 Quot(QuotKind),
114 Induct(InductiveInfo),
115 Ctor(CtorInfo),
116 Rec(RecInfo),
117}
118
119#[derive(Clone, Debug, PartialEq)]
120pub struct Const {
121 pub name: NameId,
122 pub lparams: Rc<[NameId]>,
123 pub ty: ExprId,
124 pub kind: Kind,
125}
126
127impl Const {
128 pub fn is_unsafe(&self) -> bool {
129 match &self.kind {
130 Kind::Axiom { is_unsafe } | Kind::Opaque { is_unsafe, .. } => *is_unsafe,
131 Kind::Defn { safety, .. } => *safety == Safety::Unsafe,
132 Kind::Thm { .. } | Kind::Quot(_) => false,
133 Kind::Induct(i) => i.is_unsafe,
134 Kind::Ctor(c) => c.is_unsafe,
135 Kind::Rec(r) => r.is_unsafe,
136 }
137 }
138
139 pub fn is_partial(&self) -> bool {
140 matches!(
141 self.kind,
142 Kind::Defn {
143 safety: Safety::Partial,
144 ..
145 }
146 )
147 }
148
149 pub fn delta_value(&self) -> Option<ExprId> {
151 match self.kind {
152 Kind::Defn { value, .. } | Kind::Thm { value } => Some(value),
153 _ => None,
154 }
155 }
156
157 pub fn hint(&self) -> Hint {
158 match self.kind {
159 Kind::Defn { hint, .. } => hint,
160 _ => Hint::Opaque,
161 }
162 }
163}
164
165#[derive(Clone, Default)]
167pub struct Env {
168 consts: Vec<Option<Rc<Const>>>,
169 pub count: usize,
170 pub quot_init: bool,
171 pub quotients: Vec<super::wellknown::QuotNames>,
173 provisional: Vec<NameId>,
177}
178
179impl Env {
180 #[inline]
181 pub fn get(&self, n: NameId) -> Option<&Rc<Const>> {
182 self.consts.get(n.0 as usize).and_then(|c| c.as_ref())
183 }
184
185 pub fn contains(&self, n: NameId) -> bool {
186 self.get(n).is_some()
187 }
188
189 pub fn constants(&self) -> impl Iterator<Item = &Rc<Const>> {
191 self.consts.iter().flatten()
192 }
193
194 pub fn add(&mut self, c: Const) {
195 let i = c.name.0 as usize;
196 if self.consts.len() <= i {
197 self.consts.resize(i + 1, None);
198 }
199 debug_assert!(self.consts[i].is_none());
200 self.consts[i] = Some(Rc::new(c));
201 self.count += 1;
202 }
203
204 pub fn add_provisional(&mut self, c: Const) {
207 self.provisional.push(c.name);
208 self.add(c);
209 }
210
211 pub fn remove(&mut self, n: NameId) {
213 if let Some(slot) = self.consts.get_mut(n.0 as usize) {
214 if slot.take().is_some() {
215 self.count -= 1;
216 }
217 }
218 self.provisional.retain(|p| *p != n);
219 }
220
221 #[inline]
223 pub fn is_settled(&self, n: NameId) -> bool {
224 self.provisional.is_empty() || !self.provisional.contains(&n)
225 }
226
227 pub fn inductive(&self, n: NameId) -> Option<&InductiveInfo> {
228 match &self.get(n)?.kind {
229 Kind::Induct(i) => Some(i),
230 _ => None,
231 }
232 }
233
234 pub fn ctor(&self, n: NameId) -> Option<&CtorInfo> {
235 match &self.get(n)?.kind {
236 Kind::Ctor(c) => Some(c),
237 _ => None,
238 }
239 }
240
241 pub fn rec(&self, n: NameId) -> Option<&RecInfo> {
242 match &self.get(n)?.kind {
243 Kind::Rec(r) => Some(r),
244 _ => None,
245 }
246 }
247
248 pub fn is_non_rec_structure(&self, n: NameId) -> bool {
250 matches!(self.inductive(n), Some(i) if !i.is_rec && i.ctors.len() == 1 && i.num_indices == 0)
251 }
252
253 pub fn eliminates_into_every_sort(&self, n: NameId) -> bool {
257 match (self.get(n), self.inductive(n).and_then(|i| self.get(i.rec))) {
258 (Some(i), Some(r)) => r.lparams.len() == i.lparams.len() + 1,
259 _ => false,
260 }
261 }
262}