changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/lib/obj/meta/pkg.lisp

changeset 698: 96958d3eb5b0
parent: efb4a19ff530
author: Richard Westhaver <ellis@rwest.io>
date: Fri, 04 Oct 2024 22:04:59 -0400
permissions: -rw-r--r--
description: fixes
1 ;;; obj/meta/pkg.lisp --- Meta-objects
2 
3 ;;
4 
5 ;;; Commentary:
6 
7 
8 ;;;; Notes:
9 
10 ;; ordered? https://www.reddit.com/r/lisp/comments/n88x59/metaclasses_using_structures_or_speeding_up_slot/
11 
12 ;;;; Ref:
13 
14 ;; https://franz.com/support/documentation/11.0/mop/concepts.html
15 
16 ;;; Code:
17 (defpackage :obj/meta/stealth
18  (:use :cl :std :obj/meta :sb-mop))
19 
20 (defpackage :obj/meta/typed
21  (:use :cl :std :obj/meta :sb-mop))
22 
23 (defpackage :obj/meta/filtered
24  (:use :cl :std :obj/meta :sb-mop)
25  (:export
26  :define-filtered-function :filtered :filtered-function :filtered-method
27  :generic-function-filter-expression :generic-function-filters :method-filter :simple-filtered-function))
28 
29 (defpackage :obj/meta/sealed
30  (:use :cl :std :obj/meta)
31  (:import-from :sb-pcl :eql-specializer :intern-eql-specializer
32  :eql-specializer-object :funcallable-standard-class)
33  (:import-from :sb-mop :class-finalized-p :finalize-inheritance
34  :class-precedence-list :class-direct-superclasses :specializer :method-specializers
35  :generic-function-argument-precedence-order :generic-function-name :generic-function-methods :class-direct-subclasses
36  :class-prototype)
37  (:export
38  :ensure-specializer
39  :specializer-type
40  :specializer-prototype
41  :specializer-direct-superspecializers
42  :specializer-intersectionp
43  :specializer-subsetp
44  :domain
45  :ensure-domain
46  :method-domain
47  :domain-specializers
48  :domain-arity
49  :domain-equal
50  :domain-intersectionp
51  :domain-subsetp
52 
53  :metaobject-sealable-p
54  :class-sealable-p
55  :generic-function-sealable-p
56  :method-sealable-p
57  :specializer-sealable-p
58 
59  :metaobject-sealed-p
60  :class-sealed-p
61  :generic-function-sealed-p
62  :method-sealed-p
63  :specializer-sealed-p
64 
65  :seal-class
66  :seal-generic-function
67  :seal-method
68  :seal-domain
69  :seal-specializer
70 
71  :method-properties
72  :validate-method-property
73 
74  :static-call-signature
75  :static-call-signature-types
76  :static-call-signature-prototypes
77 
78  :sealed-domains
79  :compute-static-call-signatures
80  :externalizable-object-p
81  :sealable-class
82  :sealable-generic-function
83  :sealable-standard-generic-function
84  :potentially-sealable-method
85  :potentially-sealable-standard-method))
86 
87 (defpackage :obj/meta/fast
88  (:use :cl :std :obj/meta/sealed :obj/meta)
89  (:import-from :sb-int :gensymify)
90  (:import-from :sb-walker :macroexpand-all)
91  (:export :fast-generic-function :fast-method :inlineable))
92 
93 (defpackage :obj/meta/lazy
94  (:use :cl :std :obj/meta))
95 
96 (defpackage :obj/meta/overloaded
97  (:use :cl :std :obj/meta))
98 
99 (defpackage :obj/meta/storable
100  (:use :cl :std :obj/meta :obj/id)
101  (:export
102  :storable-class :initialize-storable-class
103  :storable-slot-mixin :storable-direct-slot-definition
104  :storable-effective-slot-definition))
105 
106 (in-package :obj/meta)
107 
108 (defun class-equalp (c1 c2)
109  (when (symbolp c1) (setf c1 (find-class c1)))
110  (when (symbolp c2) (setf c2 (find-class c2)))
111  (eq c1 c2))
112 
113 (defun type-specifier-and (&rest type-specifiers)
114  (let ((relevant (remove t type-specifiers)))
115  (cond ((null relevant) t)
116  ((null (cdr relevant)) (first relevant))
117  (t `(and ,@relevant)))))
118 
119 (defun type-specifier-or (&rest type-specifiers)
120  (let ((relevant (remove nil type-specifiers)))
121  (cond ((null relevant) nil)
122  ((null (cdr relevant)) (first relevant))
123  (t `(or ,@relevant)))))
124 
125 (defun type-specifier-not (type-specifier)
126  (cond ((eql type-specifier t) nil)
127  ((eql type-specifier nil) t)
128  (t `(not ,type-specifier))))
129 
130 (defparameter *standard-metaobjects*
131  (list (find-class 'standard-object)
132  (find-class 'standard-class)
133  (find-class 'standard-generic-function)
134  (find-class 'standard-method)
135  (find-class 'built-in-class)))
136 
137 ;;; From ARNESI - Messing with the MOP
138 
139 ;; https://bese.common-lisp.dev/docs/arnesi/html/Messing_0020with_0020the_0020MOP.html#wrapping-standard_0020method_0020combination
140 
141 (define-method-combination wrapping-standard
142  (&key (around-order :most-specific-first)
143  (before-order :most-specific-first)
144  (primary-order :most-specific-first)
145  (after-order :most-specific-last)
146  (wrapping-order :most-specific-last)
147  (wrap-around-order :most-specific-last))
148  ((wrap-around (:wrap-around))
149  (around (:around))
150  (before (:before))
151  (wrapping (:wrapping))
152  (primary () :required t)
153  (after (:after)))
154  "Same semantics as standard method combination but allows
155 \"wrapping\" methods. Ordering of methods:
156 
157  (wrap-around
158  (around
159  (before)
160  (wrapping
161  (primary))
162  (after)))
163 
164 :warp-around, :around, :wrapping and :primary methods call the
165 next least/most specific method via call-next-method (as in
166 standard method combination).
167 
168 The various WHATEVER-order keyword arguments set the order in
169 which the methods are called and be set to either
170 :most-specific-last or :most-specific-first."
171  (labels ((effective-order (methods order)
172  (ecase order
173  (:most-specific-first methods)
174  (:most-specific-last (reverse methods))))
175  (call-methods (methods)
176  (mapcar (lambda (meth) `(call-method ,meth))
177  methods)))
178  (let* (;; reorder the methods based on the -order arguments
179  (wrap-around (effective-order wrap-around wrap-around-order))
180  (around (effective-order around around-order))
181  (wrapping (effective-order wrapping wrapping-order))
182  (before (effective-order before before-order))
183  (primary (effective-order primary primary-order))
184  (after (effective-order after after-order))
185  ;; inital value of the effective call is a call its primary
186  ;; method(s)
187  (form (case (length primary)
188  (1 `(call-method ,(first primary)))
189  (t `(call-method ,(first primary) ,(rest primary))))))
190  (when wrapping
191  ;; wrap form in call to the wrapping methods
192  (setf form `(call-method ,(first wrapping)
193  (,@(rest wrapping) (make-method ,form)))))
194  (when before
195  ;; wrap FORM in calls to its before methods
196  (setf form `(progn
197  ,@(call-methods before)
198  ,form)))
199  (when after
200  ;; wrap FORM in calls to its after methods
201  (setf form `(multiple-value-prog1
202  ,form
203  ,@(call-methods after))))
204  (when around
205  ;; wrap FORM in calls to its around methods
206  (setf form `(call-method ,(first around)
207  (,@(rest around)
208  (make-method ,form)))))
209  (when wrap-around
210  (setf form `(call-method ,(first wrap-around)
211  (,@(rest wrap-around)
212  (make-method ,form)))))
213  form)))