Coverage report: /home/ellis/comp/core/lib/obj/meta/pkg.lisp
Kind | Covered | All | % |
expression | 16 | 227 | 7.0 |
branch | 3 | 30 | 10.0 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;;; obj/meta/pkg.lisp --- Meta-objects
9
;; ordered? https://www.reddit.com/r/lisp/comments/n88x59/metaclasses_using_structures_or_speeding_up_slot/
13
;; https://franz.com/support/documentation/11.0/mop/concepts.html
21
:*standard-metaobjects*
22
:find-slot-def-by-name
23
:find-direct-slot-def-by-name
24
:find-slot-defs-by-type
25
:find-slot-def-names-by-type
26
:struct-slots-and-values
30
(defpackage :obj/meta/stealth
31
(:nicknames :meta/stealth :stealth)
32
(:use :cl :std :obj/meta :sb-mop)
35
#:define-stealth-mixin))
37
(defpackage :obj/meta/filtered
38
(:nicknames :meta/filtered :filtered)
39
(:use :cl :std :obj/meta :sb-mop)
41
:define-filtered-function :filtered :filtered-function :filtered-method
42
:generic-function-filter-expression :generic-function-filters :method-filter :simple-filtered-function))
44
(defpackage :obj/meta/sealed
45
(:nicknames :meta/sealed :sealed)
46
(:use :cl :std :obj/meta)
47
(:import-from :sb-pcl :eql-specializer :intern-eql-specializer
48
:eql-specializer-object :funcallable-standard-class)
49
(:import-from :sb-mop :class-finalized-p :finalize-inheritance
50
:class-precedence-list :class-direct-superclasses :specializer :method-specializers
51
:generic-function-argument-precedence-order :generic-function-name :generic-function-methods :class-direct-subclasses
56
:specializer-prototype
57
:specializer-direct-superspecializers
58
:specializer-intersectionp
69
:metaobject-sealable-p
71
:generic-function-sealable-p
73
:specializer-sealable-p
77
:generic-function-sealed-p
82
:seal-generic-function
88
:validate-method-property
90
:static-call-signature
91
:static-call-signature-types
92
:static-call-signature-prototypes
95
:compute-static-call-signatures
96
:externalizable-object-p
98
:sealable-generic-function
99
:sealable-standard-generic-function
100
:potentially-sealable-method
101
:potentially-sealable-standard-method))
103
(defpackage :obj/meta/fast
104
(:nicknames :meta/fast :fast)
105
(:use :cl :std :obj/meta/sealed :obj/meta)
106
(:import-from :sb-int :gensymify)
107
(:import-from :sb-walker :macroexpand-all)
108
(:export :fast-generic-function :fast-method :inlineable :.lambda.))
110
(defpackage :obj/meta/lazy
111
(:nicknames :meta/lazy :lazy)
112
(:use :cl :std :obj/meta))
114
(defpackage :obj/meta/overloaded
115
(:nicknames :meta/overloaded :overloaded)
116
(:use :cl :std :obj/meta))
118
(defpackage :obj/meta/stored
119
(:nicknames :meta/stored :stored)
120
(:use :cl :std :obj/meta :sb-mop)
122
:stored-class :initialize-stored-class
133
:stored-slot-definition
134
:indexed-slot-definition
135
:derived-slot-triggers
139
:clear-slot-def-index
141
:indexed-slot-indices
146
:find-slot-defs-by-type
147
:migrate-class-index-p
148
:class-indexing-enabled-p
156
:flush-instance-cache
157
:stored-slot-makunbound
165
:all-stored-slot-names
166
:all-single-valued-slot-defs
167
:cached-slot-definition
168
:cached-direct-slot-definition
169
:transient-slot-definition
172
:transient-slot-names
173
:database-allocation-p
174
:slot-definition-allocation
175
:association-slot-base
177
:association-effective-slot-definition
178
:association-slot-definition
179
:association-slot-indices
184
:association-slot-defs
185
:association-slot-names
186
:association-end-slot-names
187
:get-association-slot-index
188
:add-association-slot-index
189
:remove-association-slot-index
190
:set-valued-slot-definition
191
:set-valued-direct-slot-definition
192
:set-valued-effective-slot-definition))
194
(defpackage :obj/meta/typed
195
(:nicknames :meta/typed :typed)
196
(:use :cl :std :obj/meta :sb-mop :stored)
203
#:array-type-from-byte
204
#:byte-from-array-type
207
(defpackage :obj/meta/dynamic
208
(:nicknames :meta/dynamic :dynamic)
209
(:use :cl :std :obj/meta :std/macs)
210
(:export :dset :dref :dynamic-class
211
:slot-dlet :slot-dvar :slot-dvar*))
213
(defpackage :obj/meta/mix
216
#:mixin-class #:mixin-object #:mixin-classes
217
#:ensure-mix #:delete-from-mix #:mix
218
#:replace-class #:replace-class-in-mixin
219
#:set-mix-rule #:*class-ordering-rules*
225
(in-package :obj/meta)
227
(defun class-equalp (c1 c2)
228
(when (symbolp c1) (setf c1 (find-class c1)))
229
(when (symbolp c2) (setf c2 (find-class c2)))
232
(defun type-specifier-and (&rest type-specifiers)
233
(let ((relevant (remove t type-specifiers)))
234
(cond ((null relevant) t)
235
((null (cdr relevant)) (first relevant))
236
(t `(and ,@relevant)))))
238
(defun type-specifier-or (&rest type-specifiers)
239
(let ((relevant (remove nil type-specifiers)))
240
(cond ((null relevant) nil)
241
((null (cdr relevant)) (first relevant))
242
(t `(or ,@relevant)))))
244
(defun type-specifier-not (type-specifier)
245
(cond ((eql type-specifier t) nil)
246
((eql type-specifier nil) t)
247
(t `(not ,type-specifier))))
249
(defparameter *standard-metaobjects*
250
(list (find-class 'standard-object)
251
(find-class 'standard-class)
252
(find-class 'standard-generic-function)
253
(find-class 'standard-method)
254
(find-class 'built-in-class)))
256
(defgeneric struct-constructor (class)
257
(:documentation "Called to get the constructor name for a struct class. Users
258
should overload this when they want to serialize
259
non-standard constructor names. The default constructor
260
make-xxx will work by default. The argument is an eql style
261
type: i.e. of type (eql 'my-struct)"))
263
(defmethod struct-constructor ((class t))
264
(symbol-function (intern (concatenate 'string "MAKE-" (symbol-name class))
265
(symbol-package class))))
267
;;; From ARNESI - Messing with the MOP
269
;; https://bese.common-lisp.dev/docs/arnesi/html/Messing_0020with_0020the_0020MOP.html#wrapping-standard_0020method_0020combination
271
(define-method-combination wrapping-standard
272
(&key (around-order :most-specific-first)
273
(before-order :most-specific-first)
274
(primary-order :most-specific-first)
275
(after-order :most-specific-last)
276
(wrapping-order :most-specific-last)
277
(wrap-around-order :most-specific-last))
278
((wrap-around (:wrap-around))
281
(wrapping (:wrapping))
282
(primary () :required t)
284
"Same semantics as standard method combination but allows
285
\"wrapping\" methods. Ordering of methods:
294
:warp-around, :around, :wrapping and :primary methods call the
295
next least/most specific method via call-next-method (as in
296
standard method combination).
298
The various WHATEVER-order keyword arguments set the order in
299
which the methods are called and be set to either
300
:most-specific-last or :most-specific-first."
301
(labels ((effective-order (methods order)
303
(:most-specific-first methods)
304
(:most-specific-last (reverse methods))))
305
(call-methods (methods)
306
(mapcar (lambda (meth) `(call-method ,meth))
308
(let* (;; reorder the methods based on the -order arguments
309
(wrap-around (effective-order wrap-around wrap-around-order))
310
(around (effective-order around around-order))
311
(wrapping (effective-order wrapping wrapping-order))
312
(before (effective-order before before-order))
313
(primary (effective-order primary primary-order))
314
(after (effective-order after after-order))
315
;; inital value of the effective call is a call its primary
317
(form (case (length primary)
318
(1 `(call-method ,(first primary)))
319
(t `(call-method ,(first primary) ,(rest primary))))))
321
;; wrap form in call to the wrapping methods
322
(setf form `(call-method ,(first wrapping)
323
(,@(rest wrapping) (make-method ,form)))))
325
;; wrap FORM in calls to its before methods
327
,@(call-methods before)
330
;; wrap FORM in calls to its after methods
331
(setf form `(multiple-value-prog1
333
,@(call-methods after))))
335
;; wrap FORM in calls to its around methods
336
(setf form `(call-method ,(first around)
338
(make-method ,form)))))
340
(setf form `(call-method ,(first wrap-around)
341
(,@(rest wrap-around)
342
(make-method ,form)))))
345
(defun find-class-for-direct-slot (class def)
346
(let ((list (sb-mop:compute-class-precedence-list class)))
347
(labels ((rec (super)
350
(aif (find-direct-slot-def-by-name super (sb-mop:slot-definition-name def))
356
(defun find-direct-slot-def-by-name (class slot-name)
357
(loop for slot-def in (sb-mop:class-direct-slots class)
358
when (eq (sb-mop:slot-definition-name slot-def) slot-name)
359
do (return slot-def)))
361
(defun find-slot-def-by-name (class slot-name)
362
(loop for slot-def in (sb-mop:class-slots class)
363
when (eq (sb-mop:slot-definition-name slot-def) slot-name)
364
do (return slot-def)))
366
(defgeneric find-slot-defs-by-type (class type &optional by-subtype))
367
(defgeneric find-slot-def-names-by-type (class type &optional by-subtype))
369
(defun slots-and-values (o)
370
"List of slot names followed by values for object"
371
(loop for sd in (sb-mop:compute-slots (class-of o))
372
for slot-name = (sb-mop:slot-definition-name sd)
375
(when (and (slot-boundp o slot-name)
377
(sb-mop:slot-definition-allocation sd)))
378
(push (slot-value o slot-name) ret)
379
(push slot-name ret))
380
finally (return ret)))
382
(defun struct-slots-and-values (object)
383
"List of slot names followed by values for structure object"
386
(mapcar #'sb-mop:slot-definition-name (sb-mop:class-slots (class-of object)))))
387
(loop for slot in slots do
388
(push (slot-value object slot) result)