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
|
use crate::r#type::{Type, Type::*, util::*};
impl Type {
/// Performs substitution on the type.
///
/// Replaces all free occurrences of generics
/// named `name` with the given type `value`
/// in the type.
/// ```rust
/// use melisp::r#type::{Type::*, util::*};
///
/// assert_eq!(
/// List(vec![Integer, arr(Integer, VarType("A".to_string())), VarType("B".to_string())])
/// .subst("A", &Integer),
/// List(vec![Integer, arr(Integer, Integer), VarType("B".to_string())])
/// );
///
/// assert_eq!(
/// List(vec![Integer, arr(Integer, VarType("A".to_string())), VarType("B".to_string())])
/// .subst("B", &arr(Integer, Integer)),
/// List(vec![Integer, arr(Integer, VarType("A".to_string())), arr(Integer, Integer)])
/// );
/// ```
pub fn subst(self, name: &str, value: &Type) -> Type {
match self {
Arrow(a, b) => arr((*a).subst(name, value), (*b).subst(name, value)),
List(v) => List(
v.into_iter()
.map(|t| t.subst(name, value))
.collect()
),
VarType(s) if s == name => value.clone(),
VarType(s) => VarType(s),
Integer => Integer,
}
}
}
|