@@ -29,18 +29,31 @@ Return two values: a list of declarations and a list of forms"
2929 (push this slced)))
3030
3131(defun parse-docstring-body (doc/decls/forms)
32- " Parse a body that may have a docstring at the start
32+ " Parse a body that may have a docstring and declarations at the start
3333
3434Return three values: the docstring, or NIL, a list of declarations and
3535a list of forms."
36- (if (and (stringp (first doc/decls/forms))
37- (not (null (rest doc/decls/forms))))
38- (multiple-value-bind (decls forms)
39- (parse-simple-body (rest doc/decls/forms))
40- (values (first doc/decls/forms) decls forms))
41- (multiple-value-bind (decls forms)
42- (parse-simple-body doc/decls/forms)
43- (values nil decls forms))))
36+ ; ; Note a docstring may be intertwined with declarations: the
37+ ; ; previous version of this got that wrong.
38+ (labels ((grovel (tail docstring scled)
39+ (if (null tail)
40+ (values docstring (nreverse scled) tail)
41+ (destructuring-bind (this . more) tail
42+ (cond
43+ ((and (not docstring) (stringp this) (not (null more)))
44+ (grovel more this scled))
45+ ((stringp this)
46+ ; ; Sanity check for extra declarations
47+ (let ((next (first more)))
48+ (when (and (consp next)
49+ (eq (car next) ' declare))
50+ (warn " unexpected declare after end of preamble" )))
51+ (values docstring (nreverse scled) tail))
52+ ((and (consp this) (eq (first this) ' declare))
53+ (grovel more docstring (cons this scled)))
54+ (t
55+ (values docstring (nreverse scled) tail)))))))
56+ (grovel doc/decls/forms nil ' ())))
4457
4558(defmacro with-names ((&rest clauses) &body forms)
4659 " Bind a bunch of variables to fresh symbols with the same name
0 commit comments