[slime-devel] openmcl defclass documentation workaroud
Marco Baringer
mb at bese.it
Thu Oct 28 09:39:57 UTC 2004
the following code, put in openmcl-init.lisp, fixes a bug in openmcl's
defclass macro and should allow the inspector to work properly. it's
just a dirty hack till the next official release of openmcl.
;;;; defclass work around
(defclass common-lisp-user::!@$% () () (:documentation "x"))
(when (consp (documentation (find-class 'common-lisp-user::!@$%) t))
(handler-bind ((error (lambda (c) (declare (ignore c)) (invoke-restart 'continue))))
(defmacro defclass (class-name superclasses slots &rest class-options &environment env)
(flet ((duplicate-options (where) (signal-program-error "Duplicate options in ~S" where))
(illegal-option (option) (signal-program-error "Illegal option ~s" option))
(make-initfunction (form)
(cond ((or (eq form 't)
(equal form ''t))
'(function true))
((or (eq form 'nil)
(equal form ''nil))
'(function false))
(t
`(function (lambda () ,form))))))
(setq class-name (require-type class-name '(and symbol (not null))))
(setq superclasses (mapcar #'(lambda (s) (require-type s 'symbol)) superclasses))
(let* ((options-seen ())
(signatures ())
(slot-names))
(flet ((canonicalize-defclass-option (option)
(let* ((option-name (car option)))
(if (member option-name options-seen :test #'eq)
(duplicate-options class-options)
(push option-name options-seen))
(case option-name
(:default-initargs
(let ((canonical ()))
(let (key val (tail (cdr option)))
(loop (when (null tail) (return nil))
(setq key (pop tail)
val (pop tail))
(push ``(,',key ,',val ,,(make-initfunction val)) canonical))
`(':direct-default-initargs (list ,@(nreverse canonical))))))
(:metaclass
(unless (and (cadr option)
(typep (cadr option) 'symbol))
(illegal-option option))
`(:metaclass ',(cadr option)))
(:documentation
(let* ((doc (cadr option)))
(if (and doc (not (typep doc 'string)))
(illegal-option option))
`(:documentation ',doc)))
(t
(list `',option-name `',(cdr option))))))
(canonicalize-slot-spec (slot)
(if (null slot) (signal-program-error "Illegal slot NIL"))
(if (not (listp slot)) (setq slot (list slot)))
(let* ((slot-name (require-type (car slot) 'symbol))
(initargs nil)
(other-options ())
(initform nil)
(initform-p nil)
(initfunction nil)
(type nil)
(type-p nil)
(allocation nil)
(allocation-p nil)
(documentation nil)
(documentation-p nil)
(readers nil)
(writers nil))
(when (memq slot-name slot-names)
(SIGNAL-PROGRAM-error "Duplicate slot name ~S" slot-name))
(push slot-name slot-names)
(do ((options (cdr slot) (cddr options))
name)
((null options))
(when (null (cdr options)) (signal-program-error "Illegal slot spec ~S" slot))
(case (car options)
(:reader
(setq name (cadr options))
(push name signatures)
(push name readers))
(:writer
(setq name (cadr options))
(push name signatures)
(push name writers))
(:accessor
(setq name (cadr options))
(push name signatures)
(push name readers)
(push `(setf ,name) signatures)
(push `(setf ,name) writers))
(:initarg
(push (require-type (cadr options) 'symbol) initargs))
(:type
(if type-p
(duplicate-options slot)
(setq type-p t))
;(when (null (cadr options)) (signal-program-error "Illegal options ~S" options))
(setq type (cadr options)))
(:initform
(if initform-p
(duplicate-options slot)
(setq initform-p t))
(let ((option (cadr options)))
(setq initform `',option
initfunction
(if (constantp option)
`(constantly ,option)
`#'(lambda () ,option)))))
(:allocation
(if allocation-p
(duplicate-options slot)
(setq allocation-p t))
(setq allocation (cadr options)))
(:documentation
(if documentation-p
(duplicate-options slot)
(setq documentation-p t))
(setq documentation (cadr options)))
(t
(let* ((pair (or (assq (car options) other-options)
(car (push (list (car options)) other-options)))))
(push (cadr options) (cdr pair))))))
`(list :name ',slot-name
,@(when allocation `(:allocation ',allocation))
,@(when initform-p `(:initform ,initform
:initfunction ,initfunction))
,@(when initargs `(:initargs ',initargs))
,@(when readers `(:readers ',readers))
,@(when writers `(:writers ',writers))
,@(when type-p `(:type ',type))
,@(when documentation-p `(:documentation ,documentation))
,@(mapcan #'(lambda (opt)
`(',(car opt) ',(cdr opt))) other-options)))))
(let* ((direct-superclasses (or superclasses '(standard-object)))
(direct-slot-specs (mapcar #'canonicalize-slot-spec slots))
(other-options (apply #'append (mapcar #'canonicalize-defclass-option class-options ))))
`(progn
(eval-when (:compile-toplevel)
(%compile-time-defclass ',class-name ,env)
(progn
,@(mapcar #'(lambda (s) `(note-function-info ',s nil ,env))
signatures)))
(ensure-class-for-defclass ',class-name
:direct-superclasses ',direct-superclasses
:direct-slots ,`(list , at direct-slot-specs)
, at other-options)))))))))
hth.
--
-Marco
Ring the bells that still can ring.
Forget your perfect offering.
There is a crack in everything.
That's how the light gets in.
-Leonard Cohen
More information about the slime-devel
mailing list