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