Skip to main content

morphir_core/ir/classic/
pattern.rs

1//! Classic IR Pattern types
2//!
3//! Pattern matching for the Classic Morphir IR format.
4
5use super::naming::{FQName, Name};
6use serde::de::{self, IgnoredAny, SeqAccess, Visitor};
7use serde::ser::{SerializeTuple, Serializer};
8use serde::{Deserialize, Deserializer, Serialize};
9use std::borrow::Cow;
10use std::fmt;
11
12use super::literal::Literal;
13
14/// Pattern for pattern matching.
15///
16/// These are morphir-elm's eight patterns and no more: a variable binding is an `As` over a
17/// wildcard, so there is no `VariablePattern` to read or write.
18#[derive(Debug, Clone, PartialEq)]
19pub enum Pattern<A> {
20    Wildcard(A),
21    As(A, Box<Pattern<A>>, Name),
22    Tuple(A, Vec<Pattern<A>>),
23    Constructor(A, FQName, Vec<Pattern<A>>),
24    EmptyList(A),
25    HeadTail(A, Box<Pattern<A>>, Box<Pattern<A>>),
26    Literal(A, Literal),
27    Unit(A),
28}
29
30impl<A: Serialize> Serialize for Pattern<A> {
31    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
32    where
33        S: Serializer,
34    {
35        match self {
36            Pattern::Wildcard(a) => {
37                let mut tuple = serializer.serialize_tuple(2)?;
38                tuple.serialize_element("WildcardPattern")?;
39                tuple.serialize_element(a)?;
40                tuple.end()
41            }
42            Pattern::As(a, pattern, name) => {
43                let mut tuple = serializer.serialize_tuple(4)?;
44                tuple.serialize_element("AsPattern")?;
45                tuple.serialize_element(a)?;
46                tuple.serialize_element(pattern)?;
47                tuple.serialize_element(name)?;
48                tuple.end()
49            }
50            Pattern::Tuple(a, patterns) => {
51                let mut tuple = serializer.serialize_tuple(3)?;
52                tuple.serialize_element("TuplePattern")?;
53                tuple.serialize_element(a)?;
54                tuple.serialize_element(patterns)?;
55                tuple.end()
56            }
57            Pattern::Constructor(a, name, args) => {
58                let mut tuple = serializer.serialize_tuple(4)?;
59                tuple.serialize_element("ConstructorPattern")?;
60                tuple.serialize_element(a)?;
61                tuple.serialize_element(name)?;
62                tuple.serialize_element(args)?;
63                tuple.end()
64            }
65            Pattern::EmptyList(a) => {
66                let mut tuple = serializer.serialize_tuple(2)?;
67                tuple.serialize_element("EmptyListPattern")?;
68                tuple.serialize_element(a)?;
69                tuple.end()
70            }
71            Pattern::HeadTail(a, head, tail) => {
72                let mut tuple = serializer.serialize_tuple(4)?;
73                tuple.serialize_element("HeadTailPattern")?;
74                tuple.serialize_element(a)?;
75                tuple.serialize_element(head)?;
76                tuple.serialize_element(tail)?;
77                tuple.end()
78            }
79            Pattern::Literal(a, lit) => {
80                let mut tuple = serializer.serialize_tuple(3)?;
81                tuple.serialize_element("LiteralPattern")?;
82                tuple.serialize_element(a)?;
83                tuple.serialize_element(lit)?;
84                tuple.end()
85            }
86            Pattern::Unit(a) => {
87                let mut tuple = serializer.serialize_tuple(2)?;
88                tuple.serialize_element("UnitPattern")?;
89                tuple.serialize_element(a)?;
90                tuple.end()
91            }
92        }
93    }
94}
95
96impl<'de, A: Deserialize<'de>> Deserialize<'de> for Pattern<A> {
97    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
98    where
99        D: Deserializer<'de>,
100    {
101        struct PatternVisitor<A>(std::marker::PhantomData<A>);
102
103        impl<'de, A: Deserialize<'de>> Visitor<'de> for PatternVisitor<A> {
104            type Value = Pattern<A>;
105
106            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
107                formatter.write_str("a classic Pattern array")
108            }
109
110            fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
111            where
112                V: SeqAccess<'de>,
113            {
114                let tag: Cow<'de, str> = seq
115                    .next_element()?
116                    .ok_or_else(|| de::Error::invalid_length(0, &self))?;
117
118                match tag.as_ref() {
119                    "WildcardPattern" | "wildcard" => {
120                        let a = seq
121                            .next_element()?
122                            .ok_or_else(|| de::Error::invalid_length(1, &self))?;
123
124                        if seq.next_element::<IgnoredAny>()?.is_some() {
125                            return Err(de::Error::custom("Expected end of WildcardPattern array"));
126                        }
127
128                        Ok(Pattern::Wildcard(a))
129                    }
130                    "AsPattern" | "as_pattern" => {
131                        let a = seq
132                            .next_element()?
133                            .ok_or_else(|| de::Error::invalid_length(1, &self))?;
134                        let pattern = seq
135                            .next_element()?
136                            .ok_or_else(|| de::Error::invalid_length(2, &self))?;
137                        let name = seq
138                            .next_element()?
139                            .ok_or_else(|| de::Error::invalid_length(3, &self))?;
140
141                        if seq.next_element::<IgnoredAny>()?.is_some() {
142                            return Err(de::Error::custom("Expected end of AsPattern array"));
143                        }
144
145                        Ok(Pattern::As(a, pattern, name))
146                    }
147                    "TuplePattern" | "tuple_pattern" => {
148                        let a = seq
149                            .next_element()?
150                            .ok_or_else(|| de::Error::invalid_length(1, &self))?;
151                        let patterns = seq
152                            .next_element()?
153                            .ok_or_else(|| de::Error::invalid_length(2, &self))?;
154
155                        if seq.next_element::<IgnoredAny>()?.is_some() {
156                            return Err(de::Error::custom("Expected end of TuplePattern array"));
157                        }
158
159                        Ok(Pattern::Tuple(a, patterns))
160                    }
161                    "ConstructorPattern" | "constructor_pattern" => {
162                        let a = seq
163                            .next_element()?
164                            .ok_or_else(|| de::Error::invalid_length(1, &self))?;
165                        let name = seq
166                            .next_element()?
167                            .ok_or_else(|| de::Error::invalid_length(2, &self))?;
168                        let args = seq
169                            .next_element()?
170                            .ok_or_else(|| de::Error::invalid_length(3, &self))?;
171
172                        if seq.next_element::<IgnoredAny>()?.is_some() {
173                            return Err(de::Error::custom(
174                                "Expected end of ConstructorPattern array",
175                            ));
176                        }
177
178                        Ok(Pattern::Constructor(a, name, args))
179                    }
180                    "EmptyListPattern" | "empty_list_pattern" => {
181                        let a = seq
182                            .next_element()?
183                            .ok_or_else(|| de::Error::invalid_length(1, &self))?;
184
185                        if seq.next_element::<IgnoredAny>()?.is_some() {
186                            return Err(de::Error::custom(
187                                "Expected end of EmptyListPattern array",
188                            ));
189                        }
190
191                        Ok(Pattern::EmptyList(a))
192                    }
193                    "HeadTailPattern" | "head_tail_pattern" => {
194                        let a = seq
195                            .next_element()?
196                            .ok_or_else(|| de::Error::invalid_length(1, &self))?;
197                        let head = seq
198                            .next_element()?
199                            .ok_or_else(|| de::Error::invalid_length(2, &self))?;
200                        let tail = seq
201                            .next_element()?
202                            .ok_or_else(|| de::Error::invalid_length(3, &self))?;
203
204                        if seq.next_element::<IgnoredAny>()?.is_some() {
205                            return Err(de::Error::custom("Expected end of HeadTailPattern array"));
206                        }
207
208                        Ok(Pattern::HeadTail(a, head, tail))
209                    }
210                    "LiteralPattern" | "literal_pattern" => {
211                        let a = seq
212                            .next_element()?
213                            .ok_or_else(|| de::Error::invalid_length(1, &self))?;
214                        let lit = seq
215                            .next_element()?
216                            .ok_or_else(|| de::Error::invalid_length(2, &self))?;
217
218                        if seq.next_element::<IgnoredAny>()?.is_some() {
219                            return Err(de::Error::custom("Expected end of LiteralPattern array"));
220                        }
221
222                        Ok(Pattern::Literal(a, lit))
223                    }
224                    "UnitPattern" | "unit_pattern" => {
225                        let a = seq
226                            .next_element()?
227                            .ok_or_else(|| de::Error::invalid_length(1, &self))?;
228
229                        if seq.next_element::<IgnoredAny>()?.is_some() {
230                            return Err(de::Error::custom("Expected end of UnitPattern array"));
231                        }
232
233                        Ok(Pattern::Unit(a))
234                    }
235                    _ => Err(de::Error::unknown_variant(
236                        tag.as_ref(),
237                        &[
238                            "WildcardPattern",
239                            "AsPattern",
240                            "TuplePattern",
241                            "ConstructorPattern",
242                            "EmptyListPattern",
243                            "HeadTailPattern",
244                            "LiteralPattern",
245                            "UnitPattern",
246                        ],
247                    )),
248                }
249            }
250        }
251        deserializer.deserialize_seq(PatternVisitor(std::marker::PhantomData))
252    }
253}
254#[cfg(test)]
255mod tests {
256    use super::*;
257    use crate::ir::classic::naming::Path;
258
259    #[test]
260    fn test_serialize_pattern_wildcard() {
261        let p: Pattern<()> = Pattern::Wildcard(());
262        let json = serde_json::to_string(&p).unwrap();
263        assert_eq!(json, r#"["WildcardPattern",null]"#);
264        let deserialized: Pattern<()> = serde_json::from_str(&json).unwrap();
265        assert_eq!(deserialized, p);
266    }
267
268    #[test]
269    fn a_variable_pattern_is_refused() {
270        // morphir-elm never writes one; a variable binding is an As over a wildcard.
271        assert!(serde_json::from_str::<Pattern<()>>(r#"["VariablePattern",null,["x"]]"#).is_err());
272    }
273
274    #[test]
275    fn test_serialize_pattern_as() {
276        let p: Pattern<()> = Pattern::As((), Box::new(Pattern::Wildcard(())), Name::from_str("x"));
277        let json = serde_json::to_string(&p).unwrap();
278        assert_eq!(json, r#"["AsPattern",null,["WildcardPattern",null],["x"]]"#);
279        let deserialized: Pattern<()> = serde_json::from_str(&json).unwrap();
280        assert_eq!(deserialized, p);
281    }
282
283    #[test]
284    fn test_serialize_pattern_tuple() {
285        let p: Pattern<()> = Pattern::Tuple((), vec![Pattern::Wildcard(()), Pattern::Wildcard(())]);
286        let json = serde_json::to_string(&p).unwrap();
287        assert_eq!(
288            json,
289            r#"["TuplePattern",null,[["WildcardPattern",null],["WildcardPattern",null]]]"#
290        );
291        let deserialized: Pattern<()> = serde_json::from_str(&json).unwrap();
292        assert_eq!(deserialized, p);
293    }
294
295    #[test]
296    fn test_serialize_pattern_constructor() {
297        let fq = FQName::new(
298            Path::new(vec![Name::from_str("pkg")]),
299            Path::new(vec![Name::from_str("mod")]),
300            Name::from_str("ctor"),
301        );
302        let p: Pattern<()> = Pattern::Constructor((), fq, vec![Pattern::Wildcard(())]);
303        let json = serde_json::to_string(&p).unwrap();
304        assert_eq!(
305            json,
306            r#"["ConstructorPattern",null,[[["pkg"]],[["mod"]],["ctor"]],[["WildcardPattern",null]]]"#
307        );
308        let deserialized: Pattern<()> = serde_json::from_str(&json).unwrap();
309        assert_eq!(deserialized, p);
310    }
311
312    #[test]
313    fn test_serialize_pattern_empty_list() {
314        let p: Pattern<()> = Pattern::EmptyList(());
315        let json = serde_json::to_string(&p).unwrap();
316        assert_eq!(json, r#"["EmptyListPattern",null]"#);
317        let deserialized: Pattern<()> = serde_json::from_str(&json).unwrap();
318        assert_eq!(deserialized, p);
319    }
320
321    #[test]
322    fn test_serialize_pattern_head_tail() {
323        let p: Pattern<()> = Pattern::HeadTail(
324            (),
325            Box::new(Pattern::Wildcard(())),
326            Box::new(Pattern::Wildcard(())),
327        );
328        let json = serde_json::to_string(&p).unwrap();
329        assert_eq!(
330            json,
331            r#"["HeadTailPattern",null,["WildcardPattern",null],["WildcardPattern",null]]"#
332        );
333        let deserialized: Pattern<()> = serde_json::from_str(&json).unwrap();
334        assert_eq!(deserialized, p);
335    }
336
337    #[test]
338    fn test_serialize_pattern_literal() {
339        let p: Pattern<()> = Pattern::Literal((), Literal::WholeNumber(123));
340        let json = serde_json::to_string(&p).unwrap();
341        assert_eq!(
342            json,
343            r#"["LiteralPattern",null,["WholeNumberLiteral",123]]"#
344        );
345        let deserialized: Pattern<()> = serde_json::from_str(&json).unwrap();
346        assert_eq!(deserialized, p);
347    }
348
349    #[test]
350    fn test_serialize_pattern_unit() {
351        let p: Pattern<()> = Pattern::Unit(());
352        let json = serde_json::to_string(&p).unwrap();
353        assert_eq!(json, r#"["UnitPattern",null]"#);
354        let deserialized: Pattern<()> = serde_json::from_str(&json).unwrap();
355        assert_eq!(deserialized, p);
356    }
357}