Ignore:
Timestamp:
05/15/17 20:37:26 (6 years ago)
Author:
Mark Evenson
Message:

Fix DESTRUCTURING-BIND with &rest arguments

(Olof-Joachim Frahm)

Fixes <http://abcl.org/trac/ticket/417> aka
<https://github.com/armedbear/abcl/issues/8>.

Merges <https://github.com/armedbear/abcl/pull/42>.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/abcl/src/org/armedbear/lisp/destructuring-bind.lisp

    r14133 r15004  
    142142    (when (eq keyword (car remaining))
    143143      (return t))))
     144
     145(defun dot-length (cons)
     146  (do ((rest cons (cdr rest))
     147       (length 0 (1+ length)))
     148      ((or (null rest) (atom rest)) length)))
    144149
    145150(defun parse-defmacro-lambda-list
     
    194199                            env-arg-used t))
    195200         (t
    196           (defmacro-error "&ENVIRONMENT" error-kind name))))
     201          (defmacro-error "&ENVIRONMENT" name))))
    197202        ((or (eq var '&rest) (eq var '&body))
    198203         (cond ((and (cdr rest-of-args) (symbolp (cadr rest-of-args)))
     
    210215       destructuring-lambda-list sub name error-kind error-fun)))
    211216         (t
    212           (defmacro-error (symbol-name var) error-kind name))))
     217          (defmacro-error (symbol-name var) name))))
    213218        ((eq var '&optional)
    214219         (setq now-processing :optionals))
     
    280285        (t
    281286         (error "non-symbol in lambda-list: ~S" var)))))
    282     ;; Generate code to check the number of arguments, unless dotted
    283     ;; in which case length will not work.
    284     (unless restp
    285       (push `(unless (<= ,minimum
    286                          (length ,path-0)
    287                          ,@(unless restp
    288                              (list maximum)))
    289                ,(if (eq error-fun 'error)
    290                     `(arg-count-error ',error-kind ',name ,path-0
    291                                       ',lambda-list ,minimum
    292                                       ,(unless restp maximum))
    293                     `(,error-fun 'arg-count-error
    294                       :kind ',error-kind
    295                       ,@(when name `(:name ',name))
    296                       :argument ,path-0
    297                       :lambda-list ',lambda-list
    298                       :minimum ,minimum
    299                       ,@(unless restp `(:maximum ,maximum)))))
    300             *arg-tests*))
     287    ;; Generate code to check the number of arguments.
     288    (push `(unless (<= ,minimum
     289                       (dot-length ,path-0)
     290                       ,@(unless restp
     291                           (list maximum)))
     292             ,(if (eq error-fun 'error)
     293                  `(arg-count-error ',error-kind ',name ,path-0
     294                                    ',lambda-list ,minimum
     295                                    ,(unless restp maximum))
     296                  `(,error-fun 'arg-count-error
     297                    :kind ',error-kind
     298                    ,@(when name `(:name ',name))
     299                    :argument ,path-0
     300                    :lambda-list ',lambda-list
     301                    :minimum ,minimum
     302                    ,@(unless restp `(:maximum ,maximum)))))
     303          *arg-tests*)
    301304    (if keys
    302305        (let ((problem (gensym "KEY-PROBLEM-"))
Note: See TracChangeset for help on using the changeset viewer.