aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-12 20:15:30 +0300
committerJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-12 20:15:30 +0300
commitec13c45c8ae0f63fa715178308547cfadd8f8c39 (patch)
tree94b69a54861437b525e3fc2832118413b94baed2
parenta8a4c5b567ea6a58809dc8232ea5f1d3c93879b9 (diff)
downloadmyslip-ec13c45c8ae0f63fa715178308547cfadd8f8c39.tar.gz
myslip-ec13c45c8ae0f63fa715178308547cfadd8f8c39.zip
feat: pattern matching evaluation in step.rs
-rw-r--r--src/sexp/case.rs2
-rw-r--r--src/sexp/step.rs29
2 files changed, 30 insertions, 1 deletions
diff --git a/src/sexp/case.rs b/src/sexp/case.rs
index 71f5007..d78f7ad 100644
--- a/src/sexp/case.rs
+++ b/src/sexp/case.rs
@@ -71,7 +71,7 @@ impl SExp {
.map(|vs| vs.0.into_iter().chain(vs.1).collect())
},
- _ => todo!(),
+ _ => None,
}
}
diff --git a/src/sexp/step.rs b/src/sexp/step.rs
index fd6be9e..97675fa 100644
--- a/src/sexp/step.rs
+++ b/src/sexp/step.rs
@@ -349,6 +349,35 @@ impl SExp {
None => panic!("unreachable as per match guard arm"),
},
+ // case expressions
+ SCons(op, l) if scons(op.clone(), l.clone()).check_case().is_some() => {
+ let (scrutinee, patarms) = scons(op, l).check_case().unwrap();
+
+ let scrutinee = match scrutinee {
+ SCons(q, v) if *q == Atom(Quote) || *q == Atom(Vector) => *v,
+ t => t,
+ };
+
+ for patarm in patarms {
+ let (pat, arm) = match patarm {
+ SCons(pat, arm) => Ok((*pat, *arm)),
+ _ => Err("unreachable after type checking".to_string())
+ }?;
+ let mut arm = match arm {
+ SCons(x, n) if *n == Atom(Nil) => *x,
+ t => t,
+ };
+
+ if let Some(ctx) = scrutinee.matches_pat(&pat) {
+ for (name, value) in ctx {
+ arm = arm.subst(&name, &value);
+ }
+ return Ok(arm);
+ }
+ }
+ Err("This should be unreachable after type checking".to_string())
+ },
+
// op value and a1 .. an values, and b0, b1 .. bn not values
// ---------------------------------------------------------