diff options
Diffstat (limited to 'src/sexp/case.rs')
-rw-r--r-- | src/sexp/case.rs | 30 |
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(); |