@@ -29,18 +29,31 @@ Return two values: a list of declarations and a list of forms"
29
29
(push this slced)))
30
30
31
31
(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
33
33
34
34
Return three values: the docstring, or NIL, a list of declarations and
35
35
a 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 ' ())))
44
57
45
58
(defmacro with-names ((&rest clauses) &body forms)
46
59
" Bind a bunch of variables to fresh symbols with the same name
0 commit comments