aboutsummaryrefslogtreecommitdiff
path: root/src/sexp/case.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/sexp/case.rs')
-rw-r--r--src/sexp/case.rs30
1 files changed, 30 insertions, 0 deletions
diff --git a/src/sexp/case.rs b/src/sexp/case.rs
index cc643f3..fd39922 100644
--- a/src/sexp/case.rs
+++ b/src/sexp/case.rs
@@ -64,6 +64,17 @@ impl SExp {
* Some(vec![(Var("x".to_string()), Atom(Int(2)))])
* );
* ```
+ * But they shouldn't match the wrong hand:
+ * ```rust
+ * use myslip::r#type::Type::*;
+ * use myslip::sexp::{SExp::*, SLeaf::*, util::*};
+ *
+ * assert_eq!(
+ * scons(Coprod, scons(Ty(Boolean), scons(2, Nil)))
+ * .matches_pat(&scons(Inl, scons(var("x"), Nil))),
+ * None
+ * );
+ * ```
*/
pub fn matches_pat(&self, pat: &SExp) -> Option<Vec<(SLeaf, SExp)>> {
match (self, pat) {
@@ -72,6 +83,25 @@ impl SExp {
(a, Atom(Var(name))) => Some(vec![(Var(name.to_string()), a.clone())]),
+ (SCons(cp, ls), SCons(inx, var)) if **cp == Atom(Coprod) => {
+ let var = match (**var).clone() {
+ SCons(a, n) if *n == Atom(Nil) => *a,
+ t => t,
+ };
+ let mut ls = (**ls).clone().parts().into_iter();
+ match (ls.next(), ls.next(), (**inx).clone(), var) {
+ (Some(l), _, Atom(Inl), Atom(Var(name))) if !l.is_type_atom()
+ => Some(vec![(Var(name), l)]),
+ (_, Some(r), Atom(Inr), Atom(Var(name))) if !r.is_type_atom()
+ => Some(vec![(Var(name), r)]),
+ (Some(l), _, Atom(Inl), pat) if !l.is_type_atom()
+ => l.matches_pat(&pat),
+ (_, Some(r), Atom(Inr), pat) if !r.is_type_atom()
+ => r.matches_pat(&pat),
+ _ => None,
+ }
+ },
+
(SCons(a1, a2), SCons(b1, b2)) => {
let lefthand = a1.matches_pat(b1);
let checkres = (*b2).check_res_pat();