From 92658580c84e546d14978626fa0379d843fbe4f9 Mon Sep 17 00:00:00 2001 From: Troy Hinckley Date: Thu, 8 Feb 2024 13:06:22 -0600 Subject: [PATCH] Fix bug in function built-in with :documentation symbol Previously it was only including the first expression of the function in the closure. This because we took body from an element wise iterator. So instead we have defined a new function `rest` that will take the remainder of a cons iterator. --- src/core/cons/iter.rs | 5 +++++ src/interpreter.rs | 14 +++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/core/cons/iter.rs b/src/core/cons/iter.rs index 1a398b58..d1f363c7 100644 --- a/src/core/cons/iter.rs +++ b/src/core/cons/iter.rs @@ -66,6 +66,11 @@ impl ElemIter<'_> { self.clone().fallible().count() } + /// Take the rest of the list as a cons. + pub(crate) fn rest(&self) -> Result, ConsError> { + self.0.cons.transpose() + } + pub(crate) fn fallible(self) -> fallible_iterator::Convert { fallible_iterator::convert(self) } diff --git a/src/interpreter.rs b/src/interpreter.rs index 585d5d95..f2df68fc 100755 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -239,7 +239,11 @@ impl Interpreter<'_, '_> { /// Handle special case of (:documentation form) to build the docstring /// dynamically. If the docstring is not of this form, just return the current body. - fn replace_doc_symbol<'ob>(&mut self, quoted: &Rt, cx: &'ob mut Context) -> Result, EvalError> { + fn replace_doc_symbol<'ob>( + &mut self, + quoted: &Rt, + cx: &'ob mut Context, + ) -> Result, EvalError> { // quoted = (() (doc_str) ...) let docstring = { let Ok(list) = quoted.bind(cx).as_list() else { return Ok(quoted.bind(cx)) }; @@ -263,10 +267,10 @@ impl Interpreter<'_, '_> { } }; // (() (:documentation
) body) - let mut forms = quoted.bind(cx).as_list().unwrap().fallible(); - let arg_list = forms.next()?.unwrap(); - let _old_doc = forms.next()?.unwrap(); - let body = forms.next()?.unwrap_or_default(); + let mut forms = quoted.bind(cx).as_list().unwrap(); + let arg_list = forms.next().unwrap()?; + let _old_doc = forms.next().unwrap()?; + let body = forms.rest()?.map(|x| x.into()).unwrap_or(NIL); Ok(Cons::new(arg_list, Cons::new(docstring, body, cx), cx).into()) }