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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use crate::{
check::{
monad::{TCMS, TCS},
rules::{
clause::{
eqs::AsBind,
lhs::check_lhs,
state::{progress_lhs_state, LhsState},
},
term::{check, simplify, HasMeta},
},
},
syntax::{
abs::AbsClause,
core::{Clause, Tele, Term},
},
};
mod eqs;
mod lhs;
mod split;
mod state;
fn bind_as_and_tele<T>(
mut tcs: TCS,
as_binds: Vec<AsBind>,
mut tele: Tele,
f: impl FnOnce(TCS) -> TCMS<T>,
) -> TCMS<T> {
use std::mem::swap;
if tcs.lets.len() < as_binds.len() {
tcs.lets.reserve(as_binds.len() - tcs.lets.len());
}
for bind in as_binds {
tcs.lets.push(bind.into());
}
swap(&mut tcs.gamma, &mut tele);
let (thing, mut tcs) = f(tcs)?;
tcs.lets.clear();
swap(&mut tcs.gamma, &mut tele);
Ok((thing, tcs))
}
pub fn clause(mut tcs: TCS, cls: AbsClause, against: Term) -> TCMS<Clause> {
if !tcs.trace_tc {
return clause_impl(tcs, cls, against);
}
let depth_ws = tcs.tc_depth_ws();
tcs.tc_deeper();
let cls_name = cls.name.text.clone();
let (clause, mut tcs) = clause_impl(tcs, cls, against).map_err(|e| {
println!("{}Clause {}", depth_ws, cls_name);
e
})?;
match &clause.body {
None => println!("{}\u{22A2} clause {} ()", depth_ws, cls_name,),
Some(t) => println!("{}\u{22A2} clause {} = {}", depth_ws, cls_name, t),
}
tcs.tc_shallower();
Ok((clause, tcs))
}
fn clause_impl(tcs: TCS, cls: AbsClause, against: Term) -> TCMS<Clause> {
let body = cls.body;
let lhs_state = progress_lhs_state(LhsState::new(cls.patterns, against))?;
let (lhs, tcs) = check_lhs(tcs, lhs_state)?;
let pat_tele = lhs.tele;
let ty = lhs.ty;
let patterns = lhs.pats;
let has_absurd = lhs.has_absurd;
bind_as_and_tele(tcs, lhs.as_binds, pat_tele.clone(), |mut tcs| {
let body = if has_absurd {
None
} else {
let (ty, new_tcs) = simplify(tcs, ty)?;
let (term, new_tcs) = check(new_tcs, &body, &ty)?;
let (term, new_tcs) = term.ast.inline_meta(new_tcs)?;
tcs = new_tcs;
Some(term)
};
let clause = Clause {
pat_tele,
patterns,
body,
};
Ok((clause, tcs))
})
}