aboutsummaryrefslogtreecommitdiff
path: root/src/sexp/util.rs
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2025-07-30 17:48:11 +0300
committerJoel Kronqvist <joel.kronqvist@iki.fi>2025-07-30 17:48:11 +0300
commita4b09d523e0b500de29c08b32abc13af8e509299 (patch)
tree77e0bdfa5b39c0789e829e698846fb06becbf7e1 /src/sexp/util.rs
parentd2d4d5cffdce0ce28e59732f56a771f8fc3431de (diff)
parentcd68a2880db1400ae09ce0df64994b2bae33a3c1 (diff)
downloadmyslip-a4b09d523e0b500de29c08b32abc13af8e509299.tar.gz
myslip-a4b09d523e0b500de29c08b32abc13af8e509299.zip
Merge work done on laptop to desktop computer
Merge branch 'devel' of ssh://cron4.fi/~/melisp into devel
Diffstat (limited to 'src/sexp/util.rs')
-rw-r--r--src/sexp/util.rs29
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()),
+ }
+ }
+}