[armedbear-cvs] r13216 - trunk/abcl/src/org/armedbear/lisp
Erik Huelsmann
ehuelsmann at common-lisp.net
Sun Feb 13 11:02:16 UTC 2011
Author: ehuelsmann
Date: Sun Feb 13 06:02:14 2011
New Revision: 13216
Log:
Fixes to checking initargs:
- Use only keyword arguments for the check (not the full lambda-list)
- Add support for keyword args explicitly naming their keyword [((:e d))]
Modified:
trunk/abcl/src/org/armedbear/lisp/clos.lisp
Modified: trunk/abcl/src/org/armedbear/lisp/clos.lisp
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/clos.lisp (original)
+++ trunk/abcl/src/org/armedbear/lisp/clos.lisp Sun Feb 13 06:02:14 2011
@@ -2577,44 +2577,59 @@
(error 'program-error
:format-control "Odd number of keyword arguments."))
(unless (getf initargs :allow-other-keys)
- (let ((methods
- (nconc
- (compute-applicable-methods #'shared-initialize
- (list* instance shared-initialize-param
- initargs))
- (mapcan #'(lambda (gf)
- (compute-applicable-methods gf args))
- gf-list)))
- (slots (class-slots (class-of instance))))
- (do* ((tail initargs (cddr tail))
- (initarg (car tail) (car tail)))
- ((null tail))
- (unless (or (valid-initarg-p initarg slots)
- (valid-methodarg-p initarg methods)
- (eq initarg :allow-other-keys))
- (error 'program-error
- :format-control "Invalid initarg ~S."
- :format-arguments (list initarg)))))))
-
-(defun valid-methodarg-p (initarg methods)
- (when (symbolp initarg)
- (dolist (method methods nil)
- (let ((valid-initargs (method-lambda-list method)))
- (when (find (symbol-value initarg) valid-initargs
- :test #'(lambda (a b)
- (if (listp b)
- (eq a (car b))
- (or
- (eq a b)
- (eq b 'cl:&allow-other-keys)))))
-
- (return t))))))
-
-(defun valid-initarg-p (initarg slots)
- (dolist (slot slots nil)
- (let ((valid-initargs (slot-definition-initargs slot)))
- (when (memq initarg valid-initargs)
- (return t)))))
+ (let* ((methods
+ (nconc
+ (compute-applicable-methods #'shared-initialize
+ (list* instance
+ shared-initialize-param
+ initargs))
+ (mapcan #'(lambda (gf)
+ (compute-applicable-methods gf args))
+ gf-list)))
+ (method-keyword-args
+ (reduce #'merge-initargs-sets
+ (mapcar #'method-lambda-list methods)
+ :key #'extract-lambda-list-keywords
+ :initial-value nil))
+ (slots-initargs
+ (mapappend #'slot-definition-initargs
+ (class-slots (class-of instance))))
+ (allowable-initargs
+ (merge-initargs-sets
+ (merge-initargs-sets slots-initargs method-keyword-args)
+ '(:allow-other-keys)))) ;; allow-other-keys is always allowed
+ (unless (eq t allowable-initargs)
+ (do* ((tail initargs (cddr tail))
+ (initarg (car tail) (car tail)))
+ ((null tail))
+ (unless (memq initarg allowable-initargs)
+ (error 'program-error
+ :format-control "Invalid initarg ~S."
+ :format-arguments (list initarg))))))))
+
+(defun merge-initargs-sets (list1 list2)
+ (cond
+ ((eq list1 t) t)
+ ((eq list2 t) t)
+ (t (union list1 list2))))
+
+(defun extract-lambda-list-keywords (lambda-list)
+ "Returns a list of keywords acceptable as keyword arguments,
+or T when any keyword is acceptable due to presence of
+&allow-other-keys."
+ (when (member '&allow-other-keys lambda-list)
+ (return-from extract-lambda-list-keywords t))
+ (let* ((keyword-args (cdr (memq '&key lambda-list)))
+ (aux-vars (position '&aux keyword-args)))
+ (when keyword-args
+ (when aux-vars
+ (setq keyword-args (subseq keyword-args 0 aux-vars)))
+ (let (result)
+ (dolist (key keyword-args result)
+ (when (listp key)
+ (setq key (car key)))
+ (push (if (symbolp key) (make-keyword key) (car key)) result))))))
+
(defgeneric make-instance (class &rest initargs &key &allow-other-keys))
More information about the armedbear-cvs
mailing list