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
use super::{RTerm, Signature};
use crate::Arg;
use alloc::{vec, vec::Vec};
type Constraint<'s> = (RTerm<'s>, RTerm<'s>);
fn step<'s>((cn1, cn2): Constraint<'s>, cns: &mut Vec<Constraint<'s>>, eta: bool) -> bool {
use crate::Term::*;
match (&*cn1, &*cn2) {
(Kind, Kind) | (Type, Type) => true,
(Symb(s1), Symb(s2)) => s1 == s2,
(BVar(v1), BVar(v2)) => v1 == v2,
(Abst(_, t1), Abst(_, t2)) => {
cns.push((t1.clone(), t2.clone()));
true
}
(Prod(Arg { ty: ty1, .. }, tm1), Prod(Arg { ty: ty2, .. }, tm2)) => {
cns.push((ty1.clone(), ty2.clone()));
cns.push((tm1.clone(), tm2.clone()));
true
}
(a, Abst(_, b)) | (Abst(_, b), a) if eta => {
let app = (RTerm::new(a.clone()) << 1).apply(vec![RTerm::new(BVar(0))]);
cns.push((b.clone(), app));
true
}
(Appl(f1, args1), Appl(f2, args2)) => {
if args1.len() == args2.len() {
cns.push((f1.clone(), f2.clone()));
cns.extend(args1.clone().into_iter().zip(args2.clone()));
true
} else {
false
}
}
_ => false,
}
}
impl<'s> RTerm<'s> {
pub fn convertible(tm1: Self, tm2: Self, sig: &Signature<'s>) -> bool {
let mut cns = vec![(tm1, tm2)];
loop {
match cns.pop() {
Some((cn1, cn2)) => {
trace!("convertible: {} ~? {}", cn1, cn2);
if cn1 != cn2 && !step((cn1.whnf(sig), cn2.whnf(sig)), &mut cns, sig.eta) {
break false;
}
}
None => break true,
}
}
}
}