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
95
96
97
98
99
100
101
102
|
use crate::r#type::{Type, TypeError, Type::*, TypeError::*, PatFail::*, util::*};
use crate::sexp::{SExp, SExp::*, SLeaf::*, util::*};
impl SExp {
/// Checks if this expression matches the given type,
/// returns all variable names bound by a respective case.
///
/// Two equal values match:
/// ```rust
/// use myslip::sexp::{SExp::*, SLeaf::*, util::*};
/// use myslip::r#type::{Type::*, util::*, TypeError::*, PatFail::*};
/// assert_eq!(
/// scons(1, scons(2, Nil))
/// .matches_type(&List(vec![Integer, Integer])),
/// Ok(vec![])
/// );
/// ```
///
/// On the other hand, if values don't match, an invalid pattern
/// error should be thrown:
/// ```rust
/// use myslip::sexp::{SExp::*, SLeaf::*, util::*};
/// use myslip::r#type::{Type::*, util::*, TypeError::*, PatFail::*};
/// assert_eq!(
/// scons(1, scons(2, Nil))
/// .matches_type(&List(vec![Integer])),
/// Err(InvalidPattern(TypeMismatch {
/// pattern: scons(1, scons(2, Nil)),
/// expected: List(vec![Integer]),
/// found: List(vec![Integer, Integer])
/// }))
/// );
/// ```
///
/// A wildcard variable matches too and gets the correct type:
/// ```rust
/// use myslip::sexp::{SExp::*, SLeaf::*, util::*};
/// use myslip::r#type::{Type::*, util::*, TypeError::*, PatFail::*};
/// assert_eq!(
/// var("x").matches_type(&List(vec![Integer, Integer])),
/// Ok(vec![("x".to_string(), List(vec![Integer, Integer]))])
/// );
/// ```
///
/// Obviously that should also work for sub-expressions:
/// ```rust
/// use myslip::sexp::{SExp::*, SLeaf::*, util::*};
/// use myslip::r#type::{Type::*, util::*, TypeError::*, PatFail::*};
/// assert_eq!(
/// scons(var("x"), scons(2, Nil)).matches_type(&List(vec![arr(Integer, Integer), Integer])),
/// Ok(vec![("x".to_string(), arr(Integer, Integer))])
/// );
/// ```
///
/// If the wildcard variable is encountered multiple times,
/// an invalid operator error should be returned:
/// ```rust
/// use myslip::sexp::{SExp::*, SLeaf::*, util::*};
/// use myslip::r#type::{Type::*, util::*, TypeError::*, PatFail::*};
/// assert_eq!(
/// scons(var("x"), scons(var("x"), Nil)).matches_type(&List(vec![Integer, Integer])),
/// Err(InvalidPattern(RepeatedVariable(
/// "x".to_string(),
/// scons(var("x"), scons(var("x"), Nil))
/// )))
/// );
/// ```
///
/// Then there's also rest patterns which should be appropriately typed:
/// ```rust
/// use myslip::sexp::{SExp::*, SLeaf::*, util::*};
/// use myslip::r#type::{Type::*, util::*, TypeError::*, PatFail::*};
/// assert_eq!(
/// scons(var("h"), scons(RestPat("t".to_string()), Nil))
/// .matches_type(&List(vec![arr(Integer, Integer), Integer, Integer, Integer])),
/// Ok(vec![
/// ("h".to_string(), arr(Integer, Integer)),
/// ("t".to_string(), List(vec![Integer, Integer, Integer]))
/// ])
/// );
/// ```
///
/// They should also work with vectors:
/// ```rust
/// use myslip::sexp::{SExp::*, SLeaf::*, util::*};
/// use myslip::r#type::{Type::*, util::*, TypeError::*, PatFail::*};
/// assert_eq!(
/// scons(var("h"), scons(RestPat("t".to_string()), Nil))
/// .matches_type(&vecof(Integer)),
/// Ok(vec![
/// ("h".to_string(), Integer),
/// ("t".to_string(), vecof(Integer))
/// ])
/// );
/// ```
///
pub fn matches_type(&self, ty: &Type) -> Result<Vec<(String, Type)>, TypeError> {
todo!()
}
}
|