diff options
author | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-07-30 17:27:15 +0300 |
---|---|---|
committer | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-07-30 17:27:15 +0300 |
commit | cd68a2880db1400ae09ce0df64994b2bae33a3c1 (patch) | |
tree | 04893ee79ed16b920e7129b4eab1298a62814d65 /src/sexp/util.rs | |
parent | 8e2ca4bbc356d87ff5a37f20bea4f5b3cc561041 (diff) | |
download | myslip-cd68a2880db1400ae09ce0df64994b2bae33a3c1.tar.gz myslip-cd68a2880db1400ae09ce0df64994b2bae33a3c1.zip |
Implemented evaluation according to tests. Quite a bit of changes were required, see rest of commit message.
SExp::Quote was added to let the interpreter know whether
a list should be evaluated or treated as a literal list.
It still needs code to be added for parsing it successfully.
Some utility functions were needed:
* SExp::is_value
* SExp::consists_of_values
* SExp::into_vec
Diffstat (limited to 'src/sexp/util.rs')
-rw-r--r-- | src/sexp/util.rs | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/src/sexp/util.rs b/src/sexp/util.rs index ce6de5d..70ac152 100644 --- a/src/sexp/util.rs +++ b/src/sexp/util.rs @@ -1,4 +1,6 @@ +use std::iter; + use crate::sexp::SExp; use crate::sexp::SLeaf; use crate::sexp::SExp::*; @@ -30,3 +32,30 @@ pub fn var(name: &str) -> SExp { Atom(Var(name.to_string())) } +impl SExp { + /// Transforms this SExp into a Vec<SLeaf>. + /// + /// Errors if the left-hand side of SCons has an SCons, + /// or if the passed SExp is an Atom, or if the + /// lists aren't Nil-terminated. + /// + /// ```rust + /// use melisp::sexp::{SExp::*, SLeaf::*, util::*}; + /// assert_eq!( + /// scons(1, scons(2, scons(3, Nil))).into_vec(), + /// Ok(vec![Int(1), Int(2), Int(3)]) + /// ); + /// assert!(scons(scons(1, Nil), Nil).into_vec().is_err()); + /// assert!(scons(1, 2).into_vec().is_err()); + /// ``` + pub fn into_vec(self) -> Result<Vec<SLeaf>, String> { + match self { + SCons(a, b) => match (*a, *b) { + (Atom(a), Atom(Nil)) => Ok(iter::once(a).collect::<Vec<SLeaf>>()), + (Atom(a), b) => Ok(iter::once(a).chain(b.into_vec()?).collect::<Vec<SLeaf>>()), + (a, b) => Err(format!("invalid list structure: {:?}", scons(a, b))) + }, + _ => Err("expected list, found atom".to_string()), + } + } +} |