aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
// ---------------------------------------------------------