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
//! Delegates, as C#'s: a type of methods (`delegate bool Predicate<in T>(T
//! obj);`). A lambda or a method of its shape is one; calling one is
//! calling its `Invoke`. Each delegate's signature is typed once (its type
//! parameters standing for themselves), its arguments substituted where
//! it's used.
use std::collections::HashMap;
use super::Checker;
use super::model::Type;
use super::own::TypeKey;
/// A delegate's signature: what it takes, what it gives.
pub(super) type Sig = (Vec<Type>, Type);
/// Each declared delegate's signature, by key.
pub(super) type Delegates = HashMap<TypeKey, Sig>;
impl Checker<'_, '_, '_> {
/// Every declared delegate's signature typed, quietly (what it names
/// is the resolver's to report).
pub(super) fn type_delegates(&mut self) {
let declared: Vec<(TypeKey, Vec<String>, crate::ast::Method)> = self
.own
.all()
.filter_map(|(k, t)| Some((k.clone(), t.generics.clone(), t.delegate.clone()?)))
.collect();
let mut delegates = Delegates::new();
self.quietly(|c| {
for (key, generics, m) in declared {
let sig = c.as_declared(&key.name, &generics, |c| c.signature_types(&m));
delegates.insert(key, sig);
}
});
self.delegates = delegates;
}
/// `t`'s signature when it's a delegate: a declared one's (its type
/// arguments bound), or a lambda's or a method's own.
/// The delegate an expression tree `t` (`Expression<TDelegate>`) is of.
pub(super) fn quoted_delegate(t: &Type) -> Option<&Type> {
match t.non_null() {
Type::Own(name, args)
if name == yog_script_ids::system::EXPRESSION && args.len() == 1 =>
{
args.first()
}
_ => None,
}
}
/// What a lambda given where `t` is wanted is typed as: a delegate's
/// signature, an expression tree's delegate's.
pub(super) fn lambda_sig(&self, t: &Type) -> Option<Sig> {
match Self::quoted_delegate(t) {
Some(d) => self.delegate_sig(d),
None => self.delegate_sig(t),
}
}
pub(super) fn delegate_sig(&self, t: &Type) -> Option<Sig> {
match t.non_null() {
Type::Fn(params, ret) => Some((params.clone(), (**ret).clone())),
Type::Own(name, args) => {
let (params, ret) = self
.delegates
.get(&TypeKey::new(name.clone(), args.len()))?;
let bound = self.bound_of(name, args);
Some((
params.iter().map(|p| p.substitute(&bound)).collect(),
ret.substitute(&bound),
))
}
_ => None,
}
}
}