1use super::value::{EnvId, Head, Kind, Val, V};
20use super::{reject, Sem};
21use crate::dag::env::Kind as CKind;
22use crate::dag::error::KResult;
23use crate::dag::expr::{ExprId, Node};
24use crate::dag::level::{LevelId, LevelsId, SubstId};
25use crate::dag::name::NameId;
26
27impl Sem<'_> {
28 #[inline]
33 pub(crate) fn env_for(&mut self, env: EnvId, e: ExprId) -> EnvId {
34 let (n, mask, lparams) = self.k.s.scope_of(e);
35 let node = self.st.arena.env(env);
36 if n == 0 {
37 return self.st.arena.lsub_base(if lparams {
38 node.lsub
39 } else {
40 SubstId::IDENTITY
41 });
42 }
43 let lsub = node.lsub;
44 let Some(mask) = mask else {
45 return self.prune_wide(env, e, lsub);
46 };
47 if n == node.len && node.live == mask {
48 return env;
49 }
50 if let Some(r) = self.st.arena.last_prune(env, mask) {
51 return r;
52 }
53 self.prune(env, n, mask)
54 }
55
56 #[cold]
58 #[inline(never)]
59 fn prune(&mut self, env: EnvId, n: u32, mask: u64) -> EnvId {
60 debug_assert!(n <= 64 && mask != 0 && 64 - mask.leading_zeros() == n);
61 let r = match self.st.prune_cache.get(&(env.0, mask)) {
62 Some(e) => EnvId(e),
63 None => {
64 let mut vals: smallvec::SmallVec<[V; 16]> = smallvec::SmallVec::new();
65 self.st.arena.select(env, mask, &mut vals);
66 let lsub = self.st.arena.lsub_of(env);
67 let r = self.st.arena.frame(n, mask, &vals, lsub);
68 self.st.prune_cache.insert((env.0, mask), r.0);
69 r
70 }
71 };
72 self.st.arena.note_prune(env, mask, r);
73 r
74 }
75
76 #[cold]
82 #[inline(never)]
83 fn prune_wide(&mut self, env: EnvId, e: ExprId, lsub: SubstId) -> EnvId {
84 let set = self.loose_set(e);
85 let node = self.st.arena.env(env);
86 if node.dense && set.len() == node.len as usize && node.lsub == lsub {
87 return env;
88 }
89 let key = (env.0, e.0);
90 if let Some(r) = self.st.wide_prune_cache.get(&key) {
91 return EnvId(r);
92 }
93 let Some(&last) = set.last() else {
94 return self.st.arena.lsub_base(lsub);
95 };
96 let mut vals: smallvec::SmallVec<[V; 16]> = smallvec::SmallVec::new();
97 self.st.arena.select_indices(env, &set, &mut vals);
98 let r = if last < 64 {
99 let mask = set.iter().fold(0u64, |m, &i| m | (1 << i));
100 self.st.arena.frame(last + 1, mask, &vals, lsub)
101 } else {
102 self.st.arena.wide_frame(last + 1, &set, &vals, lsub)
103 };
104 self.st.wide_prune_cache.insert(key, r.0);
105 r
106 }
107
108 pub(crate) fn loose_set(&mut self, e: ExprId) -> std::rc::Rc<[u32]> {
111 if let (n, Some(mask)) = self.k.s.loose_bvars(e) {
112 debug_assert!(n <= 64);
113 let mut v = Vec::with_capacity(mask.count_ones() as usize);
114 let mut m = mask;
115 while m != 0 {
116 v.push(m.trailing_zeros());
117 m &= m - 1;
118 }
119 return v.into();
120 }
121 if let Some(r) = self.st.loose_sets.get(&e) {
122 return r.clone();
123 }
124 let r: std::rc::Rc<[u32]> = match self.k.s.node(e) {
125 Node::BVar(i) => vec![i].into(),
126 Node::App(f, a) => {
127 let (x, y) = (self.loose_set(f), self.loose_set(a));
128 union_shifted(&x, &y, 0)
129 }
130 Node::Lam(d, b) | Node::Pi(d, b) => {
131 let (x, y) = (self.loose_set(d), self.loose_set(b));
132 union_shifted(&x, &y, 1)
133 }
134 Node::Let(t, v, b) => {
135 let (x, y, z) = (self.loose_set(t), self.loose_set(v), self.loose_set(b));
136 union_shifted(&union_shifted(&x, &y, 0), &z, 1)
137 }
138 Node::Proj(_, _, x) => self.loose_set(x),
139 _ => Vec::new().into(),
140 };
141 if !e.is_scratch() {
142 self.st.loose_sets.insert(e, r.clone());
143 }
144 r
145 }
146
147 fn const_kind(&mut self, n: NameId, ls: LevelsId) -> KResult<Kind> {
149 let Some(c) = self.k.env.get(n) else {
150 return Err(reject(format!(
151 "unknown constant '{}'",
152 self.k.s.names.display(n)
153 )));
154 };
155 let kind = match &c.kind {
156 CKind::Defn { .. } | CKind::Thm { .. } => {
157 if self.k.s.levels.get_list(ls).len() == c.lparams.len() {
158 Kind::Delta
159 } else {
160 Kind::Opaque
161 }
162 }
163 CKind::Ctor(_) => Kind::Ctor,
164 CKind::Rec(_) => Kind::Rec,
165 CKind::Quot(_) => Kind::Quot,
166 CKind::Axiom { .. } | CKind::Opaque { .. } | CKind::Induct(_) => Kind::Opaque,
167 };
168 if !self.k.env.is_settled(n) {
169 self.st.scratch_seen = true;
170 self.st.counters.scratch_unsettled += 1;
171 }
172 Ok(kind)
173 }
174
175 pub(crate) fn const_value(&mut self, n: NameId, ls: LevelsId) -> KResult<V> {
177 let h = Head::Const {
178 name: n,
179 levels: ls,
180 };
181 if let Some(v) = self.st.arena.find_head(&h) {
182 return Ok(v);
183 }
184 let kind = self.const_kind(n, ls)?;
185 Ok(self.st.arena.head_value(kind, h))
186 }
187
188 pub(crate) fn const0(&mut self, n: NameId) -> KResult<V> {
189 self.const_value(n, LevelsId::EMPTY)
190 }
191
192 pub(crate) fn instance_base(&mut self, c: NameId, ls: LevelsId) -> KResult<EnvId> {
196 let Some(k) = self.k.env.get(c) else {
197 return Err(reject(format!(
198 "unknown constant '{}'",
199 self.k.s.names.display(c)
200 )));
201 };
202 let ps = k.lparams.clone();
203 if !self.k.env.is_settled(c) {
204 self.st.scratch_seen = true;
205 self.st.counters.scratch_instance += 1;
206 }
207 let s = self.k.s.levels.substitution(&ps, ls);
208 Ok(self.st.arena.lsub_base(s))
209 }
210
211 pub fn const_type(&mut self, n: NameId, ls: LevelsId) -> KResult<V> {
213 if let Some(v) = self.st.const_type.get(&(n.0, ls.0)) {
214 return Ok(V(v));
215 }
216 let base = self.instance_base(n, ls)?;
217 let ty = self.k.env.get(n).expect("a known constant").ty;
218 let v = self.eval(base, ty)?;
219 self.st.const_type.insert((n.0, ls.0), v.0);
220 Ok(v)
221 }
222
223 #[inline]
225 pub(crate) fn level_in(&mut self, env: EnvId, l: LevelId) -> LevelId {
226 let s = self.st.arena.lsub_of(env);
227 if s == SubstId::IDENTITY {
228 l
229 } else {
230 self.k.s.levels.subst(l, s)
231 }
232 }
233
234 #[inline]
236 pub(crate) fn levels_in(&mut self, env: EnvId, ls: LevelsId) -> LevelsId {
237 let s = self.st.arena.lsub_of(env);
238 if s == SubstId::IDENTITY {
239 ls
240 } else {
241 self.k.s.levels.subst_list(ls, s)
242 }
243 }
244
245 pub fn eval(&mut self, env: EnvId, e: ExprId) -> KResult<V> {
247 match self.k.s.node(e) {
248 Node::BVar(i) => self
249 .st
250 .arena
251 .lookup(env, i)
252 .ok_or_else(|| reject("evaluation met a loose bound variable")),
253 Node::Sort(l) => {
254 let s = self.atom_subst(env, e);
255 if let Some(v) = self.st.atom_memo(e, s) {
256 return Ok(v);
257 }
258 let l = self.k.s.levels.subst(l, s);
259 let v = self.st.arena.sort(l);
260 self.st.note_atom(e, s, v);
261 Ok(v)
262 }
263 Node::Const(n, ls) => {
264 let s = self.atom_subst(env, e);
265 if let Some(v) = self.st.atom_memo(e, s) {
266 return Ok(v);
267 }
268 let ls = self.k.s.levels.subst_list(ls, s);
269 let v = self.const_value(n, ls)?;
270 self.st.note_atom(e, s, v);
271 Ok(v)
272 }
273 Node::NatLit(n) => Ok(self.st.arena.nat(n)),
274 Node::StrLit(s) => Ok(self.st.arena.str(s)),
275 Node::FVar(_) => Err(reject("the value engine met a free variable")),
276 Node::Lam(dom, body) => {
277 self.note_expr(e);
278 let env = self.env_for(env, e);
279 Ok(self.st.arena.lam(dom, env, body))
280 }
281 _ => {
282 self.note_expr(e);
283 let env = self.env_for(env, e);
284 if let Some(v) = self.st.eval_cache.get(&(env.0, e.0)) {
285 return Ok(V(v));
286 }
287 self.enter()?;
288 let r = self.eval_node(env, e);
289 self.leave();
290 let v = r?;
291 self.st.eval_cache.insert((env.0, e.0), v.0);
292 Ok(v)
293 }
294 }
295 }
296
297 #[inline]
300 fn atom_subst(&self, env: EnvId, e: ExprId) -> SubstId {
301 let s = self.st.arena.lsub_of(env);
302 if s != SubstId::IDENTITY && self.k.s.has_lparam(e) {
303 s
304 } else {
305 SubstId::IDENTITY
306 }
307 }
308
309 #[inline]
311 pub(crate) fn note_expr(&mut self, e: ExprId) {
312 if e.is_scratch() {
313 self.st.scratch_seen = true;
314 self.st.counters.scratch_expr += 1;
315 }
316 }
317
318 fn eval_node(&mut self, env: EnvId, e: ExprId) -> KResult<V> {
319 match self.k.s.node(e) {
320 Node::App(..) => {
321 let (f, args) = self.k.s.app_args(e);
322 let mut fv = self.eval(env, f)?;
323 let mut i = 0;
324 while i < args.len() {
325 if let Val::Lam {
326 env: cenv, body, ..
327 } = self.st.arena.get(fv)
328 {
329 let a = self.eval(env, args[i])?;
330 let mut benv = self.st.arena.extend(cenv, a);
331 let mut b = body;
332 i += 1;
333 while i < args.len() {
334 let Node::Lam(_, inner) = self.k.s.node(b) else {
335 break;
336 };
337 let a = self.eval(env, args[i])?;
338 benv = self.st.arena.extend(benv, a);
339 b = inner;
340 i += 1;
341 }
342 fv = self.eval(benv, b)?;
343 } else {
344 let a = self.eval(env, args[i])?;
345 fv = self.apply(fv, a)?;
346 i += 1;
347 }
348 }
349 Ok(fv)
350 }
351 Node::Pi(dom, body) => {
352 let d = self.eval(env, dom)?;
353 Ok(self.st.arena.pi(d, env, body))
354 }
355 Node::Let(_, val, body) => {
356 let v = self.eval(env, val)?;
357 let env2 = self.st.arena.extend(env, v);
358 self.eval(env2, body)
359 }
360 Node::Proj(s, idx, x) => {
361 let xv = self.eval(env, x)?;
362 self.proj(s, idx, xv)
363 }
364 _ => unreachable!("atoms are evaluated directly"),
365 }
366 }
367
368 pub fn apply(&mut self, f: V, a: V) -> KResult<V> {
370 match self.st.arena.get(f) {
371 Val::Lam { env, body, .. } => {
372 let env2 = self.st.arena.extend(env, a);
373 self.eval(env2, body)
374 }
375 Val::Neu { .. } => Ok(self.st.arena.neutral_app(f, a)),
376 _ => Err(reject("application of a value that is not a function")),
377 }
378 }
379
380 pub(crate) fn apply_all(&mut self, mut f: V, args: &[V]) -> KResult<V> {
381 let mut i = 0;
382 while i < args.len() {
383 if let Val::Lam { env, body, .. } = self.st.arena.get(f) {
384 let mut benv = self.st.arena.extend(env, args[i]);
385 let mut b = body;
386 i += 1;
387 while i < args.len() {
388 let Node::Lam(_, inner) = self.k.s.node(b) else {
389 break;
390 };
391 benv = self.st.arena.extend(benv, args[i]);
392 b = inner;
393 i += 1;
394 }
395 f = self.eval(benv, b)?;
396 } else {
397 f = self.apply(f, args[i])?;
398 i += 1;
399 }
400 }
401 Ok(f)
402 }
403
404 pub(crate) fn lam_domain(&mut self, v: V) -> KResult<V> {
406 match self.st.arena.get(v) {
407 Val::Lam { dom, env, .. } => {
408 if let Some(d) = self.st.arena.dom_memo(v) {
409 return Ok(d);
410 }
411 let d = self.eval(env, dom)?;
412 self.st.arena.set_dom_memo(v, d);
413 Ok(d)
414 }
415 Val::Pi { dom, .. } | Val::PiLam { dom, .. } => Ok(dom),
416 _ => Err(reject("expected a function")),
417 }
418 }
419
420 pub fn instantiate(&mut self, clo: V, x: V) -> KResult<V> {
422 match self.st.arena.get(clo) {
423 Val::Lam { env, body, .. } | Val::Pi { env, body, .. } => {
424 let env2 = self.st.arena.extend(env, x);
425 self.eval(env2, body)
426 }
427 Val::PiLam {
428 dom,
429 env,
430 ctx,
431 body,
432 } => {
433 let env2 = self.st.arena.extend(env, x);
434 let ctx2 = self.st.arena.ctx_extend(ctx, dom);
435 self.infer(env2, ctx2, body, false)
436 }
437 _ => Err(reject("expected a function or function type")),
438 }
439 }
440}
441
442fn union_shifted(
446 a: &std::rc::Rc<[u32]>,
447 whole: &std::rc::Rc<[u32]>,
448 shift: u32,
449) -> std::rc::Rc<[u32]> {
450 let b = &whole[whole.partition_point(|&i| i < shift)..];
451 if b.is_empty() {
452 return a.clone();
453 }
454 if a.is_empty() && shift == 0 {
455 return whole.clone();
456 }
457 let mut out = Vec::with_capacity(a.len() + b.len());
458 let (mut i, mut j) = (0, 0);
459 while i < a.len() && j < b.len() {
460 let (x, y) = (a[i], b[j] - shift);
461 match x.cmp(&y) {
462 std::cmp::Ordering::Less => {
463 out.push(x);
464 i += 1;
465 }
466 std::cmp::Ordering::Greater => {
467 out.push(y);
468 j += 1;
469 }
470 std::cmp::Ordering::Equal => {
471 out.push(x);
472 i += 1;
473 j += 1;
474 }
475 }
476 }
477 out.extend_from_slice(&a[i..]);
478 out.extend(b[j..].iter().map(|&y| y - shift));
479 if out.len() == a.len() {
480 return a.clone();
481 }
482 out.into()
483}
484
485#[cfg(test)]
486#[path = "../../../../logicaffeine_tests/unit/logicaffeine_kernel/dag/sem/eval/union_controls.rs"]
487mod union_controls;