diff options
author | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-08-16 02:04:09 +0300 |
---|---|---|
committer | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-08-16 02:04:09 +0300 |
commit | e35522189f5217987bc455d70c3b9056541ef8c6 (patch) | |
tree | 421bcca16938157268eb9bcd4ea181ce0d099133 /src/sexp | |
parent | a97fef6f099767924c5203782a2b04b1a559ac6b (diff) | |
download | myslip-e35522189f5217987bc455d70c3b9056541ef8c6.tar.gz myslip-e35522189f5217987bc455d70c3b9056541ef8c6.zip |
feat: type conversion from (Vec/Quote X) -> X and add vec/quote to rest pattern substitutions
Diffstat (limited to 'src/sexp')
-rw-r--r-- | src/sexp/case.rs | 18 | ||||
-rw-r--r-- | src/sexp/step.rs | 16 |
2 files changed, 21 insertions, 13 deletions
diff --git a/src/sexp/case.rs b/src/sexp/case.rs index 40310e4..0c3d82d 100644 --- a/src/sexp/case.rs +++ b/src/sexp/case.rs @@ -1,5 +1,5 @@ -use crate::sexp::{SExp, SExp::*, SLeaf::*}; +use crate::sexp::{SExp, SLeaf, SExp::*, SLeaf::*, util::*}; impl SExp { /** @@ -20,7 +20,7 @@ impl SExp { * scons(1, scons(scons(2, scons(3, Nil)), Nil)) * .matches_pat(&var("x")), * Some(vec![( - * "x".to_string(), + * Var("x".to_string()), * scons(1, scons(scons(2, scons(3, Nil)), Nil)) * )]) * ); @@ -34,8 +34,8 @@ impl SExp { * scons(1, scons(scons(2, scons(3, Nil)), Nil)) * .matches_pat(&scons(var("x"), scons(var("y"), Nil))), * Some(vec![ - * ("x".to_string(), Atom(Int(1))), - * ("y".to_string(), scons(2, scons(3, Nil))) + * (Var("x".to_string()), Atom(Int(1))), + * (Var("y".to_string()), scons(2, scons(3, Nil))) * ]) * ); * ``` @@ -47,24 +47,24 @@ impl SExp { * scons(1, scons(2, scons(3, Nil))) * .matches_pat(&scons(var("x"), scons(RestPat("y".to_string()), Nil))), * Some(vec![ - * ("x".to_string(), Atom(Int(1))), - * ("y".to_string(), scons(2, scons(3, Nil))) + * (Var("x".to_string()), Atom(Int(1))), + * (RestPat("y".to_string()), scons(2, scons(3, Nil))) * ]) * ); * ``` */ - pub fn matches_pat(&self, pat: &SExp) -> Option<Vec<(String, SExp)>> { + pub fn matches_pat(&self, pat: &SExp) -> Option<Vec<(SLeaf, SExp)>> { match (self, pat) { (a, b) if a == b => Some(vec![]), - (a, Atom(Var(name))) => Some(vec![(name.clone(), a.clone())]), + (a, Atom(Var(name))) => Some(vec![(Var(name.to_string()), a.clone())]), (SCons(a1, a2), SCons(b1, b2)) => { let lefthand = a1.matches_pat(b1); let checkres = (*b2).check_res_pat(); let righthand = match checkres { - Some(name) => Some(vec![(name, *a2.clone())]), + Some(name) => Some(vec![(RestPat(name.clone()), *a2.clone())]), None => a2.matches_pat(b2), }; lefthand.zip(righthand) diff --git a/src/sexp/step.rs b/src/sexp/step.rs index 99925ac..9077401 100644 --- a/src/sexp/step.rs +++ b/src/sexp/step.rs @@ -352,9 +352,10 @@ impl SExp { return Ok(SExp::back_to_case(scrutinee.step()?, patarms)); } - let scrutinee = match scrutinee { - SCons(q, v) if *q == Atom(Quote) || *q == Atom(Vector) => *v, - t => t, + let (scrutinee, rest_pat_struct) = match scrutinee { + SCons(q, v) if *q == Atom(Quote) => (*v, Some(Quote)), + SCons(q, v) if *q == Atom(Vector) => (*v, Some(Vector)), + t => (t, None), }; for patarm in patarms { @@ -369,7 +370,14 @@ impl SExp { if let Some(ctx) = scrutinee.matches_pat(&pat) { for (name, value) in ctx { - arm = arm.subst(&name, &value); + arm = match name { + Var(name) => arm.subst(&name, &value), + RestPat(name) => match rest_pat_struct.clone() { + Some(kw) => arm.subst(&name, &scons(kw, value)), + None => arm.subst(&name, &value) + }, + _ => panic!("unreachable") + }; } return Ok(arm); } |