1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use std::rc::Rc;
use voile_util::uid::DBI;
use crate::syntax::core::{subst::PrimSubst, Elim, Term, Val};
pub trait DeBruijn {
fn dbi_view(&self) -> Option<DBI>;
fn from_dbi(dbi: DBI) -> Self;
}
impl DeBruijn for Val {
fn dbi_view(&self) -> Option<DBI> {
match self {
Val::Var(i, v) if v.is_empty() => Some(*i),
_ => None,
}
}
fn from_dbi(dbi: DBI) -> Self {
Val::Var(dbi, Default::default())
}
}
impl DeBruijn for Elim {
fn dbi_view(&self) -> Option<DBI> {
match self {
Elim::App(a) => a.dbi_view(),
Elim::Proj(..) => None,
}
}
fn from_dbi(dbi: DBI) -> Self {
Elim::app(DeBruijn::from_dbi(dbi))
}
}
impl DeBruijn for Term {
fn dbi_view(&self) -> Option<DBI> {
match self {
Term::Whnf(w) => w.dbi_view(),
Term::Redex(..) => None,
}
}
fn from_dbi(dbi: DBI) -> Self {
Term::Whnf(DeBruijn::from_dbi(dbi))
}
}
impl<T: DeBruijn> PrimSubst<T> {
pub fn concat(ts: impl DoubleEndedIterator<Item = T>, to: Rc<Self>) -> Rc<Self> {
ts.rfold(to, Self::cons)
}
pub fn parallel(ts: impl DoubleEndedIterator<Item = T>) -> Rc<Self> {
Self::concat(ts, Default::default())
}
pub fn cons(self: Rc<Self>, t: T) -> Rc<Self> {
match (t.dbi_view(), &*self) {
(Some(n), PrimSubst::Weak(m, rho)) if n + 1 == *m => {
rho.clone().lift_by(DBI(1)).weaken(*m - 1)
}
_ => Rc::new(PrimSubst::Cons(t, self)),
}
}
}