1use super::functions::*;
6use crate::declaration::{
7 ConstantInfo, ConstantVal, ConstructorVal, InductiveVal, RecursorRule, RecursorVal,
8};
9use crate::{Expr, KernelError, Level, Name};
10use std::collections::HashMap;
11
12#[allow(dead_code)]
14pub struct StatSummary {
15 count: u64,
16 sum: f64,
17 min: f64,
18 max: f64,
19}
20#[allow(dead_code)]
21impl StatSummary {
22 pub fn new() -> Self {
24 Self {
25 count: 0,
26 sum: 0.0,
27 min: f64::INFINITY,
28 max: f64::NEG_INFINITY,
29 }
30 }
31 pub fn record(&mut self, val: f64) {
33 self.count += 1;
34 self.sum += val;
35 if val < self.min {
36 self.min = val;
37 }
38 if val > self.max {
39 self.max = val;
40 }
41 }
42 pub fn mean(&self) -> Option<f64> {
44 if self.count == 0 {
45 None
46 } else {
47 Some(self.sum / self.count as f64)
48 }
49 }
50 pub fn min(&self) -> Option<f64> {
52 if self.count == 0 {
53 None
54 } else {
55 Some(self.min)
56 }
57 }
58 pub fn max(&self) -> Option<f64> {
60 if self.count == 0 {
61 None
62 } else {
63 Some(self.max)
64 }
65 }
66 pub fn count(&self) -> u64 {
68 self.count
69 }
70}
71#[derive(Clone, Debug, PartialEq)]
73pub enum InductiveError {
74 AlreadyDefined(Name),
76 UndefinedType(Name),
78 InvalidConstructorType(Name),
80 UniverseTooSmall(String),
82 NonStrictlyPositive(Name),
84 Other(String),
86}
87#[derive(Clone, Debug, PartialEq)]
89pub struct IntroRule {
90 pub name: Name,
92 pub ty: Expr,
94}
95#[derive(Clone, Debug)]
100pub struct InductiveFamily {
101 pub types: Vec<InductiveType>,
103 pub univ_params: Vec<Name>,
105}
106impl InductiveFamily {
107 pub fn singleton(ty: InductiveType) -> Self {
109 let univ_params = ty.univ_params.clone();
110 Self {
111 types: vec![ty],
112 univ_params,
113 }
114 }
115 pub fn new(types: Vec<InductiveType>, univ_params: Vec<Name>) -> Self {
117 Self { types, univ_params }
118 }
119 pub fn len(&self) -> usize {
121 self.types.len()
122 }
123 pub fn is_singleton(&self) -> bool {
125 self.types.len() == 1
126 }
127 pub fn is_empty(&self) -> bool {
129 self.types.is_empty()
130 }
131 pub fn type_names(&self) -> Vec<&Name> {
133 self.types.iter().map(|t| &t.name).collect()
134 }
135 pub fn all_constructor_names(&self) -> Vec<&Name> {
137 self.types
138 .iter()
139 .flat_map(|t| t.intro_rules.iter().map(|r| &r.name))
140 .collect()
141 }
142 pub fn find_type(&self, name: &Name) -> Option<&InductiveType> {
144 self.types.iter().find(|t| &t.name == name)
145 }
146 pub fn total_constructors(&self) -> usize {
148 self.types.iter().map(|t| t.intro_rules.len()).sum()
149 }
150}
151#[allow(dead_code)]
153pub struct SmallMap<K: Ord + Clone, V: Clone> {
154 entries: Vec<(K, V)>,
155}
156#[allow(dead_code)]
157impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
158 pub fn new() -> Self {
160 Self {
161 entries: Vec::new(),
162 }
163 }
164 pub fn insert(&mut self, key: K, val: V) {
166 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
167 Ok(i) => self.entries[i].1 = val,
168 Err(i) => self.entries.insert(i, (key, val)),
169 }
170 }
171 pub fn get(&self, key: &K) -> Option<&V> {
173 self.entries
174 .binary_search_by_key(&key, |(k, _)| k)
175 .ok()
176 .map(|i| &self.entries[i].1)
177 }
178 pub fn len(&self) -> usize {
180 self.entries.len()
181 }
182 pub fn is_empty(&self) -> bool {
184 self.entries.is_empty()
185 }
186 pub fn keys(&self) -> Vec<&K> {
188 self.entries.iter().map(|(k, _)| k).collect()
189 }
190 pub fn values(&self) -> Vec<&V> {
192 self.entries.iter().map(|(_, v)| v).collect()
193 }
194}
195#[allow(dead_code)]
197pub struct ConfigNode {
198 key: String,
199 value: Option<String>,
200 children: Vec<ConfigNode>,
201}
202#[allow(dead_code)]
203impl ConfigNode {
204 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
206 Self {
207 key: key.into(),
208 value: Some(value.into()),
209 children: Vec::new(),
210 }
211 }
212 pub fn section(key: impl Into<String>) -> Self {
214 Self {
215 key: key.into(),
216 value: None,
217 children: Vec::new(),
218 }
219 }
220 pub fn add_child(&mut self, child: ConfigNode) {
222 self.children.push(child);
223 }
224 pub fn key(&self) -> &str {
226 &self.key
227 }
228 pub fn value(&self) -> Option<&str> {
230 self.value.as_deref()
231 }
232 pub fn num_children(&self) -> usize {
234 self.children.len()
235 }
236 pub fn lookup(&self, path: &str) -> Option<&str> {
238 let mut parts = path.splitn(2, '.');
239 let head = parts.next()?;
240 let tail = parts.next();
241 if head != self.key {
242 return None;
243 }
244 match tail {
245 None => self.value.as_deref(),
246 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
247 }
248 }
249 fn lookup_relative(&self, path: &str) -> Option<&str> {
250 let mut parts = path.splitn(2, '.');
251 let head = parts.next()?;
252 let tail = parts.next();
253 if head != self.key {
254 return None;
255 }
256 match tail {
257 None => self.value.as_deref(),
258 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
259 }
260 }
261}
262#[allow(dead_code)]
264pub struct SimpleDag {
265 edges: Vec<Vec<usize>>,
267}
268#[allow(dead_code)]
269impl SimpleDag {
270 pub fn new(n: usize) -> Self {
272 Self {
273 edges: vec![Vec::new(); n],
274 }
275 }
276 pub fn add_edge(&mut self, from: usize, to: usize) {
278 if from < self.edges.len() {
279 self.edges[from].push(to);
280 }
281 }
282 pub fn successors(&self, node: usize) -> &[usize] {
284 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
285 }
286 pub fn can_reach(&self, from: usize, to: usize) -> bool {
288 let mut visited = vec![false; self.edges.len()];
289 self.dfs(from, to, &mut visited)
290 }
291 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
292 if cur == target {
293 return true;
294 }
295 if cur >= visited.len() || visited[cur] {
296 return false;
297 }
298 visited[cur] = true;
299 for &next in self.successors(cur) {
300 if self.dfs(next, target, visited) {
301 return true;
302 }
303 }
304 false
305 }
306 pub fn topological_sort(&self) -> Option<Vec<usize>> {
308 let n = self.edges.len();
309 let mut in_degree = vec![0usize; n];
310 for succs in &self.edges {
311 for &s in succs {
312 if s < n {
313 in_degree[s] += 1;
314 }
315 }
316 }
317 let mut queue: std::collections::VecDeque<usize> =
318 (0..n).filter(|&i| in_degree[i] == 0).collect();
319 let mut order = Vec::new();
320 while let Some(node) = queue.pop_front() {
321 order.push(node);
322 for &s in self.successors(node) {
323 if s < n {
324 in_degree[s] -= 1;
325 if in_degree[s] == 0 {
326 queue.push_back(s);
327 }
328 }
329 }
330 }
331 if order.len() == n {
332 Some(order)
333 } else {
334 None
335 }
336 }
337 pub fn num_nodes(&self) -> usize {
339 self.edges.len()
340 }
341}
342#[allow(dead_code)]
344pub struct WindowIterator<'a, T> {
345 pub(super) data: &'a [T],
346 pub(super) pos: usize,
347 pub(super) window: usize,
348}
349#[allow(dead_code)]
350impl<'a, T> WindowIterator<'a, T> {
351 pub fn new(data: &'a [T], window: usize) -> Self {
353 Self {
354 data,
355 pos: 0,
356 window,
357 }
358 }
359}
360pub struct InductiveEnv {
362 inductives: HashMap<Name, InductiveType>,
364 constructors: HashMap<Name, Name>,
366 recursors: HashMap<Name, Name>,
368}
369impl InductiveEnv {
370 pub fn new() -> Self {
372 Self {
373 inductives: HashMap::new(),
374 constructors: HashMap::new(),
375 recursors: HashMap::new(),
376 }
377 }
378 #[allow(clippy::result_large_err)]
380 pub fn add(&mut self, ind: InductiveType) -> Result<(), KernelError> {
381 if self.inductives.contains_key(&ind.name) {
382 return Err(KernelError::Other(format!(
383 "inductive type already declared: {}",
384 ind.name
385 )));
386 }
387 for intro in &ind.intro_rules {
388 if self.constructors.contains_key(&intro.name) {
389 return Err(KernelError::Other(format!(
390 "constructor already declared: {}",
391 intro.name
392 )));
393 }
394 self.constructors
395 .insert(intro.name.clone(), ind.name.clone());
396 }
397 self.recursors
398 .insert(ind.recursor.clone(), ind.name.clone());
399 self.inductives.insert(ind.name.clone(), ind);
400 Ok(())
401 }
402 pub fn get(&self, name: &Name) -> Option<&InductiveType> {
404 self.inductives.get(name)
405 }
406 pub fn is_constructor(&self, name: &Name) -> bool {
408 self.constructors.contains_key(name)
409 }
410 pub fn get_constructor_parent(&self, name: &Name) -> Option<&Name> {
412 self.constructors.get(name)
413 }
414 pub fn is_recursor(&self, name: &Name) -> bool {
416 self.recursors.contains_key(name)
417 }
418 pub fn get_recursor_parent(&self, name: &Name) -> Option<&Name> {
420 self.recursors.get(name)
421 }
422 #[allow(clippy::result_large_err)]
424 pub fn register_in_env(
425 &mut self,
426 ind: &InductiveType,
427 env: &mut crate::Environment,
428 ) -> Result<(), KernelError> {
429 let (ind_ci, ctor_cis, rec_ci) = ind.to_constant_infos();
430 env.add_constant(ind_ci)
431 .map_err(|e| KernelError::Other(e.to_string()))?;
432 for ctor_ci in ctor_cis {
433 env.add_constant(ctor_ci)
434 .map_err(|e| KernelError::Other(e.to_string()))?;
435 }
436 env.add_constant(rec_ci)
437 .map_err(|e| KernelError::Other(e.to_string()))?;
438 self.add(ind.clone())?;
439 Ok(())
440 }
441}
442#[allow(dead_code)]
444pub struct NonEmptyVec<T> {
445 head: T,
446 tail: Vec<T>,
447}
448#[allow(dead_code)]
449impl<T> NonEmptyVec<T> {
450 pub fn singleton(val: T) -> Self {
452 Self {
453 head: val,
454 tail: Vec::new(),
455 }
456 }
457 pub fn push(&mut self, val: T) {
459 self.tail.push(val);
460 }
461 pub fn first(&self) -> &T {
463 &self.head
464 }
465 pub fn last(&self) -> &T {
467 self.tail.last().unwrap_or(&self.head)
468 }
469 pub fn len(&self) -> usize {
471 1 + self.tail.len()
472 }
473 pub fn is_empty(&self) -> bool {
475 self.len() == 0
476 }
477 pub fn to_vec(&self) -> Vec<&T> {
479 let mut v = vec![&self.head];
480 v.extend(self.tail.iter());
481 v
482 }
483}
484#[allow(dead_code)]
486pub struct TransformStat {
487 before: StatSummary,
488 after: StatSummary,
489}
490#[allow(dead_code)]
491impl TransformStat {
492 pub fn new() -> Self {
494 Self {
495 before: StatSummary::new(),
496 after: StatSummary::new(),
497 }
498 }
499 pub fn record_before(&mut self, v: f64) {
501 self.before.record(v);
502 }
503 pub fn record_after(&mut self, v: f64) {
505 self.after.record(v);
506 }
507 pub fn mean_ratio(&self) -> Option<f64> {
509 let b = self.before.mean()?;
510 let a = self.after.mean()?;
511 if b.abs() < f64::EPSILON {
512 return None;
513 }
514 Some(a / b)
515 }
516}
517#[allow(dead_code)]
519pub struct LabelSet {
520 labels: Vec<String>,
521}
522#[allow(dead_code)]
523impl LabelSet {
524 pub fn new() -> Self {
526 Self { labels: Vec::new() }
527 }
528 pub fn add(&mut self, label: impl Into<String>) {
530 let s = label.into();
531 if !self.labels.contains(&s) {
532 self.labels.push(s);
533 }
534 }
535 pub fn has(&self, label: &str) -> bool {
537 self.labels.iter().any(|l| l == label)
538 }
539 pub fn count(&self) -> usize {
541 self.labels.len()
542 }
543 pub fn all(&self) -> &[String] {
545 &self.labels
546 }
547}
548#[allow(dead_code)]
550pub struct VersionedRecord<T: Clone> {
551 history: Vec<T>,
552}
553#[allow(dead_code)]
554impl<T: Clone> VersionedRecord<T> {
555 pub fn new(initial: T) -> Self {
557 Self {
558 history: vec![initial],
559 }
560 }
561 pub fn update(&mut self, val: T) {
563 self.history.push(val);
564 }
565 pub fn current(&self) -> &T {
567 self.history
568 .last()
569 .expect("VersionedRecord history is always non-empty after construction")
570 }
571 pub fn at_version(&self, n: usize) -> Option<&T> {
573 self.history.get(n)
574 }
575 pub fn version(&self) -> usize {
577 self.history.len() - 1
578 }
579 pub fn has_history(&self) -> bool {
581 self.history.len() > 1
582 }
583}
584#[derive(Clone, Debug, PartialEq)]
586pub struct InductiveType {
587 pub name: Name,
589 pub univ_params: Vec<Name>,
591 pub num_params: u32,
593 pub num_indices: u32,
595 pub ty: Expr,
597 pub intro_rules: Vec<IntroRule>,
599 pub recursor: Name,
601 pub is_nested: bool,
603 pub is_prop: bool,
605}
606impl InductiveType {
607 pub fn new(
609 name: Name,
610 univ_params: Vec<Name>,
611 num_params: u32,
612 num_indices: u32,
613 ty: Expr,
614 intro_rules: Vec<IntroRule>,
615 ) -> Self {
616 let recursor = Name::Str(Box::new(name.clone()), "rec".to_string());
617 Self {
618 name,
619 univ_params,
620 num_params,
621 num_indices,
622 ty,
623 intro_rules,
624 recursor,
625 is_nested: false,
626 is_prop: false,
627 }
628 }
629 pub fn arity(&self) -> u32 {
631 self.num_params + self.num_indices
632 }
633 pub fn is_recursive(&self) -> bool {
635 self.intro_rules
636 .iter()
637 .any(|rule| self.occurs_in_arguments(&self.name, &rule.ty))
638 }
639 pub fn constructor_names(&self) -> Vec<&Name> {
641 self.intro_rules.iter().map(|r| &r.name).collect()
642 }
643 pub fn num_constructors(&self) -> usize {
645 self.intro_rules.len()
646 }
647 fn occurs_in_arguments(&self, name: &Name, ty: &Expr) -> bool {
648 match ty {
649 Expr::Pi(_, _, dom, cod) => {
650 self.occurs_in_type(name, dom) || self.occurs_in_arguments(name, cod)
651 }
652 _ => false,
653 }
654 }
655 fn occurs_in_type(&self, name: &Name, ty: &Expr) -> bool {
656 match ty {
657 Expr::Const(n, _) => n == name,
658 Expr::App(f, a) => self.occurs_in_type(name, f) || self.occurs_in_type(name, a),
659 Expr::Pi(_, _, dom, cod) => {
660 self.occurs_in_type(name, dom) || self.occurs_in_type(name, cod)
661 }
662 Expr::Lam(_, _, ty_inner, body) => {
663 self.occurs_in_type(name, ty_inner) || self.occurs_in_type(name, body)
664 }
665 _ => false,
666 }
667 }
668 pub fn to_constant_infos(&self) -> (ConstantInfo, Vec<ConstantInfo>, ConstantInfo) {
672 let ind_val = self.make_inductive_val();
673 let ctor_vals: Vec<ConstantInfo> = self.make_constructor_vals();
674 let rec_val = self.make_recursor_val();
675 (ind_val, ctor_vals, rec_val)
676 }
677 fn make_inductive_val(&self) -> ConstantInfo {
678 ConstantInfo::Inductive(InductiveVal {
679 common: ConstantVal {
680 name: self.name.clone(),
681 level_params: self.univ_params.clone(),
682 ty: self.ty.clone(),
683 },
684 num_params: self.num_params,
685 num_indices: self.num_indices,
686 all: vec![self.name.clone()],
687 ctors: self.intro_rules.iter().map(|r| r.name.clone()).collect(),
688 num_nested: 0,
689 is_rec: self.is_recursive(),
690 is_unsafe: false,
691 is_reflexive: false,
692 is_prop: self.is_prop,
693 })
694 }
695 fn make_constructor_vals(&self) -> Vec<ConstantInfo> {
696 self.intro_rules
697 .iter()
698 .enumerate()
699 .map(|(i, rule)| {
700 let num_fields = count_pi_args(&rule.ty).saturating_sub(self.num_params);
701 ConstantInfo::Constructor(ConstructorVal {
702 common: ConstantVal {
703 name: rule.name.clone(),
704 level_params: self.univ_params.clone(),
705 ty: rule.ty.clone(),
706 },
707 induct: self.name.clone(),
708 cidx: i as u32,
709 num_params: self.num_params,
710 num_fields,
711 is_unsafe: false,
712 })
713 })
714 .collect()
715 }
716 fn make_recursor_val(&self) -> ConstantInfo {
717 let num_minors = self.intro_rules.len() as u32;
718 let rules: Vec<RecursorRule> = self
719 .intro_rules
720 .iter()
721 .enumerate()
722 .map(|(cidx, rule)| {
723 let nfields = count_pi_args(&rule.ty).saturating_sub(self.num_params);
724 let rhs = self.build_recursor_rhs(rule, cidx as u32, nfields, num_minors);
725 RecursorRule {
726 ctor: rule.name.clone(),
727 nfields,
728 rhs,
729 }
730 })
731 .collect();
732 let k = self.is_prop && self.intro_rules.len() <= 1;
733 let mut rec_level_params = self.univ_params.clone();
734 if !self.is_prop {
735 rec_level_params.insert(0, Name::str("u_1"));
736 }
737 let rec_ty = self.build_recursor_type(&rec_level_params);
738 ConstantInfo::Recursor(RecursorVal {
739 common: ConstantVal {
740 name: self.recursor.clone(),
741 level_params: rec_level_params,
742 ty: rec_ty,
743 },
744 all: vec![self.name.clone()],
745 num_params: self.num_params,
746 num_indices: self.num_indices,
747 num_motives: 1,
748 num_minors,
749 rules,
750 k,
751 is_unsafe: false,
752 })
753 }
754 fn collect_field_info(&self, rule: &IntroRule) -> Vec<(Expr, bool)> {
757 let mut current = &rule.ty;
758 for _ in 0..self.num_params {
759 match current {
760 Expr::Pi(_, _, _, body) => current = body,
761 _ => return vec![],
762 }
763 }
764 let mut fields = Vec::new();
765 while let Expr::Pi(_, _, dom, body) = current {
766 let is_rec = self.head_is_inductive(dom);
767 fields.push((dom.as_ref().clone(), is_rec));
768 current = body;
769 }
770 fields
771 }
772 fn head_is_inductive(&self, expr: &Expr) -> bool {
774 match expr {
775 Expr::Const(n, _) => n == &self.name,
776 Expr::App(f, _) => self.head_is_inductive(f),
777 _ => false,
778 }
779 }
780 fn build_recursor_type(&self, rec_level_params: &[Name]) -> Expr {
785 use crate::BinderInfo;
786 let np = self.num_params as usize;
787 let ni = self.num_indices as usize;
788 let nminors = self.intro_rules.len();
789 let (all_binders, _result_sort) = peel_pi_binders(&self.ty);
790 let motive_sort = if self.is_prop {
791 Level::zero()
792 } else if let Some(name) = rec_level_params.first() {
793 Level::Param(name.clone())
794 } else {
795 Level::zero()
796 };
797 let ind_applied_major = {
798 let mut e: Expr = Expr::Const(self.name.clone(), vec![]);
799 for k in 0..np {
800 let bvar = Expr::BVar((ni + nminors + 1 + np - k) as u32);
801 e = Expr::App(Box::new(e), Box::new(bvar));
802 }
803 for k in 0..ni {
804 let bvar = Expr::BVar((ni - k) as u32);
805 e = Expr::App(Box::new(e), Box::new(bvar));
806 }
807 e
808 };
809 let conclusion = {
810 let mut e: Expr = Expr::BVar((1 + ni + nminors) as u32);
811 for k in 0..ni {
812 let bvar = Expr::BVar((ni - k) as u32);
813 e = Expr::App(Box::new(e), Box::new(bvar));
814 }
815 e = Expr::App(Box::new(e), Box::new(Expr::BVar(0)));
816 e
817 };
818 let mut result = Expr::Pi(
819 BinderInfo::Default,
820 Name::str("t"),
821 Box::new(ind_applied_major),
822 Box::new(conclusion),
823 );
824 for k in (0..ni).rev() {
825 let idx_ty = if np + k < all_binders.len() {
826 lift_expr_bvars(&all_binders[np + k], (1 + nminors) as u32)
827 } else {
828 Expr::Sort(Level::zero())
829 };
830 result = Expr::Pi(
831 BinderInfo::Default,
832 Name::str("i"),
833 Box::new(idx_ty),
834 Box::new(result),
835 );
836 }
837 for cidx in (0..nminors).rev() {
838 let minor_ty = self.build_minor_type(cidx, nminors, np, ni, &all_binders);
839 result = Expr::Pi(
840 BinderInfo::Default,
841 Name::str("minor"),
842 Box::new(minor_ty),
843 Box::new(result),
844 );
845 }
846 let motive_ty = self.build_motive_type(np, ni, &all_binders, motive_sort);
847 result = Expr::Pi(
848 BinderInfo::Default,
849 Name::str("motive"),
850 Box::new(motive_ty),
851 Box::new(result),
852 );
853 for k in (0..np).rev() {
854 let param_ty = if k < all_binders.len() {
855 all_binders[k].clone()
856 } else {
857 Expr::Sort(Level::succ(Level::zero()))
858 };
859 result = Expr::Pi(
860 BinderInfo::Default,
861 Name::str("param"),
862 Box::new(param_ty),
863 Box::new(result),
864 );
865 }
866 result
867 }
868 fn build_motive_type(
871 &self,
872 np: usize,
873 ni: usize,
874 all_binders: &[Expr],
875 motive_sort: Level,
876 ) -> Expr {
877 use crate::BinderInfo;
878 let ind_applied = {
879 let mut e: Expr = Expr::Const(self.name.clone(), vec![]);
880 for k in 0..np {
881 let bvar = Expr::BVar((np + ni - 1 - k) as u32);
882 e = Expr::App(Box::new(e), Box::new(bvar));
883 }
884 for k in 0..ni {
885 let bvar = Expr::BVar((ni - 1 - k) as u32);
886 e = Expr::App(Box::new(e), Box::new(bvar));
887 }
888 e
889 };
890 let inner = Expr::Pi(
891 BinderInfo::Default,
892 Name::str("x"),
893 Box::new(ind_applied),
894 Box::new(Expr::Sort(motive_sort)),
895 );
896 let mut result = inner;
897 for k in (0..ni).rev() {
898 let idx_ty = if np + k < all_binders.len() {
899 all_binders[np + k].clone()
900 } else {
901 Expr::Sort(Level::zero())
902 };
903 result = Expr::Pi(
904 BinderInfo::Default,
905 Name::str("i"),
906 Box::new(idx_ty),
907 Box::new(result),
908 );
909 }
910 result
911 }
912 fn build_minor_type(
925 &self,
926 cidx: usize,
927 _nminors: usize,
928 np: usize,
929 ni: usize,
930 _all_binders: &[Expr],
931 ) -> Expr {
932 use crate::BinderInfo;
933 let rule = &self.intro_rules[cidx];
934 let field_info = self.collect_field_info(rule);
935 let nf = field_info.len();
936 let return_indices: Vec<Expr> = if ni > 0 {
937 let mut cod: &Expr = &rule.ty;
938 for _ in 0..(np + nf) {
939 match cod {
940 Expr::Pi(_, _, _, body) => cod = body,
941 _ => break,
942 }
943 }
944 let mut args: Vec<Expr> = Vec::new();
945 let mut cur = cod;
946 while let Expr::App(f, a) = cur {
947 args.push(a.as_ref().clone());
948 cur = f;
949 }
950 args.reverse();
951 let start = args.len().saturating_sub(ni);
952 args[start..]
953 .iter()
954 .map(|e| lift_expr_bvars(e, (1 + cidx) as u32))
955 .collect()
956 } else {
957 vec![]
958 };
959 let mut ctor_app: Expr = Expr::Const(rule.name.clone(), vec![]);
960 for k in 0..np {
961 let bvar = Expr::BVar((nf + cidx + np - k) as u32);
962 ctor_app = Expr::App(Box::new(ctor_app), Box::new(bvar));
963 }
964 for j in 0..nf {
965 let bvar = Expr::BVar((nf - 1 - j) as u32);
966 ctor_app = Expr::App(Box::new(ctor_app), Box::new(bvar));
967 }
968 let mut conclusion: Expr = Expr::BVar((nf + cidx) as u32);
969 for idx in &return_indices {
970 conclusion = Expr::App(Box::new(conclusion), Box::new(idx.clone()));
971 }
972 conclusion = Expr::App(Box::new(conclusion), Box::new(ctor_app));
973 let mut result = conclusion;
974 for j in (0..nf).rev() {
975 let (field_ty, _is_rec) = &field_info[j];
976 let adjusted = lift_expr_bvars(field_ty, (1 + cidx) as u32);
977 result = Expr::Pi(
978 BinderInfo::Default,
979 Name::str("y"),
980 Box::new(adjusted),
981 Box::new(result),
982 );
983 }
984 result
985 }
986 fn build_recursor_rhs(&self, rule: &IntroRule, cidx: u32, nfields: u32, nminors: u32) -> Expr {
1001 let np = self.num_params;
1002 let nf = nfields;
1003 let nm = nminors;
1004 let field_info = self.collect_field_info(rule);
1005 let mut result = Expr::BVar(nf + nm - 1 - cidx);
1006 for (j, (_field_ty, is_rec)) in field_info.iter().enumerate() {
1007 let j = j as u32;
1008 let field_bvar = Expr::BVar(nf - 1 - j);
1009 result = Expr::App(Box::new(result), Box::new(field_bvar.clone()));
1010 if *is_rec {
1011 let ih = self.build_ih(field_bvar, np, nm, nf);
1012 result = Expr::App(Box::new(result), Box::new(ih));
1013 }
1014 }
1015 result
1016 }
1017 fn build_ih(&self, field_expr: Expr, np: u32, nm: u32, nf: u32) -> Expr {
1020 let mut ih = Expr::Const(self.recursor.clone(), vec![]);
1021 for j in 0..np {
1022 let bvar = Expr::BVar(nf + nm + np - j);
1023 ih = Expr::App(Box::new(ih), Box::new(bvar));
1024 }
1025 ih = Expr::App(Box::new(ih), Box::new(Expr::BVar(nf + nm)));
1026 for k in 0..nm {
1027 let bvar = Expr::BVar(nf + nm - 1 - k);
1028 ih = Expr::App(Box::new(ih), Box::new(bvar));
1029 }
1030 ih = Expr::App(Box::new(ih), Box::new(field_expr));
1031 ih
1032 }
1033}
1034#[derive(Clone, Debug)]
1036pub struct InductiveTypeInfo {
1037 pub name: Name,
1039 pub num_params: u32,
1041 pub num_indices: u32,
1043 pub num_constructors: usize,
1045 pub is_prop: bool,
1047 pub is_recursive: bool,
1049 pub is_mutual: bool,
1051 pub constructor_names: Vec<Name>,
1053}
1054impl InductiveTypeInfo {
1055 pub fn from_type(ty: &InductiveType, is_mutual: bool) -> Self {
1057 Self {
1058 name: ty.name.clone(),
1059 num_params: ty.num_params,
1060 num_indices: ty.num_indices,
1061 num_constructors: ty.intro_rules.len(),
1062 is_prop: ty.is_prop,
1063 is_recursive: ty.is_recursive(),
1064 is_mutual,
1065 constructor_names: ty.intro_rules.iter().map(|r| r.name.clone()).collect(),
1066 }
1067 }
1068 pub fn summary(&self) -> String {
1070 format!(
1071 "{}: {} params, {} indices, {} ctors, prop={}, recursive={}, mutual={}",
1072 self.name,
1073 self.num_params,
1074 self.num_indices,
1075 self.num_constructors,
1076 self.is_prop,
1077 self.is_recursive,
1078 self.is_mutual
1079 )
1080 }
1081}
1082#[allow(dead_code)]
1084pub struct FocusStack<T> {
1085 items: Vec<T>,
1086}
1087#[allow(dead_code)]
1088impl<T> FocusStack<T> {
1089 pub fn new() -> Self {
1091 Self { items: Vec::new() }
1092 }
1093 pub fn focus(&mut self, item: T) {
1095 self.items.push(item);
1096 }
1097 pub fn blur(&mut self) -> Option<T> {
1099 self.items.pop()
1100 }
1101 pub fn current(&self) -> Option<&T> {
1103 self.items.last()
1104 }
1105 pub fn depth(&self) -> usize {
1107 self.items.len()
1108 }
1109 pub fn is_empty(&self) -> bool {
1111 self.items.is_empty()
1112 }
1113}
1114#[allow(dead_code)]
1116pub struct InductiveTypeBuilder {
1117 name: Option<Name>,
1118 univ_params: Vec<Name>,
1119 num_params: u32,
1120 num_indices: u32,
1121 ty: Option<Expr>,
1122 intro_rules: Vec<IntroRule>,
1123 is_prop: bool,
1124 is_nested: bool,
1125}
1126#[allow(dead_code)]
1127impl InductiveTypeBuilder {
1128 pub fn new() -> Self {
1130 Self {
1131 name: None,
1132 univ_params: vec![],
1133 num_params: 0,
1134 num_indices: 0,
1135 ty: None,
1136 intro_rules: vec![],
1137 is_prop: false,
1138 is_nested: false,
1139 }
1140 }
1141 pub fn name(mut self, name: Name) -> Self {
1143 self.name = Some(name);
1144 self
1145 }
1146 pub fn univ_params(mut self, params: Vec<Name>) -> Self {
1148 self.univ_params = params;
1149 self
1150 }
1151 pub fn num_params(mut self, n: u32) -> Self {
1153 self.num_params = n;
1154 self
1155 }
1156 pub fn num_indices(mut self, n: u32) -> Self {
1158 self.num_indices = n;
1159 self
1160 }
1161 pub fn ty(mut self, ty: Expr) -> Self {
1163 self.ty = Some(ty);
1164 self
1165 }
1166 pub fn intro_rule(mut self, name: Name, ty: Expr) -> Self {
1168 self.intro_rules.push(IntroRule { name, ty });
1169 self
1170 }
1171 pub fn is_prop(mut self, v: bool) -> Self {
1173 self.is_prop = v;
1174 self
1175 }
1176 pub fn is_nested(mut self, v: bool) -> Self {
1178 self.is_nested = v;
1179 self
1180 }
1181 pub fn build(self) -> Result<InductiveType, String> {
1183 let name = self
1184 .name
1185 .ok_or_else(|| "InductiveTypeBuilder: name not set".to_string())?;
1186 let ty = self
1187 .ty
1188 .ok_or_else(|| "InductiveTypeBuilder: ty not set".to_string())?;
1189 let mut ind = InductiveType::new(
1190 name,
1191 self.univ_params,
1192 self.num_params,
1193 self.num_indices,
1194 ty,
1195 self.intro_rules,
1196 );
1197 ind.is_prop = self.is_prop;
1198 ind.is_nested = self.is_nested;
1199 Ok(ind)
1200 }
1201}
1202#[derive(Clone, Debug)]
1207pub struct RecursorBuilder {
1208 pub name: Name,
1210 pub univ_params: Vec<Name>,
1212 pub num_params: u32,
1214 pub num_indices: u32,
1216 pub num_motives: u32,
1218 pub num_minor_premises: u32,
1220 pub rules: Vec<RecursorRule>,
1222 pub is_prop: bool,
1224}
1225impl RecursorBuilder {
1226 pub fn new(name: Name) -> Self {
1228 Self {
1229 name,
1230 univ_params: vec![],
1231 num_params: 0,
1232 num_indices: 0,
1233 num_motives: 1,
1234 num_minor_premises: 0,
1235 rules: vec![],
1236 is_prop: false,
1237 }
1238 }
1239 pub fn univ_params(mut self, params: Vec<Name>) -> Self {
1241 self.univ_params = params;
1242 self
1243 }
1244 pub fn num_params(mut self, n: u32) -> Self {
1246 self.num_params = n;
1247 self
1248 }
1249 pub fn num_indices(mut self, n: u32) -> Self {
1251 self.num_indices = n;
1252 self
1253 }
1254 pub fn is_prop(mut self, b: bool) -> Self {
1256 self.is_prop = b;
1257 self
1258 }
1259 pub fn add_rule(mut self, rule: RecursorRule) -> Self {
1261 self.rules.push(rule);
1262 self.num_minor_premises += 1;
1263 self
1264 }
1265 pub fn validate(&self) -> Result<(), String> {
1269 if self.name.is_anonymous() {
1270 return Err("recursor name must not be anonymous".to_string());
1271 }
1272 if self.num_motives == 0 {
1273 return Err("recursor must have at least one motive".to_string());
1274 }
1275 Ok(())
1276 }
1277 pub fn build_name(&self) -> Name {
1279 self.name.clone()
1280 }
1281 pub fn build(&self, ty: Expr, all: Vec<Name>) -> Result<RecursorVal, String> {
1287 self.validate()?;
1288 if self.rules.len() != self.num_minor_premises as usize {
1289 return Err(format!(
1290 "RecursorBuilder: num_minor_premises ({}) does not match rule count ({})",
1291 self.num_minor_premises,
1292 self.rules.len()
1293 ));
1294 }
1295 Ok(RecursorVal {
1296 common: ConstantVal {
1297 name: self.name.clone(),
1298 level_params: self.univ_params.clone(),
1299 ty,
1300 },
1301 all,
1302 num_params: self.num_params,
1303 num_indices: self.num_indices,
1304 num_motives: self.num_motives,
1305 num_minors: self.num_minor_premises,
1306 rules: self.rules.clone(),
1307 k: false,
1308 is_unsafe: false,
1309 })
1310 }
1311}