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))
68 (format stream " ~A._vt = &~A;~%"
69 ich (vtable-name class (ichain-head ichain))))
71 (let ((isl (format nil "~A.~A"
73 (sod-class-nickname (islots-class item)))))
74 (dolist (slot (islots-slots item))
75 (let ((dslot (effective-slot-direct-slot slot))
76 (init (effective-slot-initializer slot)))
78 (ecase (sod-initializer-value-kind init)
80 (format stream " ~A = ~A;~%"
81 isl (sod-initializer-value-form init)))
83 (format stream " ~A = (~A)~A;~%"
84 isl (sod-slot-type dslot)
85 (sod-initializer-value-form init)))))))))))))
90 (defun output-supers-vector (class stream)
91 (let ((supers (sod-class-direct-superclasses class)))
94 /* Direct superclasses. */
95 static const SodClass *const ~A__supers[] = {
100 (defun output-cpl-vector (class stream)
102 /* Class precedence list. */
103 static const SodClass *const ~A__cpl[] = {
106 class (sod-class-precedence-list class)))
108 (defun output-chains-vector (class stream)
109 (let ((chains (sod-class-chains class)))
111 /* Chain structure. */
112 ~1@*~:{static const SodClass *const ~A__chain_~A[] = {
116 ~0@*static const struct sod_chain ~A__chains[] = {
119 ~4@*offsetof(struct ~A, ~A),
120 (const struct sod_vtable *)&~A,
121 sizeof(struct ~A) }~:^,~%~}
124 (mapcar (lambda (chain) ;1
125 (let* ((head (sod-class-chain-head (car chain)))
126 (chain-nick (sod-class-nickname head)))
127 (list class chain-nick ;0 1
130 (ilayout-struct-tag class) chain-nick ;4 5
131 (vtable-name class head) ;6
132 (ichain-struct-tag class head)))) ;7
135 (defclass sod-class-slot (sod-slot)
136 ((initializer-function :initarg :initializer-function
137 :type (or symbol function)
138 :reader sod-slot-initializer-function)
139 (prepare-function :initarg :prepare-function :type (or symbol function)
140 :reader sod-slot-prepare-function))
142 "Special class for slots defined on SodClass.
144 These slots need class-specific initialization. It's easier to keep all
145 of the information (name, type, and how to initialize them) about these
146 slots in one place, so that's what we do here."))
148 (defclass sod-magic-class-initializer (sod-class-initializer)
149 ((initializer-function :initarg :initializer-function
150 :type (or symbol function)
151 :reader sod-initializer-function)
152 (prepare-function :initarg :prepare-function
153 :type (or symbol function)
154 :reader sod-initializer-prepare-function)))
156 (defmethod shared-initialize :after
157 ((slot sod-class-slot) slot-names &key pset)
158 (declare (ignore slot-names))
159 (default-slot (slot 'initializer-function)
160 (get-property pset :initializer-function t nil))
161 (default-slot (slot 'prepare-function)
162 (get-property pset :prepare-function t nil)))
164 (defclass sod-class-effective-slot (effective-slot)
165 ((initializer-function :initarg :initializer-function
166 :type (or symbol function)
167 :reader effective-slot-initializer-function)
168 (prepare-function :initarg :prepare-function :type (or symbol function)
169 :reader effective-slot-prepare-function))
171 "Special class for slots defined on SodClass.
173 This class ignores any explicit initializers and computes initializer
174 values using the slot's INIT-FUNC slot and a magical protocol during
175 metaclass instance construction."))
177 (defmethod compute-effective-slot ((class sod-class) (slot sod-class-slot))
178 (make-instance 'sod-class-effective-slot
179 :class class :slot slot
180 :initializer-function (sod-slot-initializer-function slot)
181 :prepare-function (sod-slot-prepare-function slot)
182 :initializer (find-slot-initializer class slot)))
184 ;;;--------------------------------------------------------------------------
185 ;;; Class slots table.
187 (defparameter *sod-class-slots*
191 ("name" ,(c-type const-string)
192 :initializer-function
194 (prin1-to-string (sod-class-name class))))
195 ("nick" ,(c-type const-string)
196 :initializer-function
198 (prin1-to-string (sod-class-nickname class))))
200 ;; Instance allocation and initialization.
201 ("instsz" ,(c-type size-t)
202 :initializer-function
204 (format nil "sizeof(struct ~A)"
205 (ilayout-struct-tag class))))
206 ("imprint" ,(c-type (* (fun (* void) ("/*p*/" (* void)))))
207 :prepare-function output-imprint-function
208 :initializer-function
210 (format nil "~A__imprint" class)))
211 ("init" ,(c-type (* (fun (* void) ("/*p*/" (* void)))))
212 :prepare-function output-init-function
213 :initializer-function
215 (format nil "~A__init" class)))
217 ;; Superclass structure.
218 ("n_supers" ,(c-type size-t)
219 :initializer-function
221 (length (sod-class-direct-superclasses class))))
222 ("supers" ,(c-type (* (* (class "SodClass" :const) :const)))
223 :prepare-function output-supers-vector
224 :initializer-function
226 (if (sod-class-direct-superclasses class)
227 (format nil "~A__supers" class)
229 ("n_cpl" ,(c-type size-t)
230 :initializer-function
232 (length (sod-class-precedence-list class))))
233 ("cpl" ,(c-type (* (* (class "SodClass" :const) :const)))
234 :prepare-function output-cpl-vector
235 :initializer-function
237 (format nil "~A__cpl" class)))
240 ("link" ,(c-type (* (class "SodClass" :const)))
241 :initializer-function
243 (let ((link (sod-class-chain-link class)))
245 (format nil "~A__class" link)
247 ("head" ,(c-type (* (class "SodClass" :const)))
248 :initializer-function
250 (format nil "~A__class" (sod-class-chain-head class))))
251 ("level" ,(c-type size-t)
252 :initializer-function
254 (position class (reverse (sod-class-chain class)))))
255 ("n_chains" ,(c-type size-t)
256 :initializer-function
258 (length (sod-class-chains class))))
259 ("chains" ,(c-type (* (struct "sod_chain" :const)))
260 :prepare-function output-chains-vector
261 :initializer-function
263 (format nil "~A__chains" class)))
265 ;; Class-specific layout.
266 ("off_islots" ,(c-type size-t)
267 :initializer-function
269 (format nil "offsetof(struct ~A, ~A)"
270 (ichain-struct-tag class
271 (sod-class-chain-head class))
272 (sod-class-nickname class))))
273 ("islotsz" ,(c-type size-t)
274 :initializer-function
276 (format nil "sizeof(struct ~A)"
277 (islots-struct-tag class))))))
279 ;;;--------------------------------------------------------------------------
280 ;;; Bootstrapping the class graph.
282 (defun bootstrap-classes (module)
283 (let* ((sod-object (make-sod-class "SodObject" nil
284 (make-property-set :nick 'obj)))
285 (sod-class (make-sod-class "SodClass" (list sod-object)
286 (make-property-set :nick 'cls)))
287 (classes (list sod-object sod-class)))
289 ;; Sort out the recursion.
290 (setf (slot-value sod-class 'chain-link) sod-object)
291 (dolist (class classes)
292 (setf (slot-value class 'metaclass) sod-class))
294 ;; Predeclare the class types.
295 (dolist (class classes)
296 (make-class-type (sod-class-name class)))
298 ;; Attach the class slots.
299 (loop for (name type . plist) in *sod-class-slots*
300 do (make-sod-slot sod-class name type
301 (apply #'make-property-set
302 :lisp-class 'sod-class-slot
305 ;; These classes are too closely intertwined. We must partially finalize
306 ;; them together by hand. This is cloned from FINALIZE-SOD-CLASS.
307 (dolist (class classes)
308 (with-slots (class-precedence-list chain-head chain chains) class
309 (setf class-precedence-list (compute-cpl class))
310 (setf (values chain-head chain chains) (compute-chains class))))
313 (dolist (class classes)
314 (finalize-sod-class class)
315 (add-to-module module class))))
317 (defun make-builtin-module ()
318 (let ((module (make-instance 'module
319 :name (make-pathname :name "SOD-BASE"
323 (*type-map* (make-hash-table :test #'equal)))
324 (dolist (name '("va_list" "size_t" "ptrdiff_t"))
325 (add-to-module module (make-instance 'type-item :name name)))
326 (bootstrap-classes module)
329 (defun reset-builtin-module ()
330 (setf *builtin-module* (make-builtin-module))
331 (module-import *builtin-module*))
333 ;;;--------------------------------------------------------------------------
337 (define-sod-class "AbstractStack" ("SodObject")
339 (message "emptyp" (fun int))
340 (message "push" (fun void ("item" (* void))))
341 (message "pop" (fun (* void)))
342 (method "abstk" "pop" (fun void) #{
343 assert(!me->_vt.emptyp());
347 ;;;----- That's all, folks --------------------------------------------------