1 (in-package :lisp-on-lines
)
3 (defdynamic described-object nil
)
4 (defdynamic description nil
)
6 ;;backwards-compat hacks
7 (define-symbol-macro *object
* (dynamic described-object
))
8 (define-symbol-macro *description
* (dynamic description
))
10 ;; forward compat hacks
12 (defun current-description ()
13 (dynamic description
))
15 (define-layered-function description-of
(thing)
17 (find-description 't
)))
19 (defun description-print-name (description)
20 (description-class-name (class-of description
)))
22 (defun description-attributes (description)
23 (alexandria:hash-table-values
(description-class-attributes (class-of description
))))
25 (defun description-current-attributes (description)
29 (some #'layer-active-p
31 (slot-definition-layers
32 (attribute-effective-attribute-definition attribute
))))))
33 (description-attributes description
)))
35 (defun description-active-attributes (description)
38 (description-attributes description
)))
42 (define-layered-function description-active-descriptions
(description)
43 (:method
((description t
))
44 (attribute-value (find-attribute description
'active-descriptions
)))
45 (:method
((description attribute
))
46 (attribute-active-descriptions description
)))
48 (define-layered-function description-inactive-descriptions
(description)
49 (:method
((description t
))
50 (attribute-value (find-attribute description
'inactive-descriptions
)))
51 (:method
((description attribute
))
52 (attribute-inactive-descriptions description
)))
54 (define-layered-function attributes
(description)
55 (:method
(description)
56 (let* ((active-attributes
57 (find-attribute description
'active-attributes
))
58 (attributes (when active-attributes
59 (ignore-errors (attribute-value active-attributes
)))))
63 (attribute-active-p attribute
)
64 (some #'layer-active-p
65 (attribute-layers attribute
))))
67 (mapcar (lambda (spec)
74 (description-attributes description
))))))
76 (defun funcall-with-described-object (function object description
&rest args
)
77 (setf description
(or description
(description-of object
)))
78 (dynamic-let ((description description
)
80 (dletf (((described-object description
) object
))
81 (funcall-with-layer-context
82 (modify-layer-context (adjoin-layer description
(current-layer-context))
83 :activate
(description-active-descriptions description
)
84 :deactivate
(description-inactive-descriptions description
))
86 (with-special-symbol-access
87 (contextl::funcall-with-special-initargs
88 (without-special-symbol-access
90 :for
(key val
) :on args
:by
#'cddr
91 :collect
(list (find key
(description-attributes description
)
92 :key
#'attribute-keyword
)
95 (contextl::funcall-with-special-initargs
96 (without-special-symbol-access
97 (let ((attribute (ignore-errors (find-attribute description
'active-attributes
))))
99 (loop for spec in
(attribute-value attribute
)
102 (find-attribute description
(car spec
))
103 (error "No attribute matching ~A" (car spec
)))
106 (without-special-symbol-access
107 (funcall function
))))))))))))
109 (defmacro with-described-object
((object &optional
(description `(description-of ,object
)))
111 `(funcall-with-described-object (lambda (),@body
) ,object
,description
))