1 (in-package :lisp-on-lines
)
3 (define-layered-class direct-attribute-definition-class
4 (special-layered-direct-slot-definition contextl
::singleton-direct-slot-definition
)
5 ((attribute-properties :accessor direct-attribute-properties
6 :documentation
"This is an plist to hold the values of the attribute's properties as described by this direct attrbiute definition.")))
8 (defmethod initialize-instance :after
((attribute direct-attribute-definition-class
) &rest initargs
)
9 (setf (direct-attribute-properties attribute
) initargs
))
11 (define-layered-class effective-attribute-definition-class
(special-layered-effective-slot-definition)
12 ((direct-attributes :accessor attribute-direct-attributes
)
13 (attribute-object :accessor attribute-object
17 (define-layered-function attribute-value
(object attribute
))
19 (define-layered-method attribute-value
(object attribute
)
21 (let ((fn (handler-case (attribute-function attribute
)
22 (unbound-slot () nil
))))
25 (%attribute-value attribute
))))
27 (defmethod attribute-description (attribute)
28 ;(break "description for ~A is (slot-value attribute 'description-name)")
29 (find-layer (slot-value attribute
'description-class
))
30 #+nil
(let ((name (slot-value attribute
'description-name
)))
32 (find-description name
))))
35 (define-layered-class standard-attribute
()
37 ((effective-attribute-definition :initarg effective-attribute
38 :accessor attribute-effective-attribute-definition
)
40 (description-class :initarg description-class
)
41 (initfunctions :initform nil
)
42 (attribute-class :accessor attribute-class
:initarg
:attribute-class
:initform
'standard-attribute
)
43 (name :layered-accessor attribute-name
45 (label :layered-accessor attribute-label
53 :layered-accessor attribute-function
55 (value :layered-accessor %attribute-value
61 (defmethod print-object ((object standard-attribute
) stream
)
62 (print-unreadable-object (object stream
:type nil
:identity t
)
63 (format stream
"ATTRIBUTE ~A" (or (ignore-errors (attribute-name object
)) "+unnamed-attribute+"))))
65 (defvar *bypass-property-layered-function
* nil
)
67 (define-layered-function property-layered-function
(description attribute-name property-name
)
68 (:method
(description attribute-name property-name
)
69 ;(dprint "First Time PLFunction for ~A ~A ~A" description attribute-name property-name)
70 (ensure-layered-function
71 (defining-description (intern (format nil
"~A-~A-~A"
72 (description-print-name description
)
76 :lambda-list
'(description))))
78 (define-layered-method (setf slot-value-using-layer
)
80 (new-value class
(attribute standard-attribute
) property writer
)
82 (when (or *bypass-property-layered-function
*
83 (not (slot-definition-layeredp property
)))
84 (return-from slot-value-using-layer
(call-next-method)))
87 ;;FIXME: this is wrong for so many reasons.
89 (find-layer (first (remove nil
(closer-mop::class-precedence-list
(class-of context
))
90 :key
#'class-name
)))))
96 (let ((*bypass-property-layered-function
* t
))
97 (if (slot-boundp-using-class class attribute property
)
98 (slot-value-using-class class attribute property
)
99 (setf (slot-value-using-class class attribute property
)
100 (property-layered-function
101 (attribute-description attribute
)
102 (attribute-name attribute
)
103 (closer-mop:slot-definition-name property
)))))))
104 ;(dprint "We are setting the fn ~A " fn)
105 (when (not (generic-function-methods fn
))
106 ; (dprint "... there are no methods on it ever")
107 ;; * This slot has never been set before.
108 ;; create a method on property-layered-function
109 ;; so subclasses can see this new property.
110 (ensure-layered-method
111 (layered-function-definer 'property-layered-function
)
112 `(lambda (description attribute property
)
113 (declare (ignore description attribute property
))
118 (attribute-description attribute
))
119 (closer-mop:intern-eql-specializer
120 (attribute-name attribute
))
121 (closer-mop:intern-eql-specializer
122 (closer-mop:slot-definition-name property
)))))
125 ;; finally, specialize this property to this description.
126 (ensure-layered-method
128 `(lambda (description)
131 :specializers
(list (class-of (attribute-description attribute
)
134 (if (slot-boundp attribute
'description-class
)
136 (push (lambda () (do-set-slot))
137 (slot-value attribute
'initfunctions
))))))
140 (define-layered-method slot-value-using-layer
142 :around
(class (attribute standard-attribute
) property reader
)
143 ;(dprint "Getting the slot value of ~A" property)
145 (when (not (slot-boundp-using-class class attribute property
))
146 ;; If the slot is unbound, we search for its layered-function
148 (let ((fn (property-layered-function
149 (attribute-description attribute
)
151 (attribute-name attribute
)
152 (closer-mop:slot-definition-name property
))))
153 (dprint ".. not bound yet, have function ~A" fn
)
154 (if (generic-function-methods fn
)
155 (let ((*bypass-property-layered-function
* t
))
156 ; (dprint " This shit has been bound!. We gona set the _real_ slot to the generic function like.")
157 (setf (slot-value-using-class class attribute property
) fn
))
159 ;(dprint "This shit aint never been bound nowhere! checking for initfunction...")
160 (when (slot-definition-initfunction property
)
161 ;(dprint "At least we have an initfunction. sweeet")
162 (let ((*bypass-property-layered-function
* nil
))
163 (setf (slot-value attribute
(slot-definition-name property
))
164 (funcall (slot-definition-initfunction property
)))))))))
166 ;(dprint "If we're here, the slot should be bound")
170 (contextl::slot-definition-layeredp property
)
171 (not *bypass-property-layered-function
*))
172 (let ((fn (call-next-method)))
173 ;(dprint "... using fn ~A to get value" fn)
174 (funcall fn layer
(attribute-description attribute
)))
180 (defun slot-boundp-using-property-layered-function (class attribute property
)
182 (let ((*bypass-property-layered-function
* t
))
183 (slot-boundp-using-class class attribute property
)))
184 ;; If the slot is unbound, we search for its layered-function
186 (let ((fn (property-layered-function
187 (attribute-description attribute
)
189 (attribute-name attribute
)
190 (closer-mop:slot-definition-name property
))))
191 (if (generic-function-methods fn
)
192 (let ((*bypass-property-layered-function
* t
))
193 (setf (slot-value-using-class class attribute property
) fn
))
196 #+nil
(define-layered-method slot-boundp-using-layer
198 :around
(class (attribute standard-attribute
) property reader
)
199 (if *bypass-property-layered-function
*
201 (slot-boundp-using-property-layered-function class attribute property
)))
203 (defun attribute-value* (attribute)
204 (attribute-value *object
* attribute
))
206 (defmacro with-attributes
(names description
&body body
)
207 `(with-slots ,names
,description
,@body
))
209 (defun display-attribute (attribute)
210 (display-using-description attribute
*display
* *object
*))
212 (define-layered-method display-using-description
213 ((attribute standard-attribute
) display object
&rest args
)
214 (declare (ignore args
))
215 (when (attribute-label attribute
)
216 (format display
"~A " (attribute-label attribute
)))
217 (format display
"~A" (attribute-value object attribute
)))