Skip to content

Commit

Permalink
Be more careful when parsing method bodies.
Browse files Browse the repository at this point in the history
  • Loading branch information
marcoheisig committed Jan 4, 2021
1 parent 0ca43f1 commit 9c307cd
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 19 deletions.
27 changes: 14 additions & 13 deletions code/fast-method.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,17 @@
(assert (eql lambda-symbol 'lambda))
(multiple-value-bind (required optional rest-var keyword allow-other-keys-p auxiliary)
(parse-ordinary-lambda-list lambda-list)
(let ((n-declarations (position-if-not (starts-with 'declare) body))
(partially-flattened-lambda-list
`(,@(lambda-list-variables
(unparse-ordinary-lambda-list
required optional rest-var keyword allow-other-keys-p '()))
,@(unparse-ordinary-lambda-list '() '() nil '() nil auxiliary))))
(trivial-macroexpand-all:macroexpand-all
`(lambda ,partially-flattened-lambda-list
(declare (ignorable ,@(mapcar #'required-info-variable required)))
,@(subseq body 0 n-declarations)
(block ,(block-name (generic-function-name generic-function))
,@(subseq body n-declarations)))
environment)))))
(multiple-value-bind (forms declarations)
(parse-body body)
(let ((partially-flattened-lambda-list
`(,@(lambda-list-variables
(unparse-ordinary-lambda-list
required optional rest-var keyword allow-other-keys-p '()))
,@(unparse-ordinary-lambda-list '() '() nil '() nil auxiliary))))
(trivial-macroexpand-all:macroexpand-all
`(lambda ,partially-flattened-lambda-list
(declare (ignorable ,@(mapcar #'required-info-variable required)))
,@declarations
(block ,(block-name (generic-function-name generic-function))
,@forms))
environment))))))
23 changes: 17 additions & 6 deletions code/utilities.lisp
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
(in-package #:fast-generic-functions)

(defun starts-with (item)
(lambda (sequence)
(typecase sequence
(list (eql (first sequence) item))
(sequence (eql (elt sequence 0) item))
(otherwise nil))))
(defun parse-body (body)
(let ((declarations '())
(documentation nil))
(loop for (item . rest) on body do
(cond ((and (stringp item) (consp rest))
(if (not documentation)
(setf documentation item)
(error "Multiple documentation strings in body: ~%~S~% and~%~S."
documentation item)))
((and (listp item) (eq (first item) 'declare))
(push item declarations))
(t
(return-from parse-body
(values
(list* item rest)
(reverse declarations)
documentation)))))))

(defun block-name (function-name)
(etypecase function-name
Expand Down

0 comments on commit 9c307cd

Please sign in to comment.