+(defun canonicalize-args-type-args (required optional rest)
+ (when (eq rest *empty-type*)
+ ;; or vice-versa?
+ (setq rest nil))
+ (loop with last-not-rest = nil
+ for i from 0
+ for opt in optional
+ do (cond ((eq opt *empty-type*)
+ (return (values required (subseq optional i) rest)))
+ ((neq opt rest)
+ (setq last-not-rest i)))
+ finally (return (values required
+ (if last-not-rest
+ (subseq optional 0 (1+ last-not-rest))
+ nil)
+ rest))))
+
+(defun args-types (lambda-list-like-thing)
+ (multiple-value-bind
+ (required optional restp rest keyp keys allowp auxp aux
+ morep more-context more-count llk-p)
+ (parse-lambda-list-like-thing lambda-list-like-thing)
+ (declare (ignore aux morep more-context more-count))
+ (when auxp
+ (error "&AUX in a FUNCTION or VALUES type: ~S." lambda-list-like-thing))
+ (let ((required (mapcar #'single-value-specifier-type required))
+ (optional (mapcar #'single-value-specifier-type optional))
+ (rest (when restp (single-value-specifier-type rest)))
+ (keywords
+ (collect ((key-info))
+ (dolist (key keys)
+ (unless (proper-list-of-length-p key 2)
+ (error "Keyword type description is not a two-list: ~S." key))
+ (let ((kwd (first key)))
+ (when (find kwd (key-info) :key #'key-info-name)
+ (error "~@<repeated keyword ~S in lambda list: ~2I~_~S~:>"
+ kwd lambda-list-like-thing))
+ (key-info
+ (make-key-info
+ :name kwd
+ :type (single-value-specifier-type (second key))))))
+ (key-info))))
+ (multiple-value-bind (required optional rest)
+ (canonicalize-args-type-args required optional rest)
+ (values required optional rest keyp keywords allowp llk-p)))))
+