aboutsummaryrefslogtreecommitdiff
path: root/src/sexp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sexp')
-rw-r--r--src/sexp/case.rs30
-rw-r--r--src/sexp/mod.rs12
2 files changed, 41 insertions, 1 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();
diff --git a/src/sexp/mod.rs b/src/sexp/mod.rs
index 14731dd..c1a5a8e 100644
--- a/src/sexp/mod.rs
+++ b/src/sexp/mod.rs
@@ -89,7 +89,10 @@ impl SExp {
scons(a.clone(), b.clone()).is_fun() ||
SCons(a.clone(), b.clone()).check_let().is_some() ||
(
- (**a == Atom(Quote) || **a == Atom(Vector) || (**a).is_type_lit())
+ (**a == Atom(Quote)
+ || **a == Atom(Vector)
+ || (**a).is_type_lit()
+ || **a == Atom(Coprod))
&& b.consists_of_values()
),
Atom(Var(_)) => false,
@@ -122,4 +125,11 @@ impl SExp {
_ => false
}
}
+
+ pub fn is_type_atom(&self) -> bool {
+ match self {
+ Atom(Ty(_)) => true,
+ _ => false,
+ }
+ }
}