Remove declarations without definitions
[bpt/guile.git] / libguile / goops.c
1 /* Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2008,2009,2010,2011,2012,2013,2014,2015
2 * Free Software Foundation, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation; either version 3 of
7 * the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA
18 */
19 \f
20
21 /* This software is a derivative work of other copyrighted softwares; the
22 * copyright notices of these softwares are placed in the file COPYRIGHTS
23 *
24 * This file is based upon stklos.c from the STk distribution by
25 * Erick Gallesio <eg@unice.fr>.
26 */
27
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
31
32 #include <stdio.h>
33
34 #include "libguile/_scm.h"
35 #include "libguile/alist.h"
36 #include "libguile/async.h"
37 #include "libguile/chars.h"
38 #include "libguile/debug.h"
39 #include "libguile/dynl.h"
40 #include "libguile/dynwind.h"
41 #include "libguile/eval.h"
42 #include "libguile/gsubr.h"
43 #include "libguile/hashtab.h"
44 #include "libguile/keywords.h"
45 #include "libguile/macros.h"
46 #include "libguile/modules.h"
47 #include "libguile/ports.h"
48 #include "libguile/procprop.h"
49 #include "libguile/programs.h"
50 #include "libguile/random.h"
51 #include "libguile/root.h"
52 #include "libguile/smob.h"
53 #include "libguile/strings.h"
54 #include "libguile/strports.h"
55 #include "libguile/vectors.h"
56 #include "libguile/vm.h"
57
58 #include "libguile/validate.h"
59 #include "libguile/goops.h"
60
61 /* Port classes */
62 #define SCM_IN_PCLASS_INDEX 0
63 #define SCM_OUT_PCLASS_INDEX SCM_I_MAX_PORT_TYPE_COUNT
64 #define SCM_INOUT_PCLASS_INDEX (2 * SCM_I_MAX_PORT_TYPE_COUNT)
65
66 /* this file is a mess. in theory, though, we shouldn't have many SCM references
67 -- most of the references should be to vars. */
68
69 static SCM var_slot_unbound = SCM_BOOL_F;
70 static SCM var_slot_missing = SCM_BOOL_F;
71 static SCM var_compute_cpl = SCM_BOOL_F;
72 static SCM var_no_applicable_method = SCM_BOOL_F;
73 static SCM var_change_class = SCM_BOOL_F;
74
75 SCM_SYMBOL (sym_slot_unbound, "slot-unbound");
76 SCM_SYMBOL (sym_slot_missing, "slot-missing");
77 SCM_SYMBOL (sym_compute_cpl, "compute-cpl");
78 SCM_SYMBOL (sym_no_applicable_method, "no-applicable-method");
79 SCM_SYMBOL (sym_memoize_method_x, "memoize-method!");
80 SCM_SYMBOL (sym_change_class, "change-class");
81
82 SCM_VARIABLE (scm_var_make_extended_generic, "make-extended-generic");
83
84
85 /* Class redefinition protocol:
86
87 A class is represented by a heap header h1 which points to a
88 malloc:ed memory block m1.
89
90 When a new version of a class is created, a new header h2 and
91 memory block m2 are allocated. The headers h1 and h2 then switch
92 pointers so that h1 refers to m2 and h2 to m1. In this way, names
93 bound to h1 will point to the new class at the same time as h2 will
94 be a handle which the GC will use to free m1.
95
96 The `redefined' slot of m1 will be set to point to h1. An old
97 instance will have its class pointer (the CAR of the heap header)
98 pointing to m1. The non-immediate `redefined'-slot in m1 indicates
99 the class modification and the new class pointer can be found via
100 h1.
101 */
102
103 #define TEST_CHANGE_CLASS(obj, class) \
104 { \
105 class = SCM_CLASS_OF (obj); \
106 if (scm_is_true (SCM_OBJ_CLASS_REDEF (obj))) \
107 { \
108 scm_change_object_class (obj, class, SCM_OBJ_CLASS_REDEF (obj));\
109 class = SCM_CLASS_OF (obj); \
110 } \
111 }
112
113 #define SCM_GOOPS_UNBOUND SCM_UNBOUND
114 #define SCM_GOOPS_UNBOUNDP(x) (scm_is_eq (x, SCM_GOOPS_UNBOUND))
115
116 static int goops_loaded_p = 0;
117 static scm_t_rstate *goops_rstate;
118
119 /* These variables are filled in by the object system when loaded. */
120 SCM scm_class_boolean, scm_class_char, scm_class_pair;
121 SCM scm_class_procedure, scm_class_string, scm_class_symbol;
122 SCM scm_class_primitive_generic;
123 SCM scm_class_vector, scm_class_null;
124 SCM scm_class_integer, scm_class_real, scm_class_complex, scm_class_fraction;
125 SCM scm_class_unknown;
126 SCM scm_class_top, scm_class_object, scm_class_class;
127 SCM scm_class_applicable;
128 SCM scm_class_applicable_struct, scm_class_applicable_struct_with_setter;
129 SCM scm_class_generic, scm_class_generic_with_setter;
130 SCM scm_class_accessor;
131 SCM scm_class_extended_generic, scm_class_extended_generic_with_setter;
132 SCM scm_class_extended_accessor;
133 SCM scm_class_method;
134 SCM scm_class_accessor_method;
135 SCM scm_class_procedure_class;
136 SCM scm_class_applicable_struct_class;
137 SCM scm_class_number, scm_class_list;
138 SCM scm_class_keyword;
139 SCM scm_class_port, scm_class_input_output_port;
140 SCM scm_class_input_port, scm_class_output_port;
141 SCM scm_class_foreign_slot;
142 SCM scm_class_self, scm_class_protected;
143 SCM scm_class_hidden, scm_class_opaque, scm_class_read_only;
144 SCM scm_class_protected_hidden, scm_class_protected_opaque, scm_class_protected_read_only;
145 SCM scm_class_scm;
146 SCM scm_class_int, scm_class_float, scm_class_double;
147
148 static SCM class_foreign;
149 static SCM class_hashtable;
150 static SCM class_fluid;
151 static SCM class_dynamic_state;
152 static SCM class_frame;
153 static SCM class_vm_cont;
154 static SCM class_bytevector;
155 static SCM class_uvec;
156 static SCM class_array;
157 static SCM class_bitvector;
158
159 static SCM vtable_class_map = SCM_BOOL_F;
160
161 /* Port classes. Allocate 3 times the maximum number of port types so that
162 input ports, output ports, and in/out ports can be stored at different
163 offsets. See `SCM_IN_PCLASS_INDEX' et al. */
164 SCM scm_port_class[3 * SCM_I_MAX_PORT_TYPE_COUNT];
165
166 /* SMOB classes. */
167 SCM scm_smob_class[SCM_I_MAX_SMOB_TYPE_COUNT];
168
169 SCM scm_no_applicable_method;
170
171 static SCM scm_make_unbound (void);
172 static SCM scm_unbound_p (SCM obj);
173 static SCM scm_assert_bound (SCM value, SCM obj);
174 static SCM scm_at_assert_bound_ref (SCM obj, SCM index);
175 static SCM scm_sys_goops_early_init (void);
176 static SCM scm_sys_goops_loaded (void);
177 static SCM scm_make_extended_class_from_symbol (SCM type_name_sym,
178 int applicablep);
179
180
181 SCM
182 scm_i_define_class_for_vtable (SCM vtable)
183 {
184 SCM class;
185
186 scm_i_pthread_mutex_lock (&scm_i_misc_mutex);
187 if (scm_is_false (vtable_class_map))
188 vtable_class_map = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
189 scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
190
191 if (scm_is_false (scm_struct_vtable_p (vtable)))
192 abort ();
193
194 class = scm_weak_table_refq (vtable_class_map, vtable, SCM_BOOL_F);
195
196 if (scm_is_false (class))
197 {
198 if (SCM_UNPACK (scm_class_class))
199 {
200 SCM name = SCM_VTABLE_NAME (vtable);
201 if (!scm_is_symbol (name))
202 name = scm_string_to_symbol (scm_nullstr);
203
204 class = scm_make_extended_class_from_symbol
205 (name, SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_APPLICABLE));
206 }
207 else
208 /* `create_struct_classes' will fill this in later. */
209 class = SCM_BOOL_F;
210
211 /* Don't worry about races. This only happens when creating a
212 vtable, which happens by definition in one thread. */
213 scm_weak_table_putq_x (vtable_class_map, vtable, class);
214 }
215
216 return class;
217 }
218
219 /* This function is used for efficient type dispatch. */
220 SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0,
221 (SCM x),
222 "Return the class of @var{x}.")
223 #define FUNC_NAME s_scm_class_of
224 {
225 switch (SCM_ITAG3 (x))
226 {
227 case scm_tc3_int_1:
228 case scm_tc3_int_2:
229 return scm_class_integer;
230
231 case scm_tc3_imm24:
232 if (SCM_CHARP (x))
233 return scm_class_char;
234 else if (scm_is_bool (x))
235 return scm_class_boolean;
236 else if (scm_is_null (x))
237 return scm_class_null;
238 else
239 return scm_class_unknown;
240
241 case scm_tc3_cons:
242 switch (SCM_TYP7 (x))
243 {
244 case scm_tcs_cons_nimcar:
245 return scm_class_pair;
246 case scm_tc7_symbol:
247 return scm_class_symbol;
248 case scm_tc7_vector:
249 case scm_tc7_wvect:
250 return scm_class_vector;
251 case scm_tc7_pointer:
252 return class_foreign;
253 case scm_tc7_hashtable:
254 return class_hashtable;
255 case scm_tc7_fluid:
256 return class_fluid;
257 case scm_tc7_dynamic_state:
258 return class_dynamic_state;
259 case scm_tc7_frame:
260 return class_frame;
261 case scm_tc7_keyword:
262 return scm_class_keyword;
263 case scm_tc7_vm_cont:
264 return class_vm_cont;
265 case scm_tc7_bytevector:
266 if (SCM_BYTEVECTOR_ELEMENT_TYPE (x) == SCM_ARRAY_ELEMENT_TYPE_VU8)
267 return class_bytevector;
268 else
269 return class_uvec;
270 case scm_tc7_array:
271 return class_array;
272 case scm_tc7_bitvector:
273 return class_bitvector;
274 case scm_tc7_string:
275 return scm_class_string;
276 case scm_tc7_number:
277 switch SCM_TYP16 (x) {
278 case scm_tc16_big:
279 return scm_class_integer;
280 case scm_tc16_real:
281 return scm_class_real;
282 case scm_tc16_complex:
283 return scm_class_complex;
284 case scm_tc16_fraction:
285 return scm_class_fraction;
286 }
287 case scm_tc7_program:
288 if (SCM_PROGRAM_IS_PRIMITIVE_GENERIC (x)
289 && SCM_UNPACK (*SCM_SUBR_GENERIC (x)))
290 return scm_class_primitive_generic;
291 else
292 return scm_class_procedure;
293
294 case scm_tc7_smob:
295 {
296 scm_t_bits type = SCM_TYP16 (x);
297 if (type != scm_tc16_port_with_ps)
298 return scm_smob_class[SCM_TC2SMOBNUM (type)];
299 x = SCM_PORT_WITH_PS_PORT (x);
300 /* fall through to ports */
301 }
302 case scm_tc7_port:
303 return scm_port_class[(SCM_WRTNG & SCM_CELL_WORD_0 (x)
304 ? (SCM_RDNG & SCM_CELL_WORD_0 (x)
305 ? SCM_INOUT_PCLASS_INDEX | SCM_PTOBNUM (x)
306 : SCM_OUT_PCLASS_INDEX | SCM_PTOBNUM (x))
307 : SCM_IN_PCLASS_INDEX | SCM_PTOBNUM (x))];
308 case scm_tcs_struct:
309 if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS_VALID)
310 return SCM_CLASS_OF (x);
311 else if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS)
312 {
313 /* Goops object */
314 if (! scm_is_false (SCM_OBJ_CLASS_REDEF (x)))
315 scm_change_object_class (x,
316 SCM_CLASS_OF (x), /* old */
317 SCM_OBJ_CLASS_REDEF (x)); /* new */
318 return SCM_CLASS_OF (x);
319 }
320 else
321 return scm_i_define_class_for_vtable (SCM_CLASS_OF (x));
322 default:
323 if (scm_is_pair (x))
324 return scm_class_pair;
325 else
326 return scm_class_unknown;
327 }
328
329 case scm_tc3_struct:
330 case scm_tc3_tc7_1:
331 case scm_tc3_tc7_2:
332 /* case scm_tc3_unused: */
333 /* Never reached */
334 break;
335 }
336 return scm_class_unknown;
337 }
338 #undef FUNC_NAME
339
340 /******************************************************************************
341 *
342 * compute-slots
343 *
344 ******************************************************************************/
345
346 static SCM
347 remove_duplicate_slots (SCM l, SCM res, SCM slots_already_seen)
348 {
349 SCM tmp;
350
351 if (!scm_is_pair (l))
352 return res;
353
354 tmp = SCM_CAAR (l);
355 if (!scm_is_symbol (tmp))
356 scm_misc_error ("%compute-slots", "bad slot name ~S", scm_list_1 (tmp));
357
358 if (scm_is_false (scm_c_memq (tmp, slots_already_seen))) {
359 res = scm_cons (SCM_CAR (l), res);
360 slots_already_seen = scm_cons (tmp, slots_already_seen);
361 }
362
363 return remove_duplicate_slots (SCM_CDR (l), res, slots_already_seen);
364 }
365
366 static void
367 check_cpl (SCM slots, SCM bslots)
368 {
369 for (; scm_is_pair (bslots); bslots = SCM_CDR (bslots))
370 if (scm_is_true (scm_assq (SCM_CAAR (bslots), slots)))
371 scm_misc_error ("init-object", "a predefined <class> inherited "
372 "field cannot be redefined", SCM_EOL);
373 }
374
375 enum build_class_class_slots_mode { BOOT_SLOTS, FINAL_SLOTS };
376 static SCM build_class_class_slots (enum build_class_class_slots_mode mode);
377
378 static SCM
379 build_slots_list (SCM dslots, SCM cpl)
380 {
381 SCM bslots, class_slots;
382 int classp;
383 SCM res = dslots;
384
385 class_slots = SCM_EOL;
386 classp = scm_is_true (scm_memq (scm_class_class, cpl));
387
388 if (classp)
389 {
390 bslots = build_class_class_slots (FINAL_SLOTS);
391 check_cpl (res, bslots);
392 }
393 else
394 bslots = SCM_EOL;
395
396 if (scm_is_pair (cpl))
397 {
398 for (cpl = SCM_CDR (cpl); scm_is_pair (cpl); cpl = SCM_CDR (cpl))
399 {
400 SCM new_slots = SCM_SLOT (SCM_CAR (cpl),
401 scm_si_direct_slots);
402 if (classp)
403 {
404 if (!scm_is_eq (SCM_CAR (cpl), scm_class_class))
405 check_cpl (new_slots, bslots);
406 else
407 {
408 /* Move class slots to the head of the list. */
409 class_slots = new_slots;
410 continue;
411 }
412 }
413 res = scm_append (scm_list_2 (new_slots, res));
414 }
415 }
416 else
417 scm_misc_error ("%compute-slots", "malformed cpl argument in "
418 "build_slots_list", SCM_EOL);
419
420 /* make sure to add the <class> slots to the head of the list */
421 if (classp)
422 res = scm_append (scm_list_2 (class_slots, res));
423
424 /* res contains a list of slots. Remove slots which appears more than once */
425 return remove_duplicate_slots (scm_reverse (res), SCM_EOL, SCM_EOL);
426 }
427
428 static SCM
429 maplist (SCM ls)
430 {
431 SCM orig = ls;
432 while (!scm_is_null (ls))
433 {
434 if (!scm_is_pair (ls))
435 scm_misc_error ("%compute-slots", "malformed ls argument in "
436 "maplist", SCM_EOL);
437 if (!scm_is_pair (SCM_CAR (ls)))
438 SCM_SETCAR (ls, scm_cons (SCM_CAR (ls), SCM_EOL));
439 ls = SCM_CDR (ls);
440 }
441 return orig;
442 }
443
444
445 SCM_DEFINE (scm_sys_compute_slots, "%compute-slots", 1, 0, 0,
446 (SCM class),
447 "Return a list consisting of the names of all slots belonging to\n"
448 "class @var{class}, i. e. the slots of @var{class} and of all of\n"
449 "its superclasses.")
450 #define FUNC_NAME s_scm_sys_compute_slots
451 {
452 SCM_VALIDATE_CLASS (1, class);
453 return build_slots_list (SCM_SLOT (class, scm_si_direct_slots),
454 SCM_SLOT (class, scm_si_cpl));
455 }
456 #undef FUNC_NAME
457
458
459 /******************************************************************************
460 *
461 * compute-getters-n-setters
462 *
463 * This version doesn't handle slot options. It serves only for booting
464 * classes and will be overloaded in Scheme.
465 *
466 ******************************************************************************/
467
468 SCM_KEYWORD (k_init_value, "init-value");
469 SCM_KEYWORD (k_init_thunk, "init-thunk");
470
471 static SCM
472 compute_getters_n_setters (SCM slots)
473 {
474 SCM res = SCM_EOL;
475 SCM *cdrloc = &res;
476 long i = 0;
477
478 for ( ; !scm_is_null (slots); slots = SCM_CDR (slots))
479 {
480 SCM init = SCM_BOOL_F;
481 SCM options = SCM_CDAR (slots);
482 if (!scm_is_null (options))
483 {
484 init = scm_get_keyword (k_init_value, options, SCM_PACK (0));
485 if (SCM_UNPACK (init))
486 {
487 init = scm_primitive_eval (scm_list_3 (scm_sym_lambda,
488 SCM_EOL,
489 scm_list_2 (scm_sym_quote,
490 init)));
491 }
492 else
493 init = scm_get_keyword (k_init_thunk, options, SCM_BOOL_F);
494 }
495 *cdrloc = scm_cons (scm_cons (SCM_CAAR (slots),
496 scm_cons (init,
497 scm_from_int (i++))),
498 SCM_EOL);
499 cdrloc = SCM_CDRLOC (*cdrloc);
500 }
501 return res;
502 }
503
504 /******************************************************************************
505 *
506 * initialize-object
507 *
508 ******************************************************************************/
509
510 /*fixme* Manufacture keywords in advance */
511 SCM
512 scm_i_get_keyword (SCM key, SCM l, long len, SCM default_value, const char *subr)
513 {
514 long i;
515
516 for (i = 0; i != len; i += 2)
517 {
518 SCM obj = SCM_CAR (l);
519
520 if (!scm_is_keyword (obj))
521 scm_misc_error (subr, "bad keyword: ~S", scm_list_1 (obj));
522 else if (scm_is_eq (obj, key))
523 return SCM_CADR (l);
524 else
525 l = SCM_CDDR (l);
526 }
527
528 return default_value;
529 }
530
531
532 SCM_DEFINE (scm_get_keyword, "get-keyword", 3, 0, 0,
533 (SCM key, SCM l, SCM default_value),
534 "Determine an associated value for the keyword @var{key} from\n"
535 "the list @var{l}. The list @var{l} has to consist of an even\n"
536 "number of elements, where, starting with the first, every\n"
537 "second element is a keyword, followed by its associated value.\n"
538 "If @var{l} does not hold a value for @var{key}, the value\n"
539 "@var{default_value} is returned.")
540 #define FUNC_NAME s_scm_get_keyword
541 {
542 long len;
543
544 SCM_ASSERT (scm_is_keyword (key), key, SCM_ARG1, FUNC_NAME);
545 len = scm_ilength (l);
546 if (len < 0 || len % 2 == 1)
547 scm_misc_error (FUNC_NAME, "Bad keyword-value list: ~S", scm_list_1 (l));
548
549 return scm_i_get_keyword (key, l, len, default_value, FUNC_NAME);
550 }
551 #undef FUNC_NAME
552
553
554 SCM_KEYWORD (k_init_keyword, "init-keyword");
555
556 static SCM get_slot_value (SCM class, SCM obj, SCM slotdef);
557 static SCM set_slot_value (SCM class, SCM obj, SCM slotdef, SCM value);
558
559 SCM_DEFINE (scm_sys_initialize_object, "%initialize-object", 2, 0, 0,
560 (SCM obj, SCM initargs),
561 "Initialize the object @var{obj} with the given arguments\n"
562 "@var{initargs}.")
563 #define FUNC_NAME s_scm_sys_initialize_object
564 {
565 SCM tmp, get_n_set, slots;
566 SCM class = SCM_CLASS_OF (obj);
567 long n_initargs;
568
569 SCM_VALIDATE_INSTANCE (1, obj);
570 n_initargs = scm_ilength (initargs);
571 SCM_ASSERT ((n_initargs & 1) == 0, initargs, SCM_ARG2, FUNC_NAME);
572
573 get_n_set = SCM_SLOT (class, scm_si_getters_n_setters);
574 slots = SCM_SLOT (class, scm_si_slots);
575
576 /* See for each slot how it must be initialized */
577 for (;
578 !scm_is_null (slots);
579 get_n_set = SCM_CDR (get_n_set), slots = SCM_CDR (slots))
580 {
581 SCM slot_name = SCM_CAR (slots);
582 SCM slot_value = SCM_GOOPS_UNBOUND;
583
584 if (!scm_is_null (SCM_CDR (slot_name)))
585 {
586 /* This slot admits (perhaps) to be initialized at creation time */
587 long n = scm_ilength (SCM_CDR (slot_name));
588 if (n & 1) /* odd or -1 */
589 SCM_MISC_ERROR ("class contains bogus slot definition: ~S",
590 scm_list_1 (slot_name));
591 tmp = scm_i_get_keyword (k_init_keyword,
592 SCM_CDR (slot_name),
593 n,
594 SCM_PACK (0),
595 FUNC_NAME);
596 slot_name = SCM_CAR (slot_name);
597 if (SCM_UNPACK (tmp))
598 {
599 /* an initarg was provided for this slot */
600 if (!scm_is_keyword (tmp))
601 SCM_MISC_ERROR ("initarg must be a keyword. It was ~S",
602 scm_list_1 (tmp));
603 slot_value = scm_i_get_keyword (tmp,
604 initargs,
605 n_initargs,
606 SCM_GOOPS_UNBOUND,
607 FUNC_NAME);
608 }
609 }
610
611 if (!SCM_GOOPS_UNBOUNDP (slot_value))
612 /* set slot to provided value */
613 set_slot_value (class, obj, SCM_CAR (get_n_set), slot_value);
614 else
615 {
616 /* set slot to its :init-form if it exists */
617 tmp = SCM_CADAR (get_n_set);
618 if (scm_is_true (tmp))
619 set_slot_value (class,
620 obj,
621 SCM_CAR (get_n_set),
622 scm_call_0 (tmp));
623 }
624 }
625
626 return obj;
627 }
628 #undef FUNC_NAME
629
630 /* NOTE: The following macros are interdependent with code
631 * in goops.scm:compute-getters-n-setters
632 */
633 #define SCM_GNS_INSTANCE_ALLOCATED_P(gns) \
634 (SCM_I_INUMP (SCM_CDDR (gns)) \
635 || (scm_is_pair (SCM_CDDR (gns)) \
636 && scm_is_pair (SCM_CDDDR (gns)) \
637 && scm_is_pair (SCM_CDDDDR (gns))))
638 #define SCM_GNS_INDEX(gns) \
639 (SCM_I_INUMP (SCM_CDDR (gns)) \
640 ? SCM_I_INUM (SCM_CDDR (gns)) \
641 : scm_to_long (SCM_CAR (SCM_CDDDDR (gns))))
642 #define SCM_GNS_SIZE(gns) \
643 (SCM_I_INUMP (SCM_CDDR (gns)) \
644 ? 1 \
645 : scm_to_long (SCM_CADR (SCM_CDDDDR (gns))))
646
647 SCM_KEYWORD (k_class, "class");
648 SCM_KEYWORD (k_allocation, "allocation");
649 SCM_KEYWORD (k_instance, "instance");
650
651 SCM_DEFINE (scm_sys_prep_layout_x, "%prep-layout!", 1, 0, 0,
652 (SCM class),
653 "")
654 #define FUNC_NAME s_scm_sys_prep_layout_x
655 {
656 SCM slots, getters_n_setters, nfields;
657 unsigned long int n, i;
658 char *s;
659 SCM layout;
660
661 SCM_VALIDATE_INSTANCE (1, class);
662 slots = SCM_SLOT (class, scm_si_slots);
663 getters_n_setters = SCM_SLOT (class, scm_si_getters_n_setters);
664 nfields = SCM_SLOT (class, scm_si_nfields);
665 if (!SCM_I_INUMP (nfields) || SCM_I_INUM (nfields) < 0)
666 SCM_MISC_ERROR ("bad value in nfields slot: ~S",
667 scm_list_1 (nfields));
668 n = 2 * SCM_I_INUM (nfields);
669 if (n < sizeof (SCM_CLASS_CLASS_LAYOUT) - 1
670 && SCM_SUBCLASSP (class, scm_class_class))
671 SCM_MISC_ERROR ("class object doesn't have enough fields: ~S",
672 scm_list_1 (nfields));
673
674 layout = scm_i_make_string (n, &s, 0);
675 i = 0;
676 while (scm_is_pair (getters_n_setters))
677 {
678 if (SCM_GNS_INSTANCE_ALLOCATED_P (SCM_CAR (getters_n_setters)))
679 {
680 SCM type;
681 int len, index, size;
682 char p, a;
683
684 if (i >= n || !scm_is_pair (slots))
685 goto inconsistent;
686
687 /* extract slot type */
688 len = scm_ilength (SCM_CDAR (slots));
689 type = scm_i_get_keyword (k_class, SCM_CDAR (slots),
690 len, SCM_BOOL_F, FUNC_NAME);
691 /* determine slot GC protection and access mode */
692 if (scm_is_false (type))
693 {
694 p = 'p';
695 a = 'w';
696 }
697 else
698 {
699 if (!SCM_CLASSP (type))
700 SCM_MISC_ERROR ("bad slot class", SCM_EOL);
701 else if (SCM_SUBCLASSP (type, scm_class_foreign_slot))
702 {
703 if (SCM_SUBCLASSP (type, scm_class_self))
704 p = 's';
705 else if (SCM_SUBCLASSP (type, scm_class_protected))
706 p = 'p';
707 else
708 p = 'u';
709
710 if (SCM_SUBCLASSP (type, scm_class_opaque))
711 a = 'o';
712 else if (SCM_SUBCLASSP (type, scm_class_read_only))
713 a = 'r';
714 else if (SCM_SUBCLASSP (type, scm_class_hidden))
715 a = 'h';
716 else
717 a = 'w';
718 }
719 else
720 {
721 p = 'p';
722 a = 'w';
723 }
724 }
725
726 index = SCM_GNS_INDEX (SCM_CAR (getters_n_setters));
727 if (index != (i >> 1))
728 goto inconsistent;
729 size = SCM_GNS_SIZE (SCM_CAR (getters_n_setters));
730 while (size)
731 {
732 s[i++] = p;
733 s[i++] = a;
734 --size;
735 }
736 }
737 slots = SCM_CDR (slots);
738 getters_n_setters = SCM_CDR (getters_n_setters);
739 }
740 if (!scm_is_null (slots))
741 {
742 inconsistent:
743 SCM_MISC_ERROR ("inconsistent getters-n-setters", SCM_EOL);
744 }
745 SCM_SET_VTABLE_LAYOUT (class, scm_string_to_symbol (layout));
746 return SCM_UNSPECIFIED;
747 }
748 #undef FUNC_NAME
749
750 static void prep_hashsets (SCM);
751
752 SCM_DEFINE (scm_sys_inherit_magic_x, "%inherit-magic!", 2, 0, 0,
753 (SCM class, SCM dsupers),
754 "")
755 #define FUNC_NAME s_scm_sys_inherit_magic_x
756 {
757 SCM_VALIDATE_INSTANCE (1, class);
758 scm_i_struct_inherit_vtable_magic (SCM_CLASS_OF (class), class);
759 SCM_SET_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_OR_VALID);
760
761 prep_hashsets (class);
762
763 return SCM_UNSPECIFIED;
764 }
765 #undef FUNC_NAME
766
767 static void
768 prep_hashsets (SCM class)
769 {
770 unsigned int i;
771
772 for (i = 0; i < 8; ++i)
773 SCM_SET_HASHSET (class, i, scm_c_uniform32 (goops_rstate));
774 }
775
776 /******************************************************************************/
777
778 SCM
779 scm_basic_basic_make_class (SCM class, SCM name, SCM dsupers, SCM dslots)
780 {
781 SCM z, cpl, slots, nfields, g_n_s;
782
783 /* Allocate one instance */
784 z = scm_make_struct (class, SCM_INUM0, SCM_EOL);
785
786 /* Initialize its slots */
787 SCM_SET_SLOT (z, scm_si_direct_supers, dsupers);
788 cpl = scm_call_1 (SCM_VARIABLE_REF (var_compute_cpl), z);
789 slots = build_slots_list (maplist (dslots), cpl);
790 nfields = scm_from_int (scm_ilength (slots));
791 g_n_s = compute_getters_n_setters (slots);
792
793 SCM_SET_SLOT (z, scm_vtable_index_name, name);
794 SCM_SET_SLOT (z, scm_si_direct_slots, dslots);
795 SCM_SET_SLOT (z, scm_si_direct_subclasses, SCM_EOL);
796 SCM_SET_SLOT (z, scm_si_direct_methods, SCM_EOL);
797 SCM_SET_SLOT (z, scm_si_cpl, cpl);
798 SCM_SET_SLOT (z, scm_si_slots, slots);
799 SCM_SET_SLOT (z, scm_si_nfields, nfields);
800 SCM_SET_SLOT (z, scm_si_getters_n_setters, g_n_s);
801 SCM_SET_SLOT (z, scm_si_redefined, SCM_BOOL_F);
802
803 /* Add this class in the direct-subclasses slot of dsupers */
804 {
805 SCM tmp;
806 for (tmp = dsupers; !scm_is_null (tmp); tmp = SCM_CDR (tmp))
807 SCM_SET_SLOT (SCM_CAR (tmp), scm_si_direct_subclasses,
808 scm_cons (z, SCM_SLOT (SCM_CAR (tmp),
809 scm_si_direct_subclasses)));
810 }
811
812 return z;
813 }
814
815 SCM
816 scm_basic_make_class (SCM class, SCM name, SCM dsupers, SCM dslots)
817 {
818 SCM z = scm_basic_basic_make_class (class, name, dsupers, dslots);
819 scm_sys_prep_layout_x (z);
820 scm_sys_inherit_magic_x (z, dsupers);
821 return z;
822 }
823
824 /******************************************************************************/
825
826 SCM_SYMBOL (sym_layout, "layout");
827 SCM_SYMBOL (sym_flags, "flags");
828 SCM_SYMBOL (sym_self, "%self");
829 SCM_SYMBOL (sym_instance_finalizer, "instance-finalizer");
830 SCM_SYMBOL (sym_reserved_0, "%reserved-0");
831 SCM_SYMBOL (sym_reserved_1, "%reserved-1");
832 SCM_SYMBOL (sym_print, "print");
833 SCM_SYMBOL (sym_procedure, "procedure");
834 SCM_SYMBOL (sym_setter, "setter");
835 SCM_SYMBOL (sym_redefined, "redefined");
836 SCM_SYMBOL (sym_h0, "h0");
837 SCM_SYMBOL (sym_h1, "h1");
838 SCM_SYMBOL (sym_h2, "h2");
839 SCM_SYMBOL (sym_h3, "h3");
840 SCM_SYMBOL (sym_h4, "h4");
841 SCM_SYMBOL (sym_h5, "h5");
842 SCM_SYMBOL (sym_h6, "h6");
843 SCM_SYMBOL (sym_h7, "h7");
844 SCM_SYMBOL (sym_name, "name");
845 SCM_SYMBOL (sym_direct_supers, "direct-supers");
846 SCM_SYMBOL (sym_direct_slots, "direct-slots");
847 SCM_SYMBOL (sym_direct_subclasses, "direct-subclasses");
848 SCM_SYMBOL (sym_direct_methods, "direct-methods");
849 SCM_SYMBOL (sym_cpl, "cpl");
850 SCM_SYMBOL (sym_default_slot_definition_class, "default-slot-definition-class");
851 SCM_SYMBOL (sym_slots, "slots");
852 SCM_SYMBOL (sym_getters_n_setters, "getters-n-setters");
853 SCM_SYMBOL (sym_nfields, "nfields");
854
855
856 static int specialized_slots_initialized = 0;
857
858 static SCM
859 build_class_class_slots (enum build_class_class_slots_mode mode)
860 {
861 #define SPECIALIZED_SLOT(name, class) \
862 (mode == BOOT_SLOTS ? scm_list_1 (name) : scm_list_3 (name, k_class, class))
863
864 if (mode == FINAL_SLOTS && !specialized_slots_initialized)
865 abort ();
866
867 /* has to be kept in sync with SCM_VTABLE_BASE_LAYOUT and
868 SCM_CLASS_CLASS_LAYOUT */
869 return scm_list_n (
870 SPECIALIZED_SLOT (sym_layout, scm_class_protected_read_only),
871 SPECIALIZED_SLOT (sym_flags, scm_class_hidden),
872 SPECIALIZED_SLOT (sym_self, scm_class_self),
873 SPECIALIZED_SLOT (sym_instance_finalizer, scm_class_hidden),
874 scm_list_1 (sym_print),
875 SPECIALIZED_SLOT (sym_name, scm_class_protected_hidden),
876 SPECIALIZED_SLOT (sym_reserved_0, scm_class_hidden),
877 SPECIALIZED_SLOT (sym_reserved_1, scm_class_hidden),
878 scm_list_1 (sym_redefined),
879 SPECIALIZED_SLOT (sym_h0, scm_class_int),
880 SPECIALIZED_SLOT (sym_h1, scm_class_int),
881 SPECIALIZED_SLOT (sym_h2, scm_class_int),
882 SPECIALIZED_SLOT (sym_h3, scm_class_int),
883 SPECIALIZED_SLOT (sym_h4, scm_class_int),
884 SPECIALIZED_SLOT (sym_h5, scm_class_int),
885 SPECIALIZED_SLOT (sym_h6, scm_class_int),
886 SPECIALIZED_SLOT (sym_h7, scm_class_int),
887 scm_list_1 (sym_direct_supers),
888 scm_list_1 (sym_direct_slots),
889 scm_list_1 (sym_direct_subclasses),
890 scm_list_1 (sym_direct_methods),
891 scm_list_1 (sym_cpl),
892 scm_list_1 (sym_default_slot_definition_class),
893 scm_list_1 (sym_slots),
894 scm_list_1 (sym_getters_n_setters),
895 scm_list_1 (sym_nfields),
896 SCM_UNDEFINED);
897 }
898
899 static void
900 create_basic_classes (void)
901 {
902 SCM slots_of_class = build_class_class_slots (BOOT_SLOTS);
903
904 /**** <class> ****/
905 SCM cs = scm_from_locale_string (SCM_CLASS_CLASS_LAYOUT);
906 SCM name = scm_from_latin1_symbol ("<class>");
907 scm_class_class = scm_i_make_vtable_vtable (cs);
908 SCM_SET_CLASS_FLAGS (scm_class_class, (SCM_CLASSF_GOOPS_OR_VALID
909 | SCM_CLASSF_METACLASS));
910
911 SCM_SET_SLOT (scm_class_class, scm_vtable_index_name, name);
912 SCM_SET_SLOT (scm_class_class, scm_si_direct_supers, SCM_EOL); /* will be changed */
913 SCM_SET_SLOT (scm_class_class, scm_si_direct_slots, slots_of_class); /* will be changed */
914 SCM_SET_SLOT (scm_class_class, scm_si_direct_subclasses, SCM_EOL);
915 SCM_SET_SLOT (scm_class_class, scm_si_direct_methods, SCM_EOL);
916 SCM_SET_SLOT (scm_class_class, scm_si_cpl, SCM_EOL); /* will be changed */
917 SCM_SET_SLOT (scm_class_class, scm_si_slots, slots_of_class); /* will be changed */
918 SCM_SET_SLOT (scm_class_class, scm_si_nfields, scm_from_int (SCM_N_CLASS_SLOTS));
919 SCM_SET_SLOT (scm_class_class, scm_si_getters_n_setters,
920 compute_getters_n_setters (slots_of_class)); /* will be changed */
921 SCM_SET_SLOT (scm_class_class, scm_si_redefined, SCM_BOOL_F);
922
923 prep_hashsets (scm_class_class);
924
925 scm_module_define (scm_module_goops, name, scm_class_class);
926
927 /**** <top> ****/
928 name = scm_from_latin1_symbol ("<top>");
929 scm_class_top = scm_basic_make_class (scm_class_class, name,
930 SCM_EOL, SCM_EOL);
931
932 scm_module_define (scm_module_goops, name, scm_class_top);
933
934 /**** <object> ****/
935 name = scm_from_latin1_symbol ("<object>");
936 scm_class_object = scm_basic_make_class (scm_class_class, name,
937 scm_list_1 (scm_class_top), SCM_EOL);
938
939 scm_module_define (scm_module_goops, name, scm_class_object);
940
941 /* <top> <object> and <class> were partially initialized. Correct them here */
942 SCM_SET_SLOT (scm_class_object, scm_si_direct_subclasses, scm_list_1 (scm_class_class));
943
944 SCM_SET_SLOT (scm_class_class, scm_si_direct_supers, scm_list_1 (scm_class_object));
945 SCM_SET_SLOT (scm_class_class, scm_si_cpl, scm_list_3 (scm_class_class, scm_class_object, scm_class_top));
946 }
947
948 /******************************************************************************/
949
950 SCM_DEFINE (scm_instance_p, "instance?", 1, 0, 0,
951 (SCM obj),
952 "Return @code{#t} if @var{obj} is an instance.")
953 #define FUNC_NAME s_scm_instance_p
954 {
955 return scm_from_bool (SCM_INSTANCEP (obj));
956 }
957 #undef FUNC_NAME
958
959
960 /******************************************************************************
961 *
962 * Meta object accessors
963 *
964 ******************************************************************************/
965 SCM_DEFINE (scm_class_name, "class-name", 1, 0, 0,
966 (SCM obj),
967 "Return the class name of @var{obj}.")
968 #define FUNC_NAME s_scm_class_name
969 {
970 SCM_VALIDATE_CLASS (1, obj);
971 return scm_slot_ref (obj, sym_name);
972 }
973 #undef FUNC_NAME
974
975 SCM_DEFINE (scm_class_direct_supers, "class-direct-supers", 1, 0, 0,
976 (SCM obj),
977 "Return the direct superclasses of the class @var{obj}.")
978 #define FUNC_NAME s_scm_class_direct_supers
979 {
980 SCM_VALIDATE_CLASS (1, obj);
981 return scm_slot_ref (obj, sym_direct_supers);
982 }
983 #undef FUNC_NAME
984
985 SCM_DEFINE (scm_class_direct_slots, "class-direct-slots", 1, 0, 0,
986 (SCM obj),
987 "Return the direct slots of the class @var{obj}.")
988 #define FUNC_NAME s_scm_class_direct_slots
989 {
990 SCM_VALIDATE_CLASS (1, obj);
991 return scm_slot_ref (obj, sym_direct_slots);
992 }
993 #undef FUNC_NAME
994
995 SCM_DEFINE (scm_class_direct_subclasses, "class-direct-subclasses", 1, 0, 0,
996 (SCM obj),
997 "Return the direct subclasses of the class @var{obj}.")
998 #define FUNC_NAME s_scm_class_direct_subclasses
999 {
1000 SCM_VALIDATE_CLASS (1, obj);
1001 return scm_slot_ref(obj, sym_direct_subclasses);
1002 }
1003 #undef FUNC_NAME
1004
1005 SCM_DEFINE (scm_class_direct_methods, "class-direct-methods", 1, 0, 0,
1006 (SCM obj),
1007 "Return the direct methods of the class @var{obj}")
1008 #define FUNC_NAME s_scm_class_direct_methods
1009 {
1010 SCM_VALIDATE_CLASS (1, obj);
1011 return scm_slot_ref (obj, sym_direct_methods);
1012 }
1013 #undef FUNC_NAME
1014
1015 SCM_DEFINE (scm_class_precedence_list, "class-precedence-list", 1, 0, 0,
1016 (SCM obj),
1017 "Return the class precedence list of the class @var{obj}.")
1018 #define FUNC_NAME s_scm_class_precedence_list
1019 {
1020 SCM_VALIDATE_CLASS (1, obj);
1021 return scm_slot_ref (obj, sym_cpl);
1022 }
1023 #undef FUNC_NAME
1024
1025 SCM_DEFINE (scm_class_slots, "class-slots", 1, 0, 0,
1026 (SCM obj),
1027 "Return the slot list of the class @var{obj}.")
1028 #define FUNC_NAME s_scm_class_slots
1029 {
1030 SCM_VALIDATE_CLASS (1, obj);
1031 return scm_slot_ref (obj, sym_slots);
1032 }
1033 #undef FUNC_NAME
1034
1035 SCM_DEFINE (scm_generic_function_name, "generic-function-name", 1, 0, 0,
1036 (SCM obj),
1037 "Return the name of the generic function @var{obj}.")
1038 #define FUNC_NAME s_scm_generic_function_name
1039 {
1040 SCM_VALIDATE_GENERIC (1, obj);
1041 return scm_procedure_property (obj, scm_sym_name);
1042 }
1043 #undef FUNC_NAME
1044
1045 SCM_SYMBOL (sym_methods, "methods");
1046 SCM_SYMBOL (sym_extended_by, "extended-by");
1047 SCM_SYMBOL (sym_extends, "extends");
1048
1049 static
1050 SCM fold_downward_gf_methods (SCM method_lists, SCM gf)
1051 {
1052 SCM gfs = scm_slot_ref (gf, sym_extended_by);
1053 method_lists = scm_cons (scm_slot_ref (gf, sym_methods), method_lists);
1054 while (!scm_is_null (gfs))
1055 {
1056 method_lists = fold_downward_gf_methods (method_lists, SCM_CAR (gfs));
1057 gfs = SCM_CDR (gfs);
1058 }
1059 return method_lists;
1060 }
1061
1062 static
1063 SCM fold_upward_gf_methods (SCM method_lists, SCM gf)
1064 {
1065 if (SCM_IS_A_P (gf, scm_class_extended_generic))
1066 {
1067 SCM gfs = scm_slot_ref (gf, sym_extends);
1068 while (!scm_is_null (gfs))
1069 {
1070 SCM methods = scm_slot_ref (SCM_CAR (gfs), sym_methods);
1071 method_lists = fold_upward_gf_methods (scm_cons (methods,
1072 method_lists),
1073 SCM_CAR (gfs));
1074 gfs = SCM_CDR (gfs);
1075 }
1076 }
1077 return method_lists;
1078 }
1079
1080 SCM_DEFINE (scm_generic_function_methods, "generic-function-methods", 1, 0, 0,
1081 (SCM obj),
1082 "Return the methods of the generic function @var{obj}.")
1083 #define FUNC_NAME s_scm_generic_function_methods
1084 {
1085 SCM methods;
1086 SCM_VALIDATE_GENERIC (1, obj);
1087 methods = fold_upward_gf_methods (SCM_EOL, obj);
1088 methods = fold_downward_gf_methods (methods, obj);
1089 return scm_append (methods);
1090 }
1091 #undef FUNC_NAME
1092
1093 SCM_DEFINE (scm_method_generic_function, "method-generic-function", 1, 0, 0,
1094 (SCM obj),
1095 "Return the generic function for the method @var{obj}.")
1096 #define FUNC_NAME s_scm_method_generic_function
1097 {
1098 SCM_VALIDATE_METHOD (1, obj);
1099 return scm_slot_ref (obj, scm_from_latin1_symbol ("generic-function"));
1100 }
1101 #undef FUNC_NAME
1102
1103 SCM_DEFINE (scm_method_specializers, "method-specializers", 1, 0, 0,
1104 (SCM obj),
1105 "Return specializers of the method @var{obj}.")
1106 #define FUNC_NAME s_scm_method_specializers
1107 {
1108 SCM_VALIDATE_METHOD (1, obj);
1109 return scm_slot_ref (obj, scm_from_latin1_symbol ("specializers"));
1110 }
1111 #undef FUNC_NAME
1112
1113 SCM_DEFINE (scm_method_procedure, "method-procedure", 1, 0, 0,
1114 (SCM obj),
1115 "Return the procedure of the method @var{obj}.")
1116 #define FUNC_NAME s_scm_method_procedure
1117 {
1118 SCM_VALIDATE_METHOD (1, obj);
1119 return scm_slot_ref (obj, sym_procedure);
1120 }
1121 #undef FUNC_NAME
1122
1123 /******************************************************************************
1124 *
1125 * S l o t a c c e s s
1126 *
1127 ******************************************************************************/
1128
1129 SCM_DEFINE (scm_make_unbound, "make-unbound", 0, 0, 0,
1130 (),
1131 "Return the unbound value.")
1132 #define FUNC_NAME s_scm_make_unbound
1133 {
1134 return SCM_GOOPS_UNBOUND;
1135 }
1136 #undef FUNC_NAME
1137
1138 SCM_DEFINE (scm_unbound_p, "unbound?", 1, 0, 0,
1139 (SCM obj),
1140 "Return @code{#t} if @var{obj} is unbound.")
1141 #define FUNC_NAME s_scm_unbound_p
1142 {
1143 return SCM_GOOPS_UNBOUNDP (obj) ? SCM_BOOL_T : SCM_BOOL_F;
1144 }
1145 #undef FUNC_NAME
1146
1147 SCM_DEFINE (scm_assert_bound, "assert-bound", 2, 0, 0,
1148 (SCM value, SCM obj),
1149 "Return @var{value} if it is bound, and invoke the\n"
1150 "@var{slot-unbound} method of @var{obj} if it is not.")
1151 #define FUNC_NAME s_scm_assert_bound
1152 {
1153 if (SCM_GOOPS_UNBOUNDP (value))
1154 return scm_call_1 (SCM_VARIABLE_REF (var_slot_unbound), obj);
1155 return value;
1156 }
1157 #undef FUNC_NAME
1158
1159 SCM_DEFINE (scm_at_assert_bound_ref, "@assert-bound-ref", 2, 0, 0,
1160 (SCM obj, SCM index),
1161 "Like @code{assert-bound}, but use @var{index} for accessing\n"
1162 "the value from @var{obj}.")
1163 #define FUNC_NAME s_scm_at_assert_bound_ref
1164 {
1165 SCM value = SCM_SLOT (obj, scm_to_int (index));
1166 if (SCM_GOOPS_UNBOUNDP (value))
1167 return scm_call_1 (SCM_VARIABLE_REF (var_slot_unbound), obj);
1168 return value;
1169 }
1170 #undef FUNC_NAME
1171
1172
1173 \f
1174 /** Utilities **/
1175
1176 /* In the future, this function will return the effective slot
1177 * definition associated with SLOT_NAME. Now it just returns some of
1178 * the information which will be stored in the effective slot
1179 * definition.
1180 */
1181
1182 static SCM
1183 slot_definition_using_name (SCM class, SCM slot_name)
1184 {
1185 register SCM slots = SCM_SLOT (class, scm_si_getters_n_setters);
1186 for (; !scm_is_null (slots); slots = SCM_CDR (slots))
1187 if (scm_is_eq (SCM_CAAR (slots), slot_name))
1188 return SCM_CAR (slots);
1189 return SCM_BOOL_F;
1190 }
1191
1192 static SCM
1193 get_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef)
1194 #define FUNC_NAME "%get-slot-value"
1195 {
1196 SCM access = SCM_CDDR (slotdef);
1197 /* Two cases here:
1198 * - access is an integer (the offset of this slot in the slots vector)
1199 * - otherwise (car access) is the getter function to apply
1200 *
1201 * Instances have never more than SCM_MOST_POSITIVE_FIXNUM slots, so
1202 * we can just assume fixnums here.
1203 */
1204 if (SCM_I_INUMP (access))
1205 /* Don't poke at the slots directly, because scm_struct_ref handles the
1206 access bits for us. */
1207 return scm_struct_ref (obj, access);
1208 else
1209 return scm_call_1 (SCM_CAR (access), obj);
1210 }
1211 #undef FUNC_NAME
1212
1213 static SCM
1214 get_slot_value_using_name (SCM class, SCM obj, SCM slot_name)
1215 {
1216 SCM slotdef = slot_definition_using_name (class, slot_name);
1217 if (scm_is_true (slotdef))
1218 return get_slot_value (class, obj, slotdef);
1219 else
1220 return scm_call_3 (SCM_VARIABLE_REF (var_slot_missing), class, obj, slot_name);
1221 }
1222
1223 static SCM
1224 set_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef, SCM value)
1225 #define FUNC_NAME "%set-slot-value"
1226 {
1227 SCM access = SCM_CDDR (slotdef);
1228 /* Two cases here:
1229 * - access is an integer (the offset of this slot in the slots vector)
1230 * - otherwise (cadr access) is the setter function to apply
1231 *
1232 * Instances have never more than SCM_MOST_POSITIVE_FIXNUM slots, so
1233 * we can just assume fixnums here.
1234 */
1235 if (SCM_I_INUMP (access))
1236 /* obey permissions bits via going through struct-set! */
1237 scm_struct_set_x (obj, access, value);
1238 else
1239 /* ((cadr l) obj value) */
1240 scm_call_2 (SCM_CADR (access), obj, value);
1241 return SCM_UNSPECIFIED;
1242 }
1243 #undef FUNC_NAME
1244
1245 static SCM
1246 set_slot_value_using_name (SCM class, SCM obj, SCM slot_name, SCM value)
1247 {
1248 SCM slotdef = slot_definition_using_name (class, slot_name);
1249 if (scm_is_true (slotdef))
1250 return set_slot_value (class, obj, slotdef, value);
1251 else
1252 return scm_call_4 (SCM_VARIABLE_REF (var_slot_missing), class, obj, slot_name, value);
1253 }
1254
1255 static SCM
1256 test_slot_existence (SCM class SCM_UNUSED, SCM obj, SCM slot_name)
1257 {
1258 register SCM l;
1259
1260 for (l = SCM_ACCESSORS_OF (obj); !scm_is_null (l); l = SCM_CDR (l))
1261 if (scm_is_eq (SCM_CAAR (l), slot_name))
1262 return SCM_BOOL_T;
1263
1264 return SCM_BOOL_F;
1265 }
1266
1267 /* ======================================== */
1268
1269 SCM_DEFINE (scm_slot_ref_using_class, "slot-ref-using-class", 3, 0, 0,
1270 (SCM class, SCM obj, SCM slot_name),
1271 "")
1272 #define FUNC_NAME s_scm_slot_ref_using_class
1273 {
1274 SCM res;
1275
1276 SCM_VALIDATE_CLASS (1, class);
1277 SCM_VALIDATE_INSTANCE (2, obj);
1278 SCM_VALIDATE_SYMBOL (3, slot_name);
1279
1280 res = get_slot_value_using_name (class, obj, slot_name);
1281 if (SCM_GOOPS_UNBOUNDP (res))
1282 return scm_call_3 (SCM_VARIABLE_REF (var_slot_unbound), class, obj, slot_name);
1283 return res;
1284 }
1285 #undef FUNC_NAME
1286
1287
1288 SCM_DEFINE (scm_slot_set_using_class_x, "slot-set-using-class!", 4, 0, 0,
1289 (SCM class, SCM obj, SCM slot_name, SCM value),
1290 "")
1291 #define FUNC_NAME s_scm_slot_set_using_class_x
1292 {
1293 SCM_VALIDATE_CLASS (1, class);
1294 SCM_VALIDATE_INSTANCE (2, obj);
1295 SCM_VALIDATE_SYMBOL (3, slot_name);
1296
1297 return set_slot_value_using_name (class, obj, slot_name, value);
1298 }
1299 #undef FUNC_NAME
1300
1301
1302 SCM_DEFINE (scm_slot_bound_using_class_p, "slot-bound-using-class?", 3, 0, 0,
1303 (SCM class, SCM obj, SCM slot_name),
1304 "")
1305 #define FUNC_NAME s_scm_slot_bound_using_class_p
1306 {
1307 SCM_VALIDATE_CLASS (1, class);
1308 SCM_VALIDATE_INSTANCE (2, obj);
1309 SCM_VALIDATE_SYMBOL (3, slot_name);
1310
1311 return (SCM_GOOPS_UNBOUNDP (get_slot_value_using_name (class, obj, slot_name))
1312 ? SCM_BOOL_F
1313 : SCM_BOOL_T);
1314 }
1315 #undef FUNC_NAME
1316
1317 SCM_DEFINE (scm_slot_exists_using_class_p, "slot-exists-using-class?", 3, 0, 0,
1318 (SCM class, SCM obj, SCM slot_name),
1319 "")
1320 #define FUNC_NAME s_scm_slot_exists_using_class_p
1321 {
1322 SCM_VALIDATE_CLASS (1, class);
1323 SCM_VALIDATE_INSTANCE (2, obj);
1324 SCM_VALIDATE_SYMBOL (3, slot_name);
1325 return test_slot_existence (class, obj, slot_name);
1326 }
1327 #undef FUNC_NAME
1328
1329
1330 /* ======================================== */
1331
1332 SCM_DEFINE (scm_slot_ref, "slot-ref", 2, 0, 0,
1333 (SCM obj, SCM slot_name),
1334 "Return the value from @var{obj}'s slot with the name\n"
1335 "@var{slot_name}.")
1336 #define FUNC_NAME s_scm_slot_ref
1337 {
1338 SCM res, class;
1339
1340 SCM_VALIDATE_INSTANCE (1, obj);
1341 TEST_CHANGE_CLASS (obj, class);
1342
1343 res = get_slot_value_using_name (class, obj, slot_name);
1344 if (SCM_GOOPS_UNBOUNDP (res))
1345 return scm_call_3 (SCM_VARIABLE_REF (var_slot_unbound), class, obj, slot_name);
1346 return res;
1347 }
1348 #undef FUNC_NAME
1349
1350 SCM_DEFINE (scm_slot_set_x, "slot-set!", 3, 0, 0,
1351 (SCM obj, SCM slot_name, SCM value),
1352 "Set the slot named @var{slot_name} of @var{obj} to @var{value}.")
1353 #define FUNC_NAME s_scm_slot_set_x
1354 {
1355 SCM class;
1356
1357 SCM_VALIDATE_INSTANCE (1, obj);
1358 TEST_CHANGE_CLASS(obj, class);
1359
1360 return set_slot_value_using_name (class, obj, slot_name, value);
1361 }
1362 #undef FUNC_NAME
1363
1364 const char *scm_s_slot_set_x = s_scm_slot_set_x;
1365
1366 SCM_DEFINE (scm_slot_bound_p, "slot-bound?", 2, 0, 0,
1367 (SCM obj, SCM slot_name),
1368 "Return @code{#t} if the slot named @var{slot_name} of @var{obj}\n"
1369 "is bound.")
1370 #define FUNC_NAME s_scm_slot_bound_p
1371 {
1372 SCM class;
1373
1374 SCM_VALIDATE_INSTANCE (1, obj);
1375 TEST_CHANGE_CLASS(obj, class);
1376
1377 return (SCM_GOOPS_UNBOUNDP (get_slot_value_using_name (class,
1378 obj,
1379 slot_name))
1380 ? SCM_BOOL_F
1381 : SCM_BOOL_T);
1382 }
1383 #undef FUNC_NAME
1384
1385 SCM_DEFINE (scm_slot_exists_p, "slot-exists?", 2, 0, 0,
1386 (SCM obj, SCM slot_name),
1387 "Return @code{#t} if @var{obj} has a slot named @var{slot_name}.")
1388 #define FUNC_NAME s_scm_slot_exists_p
1389 {
1390 SCM class;
1391
1392 SCM_VALIDATE_INSTANCE (1, obj);
1393 SCM_VALIDATE_SYMBOL (2, slot_name);
1394 TEST_CHANGE_CLASS (obj, class);
1395
1396 return test_slot_existence (class, obj, slot_name);
1397 }
1398 #undef FUNC_NAME
1399
1400
1401 /******************************************************************************
1402 *
1403 * %allocate-instance (the low level instance allocation primitive)
1404 *
1405 ******************************************************************************/
1406
1407 static void clear_method_cache (SCM);
1408
1409 SCM_DEFINE (scm_sys_allocate_instance, "%allocate-instance", 2, 0, 0,
1410 (SCM class, SCM initargs),
1411 "Create a new instance of class @var{class} and initialize it\n"
1412 "from the arguments @var{initargs}.")
1413 #define FUNC_NAME s_scm_sys_allocate_instance
1414 {
1415 SCM obj;
1416 scm_t_signed_bits n, i;
1417 SCM layout;
1418
1419 SCM_VALIDATE_CLASS (1, class);
1420
1421 /* FIXME: duplicates some of scm_make_struct. */
1422
1423 n = SCM_I_INUM (SCM_SLOT (class, scm_si_nfields));
1424 obj = scm_i_alloc_struct (SCM_STRUCT_DATA (class), n);
1425
1426 layout = SCM_VTABLE_LAYOUT (class);
1427
1428 /* Set all SCM-holding slots to unbound */
1429 for (i = 0; i < n; i++)
1430 {
1431 scm_t_wchar c = scm_i_symbol_ref (layout, i*2);
1432 if (c == 'p')
1433 SCM_STRUCT_DATA (obj)[i] = SCM_UNPACK (SCM_GOOPS_UNBOUND);
1434 else if (c == 's')
1435 SCM_STRUCT_DATA (obj)[i] = SCM_UNPACK (obj);
1436 else
1437 SCM_STRUCT_DATA (obj)[i] = 0;
1438 }
1439
1440 if (SCM_CLASS_FLAGS (class) & SCM_CLASSF_PURE_GENERIC)
1441 clear_method_cache (obj);
1442
1443 return obj;
1444 }
1445 #undef FUNC_NAME
1446
1447 SCM_DEFINE (scm_sys_set_object_setter_x, "%set-object-setter!", 2, 0, 0,
1448 (SCM obj, SCM setter),
1449 "")
1450 #define FUNC_NAME s_scm_sys_set_object_setter_x
1451 {
1452 SCM_ASSERT (SCM_STRUCTP (obj)
1453 && (SCM_OBJ_CLASS_FLAGS (obj) & SCM_CLASSF_PURE_GENERIC),
1454 obj,
1455 SCM_ARG1,
1456 FUNC_NAME);
1457 SCM_SET_GENERIC_SETTER (obj, setter);
1458 return SCM_UNSPECIFIED;
1459 }
1460 #undef FUNC_NAME
1461
1462 /******************************************************************************
1463 *
1464 * %modify-instance (used by change-class to modify in place)
1465 *
1466 ******************************************************************************/
1467
1468 SCM_DEFINE (scm_sys_modify_instance, "%modify-instance", 2, 0, 0,
1469 (SCM old, SCM new),
1470 "")
1471 #define FUNC_NAME s_scm_sys_modify_instance
1472 {
1473 SCM_VALIDATE_INSTANCE (1, old);
1474 SCM_VALIDATE_INSTANCE (2, new);
1475
1476 /* Exchange the data contained in old and new. We exchange rather than
1477 * scratch the old value with new to be correct with GC.
1478 * See "Class redefinition protocol above".
1479 */
1480 SCM_CRITICAL_SECTION_START;
1481 {
1482 scm_t_bits word0, word1;
1483 word0 = SCM_CELL_WORD_0 (old);
1484 word1 = SCM_CELL_WORD_1 (old);
1485 SCM_SET_CELL_WORD_0 (old, SCM_CELL_WORD_0 (new));
1486 SCM_SET_CELL_WORD_1 (old, SCM_CELL_WORD_1 (new));
1487 SCM_SET_CELL_WORD_0 (new, word0);
1488 SCM_SET_CELL_WORD_1 (new, word1);
1489 }
1490 SCM_CRITICAL_SECTION_END;
1491 return SCM_UNSPECIFIED;
1492 }
1493 #undef FUNC_NAME
1494
1495 SCM_DEFINE (scm_sys_modify_class, "%modify-class", 2, 0, 0,
1496 (SCM old, SCM new),
1497 "")
1498 #define FUNC_NAME s_scm_sys_modify_class
1499 {
1500 SCM_VALIDATE_CLASS (1, old);
1501 SCM_VALIDATE_CLASS (2, new);
1502
1503 SCM_CRITICAL_SECTION_START;
1504 {
1505 scm_t_bits word0, word1;
1506 word0 = SCM_CELL_WORD_0 (old);
1507 word1 = SCM_CELL_WORD_1 (old);
1508 SCM_SET_CELL_WORD_0 (old, SCM_CELL_WORD_0 (new));
1509 SCM_SET_CELL_WORD_1 (old, SCM_CELL_WORD_1 (new));
1510 SCM_STRUCT_DATA (old)[scm_vtable_index_self] = SCM_UNPACK (old);
1511 SCM_SET_CELL_WORD_0 (new, word0);
1512 SCM_SET_CELL_WORD_1 (new, word1);
1513 SCM_STRUCT_DATA (new)[scm_vtable_index_self] = SCM_UNPACK (new);
1514 }
1515 SCM_CRITICAL_SECTION_END;
1516 return SCM_UNSPECIFIED;
1517 }
1518 #undef FUNC_NAME
1519
1520 SCM_DEFINE (scm_sys_invalidate_class, "%invalidate-class", 1, 0, 0,
1521 (SCM class),
1522 "")
1523 #define FUNC_NAME s_scm_sys_invalidate_class
1524 {
1525 SCM_VALIDATE_CLASS (1, class);
1526 SCM_CLEAR_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_VALID);
1527 return SCM_UNSPECIFIED;
1528 }
1529 #undef FUNC_NAME
1530
1531 /* When instances change class, they finally get a new body, but
1532 * before that, they go through purgatory in hell. Odd as it may
1533 * seem, this data structure saves us from eternal suffering in
1534 * infinite recursions.
1535 */
1536
1537 static scm_t_bits **hell;
1538 static long n_hell = 1; /* one place for the evil one himself */
1539 static long hell_size = 4;
1540 static SCM hell_mutex;
1541
1542 static long
1543 burnin (SCM o)
1544 {
1545 long i;
1546 for (i = 1; i < n_hell; ++i)
1547 if (SCM_STRUCT_DATA (o) == hell[i])
1548 return i;
1549 return 0;
1550 }
1551
1552 static void
1553 go_to_hell (void *o)
1554 {
1555 SCM obj = *(SCM*)o;
1556 scm_lock_mutex (hell_mutex);
1557 if (n_hell >= hell_size)
1558 {
1559 hell_size *= 2;
1560 hell = scm_realloc (hell, hell_size * sizeof(*hell));
1561 }
1562 hell[n_hell++] = SCM_STRUCT_DATA (obj);
1563 scm_unlock_mutex (hell_mutex);
1564 }
1565
1566 static void
1567 go_to_heaven (void *o)
1568 {
1569 SCM obj = *(SCM*)o;
1570 scm_lock_mutex (hell_mutex);
1571 hell[burnin (obj)] = hell[--n_hell];
1572 scm_unlock_mutex (hell_mutex);
1573 }
1574
1575
1576 SCM_SYMBOL (scm_sym_change_class, "change-class");
1577
1578 static SCM
1579 purgatory (SCM obj, SCM new_class)
1580 {
1581 return scm_call_2 (SCM_VARIABLE_REF (var_change_class), obj, new_class);
1582 }
1583
1584 /* This function calls the generic function change-class for all
1585 * instances which aren't currently undergoing class change.
1586 */
1587
1588 void
1589 scm_change_object_class (SCM obj, SCM old_class SCM_UNUSED, SCM new_class)
1590 {
1591 if (!burnin (obj))
1592 {
1593 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
1594 scm_dynwind_rewind_handler (go_to_hell, &obj, SCM_F_WIND_EXPLICITLY);
1595 scm_dynwind_unwind_handler (go_to_heaven, &obj, SCM_F_WIND_EXPLICITLY);
1596 purgatory (obj, new_class);
1597 scm_dynwind_end ();
1598 }
1599 }
1600
1601 /******************************************************************************
1602 *
1603 * GGGG FFFFF
1604 * G F
1605 * G GG FFF
1606 * G G F
1607 * GGG E N E R I C F U N C T I O N S
1608 *
1609 * This implementation provides
1610 * - generic functions (with class specializers)
1611 * - multi-methods
1612 * - next-method
1613 * - a hard-coded MOP for standard gf, which can be overloaded for non-std gf
1614 *
1615 ******************************************************************************/
1616
1617 SCM_KEYWORD (k_name, "name");
1618
1619 SCM_GLOBAL_SYMBOL (scm_sym_args, "args");
1620
1621 SCM_SYMBOL (sym_delayed_compile, "delayed-compile");
1622
1623 static SCM delayed_compile_var;
1624
1625 static void
1626 init_delayed_compile_var (void)
1627 {
1628 delayed_compile_var
1629 = scm_c_private_lookup ("oop goops dispatch", "delayed-compile");
1630 }
1631
1632 static SCM
1633 make_dispatch_procedure (SCM gf)
1634 {
1635 static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
1636 scm_i_pthread_once (&once, init_delayed_compile_var);
1637
1638 return scm_call_1 (scm_variable_ref (delayed_compile_var), gf);
1639 }
1640
1641 static void
1642 clear_method_cache (SCM gf)
1643 {
1644 SCM_SET_GENERIC_DISPATCH_PROCEDURE (gf, make_dispatch_procedure (gf));
1645 SCM_CLEAR_GENERIC_EFFECTIVE_METHODS (gf);
1646 }
1647
1648 SCM_DEFINE (scm_sys_invalidate_method_cache_x, "%invalidate-method-cache!", 1, 0, 0,
1649 (SCM gf),
1650 "")
1651 #define FUNC_NAME s_scm_sys_invalidate_method_cache_x
1652 {
1653 SCM_ASSERT (SCM_PUREGENERICP (gf), gf, SCM_ARG1, FUNC_NAME);
1654 clear_method_cache (gf);
1655 return SCM_UNSPECIFIED;
1656 }
1657 #undef FUNC_NAME
1658
1659 SCM_DEFINE (scm_generic_capability_p, "generic-capability?", 1, 0, 0,
1660 (SCM proc),
1661 "")
1662 #define FUNC_NAME s_scm_generic_capability_p
1663 {
1664 SCM_ASSERT (scm_is_true (scm_procedure_p (proc)),
1665 proc, SCM_ARG1, FUNC_NAME);
1666 return (SCM_PRIMITIVE_GENERIC_P (proc) ? SCM_BOOL_T : SCM_BOOL_F);
1667 }
1668 #undef FUNC_NAME
1669
1670 SCM_DEFINE (scm_enable_primitive_generic_x, "enable-primitive-generic!", 0, 0, 1,
1671 (SCM subrs),
1672 "")
1673 #define FUNC_NAME s_scm_enable_primitive_generic_x
1674 {
1675 SCM_VALIDATE_REST_ARGUMENT (subrs);
1676 while (!scm_is_null (subrs))
1677 {
1678 SCM subr = SCM_CAR (subrs);
1679 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARGn, FUNC_NAME);
1680 SCM_SET_SUBR_GENERIC (subr,
1681 scm_make (scm_list_3 (scm_class_generic,
1682 k_name,
1683 SCM_SUBR_NAME (subr))));
1684 subrs = SCM_CDR (subrs);
1685 }
1686 return SCM_UNSPECIFIED;
1687 }
1688 #undef FUNC_NAME
1689
1690 SCM_DEFINE (scm_set_primitive_generic_x, "set-primitive-generic!", 2, 0, 0,
1691 (SCM subr, SCM generic),
1692 "")
1693 #define FUNC_NAME s_scm_set_primitive_generic_x
1694 {
1695 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARG1, FUNC_NAME);
1696 SCM_ASSERT (SCM_PUREGENERICP (generic), generic, SCM_ARG2, FUNC_NAME);
1697 SCM_SET_SUBR_GENERIC (subr, generic);
1698 return SCM_UNSPECIFIED;
1699 }
1700 #undef FUNC_NAME
1701
1702 SCM_DEFINE (scm_primitive_generic_generic, "primitive-generic-generic", 1, 0, 0,
1703 (SCM subr),
1704 "")
1705 #define FUNC_NAME s_scm_primitive_generic_generic
1706 {
1707 if (SCM_PRIMITIVE_GENERIC_P (subr))
1708 {
1709 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (subr)))
1710 scm_enable_primitive_generic_x (scm_list_1 (subr));
1711 return *SCM_SUBR_GENERIC (subr);
1712 }
1713 SCM_WRONG_TYPE_ARG (SCM_ARG1, subr);
1714 }
1715 #undef FUNC_NAME
1716
1717 typedef struct t_extension {
1718 struct t_extension *next;
1719 SCM extended;
1720 SCM extension;
1721 } t_extension;
1722
1723
1724 /* Hint for `scm_gc_malloc ()' et al. when allocating `t_extension'
1725 objects. */
1726 static const char extension_gc_hint[] = "GOOPS extension";
1727
1728 static t_extension *extensions = 0;
1729
1730 void
1731 scm_c_extend_primitive_generic (SCM extended, SCM extension)
1732 {
1733 if (goops_loaded_p)
1734 {
1735 SCM gf, gext;
1736 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (extended)))
1737 scm_enable_primitive_generic_x (scm_list_1 (extended));
1738 gf = *SCM_SUBR_GENERIC (extended);
1739 gext = scm_call_2 (SCM_VARIABLE_REF (scm_var_make_extended_generic),
1740 gf,
1741 SCM_SUBR_NAME (extension));
1742 SCM_SET_SUBR_GENERIC (extension, gext);
1743 }
1744 else
1745 {
1746 t_extension *e = scm_gc_malloc (sizeof (t_extension),
1747 extension_gc_hint);
1748 t_extension **loc = &extensions;
1749 /* Make sure that extensions are placed before their own
1750 * extensions in the extensions list. O(N^2) algorithm, but
1751 * extensions of primitive generics are rare.
1752 */
1753 while (*loc && !scm_is_eq (extension, (*loc)->extended))
1754 loc = &(*loc)->next;
1755 e->next = *loc;
1756 e->extended = extended;
1757 e->extension = extension;
1758 *loc = e;
1759 }
1760 }
1761
1762 static void
1763 setup_extended_primitive_generics ()
1764 {
1765 while (extensions)
1766 {
1767 t_extension *e = extensions;
1768 scm_c_extend_primitive_generic (e->extended, e->extension);
1769 extensions = e->next;
1770 }
1771 }
1772
1773 /* Dirk:FIXME:: In all of these scm_wta_dispatch_* routines it is
1774 * assumed that 'gf' is zero if uninitialized. It would be cleaner if
1775 * some valid SCM value like SCM_BOOL_F or SCM_UNDEFINED were chosen.
1776 */
1777
1778 SCM
1779 scm_wta_dispatch_0 (SCM gf, const char *subr)
1780 {
1781 if (!SCM_UNPACK (gf))
1782 scm_error_num_args_subr (subr);
1783
1784 return scm_call_0 (gf);
1785 }
1786
1787 SCM
1788 scm_wta_dispatch_1 (SCM gf, SCM a1, int pos, const char *subr)
1789 {
1790 if (!SCM_UNPACK (gf))
1791 scm_wrong_type_arg (subr, pos, a1);
1792
1793 return scm_call_1 (gf, a1);
1794 }
1795
1796 SCM
1797 scm_wta_dispatch_2 (SCM gf, SCM a1, SCM a2, int pos, const char *subr)
1798 {
1799 if (!SCM_UNPACK (gf))
1800 scm_wrong_type_arg (subr, pos, (pos == SCM_ARG1) ? a1 : a2);
1801
1802 return scm_call_2 (gf, a1, a2);
1803 }
1804
1805 SCM
1806 scm_wta_dispatch_n (SCM gf, SCM args, int pos, const char *subr)
1807 {
1808 if (!SCM_UNPACK (gf))
1809 scm_wrong_type_arg (subr, pos, scm_list_ref (args, scm_from_int (pos)));
1810
1811 return scm_apply_0 (gf, args);
1812 }
1813
1814 /******************************************************************************
1815 *
1816 * Protocol for calling a generic fumction
1817 * This protocol is roughly equivalent to (parameter are a little bit different
1818 * for efficiency reasons):
1819 *
1820 * + apply-generic (gf args)
1821 * + compute-applicable-methods (gf args ...)
1822 * + sort-applicable-methods (methods args)
1823 * + apply-methods (gf methods args)
1824 *
1825 * apply-methods calls make-next-method to build the "continuation" of a a
1826 * method. Applying a next-method will call apply-next-method which in
1827 * turn will call apply again to call effectively the following method.
1828 *
1829 ******************************************************************************/
1830
1831 /******************************************************************************
1832 *
1833 * A simple make (which will be redefined later in Scheme)
1834 * This version handles only creation of gf, methods and classes (no instances)
1835 *
1836 * Since this code will disappear when Goops will be fully booted,
1837 * no precaution is taken to be efficient.
1838 *
1839 ******************************************************************************/
1840
1841 SCM_KEYWORD (k_setter, "setter");
1842 SCM_KEYWORD (k_specializers, "specializers");
1843 SCM_KEYWORD (k_procedure, "procedure");
1844 SCM_KEYWORD (k_formals, "formals");
1845 SCM_KEYWORD (k_body, "body");
1846 SCM_KEYWORD (k_make_procedure, "make-procedure");
1847 SCM_KEYWORD (k_dsupers, "dsupers");
1848 SCM_KEYWORD (k_slots, "slots");
1849 SCM_KEYWORD (k_gf, "generic-function");
1850
1851 SCM_DEFINE (scm_make, "make", 0, 0, 1,
1852 (SCM args),
1853 "Make a new object. @var{args} must contain the class and\n"
1854 "all necessary initialization information.")
1855 #define FUNC_NAME s_scm_make
1856 {
1857 SCM class, z;
1858 long len = scm_ilength (args);
1859
1860 if (len <= 0 || (len & 1) == 0)
1861 SCM_WRONG_NUM_ARGS ();
1862
1863 class = SCM_CAR(args);
1864 args = SCM_CDR(args);
1865
1866 if (scm_is_eq (class, scm_class_generic)
1867 || scm_is_eq (class, scm_class_accessor))
1868 {
1869 z = scm_make_struct (class, SCM_INUM0,
1870 scm_list_4 (SCM_BOOL_F,
1871 SCM_EOL,
1872 SCM_INUM0,
1873 SCM_EOL));
1874 scm_set_procedure_property_x (z, scm_sym_name,
1875 scm_get_keyword (k_name,
1876 args,
1877 SCM_BOOL_F));
1878 clear_method_cache (z);
1879 if (scm_is_eq (class, scm_class_accessor))
1880 {
1881 SCM setter = scm_get_keyword (k_setter, args, SCM_BOOL_F);
1882 if (scm_is_true (setter))
1883 scm_sys_set_object_setter_x (z, setter);
1884 }
1885 }
1886 else
1887 {
1888 z = scm_sys_allocate_instance (class, args);
1889
1890 if (scm_is_eq (class, scm_class_method)
1891 || scm_is_eq (class, scm_class_accessor_method))
1892 {
1893 SCM_SET_SLOT (z, scm_si_generic_function,
1894 scm_i_get_keyword (k_gf,
1895 args,
1896 len - 1,
1897 SCM_BOOL_F,
1898 FUNC_NAME));
1899 SCM_SET_SLOT (z, scm_si_specializers,
1900 scm_i_get_keyword (k_specializers,
1901 args,
1902 len - 1,
1903 SCM_EOL,
1904 FUNC_NAME));
1905 SCM_SET_SLOT (z, scm_si_procedure,
1906 scm_i_get_keyword (k_procedure,
1907 args,
1908 len - 1,
1909 SCM_BOOL_F,
1910 FUNC_NAME));
1911 SCM_SET_SLOT (z, scm_si_formals,
1912 scm_i_get_keyword (k_formals,
1913 args,
1914 len - 1,
1915 SCM_EOL,
1916 FUNC_NAME));
1917 SCM_SET_SLOT (z, scm_si_body,
1918 scm_i_get_keyword (k_body,
1919 args,
1920 len - 1,
1921 SCM_EOL,
1922 FUNC_NAME));
1923 SCM_SET_SLOT (z, scm_si_make_procedure,
1924 scm_i_get_keyword (k_make_procedure,
1925 args,
1926 len - 1,
1927 SCM_BOOL_F,
1928 FUNC_NAME));
1929 }
1930 else
1931 {
1932 /* In all the others case, make a new class .... No instance here */
1933 SCM_SET_SLOT (z, scm_vtable_index_name,
1934 scm_i_get_keyword (k_name,
1935 args,
1936 len - 1,
1937 scm_from_latin1_symbol ("???"),
1938 FUNC_NAME));
1939 SCM_SET_SLOT (z, scm_si_direct_supers,
1940 scm_i_get_keyword (k_dsupers,
1941 args,
1942 len - 1,
1943 SCM_EOL,
1944 FUNC_NAME));
1945 SCM_SET_SLOT (z, scm_si_direct_slots,
1946 scm_i_get_keyword (k_slots,
1947 args,
1948 len - 1,
1949 SCM_EOL,
1950 FUNC_NAME));
1951 }
1952 }
1953 return z;
1954 }
1955 #undef FUNC_NAME
1956
1957
1958 /******************************************************************************
1959 *
1960 * Initializations
1961 *
1962 ******************************************************************************/
1963
1964 static void
1965 make_stdcls (SCM *var, char *name, SCM meta, SCM super, SCM slots)
1966 {
1967 SCM tmp = scm_from_utf8_symbol (name);
1968
1969 *var = scm_basic_make_class (meta, tmp,
1970 scm_is_pair (super) ? super : scm_list_1 (super),
1971 slots);
1972 scm_module_define (scm_module_goops, tmp, *var);
1973 }
1974
1975
1976 SCM_KEYWORD (k_slot_definition, "slot-definition");
1977
1978 static void
1979 create_standard_classes (void)
1980 {
1981 SCM slots;
1982 SCM method_slots = scm_list_n (scm_from_latin1_symbol ("generic-function"),
1983 scm_from_latin1_symbol ("specializers"),
1984 sym_procedure,
1985 scm_from_latin1_symbol ("formals"),
1986 scm_from_latin1_symbol ("body"),
1987 scm_from_latin1_symbol ("make-procedure"),
1988 SCM_UNDEFINED);
1989 SCM amethod_slots = scm_list_1 (scm_list_3 (scm_from_latin1_symbol ("slot-definition"),
1990 k_init_keyword,
1991 k_slot_definition));
1992 SCM gf_slots = scm_list_4 (scm_from_latin1_symbol ("methods"),
1993 scm_list_3 (scm_from_latin1_symbol ("n-specialized"),
1994 k_init_value,
1995 SCM_INUM0),
1996 scm_list_3 (scm_from_latin1_symbol ("extended-by"),
1997 k_init_value,
1998 SCM_EOL),
1999 scm_from_latin1_symbol ("effective-methods"));
2000 SCM setter_slots = scm_list_1 (sym_setter);
2001 SCM egf_slots = scm_list_1 (scm_list_3 (scm_from_latin1_symbol ("extends"),
2002 k_init_value,
2003 SCM_EOL));
2004 /* Foreign class slot classes */
2005 make_stdcls (&scm_class_foreign_slot, "<foreign-slot>",
2006 scm_class_class, scm_class_top, SCM_EOL);
2007 make_stdcls (&scm_class_protected, "<protected-slot>",
2008 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2009 make_stdcls (&scm_class_hidden, "<hidden-slot>",
2010 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2011 make_stdcls (&scm_class_opaque, "<opaque-slot>",
2012 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2013 make_stdcls (&scm_class_read_only, "<read-only-slot>",
2014 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2015 make_stdcls (&scm_class_self, "<self-slot>",
2016 scm_class_class, scm_class_read_only, SCM_EOL);
2017 make_stdcls (&scm_class_protected_opaque, "<protected-opaque-slot>",
2018 scm_class_class,
2019 scm_list_2 (scm_class_protected, scm_class_opaque),
2020 SCM_EOL);
2021 make_stdcls (&scm_class_protected_hidden, "<protected-hidden-slot>",
2022 scm_class_class,
2023 scm_list_2 (scm_class_protected, scm_class_hidden),
2024 SCM_EOL);
2025 make_stdcls (&scm_class_protected_read_only, "<protected-read-only-slot>",
2026 scm_class_class,
2027 scm_list_2 (scm_class_protected, scm_class_read_only),
2028 SCM_EOL);
2029 make_stdcls (&scm_class_scm, "<scm-slot>",
2030 scm_class_class, scm_class_protected, SCM_EOL);
2031 make_stdcls (&scm_class_int, "<int-slot>",
2032 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2033 make_stdcls (&scm_class_float, "<float-slot>",
2034 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2035 make_stdcls (&scm_class_double, "<double-slot>",
2036 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2037
2038 specialized_slots_initialized = 1;
2039
2040 /* Finish initialization of class <class> */
2041
2042 slots = build_class_class_slots (FINAL_SLOTS);
2043 SCM_SET_SLOT (scm_class_class, scm_si_direct_slots, slots);
2044 SCM_SET_SLOT (scm_class_class, scm_si_slots, slots);
2045 SCM_SET_SLOT (scm_class_class, scm_si_getters_n_setters,
2046 compute_getters_n_setters (slots));
2047
2048 /* scm_class_generic functions classes */
2049 make_stdcls (&scm_class_procedure_class, "<procedure-class>",
2050 scm_class_class, scm_class_class, SCM_EOL);
2051 make_stdcls (&scm_class_applicable_struct_class, "<applicable-struct-class>",
2052 scm_class_class, scm_class_procedure_class, SCM_EOL);
2053 SCM_SET_VTABLE_FLAGS (scm_class_applicable_struct_class, SCM_VTABLE_FLAG_APPLICABLE_VTABLE);
2054 make_stdcls (&scm_class_method, "<method>",
2055 scm_class_class, scm_class_object, method_slots);
2056 make_stdcls (&scm_class_accessor_method, "<accessor-method>",
2057 scm_class_class, scm_class_method, amethod_slots);
2058 make_stdcls (&scm_class_applicable, "<applicable>",
2059 scm_class_class, scm_class_top, SCM_EOL);
2060 make_stdcls (&scm_class_applicable_struct, "<applicable-struct>",
2061 scm_class_applicable_struct_class,
2062 scm_list_2 (scm_class_object, scm_class_applicable),
2063 scm_list_1 (sym_procedure));
2064 make_stdcls (&scm_class_generic, "<generic>",
2065 scm_class_applicable_struct_class, scm_class_applicable_struct, gf_slots);
2066 SCM_SET_CLASS_FLAGS (scm_class_generic, SCM_CLASSF_PURE_GENERIC);
2067 make_stdcls (&scm_class_extended_generic, "<extended-generic>",
2068 scm_class_applicable_struct_class, scm_class_generic, egf_slots);
2069 SCM_SET_CLASS_FLAGS (scm_class_extended_generic, SCM_CLASSF_PURE_GENERIC);
2070 make_stdcls (&scm_class_generic_with_setter, "<generic-with-setter>",
2071 scm_class_applicable_struct_class, scm_class_generic, setter_slots);
2072 SCM_SET_CLASS_FLAGS (scm_class_generic_with_setter, SCM_CLASSF_PURE_GENERIC);
2073 make_stdcls (&scm_class_accessor, "<accessor>",
2074 scm_class_applicable_struct_class, scm_class_generic_with_setter, SCM_EOL);
2075 SCM_SET_CLASS_FLAGS (scm_class_accessor, SCM_CLASSF_PURE_GENERIC);
2076 make_stdcls (&scm_class_extended_generic_with_setter,
2077 "<extended-generic-with-setter>",
2078 scm_class_applicable_struct_class,
2079 scm_list_2 (scm_class_extended_generic,
2080 scm_class_generic_with_setter),
2081 SCM_EOL);
2082 SCM_SET_CLASS_FLAGS (scm_class_extended_generic_with_setter,
2083 SCM_CLASSF_PURE_GENERIC);
2084 make_stdcls (&scm_class_extended_accessor, "<extended-accessor>",
2085 scm_class_applicable_struct_class,
2086 scm_list_2 (scm_class_accessor,
2087 scm_class_extended_generic_with_setter),
2088 SCM_EOL);
2089 SCM_SET_CLASS_FLAGS (scm_class_extended_accessor, SCM_CLASSF_PURE_GENERIC);
2090
2091 /* Primitive types classes */
2092 make_stdcls (&scm_class_boolean, "<boolean>",
2093 scm_class_class, scm_class_top, SCM_EOL);
2094 make_stdcls (&scm_class_char, "<char>",
2095 scm_class_class, scm_class_top, SCM_EOL);
2096 make_stdcls (&scm_class_list, "<list>",
2097 scm_class_class, scm_class_top, SCM_EOL);
2098 make_stdcls (&scm_class_pair, "<pair>",
2099 scm_class_class, scm_class_list, SCM_EOL);
2100 make_stdcls (&scm_class_null, "<null>",
2101 scm_class_class, scm_class_list, SCM_EOL);
2102 make_stdcls (&scm_class_string, "<string>",
2103 scm_class_class, scm_class_top, SCM_EOL);
2104 make_stdcls (&scm_class_symbol, "<symbol>",
2105 scm_class_class, scm_class_top, SCM_EOL);
2106 make_stdcls (&scm_class_vector, "<vector>",
2107 scm_class_class, scm_class_top, SCM_EOL);
2108 make_stdcls (&class_foreign, "<foreign>",
2109 scm_class_class, scm_class_top, SCM_EOL);
2110 make_stdcls (&class_hashtable, "<hashtable>",
2111 scm_class_class, scm_class_top, SCM_EOL);
2112 make_stdcls (&class_fluid, "<fluid>",
2113 scm_class_class, scm_class_top, SCM_EOL);
2114 make_stdcls (&class_dynamic_state, "<dynamic-state>",
2115 scm_class_class, scm_class_top, SCM_EOL);
2116 make_stdcls (&class_frame, "<frame>",
2117 scm_class_class, scm_class_top, SCM_EOL);
2118 make_stdcls (&class_vm_cont, "<vm-continuation>",
2119 scm_class_class, scm_class_top, SCM_EOL);
2120 make_stdcls (&class_bytevector, "<bytevector>",
2121 scm_class_class, scm_class_top, SCM_EOL);
2122 make_stdcls (&class_uvec, "<uvec>",
2123 scm_class_class, class_bytevector, SCM_EOL);
2124 make_stdcls (&class_array, "<array>",
2125 scm_class_class, scm_class_top, SCM_EOL);
2126 make_stdcls (&class_bitvector, "<bitvector>",
2127 scm_class_class, scm_class_top, SCM_EOL);
2128 make_stdcls (&scm_class_number, "<number>",
2129 scm_class_class, scm_class_top, SCM_EOL);
2130 make_stdcls (&scm_class_complex, "<complex>",
2131 scm_class_class, scm_class_number, SCM_EOL);
2132 make_stdcls (&scm_class_real, "<real>",
2133 scm_class_class, scm_class_complex, SCM_EOL);
2134 make_stdcls (&scm_class_integer, "<integer>",
2135 scm_class_class, scm_class_real, SCM_EOL);
2136 make_stdcls (&scm_class_fraction, "<fraction>",
2137 scm_class_class, scm_class_real, SCM_EOL);
2138 make_stdcls (&scm_class_keyword, "<keyword>",
2139 scm_class_class, scm_class_top, SCM_EOL);
2140 make_stdcls (&scm_class_unknown, "<unknown>",
2141 scm_class_class, scm_class_top, SCM_EOL);
2142 make_stdcls (&scm_class_procedure, "<procedure>",
2143 scm_class_procedure_class, scm_class_applicable, SCM_EOL);
2144 make_stdcls (&scm_class_primitive_generic, "<primitive-generic>",
2145 scm_class_procedure_class, scm_class_procedure, SCM_EOL);
2146 make_stdcls (&scm_class_port, "<port>",
2147 scm_class_class, scm_class_top, SCM_EOL);
2148 make_stdcls (&scm_class_input_port, "<input-port>",
2149 scm_class_class, scm_class_port, SCM_EOL);
2150 make_stdcls (&scm_class_output_port, "<output-port>",
2151 scm_class_class, scm_class_port, SCM_EOL);
2152 make_stdcls (&scm_class_input_output_port, "<input-output-port>",
2153 scm_class_class,
2154 scm_list_2 (scm_class_input_port, scm_class_output_port),
2155 SCM_EOL);
2156 }
2157
2158 /**********************************************************************
2159 *
2160 * Smob classes
2161 *
2162 **********************************************************************/
2163
2164 static SCM
2165 make_class_from_template (char const *template, char const *type_name, SCM supers, int applicablep)
2166 {
2167 SCM name;
2168 if (type_name)
2169 {
2170 char buffer[100];
2171 sprintf (buffer, template, type_name);
2172 name = scm_from_utf8_symbol (buffer);
2173 }
2174 else
2175 name = SCM_GOOPS_UNBOUND;
2176
2177 return scm_basic_make_class (applicablep ? scm_class_procedure_class : scm_class_class,
2178 name, supers, SCM_EOL);
2179 }
2180
2181 static SCM
2182 make_class_from_symbol (SCM type_name_sym, SCM supers, int applicablep)
2183 {
2184 SCM name;
2185
2186 if (scm_is_true (type_name_sym))
2187 {
2188 name = scm_string_append (scm_list_3 (scm_from_locale_string ("<"),
2189 scm_symbol_to_string (type_name_sym),
2190 scm_from_locale_string (">")));
2191 name = scm_string_to_symbol (name);
2192 }
2193 else
2194 name = SCM_GOOPS_UNBOUND;
2195
2196 return scm_basic_make_class (applicablep ? scm_class_procedure_class : scm_class_class,
2197 name, supers, SCM_EOL);
2198 }
2199
2200 SCM
2201 scm_make_extended_class (char const *type_name, int applicablep)
2202 {
2203 return make_class_from_template ("<%s>",
2204 type_name,
2205 scm_list_1 (applicablep
2206 ? scm_class_applicable
2207 : scm_class_top),
2208 applicablep);
2209 }
2210
2211 static SCM
2212 scm_make_extended_class_from_symbol (SCM type_name_sym, int applicablep)
2213 {
2214 return make_class_from_symbol (type_name_sym,
2215 scm_list_1 (applicablep
2216 ? scm_class_applicable
2217 : scm_class_top),
2218 applicablep);
2219 }
2220
2221 void
2222 scm_i_inherit_applicable (SCM c)
2223 {
2224 if (!SCM_SUBCLASSP (c, scm_class_applicable))
2225 {
2226 SCM dsupers = SCM_SLOT (c, scm_si_direct_supers);
2227 SCM cpl = SCM_SLOT (c, scm_si_cpl);
2228 /* patch scm_class_applicable into direct-supers */
2229 SCM top = scm_c_memq (scm_class_top, dsupers);
2230 if (scm_is_false (top))
2231 dsupers = scm_append (scm_list_2 (dsupers,
2232 scm_list_1 (scm_class_applicable)));
2233 else
2234 {
2235 SCM_SETCAR (top, scm_class_applicable);
2236 SCM_SETCDR (top, scm_cons (scm_class_top, SCM_CDR (top)));
2237 }
2238 SCM_SET_SLOT (c, scm_si_direct_supers, dsupers);
2239 /* patch scm_class_applicable into cpl */
2240 top = scm_c_memq (scm_class_top, cpl);
2241 if (scm_is_false (top))
2242 abort ();
2243 else
2244 {
2245 SCM_SETCAR (top, scm_class_applicable);
2246 SCM_SETCDR (top, scm_cons (scm_class_top, SCM_CDR (top)));
2247 }
2248 /* add class to direct-subclasses of scm_class_applicable */
2249 SCM_SET_SLOT (scm_class_applicable,
2250 scm_si_direct_subclasses,
2251 scm_cons (c, SCM_SLOT (scm_class_applicable,
2252 scm_si_direct_subclasses)));
2253 }
2254 }
2255
2256 static void
2257 create_smob_classes (void)
2258 {
2259 long i;
2260
2261 for (i = 0; i < SCM_I_MAX_SMOB_TYPE_COUNT; ++i)
2262 scm_smob_class[i] = SCM_BOOL_F;
2263
2264 for (i = 0; i < scm_numsmob; ++i)
2265 if (scm_is_false (scm_smob_class[i]))
2266 scm_smob_class[i] = scm_make_extended_class (SCM_SMOBNAME (i),
2267 scm_smobs[i].apply != 0);
2268 }
2269
2270 void
2271 scm_make_port_classes (long ptobnum, char *type_name)
2272 {
2273 SCM c, class = make_class_from_template ("<%s-port>",
2274 type_name,
2275 scm_list_1 (scm_class_port),
2276 0);
2277 scm_port_class[SCM_IN_PCLASS_INDEX + ptobnum]
2278 = make_class_from_template ("<%s-input-port>",
2279 type_name,
2280 scm_list_2 (class, scm_class_input_port),
2281 0);
2282 scm_port_class[SCM_OUT_PCLASS_INDEX + ptobnum]
2283 = make_class_from_template ("<%s-output-port>",
2284 type_name,
2285 scm_list_2 (class, scm_class_output_port),
2286 0);
2287 scm_port_class[SCM_INOUT_PCLASS_INDEX + ptobnum]
2288 = c
2289 = make_class_from_template ("<%s-input-output-port>",
2290 type_name,
2291 scm_list_2 (class, scm_class_input_output_port),
2292 0);
2293 /* Patch cpl (since this tree is too complex for the C level compute-cpl) */
2294 SCM_SET_SLOT (c, scm_si_cpl,
2295 scm_cons2 (c, class, SCM_SLOT (scm_class_input_output_port, scm_si_cpl)));
2296 }
2297
2298 static void
2299 create_port_classes (void)
2300 {
2301 long i;
2302
2303 for (i = scm_c_num_port_types () - 1; i >= 0; i--)
2304 scm_make_port_classes (i, SCM_PTOBNAME (i));
2305 }
2306
2307 static SCM
2308 make_struct_class (void *closure SCM_UNUSED,
2309 SCM vtable, SCM data, SCM prev SCM_UNUSED)
2310 {
2311 if (scm_is_false (data))
2312 scm_i_define_class_for_vtable (vtable);
2313 return SCM_UNSPECIFIED;
2314 }
2315
2316 static void
2317 create_struct_classes (void)
2318 {
2319 /* FIXME: take the vtable_class_map while initializing goops? */
2320 scm_internal_hash_fold (make_struct_class, 0, SCM_BOOL_F,
2321 vtable_class_map);
2322 }
2323
2324 /**********************************************************************
2325 *
2326 * C interface
2327 *
2328 **********************************************************************/
2329
2330 void
2331 scm_load_goops ()
2332 {
2333 if (!goops_loaded_p)
2334 scm_c_resolve_module ("oop goops");
2335 }
2336
2337
2338 SCM_SYMBOL (sym_o, "o");
2339 SCM_SYMBOL (sym_x, "x");
2340
2341 SCM_KEYWORD (k_accessor, "accessor");
2342 SCM_KEYWORD (k_getter, "getter");
2343
2344 SCM
2345 scm_ensure_accessor (SCM name)
2346 {
2347 SCM var, gf;
2348
2349 var = scm_module_variable (scm_current_module (), name);
2350 if (SCM_VARIABLEP (var) && !SCM_UNBNDP (SCM_VARIABLE_REF (var)))
2351 gf = SCM_VARIABLE_REF (var);
2352 else
2353 gf = SCM_BOOL_F;
2354
2355 if (!SCM_IS_A_P (gf, scm_class_accessor))
2356 {
2357 gf = scm_make (scm_list_3 (scm_class_generic, k_name, name));
2358 gf = scm_make (scm_list_5 (scm_class_accessor,
2359 k_name, name, k_setter, gf));
2360 }
2361
2362 return gf;
2363 }
2364
2365 #ifdef GUILE_DEBUG
2366 /*
2367 * Debugging utilities
2368 */
2369
2370 SCM_DEFINE (scm_pure_generic_p, "pure-generic?", 1, 0, 0,
2371 (SCM obj),
2372 "Return @code{#t} if @var{obj} is a pure generic.")
2373 #define FUNC_NAME s_scm_pure_generic_p
2374 {
2375 return scm_from_bool (SCM_PUREGENERICP (obj));
2376 }
2377 #undef FUNC_NAME
2378
2379 #endif /* GUILE_DEBUG */
2380
2381 /*
2382 * Initialization
2383 */
2384
2385 SCM_DEFINE (scm_sys_goops_early_init, "%goops-early-init", 0, 0, 0,
2386 (),
2387 "")
2388 #define FUNC_NAME s_scm_sys_goops_early_init
2389 {
2390 create_basic_classes ();
2391 create_standard_classes ();
2392 create_smob_classes ();
2393 create_struct_classes ();
2394 create_port_classes ();
2395
2396 {
2397 SCM name = scm_from_latin1_symbol ("no-applicable-method");
2398 scm_no_applicable_method =
2399 scm_make (scm_list_3 (scm_class_generic, k_name, name));
2400 scm_module_define (scm_module_goops, name, scm_no_applicable_method);
2401 }
2402
2403 return SCM_UNSPECIFIED;
2404 }
2405 #undef FUNC_NAME
2406
2407 SCM_DEFINE (scm_sys_goops_loaded, "%goops-loaded", 0, 0, 0,
2408 (),
2409 "Announce that GOOPS is loaded and perform initialization\n"
2410 "on the C level which depends on the loaded GOOPS modules.")
2411 #define FUNC_NAME s_scm_sys_goops_loaded
2412 {
2413 goops_loaded_p = 1;
2414 var_slot_unbound =
2415 scm_module_variable (scm_module_goops, sym_slot_unbound);
2416 var_slot_missing =
2417 scm_module_variable (scm_module_goops, sym_slot_missing);
2418 var_no_applicable_method =
2419 scm_module_variable (scm_module_goops, sym_no_applicable_method);
2420 var_change_class =
2421 scm_module_variable (scm_module_goops, sym_change_class);
2422 setup_extended_primitive_generics ();
2423 return SCM_UNSPECIFIED;
2424 }
2425 #undef FUNC_NAME
2426
2427 SCM scm_module_goops;
2428
2429 static void
2430 scm_init_goops_builtins (void *unused)
2431 {
2432 scm_module_goops = scm_current_module ();
2433
2434 goops_rstate = scm_c_make_rstate ("GOOPS", 5);
2435
2436 hell = scm_calloc (hell_size * sizeof (*hell));
2437 hell_mutex = scm_make_mutex ();
2438
2439 #include "libguile/goops.x"
2440
2441 var_compute_cpl =
2442 scm_module_variable (scm_module_goops, sym_compute_cpl);
2443 }
2444
2445 void
2446 scm_init_goops ()
2447 {
2448 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
2449 "scm_init_goops_builtins", scm_init_goops_builtins,
2450 NULL);
2451 }
2452
2453 /*
2454 Local Variables:
2455 c-file-style: "gnu"
2456 End:
2457 */