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 static void *~A__imprint(void *p)
36 struct ~A *sod__obj = p;
38 ~:{sod__obj.~A._vt = &~A;~:^~% ~}
42 (ilayout-struct-tag class)
43 (mapcar (lambda (ichain)
44 (list (sod-class-nickname (ichain-head ichain))
45 (vtable-name class (ichain-head ichain))))
46 (ilayout-ichains ilayout)))))
48 (defun output-init-function (class stream)
49 ;; FIXME this needs a metaobject protocol
50 (let ((ilayout (sod-class-ilayout class)))
52 static void *~A__init(void *p)
54 struct ~A *sod__obj = ~0@*~A__imprint(p);~2%"
56 (ilayout-struct-tag class))
57 (dolist (ichain (ilayout-ichains ilayout))
58 (let ((ich (format nil "sod__obj.~A"
59 (sod-class-nickname (ichain-head ichain)))))
60 (dolist (item (ichain-body ichain))
63 (format stream " ~A._vt = &~A;~%"
64 ich (vtable-name class (ichain-head ichain))))
66 (let ((isl (format nil "~A.~A"
68 (sod-class-nickname (islots-class item)))))
69 (dolist (slot (islots-slots item))
70 (let ((dslot (effective-slot-direct-slot slot))
71 (init (effective-slot-initializer slot)))
73 (ecase (sod-initializer-value-kind init)
75 (format stream " ~A = ~A;~%"
76 isl (sod-initializer-value-form slot)))
78 (format stream " ~A = (~A)~A;~%"
79 isl (sod-slot-type dslot)
80 (sod-initializer-value-form slot)))))))))))))
85 (defun output-supers-vector (class stream)
86 (let ((supers (sod-class-direct-superclasses class)))
89 static const SodClass *const ~A__supers[] = {
94 (defun output-cpl-vector (class stream)
96 static const SodClass *const ~A__cpl[] = {
99 class (sod-class-precedence-list class)))
101 (defun output-chains-vector (class stream)
102 (let ((chains (sod-class-chains class)))
104 ~1@*~:{static const SodClass *const ~A__chain_~A[] = {
108 ~0@*static const struct sod_chain ~A__chains[] = {
111 ~4@*offsetof(struct ~A, ~A),
112 (const struct sod_vtable *)&~A,
113 sizeof(struct ~A) }~:^,~%~}
116 (mapcar (lambda (chain) ;1
117 (let* ((head (sod-class-chain-head (car chain)))
118 (chain-nick (sod-class-nickname head)))
119 (list class chain-nick ;0 1
122 (ilayout-struct-tag class) chain-nick ;4 5
123 (vtable-name class head) ;6
124 (ichain-struct-tag class head)))) ;7
127 (defclass sod-class-slot (sod-slot)
128 ((initializer-function :initarg :initializer-function
129 :type (or symbol function)
130 :reader sod-slot-initializer-function)
131 (prepare-function :initarg :prepare-function :type (or symbol function)
132 :reader sod-slot-prepare-function))
134 "Special class for slots defined on SodClass.
136 These slots need class-specific initialization. It's easier to keep all
137 of the information (name, type, and how to initialize them) about these
138 slots in one place, so that's what we do here."))
140 (defmethod shared-initialize :after
141 ((slot sod-class-slot) slot-names &key pset)
142 (declare (ignore slot-names))
143 (default-slot (slot 'initializer-function)
144 (get-property pset :initializer-function t nil))
145 (default-slot (slot 'prepare-function)
146 (get-property pset :prepare-function t nil)))
148 (defclass sod-class-effective-slot (effective-slot)
149 ((initializer-function :initarg :initializer-function
150 :type (or symbol function)
151 :reader effective-slot-initializer-function)
152 (prepare-function :initarg :prepare-function :type (or symbol function)
153 :reader effective-slot-prepare-function))
155 "Special class for slots defined on SodClass.
157 This class ignores any explicit initializers and computes initializer
158 values using the slot's INIT-FUNC slot and a magical protocol during
159 metaclass instance construction."))
161 (defmethod compute-effective-slot ((class sod-class) (slot sod-class-slot))
162 (make-instance 'sod-class-effective-slot
164 :initializer-function (sod-slot-initializer-function slot)
165 :prepare-function (sod-slot-prepare-function slot)
166 :initializer (find-slot-initializer class slot)))
168 ;;;--------------------------------------------------------------------------
169 ;;; Class slots table.
171 (defparameter *sod-class-slots*
175 ("name" ,(c-type const-string)
176 :initializer-function
178 (prin1-to-string (sod-class-name class))))
179 ("nick" ,(c-type const-string)
180 :initializer-function
182 (prin1-to-string (sod-class-nickname class))))
184 ;; Instance allocation and initialization.
185 ("instsz" ,(c-type size-t)
186 :initializer-function
188 (format nil "sizeof(struct ~A)"
189 (ilayout-struct-tag class))))
190 ("imprint" ,(c-type (* (fun (* void) ("/*p*/" (* void)))))
191 :prepare-function 'output-imprint-function
192 :initializer-function
194 (format nil "~A__imprint" class)))
195 ("init" ,(c-type (* (fun (* void) ("/*p*/" (* void)))))
196 :prepare-function 'output-init-function
197 :initializer-function
199 (format nil "~A__init" class)))
201 ;; Superclass structure.
202 ("n_supers" ,(c-type size-t)
203 :initializer-function
205 (length (sod-class-direct-superclasses class))))
206 ("supers" ,(c-type (* (* (class "SodClass" :const) :const)))
207 :prepare-function 'output-supers-vector
208 :initializer-function
210 (if (sod-class-direct-superclasses class)
211 (format nil "~A__supers" class)
213 ("n_cpl" ,(c-type size-t)
214 :initializer-function
216 (length (sod-class-precedence-list class))))
217 ("cpl" ,(c-type (* (* (class "SodClass" :const) :const)))
218 :prepare-function 'output-cpl-vector
219 :initializer-function
221 (format nil "~A__cpl" class)))
224 ("link" ,(c-type (* (class "SodClass" :const)))
225 :initializer-function
227 (let ((link (sod-class-chain-link class)))
229 (format nil "~A__class" link)
231 ("head" ,(c-type (* (class "SodClass" :const)))
232 :initializer-function
234 (format nil "~A__class" (sod-class-chain-head class))))
235 ("level" ,(c-type size-t)
236 :initializer-function
238 (position class (reverse (sod-class-chain class)))))
239 ("n_chains" ,(c-type size-t)
240 :initializer-function
242 (length (sod-class-chains class))))
243 ("chains" ,(c-type (* (struct "sod_chain" :const)))
244 :prepare-function 'output-chains-vector
245 :initializer-function
247 (format nil "~A__chains" class)))
249 ;; Class-specific layout.
250 ("off_islots" ,(c-type size-t)
251 :initializer-function
253 (format nil "offsetof(struct ~A, ~A)"
254 (ichain-struct-tag class
255 (sod-class-chain-head class))
256 (sod-class-nickname class))))
257 ("islotsz" ,(c-type size-t)
258 :initializer-function
260 (format nil "sizeof(struct ~A)"
261 (islots-struct-tag class))))))
263 ;;;--------------------------------------------------------------------------
264 ;;; Bootstrapping the class graph.
266 (defun bootstrap-classes (module)
267 (let* ((sod-object (make-sod-class "SodObject" nil
268 (make-property-set :nick 'obj)))
269 (sod-class (make-sod-class "SodClass" (list sod-object)
270 (make-property-set :nick 'cls)))
271 (classes (list sod-object sod-class)))
273 ;; Sort out the recursion.
274 (setf (slot-value sod-class 'chain-link) sod-object)
275 (dolist (class classes)
276 (setf (slot-value class 'metaclass) sod-class))
278 ;; Predeclare the class types.
279 (dolist (class classes)
280 (make-class-type (sod-class-name class)))
282 ;; Attach the class slots.
283 (loop for (name type . plist) in *sod-class-slots*
284 do (make-sod-slot sod-class name type
285 (apply #'make-property-set
286 :lisp-class 'sod-class-slot
289 ;; These classes are too closely intertwined. We must partially finalize
290 ;; them together by hand. This is cloned from FINALIZE-SOD-CLASS.
291 (dolist (class classes)
292 (with-slots (class-precedence-list chain-head chain chains) class
293 (setf class-precedence-list (compute-cpl class))
294 (setf (values chain-head chain chains) (compute-chains class))))
297 (dolist (class classes)
298 (finalize-sod-class class)
299 (add-to-module module class))))
301 (defun make-builtin-module ()
302 (let ((module (make-instance 'module
303 :name (make-pathname :name "SOD-BASE"
307 (*type-map* (make-hash-table :test #'equal)))
308 (dolist (name '("va_list" "size_t" "ptrdiff_t"))
309 (add-to-module module (make-instance 'type-item :name name)))
310 (bootstrap-classes module)
313 (defun reset-builtin-module ()
314 (setf *builtin-module* (make-builtin-module))
315 (module-import *builtin-module*))
317 ;;;--------------------------------------------------------------------------
321 (define-sod-class "AbstractStack" ("SodObject")
323 (message "emptyp" (fun int))
324 (message "push" (fun void ("item" (* void))))
325 (message "pop" (fun (* void)))
326 (method "abstk" "pop" (fun void) #{
327 assert(!me->_vt.emptyp());
331 ;;;----- That's all, folks --------------------------------------------------