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
use crate::ast::{reduce_to_value, Expression, Value};
use crate::check::read_back::{generate_value, ReadBack};
use crate::check::tcm::{TCE, TCM, TCS};
use either::Either;
use std::collections::BTreeMap;
pub fn check_subtype(index: u32, tcs: TCS, subtype: Value, supertype: Value) -> TCM<TCS> {
match (subtype, supertype) {
(Value::Sum(sub_tree), Value::Sum(super_tree)) => {
let (super_tree, super_environment) = super_tree.destruct();
let (sub_tree, sub_environment) = sub_tree.destruct();
let super_eval = |sup: Box<Either<Value, Expression>>| {
reduce_to_value(*sup, super_environment.clone())
};
let sub_eval = |sub: Box<Either<Value, Expression>>| {
reduce_to_value(*sub, sub_environment.clone())
};
check_subtype_sum(index, tcs, sub_tree, super_tree, sub_eval, super_eval)
}
(Value::Pi(sub_param, sub_closure), Value::Pi(super_param, super_closure))
| (Value::Sigma(sub_param, sub_closure), Value::Sigma(super_param, super_closure)) => {
let tcs = check_subtype(index, tcs, *super_param, *sub_param)?;
let generated = generate_value(index);
check_subtype(
index + 1,
tcs_borrow!(tcs),
sub_closure.instantiate(generated.clone()),
super_closure.instantiate(generated),
)?;
Ok(tcs)
}
(subtype, supertype) => compare_normal(index, tcs, subtype, supertype),
}
}
#[inline]
pub fn check_subtype_sum<Sub, Super>(
index: u32,
tcs: TCS,
sub_tree: BTreeMap<String, Sub>,
mut super_tree: BTreeMap<String, Super>,
sub_tree_eval: impl Fn(Sub) -> Value,
super_tree_eval: impl Fn(Super) -> Value,
) -> TCM<TCS> {
for (constructor, sub_parameter) in sub_tree.into_iter() {
let super_parameter = super_tree
.remove(constructor.as_str())
.ok_or_else(|| TCE::UnexpectedCases(constructor))?;
let sub_parameter = sub_tree_eval(sub_parameter);
let super_parameter = super_tree_eval(super_parameter);
compare_normal(index, tcs_borrow!(tcs), sub_parameter, super_parameter)?;
}
return Ok(tcs);
}
pub fn compare_normal(index: u32, tcs: TCS, subtype: Value, supertype: Value) -> TCM<TCS> {
let (inferred_normal, expected_normal) = ReadBack::normal(index, subtype, supertype);
if inferred_normal == expected_normal {
Ok(tcs)
} else {
Err(TCE::InferredDoesNotMatchExpected(
inferred_normal,
expected_normal,
))
}
}