3 ;;; Builtin module provides basic definitions
5 ;;; (c) 2009 Straylight/Edgeware
8 ;;;----- Licensing notice ---------------------------------------------------
10 ;;; This file is part of the Simple Object Definition system.
12 ;;; SOD is free software; you can redistribute it and/or modify
13 ;;; it under the terms of the GNU General Public License as published by
14 ;;; the Free Software Foundation; either version 2 of the License, or
15 ;;; (at your option) any later version.
17 ;;; SOD is distributed in the hope that it will be useful,
18 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;;; GNU General Public License for more details.
22 ;;; You should have received a copy of the GNU General Public License
23 ;;; along with SOD; if not, write to the Free Software Foundation,
24 ;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 ;;;--------------------------------------------------------------------------
29 ;;; Output of class instances.
31 (defun output-imprint-function (class stream)
32 (let ((ilayout (sod-class-ilayout class)))
34 /* Imprint raw memory with instance structure. */
35 static void *~A__imprint(void *p)
37 struct ~A *sod__obj = p;
39 ~:{sod__obj.~A.~A._vt = &~A;~:^~% ~}
43 (ilayout-struct-tag class)
44 (mapcar (lambda (ichain)
45 (let* ((head (ichain-head ichain))
46 (tail (ichain-tail ichain)))
47 (list (sod-class-nickname head)
48 (sod-class-nickname tail)
49 (vtable-name class head))))
50 (ilayout-ichains ilayout)))))
52 (defun output-init-function (class stream)
53 ;; FIXME this needs a metaobject protocol
54 (let ((ilayout (sod-class-ilayout class)))
56 static void *~A__init(void *p)
58 struct ~A *sod__obj = ~0@*~A__imprint(p);~2%"
60 (ilayout-struct-tag class))
61 (dolist (ichain (ilayout-ichains ilayout))
62 (let ((ich (format nil "sod__obj.~A.~A"
63 (sod-class-nickname (ichain-head ichain))
64 (sod-class-nickname (ichain-tail ichain)))))
65 (dolist (item (ichain-body ichain))
70 (let ((isl (format nil "~A.~A"
72 (sod-class-nickname (islots-class item)))))
73 (dolist (slot (islots-slots item))
74 (let ((dslot (effective-slot-direct-slot slot))
75 (init (effective-slot-initializer slot)))
77 (format stream " ~A =" isl)
78 (ecase (sod-initializer-value-kind init)
79 (:simple (write (sod-initializer-value-form init)
81 :pretty nil :escape nil)
82 (format stream ";~%"))
83 (:compound (format stream " (~A) {"
84 (sod-slot-type dslot))
85 (write (sod-initializer-value-form init)
87 :pretty nil :escape nil)
88 (format stream "};~%"))))))))))))
93 (defun output-supers-vector (class stream)
94 (let ((supers (sod-class-direct-superclasses class)))
97 /* Direct superclasses. */
98 static const SodClass *const ~A__supers[] = {
103 (defun output-cpl-vector (class stream)
105 /* Class precedence list. */
106 static const SodClass *const ~A__cpl[] = {
109 class (sod-class-precedence-list class)))
111 (defun output-chains-vector (class stream)
112 (let ((chains (sod-class-chains class)))
114 /* Chain structure. */
115 ~1@*~:{static const SodClass *const ~A__chain_~A[] = {
119 ~0@*static const struct sod_chain ~A__chains[] = {
122 ~4@*offsetof(struct ~A, ~A),
123 (const struct sod_vtable *)&~A,
124 sizeof(struct ~A) }~:^,~%~}
127 (mapcar (lambda (chain) ;1
128 (let* ((head (sod-class-chain-head (car chain)))
129 (chain-nick (sod-class-nickname head)))
130 (list class chain-nick ;0 1
133 (ilayout-struct-tag class) chain-nick ;4 5
134 (vtable-name class head) ;6
135 (ichain-struct-tag class head)))) ;7
138 (defclass sod-class-slot (sod-slot)
139 ((initializer-function :initarg :initializer-function
140 :type (or symbol function)
141 :reader sod-slot-initializer-function)
142 (prepare-function :initarg :prepare-function :type (or symbol function)
143 :reader sod-slot-prepare-function))
145 "Special class for slots defined on SodClass.
147 These slots need class-specific initialization. It's easier to keep all
148 of the information (name, type, and how to initialize them) about these
149 slots in one place, so that's what we do here."))
151 (defclass sod-magic-class-initializer (sod-class-initializer)
152 ((initializer-function :initarg :initializer-function
153 :type (or symbol function)
154 :reader sod-initializer-function)
155 (prepare-function :initarg :prepare-function
156 :type (or symbol function)
157 :reader sod-initializer-prepare-function)))
159 (defmethod shared-initialize :after
160 ((slot sod-class-slot) slot-names &key pset)
161 (declare (ignore slot-names))
162 (default-slot (slot 'initializer-function)
163 (get-property pset :initializer-function t nil))
164 (default-slot (slot 'prepare-function)
165 (get-property pset :prepare-function t nil)))
167 (defclass sod-class-effective-slot (effective-slot)
168 ((initializer-function :initarg :initializer-function
169 :type (or symbol function)
170 :reader effective-slot-initializer-function)
171 (prepare-function :initarg :prepare-function :type (or symbol function)
172 :reader effective-slot-prepare-function))
174 "Special class for slots defined on SodClass.
176 This class ignores any explicit initializers and computes initializer
177 values using the slot's INIT-FUNC slot and a magical protocol during
178 metaclass instance construction."))
180 (defmethod compute-effective-slot ((class sod-class) (slot sod-class-slot))
181 (make-instance 'sod-class-effective-slot
182 :class class :slot slot
183 :initializer-function (sod-slot-initializer-function slot)
184 :prepare-function (sod-slot-prepare-function slot)
185 :initializer (find-slot-initializer class slot)))
187 ;;;--------------------------------------------------------------------------
188 ;;; Class slots table.
190 (defparameter *sod-class-slots*
194 ("name" ,(c-type const-string)
195 :initializer-function
197 (prin1-to-string (sod-class-name class))))
198 ("nick" ,(c-type const-string)
199 :initializer-function
201 (prin1-to-string (sod-class-nickname class))))
203 ;; Instance allocation and initialization.
204 ("instsz" ,(c-type size-t)
205 :initializer-function
207 (format nil "sizeof(struct ~A)"
208 (ilayout-struct-tag class))))
209 ("imprint" ,(c-type (* (fun (* void) ("/*p*/" (* void)))))
210 :prepare-function output-imprint-function
211 :initializer-function
213 (format nil "~A__imprint" class)))
214 ("init" ,(c-type (* (fun (* void) ("/*p*/" (* void)))))
215 :prepare-function output-init-function
216 :initializer-function
218 (format nil "~A__init" class)))
220 ;; Superclass structure.
221 ("n_supers" ,(c-type size-t)
222 :initializer-function
224 (length (sod-class-direct-superclasses class))))
225 ("supers" ,(c-type (* (* (class "SodClass" :const) :const)))
226 :prepare-function output-supers-vector
227 :initializer-function
229 (if (sod-class-direct-superclasses class)
230 (format nil "~A__supers" class)
232 ("n_cpl" ,(c-type size-t)
233 :initializer-function
235 (length (sod-class-precedence-list class))))
236 ("cpl" ,(c-type (* (* (class "SodClass" :const) :const)))
237 :prepare-function output-cpl-vector
238 :initializer-function
240 (format nil "~A__cpl" class)))
243 ("link" ,(c-type (* (class "SodClass" :const)))
244 :initializer-function
246 (let ((link (sod-class-chain-link class)))
248 (format nil "~A__class" link)
250 ("head" ,(c-type (* (class "SodClass" :const)))
251 :initializer-function
253 (format nil "~A__class" (sod-class-chain-head class))))
254 ("level" ,(c-type size-t)
255 :initializer-function
257 (position class (reverse (sod-class-chain class)))))
258 ("n_chains" ,(c-type size-t)
259 :initializer-function
261 (length (sod-class-chains class))))
262 ("chains" ,(c-type (* (struct "sod_chain" :const)))
263 :prepare-function output-chains-vector
264 :initializer-function
266 (format nil "~A__chains" class)))
268 ;; Class-specific layout.
269 ("off_islots" ,(c-type size-t)
270 :initializer-function
272 (format nil "offsetof(struct ~A, ~A)"
273 (ichain-struct-tag class
274 (sod-class-chain-head class))
275 (sod-class-nickname class))))
276 ("islotsz" ,(c-type size-t)
277 :initializer-function
279 (format nil "sizeof(struct ~A)"
280 (islots-struct-tag class))))))
282 ;;;--------------------------------------------------------------------------
283 ;;; Bootstrapping the class graph.
285 (defun bootstrap-classes (module)
286 (let* ((sod-object (make-sod-class "SodObject" nil
287 (make-property-set :nick 'obj)))
288 (sod-class (make-sod-class "SodClass" (list sod-object)
289 (make-property-set :nick 'cls)))
290 (classes (list sod-object sod-class)))
292 ;; Sort out the recursion.
293 (setf (slot-value sod-class 'chain-link) sod-object)
294 (dolist (class classes)
295 (setf (slot-value class 'metaclass) sod-class))
297 ;; Predeclare the class types.
298 (dolist (class classes)
299 (make-class-type (sod-class-name class)))
301 ;; Attach the class slots.
302 (loop for (name type . plist) in *sod-class-slots*
303 do (make-sod-slot sod-class name type
304 (apply #'make-property-set
305 :lisp-class 'sod-class-slot
308 ;; These classes are too closely intertwined. We must partially finalize
309 ;; them together by hand. This is cloned from FINALIZE-SOD-CLASS.
310 (dolist (class classes)
311 (with-slots (class-precedence-list chain-head chain chains) class
312 (setf class-precedence-list (compute-cpl class))
313 (setf (values chain-head chain chains) (compute-chains class))))
316 (dolist (class classes)
317 (finalize-sod-class class)
318 (add-to-module module class))))
320 (defun make-builtin-module ()
321 (let ((module (make-instance 'module
322 :name (make-pathname :name "SOD-BASE"
326 (*type-map* (make-hash-table :test #'equal)))
327 (dolist (name '("va_list" "size_t" "ptrdiff_t"))
328 (add-to-module module (make-instance 'type-item :name name)))
329 (bootstrap-classes module)
332 (defun reset-builtin-module ()
333 (setf *builtin-module* (make-builtin-module))
334 (module-import *builtin-module*))
336 ;;;--------------------------------------------------------------------------
340 (define-sod-class "AbstractStack" ("SodObject")
342 (message "emptyp" (fun int))
343 (message "push" (fun void ("item" (* void))))
344 (message "pop" (fun (* void)))
345 (method "abstk" "pop" (fun void) #{
346 assert(!me->_vt.emptyp());
350 ;;;----- That's all, folks --------------------------------------------------