1 (in-package :lisp-on-lines
)
6 (define-layered-function description-of
(thing)
8 (find-description 't
)))
10 (defun description-print-name (description)
11 (description-class-name (class-of description
)))
13 (defun description-attributes (description)
14 (description-class-attributes (class-of description
)))
16 (defun description-current-attributes (description)
20 (some #'layer-active-p
22 (slot-definition-layers
23 (attribute-effective-attribute-definition attribute
))))))
24 (description-attributes description
)))
26 (defun description-active-attributes (description)
29 (description-attributes description
)))
31 (defun find-attribute (description attribute-name
)
32 (find attribute-name
(description-attributes description
)
33 :key
#'attribute-name
))
35 (define-layered-function description-active-descriptions
(description)
36 (:method
((description standard-description-object
))
37 (attribute-value (find-attribute description
'active-descriptions
)))
38 (:method
((description attribute
))
39 (attribute-active-descriptions description
)))
41 (define-layered-function description-inactive-descriptions
(description)
42 (:method
((description standard-description-object
))
43 (attribute-value (find-attribute description
'inactive-descriptions
)))
44 (:method
((description attribute
))
45 (attribute-inactive-descriptions description
)))
47 (define-layered-function attributes
(description)
48 (:method
(description)
49 (let* ((active-attributes
50 (find-attribute description
'active-attributes
))
51 (attributes (when active-attributes
52 (ignore-errors (attribute-value active-attributes
)))))
54 (mapcar (lambda (spec)
63 (and (attribute-active-p attribute
)
64 (some #'layer-active-p
66 (slot-definition-layers
67 (attribute-effective-attribute-definition attribute
))))))
68 (description-attributes description
))))))
71 (defun funcall-with-described-object (function object description
&rest args
)
72 (setf description
(or description
(description-of object
)))
73 (let ((*description
* description
)
75 (dletf (((described-object *description
*) object
))
76 (funcall-with-layer-context
78 (if (standard-description-p *description
*)
79 (adjoin-layer *description
* (current-layer-context))
80 (current-layer-context))
81 :activate
(description-active-descriptions *description
*)
82 :deactivate
(description-inactive-descriptions *description
*))
83 (lambda () (contextl::funcall-with-special-initargs
85 :for
(key val
) :on args
:by
#'cddr
86 :collect
(list (find key
(description-attributes *description
*)
87 :key
#'attribute-keyword
)
90 (contextl::funcall-with-special-initargs
91 (let ((attribute (ignore-errors (find-attribute *description
* 'active-attributes
))))
93 (loop for spec in
(attribute-value attribute
)
96 (find-attribute *description
* (car spec
))
97 (error "No attribute matching ~A" (car spec
)))
102 (defmacro with-described-object
((object description
&rest args
)
104 `(funcall-with-described-object
110 (defmacro define-description
(name &optional superdescriptions
&body options
)
111 (let ((description-name (defining-description name
)))
112 (destructuring-bind (&optional slots
&rest options
) options
113 (let ((description-layers (cdr (assoc :in-description options
))))
114 (if description-layers
115 `(progn ;eval-when (:compile-toplevel :load-toplevel :execute)
118 :in description-layers
119 :collect
`(define-description
120 ,name
,superdescriptions
,slots
122 :in-layer
(defining-description layer
)
123 (remove :in-description options
:key
#'car
)))))
124 `(progn ;eval-when (:compile-toplevel :load-toplevel :execute)
126 (defclass ,description-name
127 ,(append (mapcar #'defining-description
129 (unless (or (eq t name
)
130 (assoc :mixinp options
))
131 (list (defining-description t
))))
132 ,(if slots slots
'())
134 ,@(unless (assoc :metaclass options
)
135 '((:metaclass standard-description-class
))))
136 (initialize-descriptions)
137 (find-description ',name
)))))))