1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
(defmacro define-data-class
(class-name parent-classes slot-names
&key (no-print-slot-names nil) (no-equals-slot-names nil))
(flet ((accessor-symbol (slot-name)
(alexandria:format-symbol *package*
"~a-~a" class-name slot-name)))
(list 'progn
;; defclass
(let ((slot-defs (loop for slot-name in slot-names
collecting `(,slot-name
:initarg ,(alexandria:make-keyword slot-name)
:accessor ,(accessor-symbol slot-name)))))
`(defclass ,class-name ,parent-classes ,slot-defs))
;; defmethod print-object
(let* ((print-slot-names (set-difference slot-names
no-print-slot-names))
(fmt-ctrl (format nil "~{~a=~~a~^, ~}" print-slot-names)))
`(defmethod print-object ((obj ,class-name) stream)
(print-unreadable-object (obj stream :type t)
(with-slots ,print-slot-names obj
(format stream ,fmt-ctrl ,@print-slot-names)))))
;; defmethod equals:equals
(let* ((equals-slot-names (set-difference slot-names
no-equals-slot-names))
(equals-exprs (loop for equals-slot-name in equals-slot-names
collecting `(equals:equals (slot-value lhs (quote ,equals-slot-name))
(slot-value rhs (quote ,equals-slot-name))))))
`(defmethod equals:equals ((lhs ,class-name) (rhs ,class-name) &rest args)
(declare (ignore args))
(and t ,@equals-exprs)))
)))
|