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
|
use itertools::Itertools;
use std::iter::FromIterator;
use crate::syntax::*;
fn opt<'a, T, U, Err>(
x: &'a Option<T>,
f: impl FnOnce(&'a T) -> Result<U, Err>,
) -> Result<Option<U>, Err> {
x.as_ref().map(f).transpose()
}
fn dupmap<'a, SE1, SE2, T, Err>(
x: impl IntoIterator<Item = (&'a Label, &'a SE1)>,
mut f: impl FnMut(&'a SE1) -> Result<SE2, Err>,
) -> Result<T, Err>
where
SE1: 'a,
T: FromIterator<(Label, SE2)>,
{
x.into_iter().map(|(k, x)| Ok((k.clone(), f(x)?))).collect()
}
pub fn visit_ref<'a, F, SE1, SE2, Err>(
input: &'a ExprKind<SE1>,
mut f: F,
) -> Result<ExprKind<SE2>, Err>
where
F: FnMut(Option<&'a Label>, &'a SE1) -> Result<SE2, Err>,
{
// Can't use closures because of borrowing rules
macro_rules! expr {
() => {
|e| Ok(expr!(e))
};
($e:expr) => {
f(None, $e)?
};
($l:expr, $e:expr) => {
f(Some($l), $e)?
};
}
macro_rules! opt {
() => {
|e| Ok(opt!(e))
};
($e:expr) => {
opt($e, |e| Ok(expr!(e)))?
};
}
use crate::syntax::ExprKind::*;
Ok(match input {
Var(v) => Var(v.clone()),
Lam(l, t, e) => Lam(l.clone(), expr!(t), expr!(l, e)),
Pi(l, t, e) => Pi(l.clone(), expr!(t), expr!(l, e)),
Let(l, t, a, e) => Let(l.clone(), opt!(t), expr!(a), expr!(l, e)),
Const(k) => Const(*k),
Num(n) => Num(n.clone()),
Builtin(v) => Builtin(*v),
TextLit(t) => TextLit(t.traverse_ref(expr!())?),
SomeLit(e) => SomeLit(expr!(e)),
EmptyListLit(t) => EmptyListLit(expr!(t)),
NEListLit(es) => NEListLit(es.iter().map(expr!()).try_collect()?),
RecordType(kts) => RecordType(dupmap(kts, expr!())?),
RecordLit(kvs) => RecordLit(dupmap(kvs, expr!())?),
UnionType(kts) => UnionType(dupmap(kts, opt!())?),
Op(op) => Op(op.traverse_ref(expr!())?),
Annot(x, t) => Annot(expr!(x), expr!(t)),
Assert(e) => Assert(expr!(e)),
Import(i) => Import(i.traverse_ref(expr!())?),
})
}
|