diff options
author | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-08-14 12:17:41 +0300 |
---|---|---|
committer | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-08-14 12:17:41 +0300 |
commit | 0975bff6ddcf48de4072561adea67a5c1cd4456f (patch) | |
tree | f77291d0430079d6927bf896c133e97a6e59c684 | |
parent | 189d06730ae23770fbb970bf37eb0993edb8cd2d (diff) | |
download | myslip-0975bff6ddcf48de4072561adea67a5c1cd4456f.tar.gz myslip-0975bff6ddcf48de4072561adea67a5c1cd4456f.zip |
fix: step scrutinee of case & can instantiate empty vec
-rw-r--r-- | src/sexp/case.rs | 1 | ||||
-rw-r--r-- | src/sexp/step.rs | 23 | ||||
-rw-r--r-- | src/sexp/util.rs | 8 | ||||
-rw-r--r-- | src/type/check.rs | 15 |
4 files changed, 45 insertions, 2 deletions
diff --git a/src/sexp/case.rs b/src/sexp/case.rs index d78f7ad..eb98446 100644 --- a/src/sexp/case.rs +++ b/src/sexp/case.rs @@ -54,6 +54,7 @@ impl SExp { * ``` */ pub fn matches_pat(&self, pat: &SExp) -> Option<Vec<(String, SExp)>> { + println!("matchin {self} against {pat}"); match (self, pat) { (a, b) if a == b => Some(vec![]), diff --git a/src/sexp/step.rs b/src/sexp/step.rs index 97675fa..bae47a5 100644 --- a/src/sexp/step.rs +++ b/src/sexp/step.rs @@ -286,6 +286,20 @@ impl SExp { /// ); /// ``` /// + /// **Pattern matching** + /// ```rust + /// use myslip::{sexp::{SExp::*, SLeaf::*, util::*}, r#type::{Type::*, util::*}}; + /// use myslip::parse::parsetree::parse_to_ast; + /// + /// let exp = "case (+ 1 2) (3 true) (_ false)"; + /// let exp = parse_to_ast(exp); + /// let exp = exp.and_then(|e| e.step()); + /// let expshould = parse_to_ast("case 3 (3 true) (_ false)"); + /// assert_eq!(exp, expshould); + /// let exp = exp.and_then(|e| e.step()); + /// assert_eq!(exp, Ok(Atom(True))); + /// ``` + /// /// Shadowing: /// ```rust /// use myslip::sexp::{SExp::*, SLeaf::*, util::*}; @@ -352,6 +366,10 @@ impl SExp { // case expressions SCons(op, l) if scons(op.clone(), l.clone()).check_case().is_some() => { let (scrutinee, patarms) = scons(op, l).check_case().unwrap(); + if !scrutinee.is_value() { + return Ok(SExp::back_to_case(scrutinee.step()?, patarms)); + // return scons(Case, scons(scrutinee.step()?)) + } let scrutinee = match scrutinee { SCons(q, v) if *q == Atom(Quote) || *q == Atom(Vector) => *v, @@ -627,6 +645,11 @@ impl SExp { } }, + // Nil in list + SCons(op, l) if *op == Atom(Nil) => { + Ok(scons(Vector, Nil)) + }, + // Print SCons(op, l) if *op == Atom(Print) => { println!("{}", *l); diff --git a/src/sexp/util.rs b/src/sexp/util.rs index 3de45d4..aa7ae18 100644 --- a/src/sexp/util.rs +++ b/src/sexp/util.rs @@ -94,4 +94,12 @@ impl SExp { _ => None, } } + + pub fn back_to_case(scrutinee: SExp, arms: Vec<SExp>) -> SExp { + let mut res = Atom(Nil); + for arm in arms.into_iter().rev() { + res = scons(arm, res); + } + scons(Case, scons(scrutinee, res)) + } } diff --git a/src/type/check.rs b/src/type/check.rs index f842b4c..02b629c 100644 --- a/src/type/check.rs +++ b/src/type/check.rs @@ -218,10 +218,10 @@ impl SExp { pub fn type_check(&self) -> Result<Type, TypeError> { let res = self.infer_type(HashMap::new()); match res { - Ok(res) => match res.is_concrete() { + Ok(res) => {println!("maybe unbound: {}", res); match res.is_concrete() { Ok(()) => Ok(res), Err(name) => Err(UnboundGeneric(name)), - }, + }}, e => e, } } @@ -281,6 +281,17 @@ impl SExp { return scons(op.clone(), l.clone()).get_fun_type(ctx); } + // Nil vector + if (**op).clone() == Atom(Nil) { + return match (**l).clone() { + SCons(v, n) if *n == Atom(Nil) => match *v { + Atom(Ty(t)) => Ok(vecof(t)), + _ => Err(OtherError), + }, + _ => Err(OtherError) + } + } + // Case expressions if let Some((scrutinee, patarms)) = scons(op.clone(), l.clone()).check_case() { let scruty = scrutinee.infer_type(ctx.clone())?; |