aboutsummaryrefslogtreecommitdiff
path: root/src/sexp/util.rs
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-15 11:27:52 +0300
committerJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-15 11:27:52 +0300
commit0ca4c3f103acd9d1ea78bbc42b9b70161a94308d (patch)
tree7e8144434656f44e2e1f66175bb80ec6364a6ce5 /src/sexp/util.rs
parent322f541d6922422e5a4aa29f50c6534517ee85be (diff)
downloadmyslip-0ca4c3f103acd9d1ea78bbc42b9b70161a94308d.tar.gz
myslip-0ca4c3f103acd9d1ea78bbc42b9b70161a94308d.zip
feat: fixed point dynamics
Diffstat (limited to 'src/sexp/util.rs')
-rw-r--r--src/sexp/util.rs41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/sexp/util.rs b/src/sexp/util.rs
index aa7ae18..db400e9 100644
--- a/src/sexp/util.rs
+++ b/src/sexp/util.rs
@@ -87,6 +87,47 @@ impl SExp {
}
}
+ pub fn get_vars_bound_by_pattern(&self) -> Vec<String> {
+ match self {
+ Atom(Var(s)) => vec![s.clone()],
+ Atom(RestPat(s)) => vec![s.clone()],
+ SCons(a, b) =>
+ (*a).get_vars_bound_by_pattern()
+ .into_iter()
+ .chain((*b).get_vars_bound_by_pattern())
+ .collect(),
+ _ => vec![],
+ }
+ }
+
+ pub fn get_case_scrut_pats_and_arms(self) ->
+ Option<(SExp, Vec<(SExp, SExp)>)> {
+ let (scrutinee, patarms) = self.check_case()?;
+
+ let scrutinee = match scrutinee {
+ SCons(q, v) if *q == Atom(Quote) || *q == Atom(Vector) => *v,
+ t => t,
+ };
+
+ let mut res = vec![];
+ for patarm in patarms {
+ let (pat, arm) = match patarm {
+ SCons(pat, arm) => Some((*pat, *arm)),
+ _ => {
+ println!("warn: invalid structure in case arms,");
+ println!(" should be unreachable after type checking");
+ None
+ },
+ }?;
+ let arm = match arm {
+ SCons(x, n) if *n == Atom(Nil) => *x,
+ t => t,
+ };
+ res.push((pat, arm));
+ }
+ Some((scrutinee, res))
+ }
+
pub fn check_case(self) -> Option<(SExp, Vec<SExp>)> {
match &(self.parts())[..] {
[casekw, scrutinee, cases @ ..] if casekw.clone() == Atom(Case) =>