Skip to content

Commit 09f8b11

Browse files
committed
utilities: fix parse-docstring-body!
1 parent adfa68c commit 09f8b11

File tree

2 files changed

+68
-9
lines changed

2 files changed

+68
-9
lines changed

test/test-utilities.lisp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
;;;; Some rudimentary tests for some of the utilities
2+
;;;
3+
4+
#+org.tfeb.tools.require-module
5+
(org.tfeb.tools.require-module:needs
6+
:org.tfeb.hax.utilities
7+
#+Quicklisp
8+
("parachute" :fallback ql:quickload))
9+
10+
(defpackage :org.tfeb.hax.utilities/test
11+
(:use :cl :org.tfeb.hax.utilities :org.shirakumo.parachute))
12+
13+
(in-package :org.tfeb.hax.utilities/test)
14+
15+
(define-test "org.tfeb.hax.utilities")
16+
17+
(define-test ("org.tfeb.hax.utilities" "parse-docstring-body")
18+
(is-values (parse-docstring-body '())
19+
(equal nil)
20+
(equal '())
21+
(equal '()))
22+
(is-values (parse-docstring-body '("foo"))
23+
(equal nil)
24+
(equal '())
25+
(equal '("foo")))
26+
(is-values (parse-docstring-body '("foo" (declare) 1))
27+
(equal "foo")
28+
(equal '((declare)))
29+
(equal '(1)))
30+
(is-values (parse-docstring-body
31+
'((declare 1)
32+
"foo"
33+
(declare 2)
34+
"foo"))
35+
(equal "foo")
36+
(equal '((declare 1) (declare 2)))
37+
(equal '("foo")))
38+
(is-values (parse-docstring-body
39+
'((declare 1)
40+
"foo"
41+
(declare 2)))
42+
(equal "foo")
43+
(equal '((declare 1) (declare 2)))
44+
(equal '())))
45+
46+
(test "org.tfeb.hax.utilities" :report 'summary)

utilities.lisp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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
3434
Return three values: the docstring, or NIL, a list of declarations and
3535
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 '())))
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

Comments
 (0)