Skip to content

Commit

Permalink
Fix docstring and body parsing
Browse files Browse the repository at this point in the history
Consider cases where there are multiple declarations or a docstring in
between. Those cases do not seem very clearly specified in the CLHS,
but I have tried to interpret it in the more flexible way.

It fixes some code examples from PAIP and it is consistent with SBCL.

Some test cases were added.
  • Loading branch information
davazp committed May 1, 2018
1 parent 66a69ab commit 0234901
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 14 deletions.
38 changes: 24 additions & 14 deletions src/compiler/compiler.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -397,20 +397,30 @@
;;; list of declaration forms and the docstring.
(defun parse-body (body &key declarations docstring)
(let ((value-declarations)
(value-docstring))
;; Parse declarations
(when declarations
(do* ((rest body (cdr rest))
(form (car rest) (car rest)))
((or (atom form) (not (eq (car form) 'declare)))
(setf body rest))
(push form value-declarations)))
;; Parse docstring
(when (and docstring
(stringp (car body))
(not (null (cdr body))))
(setq value-docstring (car body))
(setq body (cdr body)))
(value-docstring)
(end nil))

(while (not end)
(cond
;; Docstring
((and docstring
(stringp (car body))
(not (null (cdr body))))
(when value-docstring
(error "Duplicated docstring ~S" (car body)))
(setq value-docstring (car body))
(setq body (cdr body)))

;; Declaration
((and declarations
(consp (car body))
(eq (caar body) 'declare))
(push (car body) value-declarations)
(setq body (cdr body)))

(t
(setq end t))))

(values body value-declarations value-docstring)))


Expand Down
29 changes: 29 additions & 0 deletions tests/defun.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,32 @@

;;; Regression test for #111
(test (eql (defun foo () "foo's" ()) 'foo))


;;; Body, declarations and docstrings

(let ((actual
(multiple-value-list
(parse-body '((declare (integerp x)) "foo" 3)
:declarations t
:docstring t))))

(test (equal actual '((3) ((DECLARE (INTEGERP X))) "foo"))))

(let ((actual
(multiple-value-list
(parse-body '((declare (integerp x)) "foo")
:declarations t
:docstring t))))

(test (equal actual '(("foo") ((DECLARE (INTEGERP X))) nil))))


(let ((actual
(multiple-value-list
(parse-body '("foo" 3)
:declarations t
:docstring t))))

(test (equal actual '((3) nil "foo"))))

0 comments on commit 0234901

Please sign in to comment.