<class> accessors implemented in Scheme
[bpt/guile.git] / libguile / goops.c
CommitLineData
e2fafeb9 1/* Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2008,2009,2010,2011,2012,2013,2014,2015
366ecaec 2 * Free Software Foundation, Inc.
6d77c894 3 *
73be1d9e 4 * This library is free software; you can redistribute it and/or
53befeb7
NJ
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.
6d77c894 8 *
53befeb7
NJ
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
6d77c894 13 *
73be1d9e
MV
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
53befeb7
NJ
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA
73be1d9e 18 */
80662eda
MD
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
dbb605f5
LC
28#ifdef HAVE_CONFIG_H
29# include <config.h>
30#endif
31
80662eda 32#include "libguile/_scm.h"
4e047c3e 33#include "libguile/async.h"
539d5410 34#include "libguile/chars.h"
80662eda
MD
35#include "libguile/dynwind.h"
36#include "libguile/eval.h"
9fdf9fd3 37#include "libguile/gsubr.h"
80662eda
MD
38#include "libguile/hashtab.h"
39#include "libguile/keywords.h"
40#include "libguile/macros.h"
41#include "libguile/modules.h"
80662eda
MD
42#include "libguile/ports.h"
43#include "libguile/procprop.h"
efcebb5b 44#include "libguile/programs.h"
80662eda
MD
45#include "libguile/smob.h"
46#include "libguile/strings.h"
47#include "libguile/strports.h"
48#include "libguile/vectors.h"
80662eda 49
ca83b028 50#include "libguile/validate.h"
80662eda
MD
51#include "libguile/goops.h"
52
efcebb5b
AW
53/* Port classes */
54#define SCM_IN_PCLASS_INDEX 0
55#define SCM_OUT_PCLASS_INDEX SCM_I_MAX_PORT_TYPE_COUNT
56#define SCM_INOUT_PCLASS_INDEX (2 * SCM_I_MAX_PORT_TYPE_COUNT)
57
51fd1cd6
AW
58/* Objects have identity, so references to classes and instances are by
59 value, not by reference. Redefinition of a class or modification of
60 an instance causes in-place update; you can think of GOOPS as
61 building in its own indirection, and for that reason referring to
62 GOOPS values by variable reference is unnecessary.
bef95911 63
51fd1cd6
AW
64 References to ordinary procedures is by reference (by variable),
65 though, as in the rest of Guile. */
66
67static SCM var_make_standard_class = SCM_BOOL_F;
bef95911
AW
68static SCM var_slot_unbound = SCM_BOOL_F;
69static SCM var_slot_missing = SCM_BOOL_F;
bef95911 70static SCM var_change_class = SCM_BOOL_F;
e0590e7c 71static SCM var_make = SCM_BOOL_F;
70dd6000
AW
72static SCM var_class_name = SCM_BOOL_F;
73static SCM var_class_direct_supers = SCM_BOOL_F;
74static SCM var_class_direct_slots = SCM_BOOL_F;
75static SCM var_class_direct_subclasses = SCM_BOOL_F;
76static SCM var_class_direct_methods = SCM_BOOL_F;
77static SCM var_class_precedence_list = SCM_BOOL_F;
78static SCM var_class_slots = SCM_BOOL_F;
bef95911
AW
79
80SCM_SYMBOL (sym_slot_unbound, "slot-unbound");
81SCM_SYMBOL (sym_slot_missing, "slot-missing");
bef95911
AW
82SCM_SYMBOL (sym_change_class, "change-class");
83
84SCM_VARIABLE (scm_var_make_extended_generic, "make-extended-generic");
85
86
80662eda
MD
87/* Class redefinition protocol:
88
89 A class is represented by a heap header h1 which points to a
90 malloc:ed memory block m1.
91
92 When a new version of a class is created, a new header h2 and
93 memory block m2 are allocated. The headers h1 and h2 then switch
94 pointers so that h1 refers to m2 and h2 to m1. In this way, names
95 bound to h1 will point to the new class at the same time as h2 will
7346de61 96 be a handle which the GC will use to free m1.
80662eda
MD
97
98 The `redefined' slot of m1 will be set to point to h1. An old
7346de61 99 instance will have its class pointer (the CAR of the heap header)
80662eda
MD
100 pointing to m1. The non-immediate `redefined'-slot in m1 indicates
101 the class modification and the new class pointer can be found via
102 h1.
103*/
104
0fd7dcd3
MD
105#define TEST_CHANGE_CLASS(obj, class) \
106 { \
107 class = SCM_CLASS_OF (obj); \
7888309b 108 if (scm_is_true (SCM_OBJ_CLASS_REDEF (obj))) \
0fd7dcd3
MD
109 { \
110 scm_change_object_class (obj, class, SCM_OBJ_CLASS_REDEF (obj));\
111 class = SCM_CLASS_OF (obj); \
112 } \
80662eda
MD
113 }
114
80662eda 115#define SCM_GOOPS_UNBOUND SCM_UNBOUND
d223c3fc 116#define SCM_GOOPS_UNBOUNDP(x) (scm_is_eq (x, SCM_GOOPS_UNBOUND))
80662eda
MD
117
118static int goops_loaded_p = 0;
80662eda 119
539d5410 120/* These variables are filled in by the object system when loaded. */
57898597
AW
121static SCM class_boolean, class_char, class_pair;
122static SCM class_procedure, class_string, class_symbol;
123static SCM class_primitive_generic;
124static SCM class_vector, class_null;
125static SCM class_integer, class_real, class_complex, class_fraction;
126static SCM class_unknown;
127static SCM class_top, class_object, class_class;
128static SCM class_applicable;
129static SCM class_applicable_struct, class_applicable_struct_with_setter;
130static SCM class_generic, class_generic_with_setter;
131static SCM class_accessor;
132static SCM class_extended_generic, class_extended_generic_with_setter;
133static SCM class_extended_accessor;
134static SCM class_method;
135static SCM class_accessor_method;
136static SCM class_procedure_class;
137static SCM class_applicable_struct_class;
138static SCM class_applicable_struct_with_setter_class;
139static SCM class_number, class_list;
140static SCM class_keyword;
141static SCM class_port, class_input_output_port;
142static SCM class_input_port, class_output_port;
143static SCM class_foreign_slot;
144static SCM class_self, class_protected;
145static SCM class_hidden, class_opaque, class_read_only;
146static SCM class_protected_hidden, class_protected_opaque, class_protected_read_only;
147static SCM class_scm;
148static SCM class_int, class_float, class_double;
80662eda 149
e2c2a699 150static SCM class_foreign;
9ea31741
AW
151static SCM class_hashtable;
152static SCM class_fluid;
153static SCM class_dynamic_state;
6f3b0cc2 154static SCM class_frame;
6f3b0cc2 155static SCM class_vm_cont;
f826a886
AW
156static SCM class_bytevector;
157static SCM class_uvec;
b2637c98 158static SCM class_array;
ff1feca9 159static SCM class_bitvector;
9ea31741 160
f3c6a02c
AW
161static SCM vtable_class_map = SCM_BOOL_F;
162
63385df2
LC
163/* Port classes. Allocate 3 times the maximum number of port types so that
164 input ports, output ports, and in/out ports can be stored at different
165 offsets. See `SCM_IN_PCLASS_INDEX' et al. */
57898597 166SCM scm_i_port_class[3 * SCM_I_MAX_PORT_TYPE_COUNT];
63385df2
LC
167
168/* SMOB classes. */
57898597 169SCM scm_i_smob_class[SCM_I_MAX_SMOB_TYPE_COUNT];
539d5410 170
80662eda
MD
171static SCM scm_make_unbound (void);
172static SCM scm_unbound_p (SCM obj);
70dd6000 173static SCM scm_class_p (SCM obj);
6c7dd9eb
AW
174static SCM scm_sys_bless_applicable_struct_vtables_x (SCM applicable,
175 SCM setter);
51fd1cd6
AW
176static SCM scm_sys_bless_pure_generic_vtable_x (SCM vtable);
177static SCM scm_sys_make_root_class (SCM name, SCM dslots,
178 SCM getters_n_setters);
179static SCM scm_sys_init_layout_x (SCM class, SCM layout);
82ab5090 180static SCM scm_sys_goops_early_init (void);
398d8ee1 181static SCM scm_sys_goops_loaded (void);
80662eda 182
f3c6a02c 183
539d5410
MV
184/* This function is used for efficient type dispatch. */
185SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0,
186 (SCM x),
187 "Return the class of @var{x}.")
188#define FUNC_NAME s_scm_class_of
189{
190 switch (SCM_ITAG3 (x))
191 {
192 case scm_tc3_int_1:
193 case scm_tc3_int_2:
57898597 194 return class_integer;
539d5410
MV
195
196 case scm_tc3_imm24:
197 if (SCM_CHARP (x))
57898597 198 return class_char;
539d5410 199 else if (scm_is_bool (x))
57898597 200 return class_boolean;
539d5410 201 else if (scm_is_null (x))
57898597 202 return class_null;
539d5410 203 else
57898597 204 return class_unknown;
539d5410
MV
205
206 case scm_tc3_cons:
207 switch (SCM_TYP7 (x))
208 {
209 case scm_tcs_cons_nimcar:
57898597 210 return class_pair;
539d5410 211 case scm_tc7_symbol:
57898597 212 return class_symbol;
539d5410
MV
213 case scm_tc7_vector:
214 case scm_tc7_wvect:
57898597 215 return class_vector;
5b46a8c2 216 case scm_tc7_pointer:
e2c2a699 217 return class_foreign;
c99de5aa 218 case scm_tc7_hashtable:
9ea31741
AW
219 return class_hashtable;
220 case scm_tc7_fluid:
221 return class_fluid;
222 case scm_tc7_dynamic_state:
223 return class_dynamic_state;
6f3b0cc2
AW
224 case scm_tc7_frame:
225 return class_frame;
e2fafeb9 226 case scm_tc7_keyword:
57898597 227 return class_keyword;
6f3b0cc2
AW
228 case scm_tc7_vm_cont:
229 return class_vm_cont;
f826a886
AW
230 case scm_tc7_bytevector:
231 if (SCM_BYTEVECTOR_ELEMENT_TYPE (x) == SCM_ARRAY_ELEMENT_TYPE_VU8)
232 return class_bytevector;
233 else
234 return class_uvec;
b2637c98
AW
235 case scm_tc7_array:
236 return class_array;
ff1feca9
AW
237 case scm_tc7_bitvector:
238 return class_bitvector;
539d5410 239 case scm_tc7_string:
57898597 240 return class_string;
539d5410
MV
241 case scm_tc7_number:
242 switch SCM_TYP16 (x) {
243 case scm_tc16_big:
57898597 244 return class_integer;
539d5410 245 case scm_tc16_real:
57898597 246 return class_real;
539d5410 247 case scm_tc16_complex:
57898597 248 return class_complex;
539d5410 249 case scm_tc16_fraction:
57898597 250 return class_fraction;
539d5410 251 }
e0755cd1 252 case scm_tc7_program:
b2b33168
AW
253 if (SCM_PROGRAM_IS_PRIMITIVE_GENERIC (x)
254 && SCM_UNPACK (*SCM_SUBR_GENERIC (x)))
57898597 255 return class_primitive_generic;
fd12a19a 256 else
57898597 257 return class_procedure;
539d5410
MV
258
259 case scm_tc7_smob:
260 {
261 scm_t_bits type = SCM_TYP16 (x);
262 if (type != scm_tc16_port_with_ps)
57898597 263 return scm_i_smob_class[SCM_TC2SMOBNUM (type)];
539d5410
MV
264 x = SCM_PORT_WITH_PS_PORT (x);
265 /* fall through to ports */
266 }
267 case scm_tc7_port:
57898597
AW
268 return scm_i_port_class[(SCM_WRTNG & SCM_CELL_WORD_0 (x)
269 ? (SCM_RDNG & SCM_CELL_WORD_0 (x)
270 ? SCM_INOUT_PCLASS_INDEX | SCM_PTOBNUM (x)
271 : SCM_OUT_PCLASS_INDEX | SCM_PTOBNUM (x))
272 : SCM_IN_PCLASS_INDEX | SCM_PTOBNUM (x))];
539d5410
MV
273 case scm_tcs_struct:
274 if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS_VALID)
275 return SCM_CLASS_OF (x);
276 else if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS)
277 {
278 /* Goops object */
279 if (! scm_is_false (SCM_OBJ_CLASS_REDEF (x)))
280 scm_change_object_class (x,
281 SCM_CLASS_OF (x), /* old */
282 SCM_OBJ_CLASS_REDEF (x)); /* new */
283 return SCM_CLASS_OF (x);
284 }
285 else
f3c6a02c 286 return scm_i_define_class_for_vtable (SCM_CLASS_OF (x));
539d5410
MV
287 default:
288 if (scm_is_pair (x))
57898597 289 return class_pair;
539d5410 290 else
57898597 291 return class_unknown;
539d5410
MV
292 }
293
294 case scm_tc3_struct:
295 case scm_tc3_tc7_1:
296 case scm_tc3_tc7_2:
314b8716 297 /* case scm_tc3_unused: */
539d5410
MV
298 /* Never reached */
299 break;
300 }
57898597 301 return class_unknown;
539d5410
MV
302}
303#undef FUNC_NAME
304
80662eda
MD
305/******************************************************************************
306 *
307 * initialize-object
308 *
309 ******************************************************************************/
310
311/*fixme* Manufacture keywords in advance */
312SCM
c014a02e 313scm_i_get_keyword (SCM key, SCM l, long len, SCM default_value, const char *subr)
80662eda 314{
c014a02e 315 long i;
23437298
DH
316
317 for (i = 0; i != len; i += 2)
80662eda 318 {
23437298
DH
319 SCM obj = SCM_CAR (l);
320
c598539a 321 if (!scm_is_keyword (obj))
1afff620 322 scm_misc_error (subr, "bad keyword: ~S", scm_list_1 (obj));
bc36d050 323 else if (scm_is_eq (obj, key))
80662eda 324 return SCM_CADR (l);
23437298
DH
325 else
326 l = SCM_CDDR (l);
80662eda 327 }
23437298 328
80662eda
MD
329 return default_value;
330}
331
80662eda 332
23437298
DH
333SCM_DEFINE (scm_get_keyword, "get-keyword", 3, 0, 0,
334 (SCM key, SCM l, SCM default_value),
5352393c
MG
335 "Determine an associated value for the keyword @var{key} from\n"
336 "the list @var{l}. The list @var{l} has to consist of an even\n"
337 "number of elements, where, starting with the first, every\n"
338 "second element is a keyword, followed by its associated value.\n"
339 "If @var{l} does not hold a value for @var{key}, the value\n"
340 "@var{default_value} is returned.")
23437298 341#define FUNC_NAME s_scm_get_keyword
80662eda 342{
c014a02e 343 long len;
23437298 344
c598539a 345 SCM_ASSERT (scm_is_keyword (key), key, SCM_ARG1, FUNC_NAME);
80662eda 346 len = scm_ilength (l);
b6311c08 347 if (len < 0 || len % 2 == 1)
1afff620 348 scm_misc_error (FUNC_NAME, "Bad keyword-value list: ~S", scm_list_1 (l));
23437298
DH
349
350 return scm_i_get_keyword (key, l, len, default_value, FUNC_NAME);
80662eda 351}
23437298
DH
352#undef FUNC_NAME
353
80662eda 354
80662eda
MD
355SCM_KEYWORD (k_init_keyword, "init-keyword");
356
357static SCM get_slot_value (SCM class, SCM obj, SCM slotdef);
358static SCM set_slot_value (SCM class, SCM obj, SCM slotdef, SCM value);
359
398d8ee1
KN
360SCM_DEFINE (scm_sys_initialize_object, "%initialize-object", 2, 0, 0,
361 (SCM obj, SCM initargs),
6bcefd15
MG
362 "Initialize the object @var{obj} with the given arguments\n"
363 "@var{initargs}.")
398d8ee1 364#define FUNC_NAME s_scm_sys_initialize_object
80662eda
MD
365{
366 SCM tmp, get_n_set, slots;
367 SCM class = SCM_CLASS_OF (obj);
c014a02e 368 long n_initargs;
80662eda 369
398d8ee1 370 SCM_VALIDATE_INSTANCE (1, obj);
80662eda 371 n_initargs = scm_ilength (initargs);
398d8ee1 372 SCM_ASSERT ((n_initargs & 1) == 0, initargs, SCM_ARG2, FUNC_NAME);
6d77c894 373
80662eda
MD
374 get_n_set = SCM_SLOT (class, scm_si_getters_n_setters);
375 slots = SCM_SLOT (class, scm_si_slots);
6d77c894 376
80662eda
MD
377 /* See for each slot how it must be initialized */
378 for (;
d2e53ed6 379 !scm_is_null (slots);
80662eda
MD
380 get_n_set = SCM_CDR (get_n_set), slots = SCM_CDR (slots))
381 {
382 SCM slot_name = SCM_CAR (slots);
48ad85fb 383 SCM slot_value = SCM_GOOPS_UNBOUND;
6d77c894 384
d2e53ed6 385 if (!scm_is_null (SCM_CDR (slot_name)))
80662eda
MD
386 {
387 /* This slot admits (perhaps) to be initialized at creation time */
c014a02e 388 long n = scm_ilength (SCM_CDR (slot_name));
80662eda 389 if (n & 1) /* odd or -1 */
398d8ee1 390 SCM_MISC_ERROR ("class contains bogus slot definition: ~S",
1afff620 391 scm_list_1 (slot_name));
80662eda
MD
392 tmp = scm_i_get_keyword (k_init_keyword,
393 SCM_CDR (slot_name),
394 n,
b2b33168 395 SCM_PACK (0),
398d8ee1 396 FUNC_NAME);
80662eda 397 slot_name = SCM_CAR (slot_name);
b2b33168 398 if (SCM_UNPACK (tmp))
80662eda
MD
399 {
400 /* an initarg was provided for this slot */
c598539a 401 if (!scm_is_keyword (tmp))
398d8ee1 402 SCM_MISC_ERROR ("initarg must be a keyword. It was ~S",
1afff620 403 scm_list_1 (tmp));
80662eda
MD
404 slot_value = scm_i_get_keyword (tmp,
405 initargs,
406 n_initargs,
48ad85fb 407 SCM_GOOPS_UNBOUND,
398d8ee1 408 FUNC_NAME);
80662eda
MD
409 }
410 }
411
48ad85fb 412 if (!SCM_GOOPS_UNBOUNDP (slot_value))
80662eda
MD
413 /* set slot to provided value */
414 set_slot_value (class, obj, SCM_CAR (get_n_set), slot_value);
415 else
416 {
417 /* set slot to its :init-form if it exists */
418 tmp = SCM_CADAR (get_n_set);
7888309b 419 if (scm_is_true (tmp))
48ad85fb
AW
420 set_slot_value (class,
421 obj,
422 SCM_CAR (get_n_set),
423 scm_call_0 (tmp));
80662eda
MD
424 }
425 }
6d77c894 426
80662eda
MD
427 return obj;
428}
398d8ee1 429#undef FUNC_NAME
80662eda 430
51fd1cd6
AW
431SCM_DEFINE (scm_sys_init_layout_x, "%init-layout!", 2, 0, 0,
432 (SCM class, SCM layout),
398d8ee1 433 "")
51fd1cd6 434#define FUNC_NAME s_scm_sys_init_layout_x
80662eda 435{
398d8ee1 436 SCM_VALIDATE_INSTANCE (1, class);
51fd1cd6
AW
437 SCM_ASSERT (!scm_is_symbol (SCM_VTABLE_LAYOUT (class)), class, 1, FUNC_NAME);
438 SCM_VALIDATE_STRING (2, layout);
439
440 SCM_SET_VTABLE_LAYOUT (class, scm_make_struct_layout (layout));
80662eda
MD
441 return SCM_UNSPECIFIED;
442}
398d8ee1 443#undef FUNC_NAME
80662eda 444
398d8ee1
KN
445SCM_DEFINE (scm_sys_inherit_magic_x, "%inherit-magic!", 2, 0, 0,
446 (SCM class, SCM dsupers),
447 "")
448#define FUNC_NAME s_scm_sys_inherit_magic_x
80662eda 449{
398d8ee1 450 SCM_VALIDATE_INSTANCE (1, class);
51f66c91
AW
451 scm_i_struct_inherit_vtable_magic (SCM_CLASS_OF (class), class);
452 SCM_SET_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_OR_VALID);
80662eda 453
80662eda
MD
454 return SCM_UNSPECIFIED;
455}
398d8ee1 456#undef FUNC_NAME
80662eda 457
80662eda
MD
458/******************************************************************************/
459
80662eda 460SCM
28b818d3 461scm_make_standard_class (SCM meta, SCM name, SCM dsupers, SCM dslots)
80662eda 462{
51fd1cd6 463 return scm_call_4 (scm_variable_ref (var_make_standard_class),
28b818d3 464 meta, name, dsupers, dslots);
80662eda
MD
465}
466
467/******************************************************************************/
468
51fd1cd6
AW
469SCM_DEFINE (scm_sys_make_root_class, "%make-root-class", 3, 0, 0,
470 (SCM name, SCM dslots, SCM getters_n_setters),
471 "")
472#define FUNC_NAME s_scm_sys_make_root_class
80662eda 473{
51fd1cd6 474 SCM cs, z;
6d77c894 475
51fd1cd6
AW
476 cs = scm_from_locale_string (SCM_CLASS_CLASS_LAYOUT);
477 z = scm_i_make_vtable_vtable (cs);
478 SCM_SET_CLASS_FLAGS (z, (SCM_CLASSF_GOOPS_OR_VALID
479 | SCM_CLASSF_METACLASS));
80662eda 480
51fd1cd6
AW
481 SCM_SET_SLOT (z, scm_vtable_index_name, name);
482 SCM_SET_SLOT (z, scm_si_direct_supers, SCM_EOL); /* will be changed */
483 SCM_SET_SLOT (z, scm_si_direct_slots, dslots); /* will be changed */
484 SCM_SET_SLOT (z, scm_si_direct_subclasses, SCM_EOL);
485 SCM_SET_SLOT (z, scm_si_direct_methods, SCM_EOL);
486 SCM_SET_SLOT (z, scm_si_cpl, SCM_EOL); /* will be changed */
487 SCM_SET_SLOT (z, scm_si_slots, dslots); /* will be changed */
488 SCM_SET_SLOT (z, scm_si_nfields, scm_from_int (SCM_N_CLASS_SLOTS));
489 SCM_SET_SLOT (z, scm_si_getters_n_setters, getters_n_setters); /* will be changed */
490 SCM_SET_SLOT (z, scm_si_redefined, SCM_BOOL_F);
80662eda 491
51fd1cd6 492 return z;
80662eda 493}
51fd1cd6 494#undef FUNC_NAME
80662eda
MD
495
496/******************************************************************************/
497
398d8ee1
KN
498SCM_DEFINE (scm_instance_p, "instance?", 1, 0, 0,
499 (SCM obj),
6bcefd15 500 "Return @code{#t} if @var{obj} is an instance.")
398d8ee1 501#define FUNC_NAME s_scm_instance_p
80662eda 502{
7888309b 503 return scm_from_bool (SCM_INSTANCEP (obj));
80662eda 504}
398d8ee1 505#undef FUNC_NAME
80662eda 506
70dd6000
AW
507SCM_DEFINE (scm_class_p, "class?", 1, 0, 0,
508 (SCM obj),
509 "Return @code{#t} if @var{obj} is a class.")
510#define FUNC_NAME s_scm_class_p
511{
512 return scm_from_bool (SCM_CLASSP (obj));
513}
514#undef FUNC_NAME
515
57898597
AW
516int
517scm_is_generic (SCM x)
518{
519 return SCM_INSTANCEP (x) && SCM_SUBCLASSP (SCM_CLASS_OF (x), class_generic);
520}
521
522int
523scm_is_method (SCM x)
524{
525 return SCM_INSTANCEP (x) && SCM_SUBCLASSP (SCM_CLASS_OF (x), class_method);
526}
80662eda
MD
527
528/******************************************************************************
6d77c894 529 *
80662eda
MD
530 * Meta object accessors
531 *
532 ******************************************************************************/
51fd1cd6
AW
533
534SCM_SYMBOL (sym_procedure, "procedure");
70dd6000
AW
535
536SCM
537scm_class_name (SCM obj)
80662eda 538{
70dd6000 539 return scm_call_1 (scm_variable_ref (var_class_name), obj);
80662eda
MD
540}
541
70dd6000
AW
542SCM
543scm_class_direct_supers (SCM obj)
80662eda 544{
70dd6000 545 return scm_call_1 (scm_variable_ref (var_class_direct_supers), obj);
80662eda
MD
546}
547
70dd6000
AW
548SCM
549scm_class_direct_slots (SCM obj)
80662eda 550{
70dd6000 551 return scm_call_1 (scm_variable_ref (var_class_direct_slots), obj);
80662eda
MD
552}
553
70dd6000
AW
554SCM
555scm_class_direct_subclasses (SCM obj)
80662eda 556{
70dd6000 557 return scm_call_1 (scm_variable_ref (var_class_direct_subclasses), obj);
80662eda
MD
558}
559
70dd6000
AW
560SCM
561scm_class_direct_methods (SCM obj)
80662eda 562{
70dd6000 563 return scm_call_1 (scm_variable_ref (var_class_direct_methods), obj);
80662eda
MD
564}
565
70dd6000
AW
566SCM
567scm_class_precedence_list (SCM obj)
80662eda 568{
70dd6000 569 return scm_call_1 (scm_variable_ref (var_class_precedence_list), obj);
80662eda
MD
570}
571
70dd6000
AW
572SCM
573scm_class_slots (SCM obj)
80662eda 574{
70dd6000 575 return scm_call_1 (scm_variable_ref (var_class_slots), obj);
80662eda
MD
576}
577
398d8ee1 578SCM_DEFINE (scm_generic_function_name, "generic-function-name", 1, 0, 0,
70dd6000 579 (SCM obj),
6bcefd15 580 "Return the name of the generic function @var{obj}.")
398d8ee1 581#define FUNC_NAME s_scm_generic_function_name
80662eda 582{
398d8ee1 583 SCM_VALIDATE_GENERIC (1, obj);
80662eda
MD
584 return scm_procedure_property (obj, scm_sym_name);
585}
398d8ee1 586#undef FUNC_NAME
80662eda 587
bbf8d523
MD
588SCM_SYMBOL (sym_methods, "methods");
589SCM_SYMBOL (sym_extended_by, "extended-by");
590SCM_SYMBOL (sym_extends, "extends");
591
592static
593SCM fold_downward_gf_methods (SCM method_lists, SCM gf)
594{
595 SCM gfs = scm_slot_ref (gf, sym_extended_by);
596 method_lists = scm_cons (scm_slot_ref (gf, sym_methods), method_lists);
d2e53ed6 597 while (!scm_is_null (gfs))
bbf8d523
MD
598 {
599 method_lists = fold_downward_gf_methods (method_lists, SCM_CAR (gfs));
600 gfs = SCM_CDR (gfs);
601 }
602 return method_lists;
603}
604
605static
606SCM fold_upward_gf_methods (SCM method_lists, SCM gf)
607{
57898597 608 if (SCM_IS_A_P (gf, class_extended_generic))
bbf8d523
MD
609 {
610 SCM gfs = scm_slot_ref (gf, sym_extends);
d2e53ed6 611 while (!scm_is_null (gfs))
bbf8d523
MD
612 {
613 SCM methods = scm_slot_ref (SCM_CAR (gfs), sym_methods);
614 method_lists = fold_upward_gf_methods (scm_cons (methods,
615 method_lists),
616 SCM_CAR (gfs));
617 gfs = SCM_CDR (gfs);
618 }
619 }
620 return method_lists;
621}
622
398d8ee1
KN
623SCM_DEFINE (scm_generic_function_methods, "generic-function-methods", 1, 0, 0,
624 (SCM obj),
6bcefd15 625 "Return the methods of the generic function @var{obj}.")
398d8ee1 626#define FUNC_NAME s_scm_generic_function_methods
80662eda 627{
bbf8d523 628 SCM methods;
398d8ee1 629 SCM_VALIDATE_GENERIC (1, obj);
bbf8d523
MD
630 methods = fold_upward_gf_methods (SCM_EOL, obj);
631 methods = fold_downward_gf_methods (methods, obj);
632 return scm_append (methods);
80662eda 633}
398d8ee1 634#undef FUNC_NAME
80662eda 635
398d8ee1
KN
636SCM_DEFINE (scm_method_generic_function, "method-generic-function", 1, 0, 0,
637 (SCM obj),
bb2c02f2 638 "Return the generic function for the method @var{obj}.")
398d8ee1 639#define FUNC_NAME s_scm_method_generic_function
80662eda 640{
398d8ee1 641 SCM_VALIDATE_METHOD (1, obj);
4a655e50 642 return scm_slot_ref (obj, scm_from_latin1_symbol ("generic-function"));
80662eda 643}
398d8ee1 644#undef FUNC_NAME
80662eda 645
398d8ee1
KN
646SCM_DEFINE (scm_method_specializers, "method-specializers", 1, 0, 0,
647 (SCM obj),
6bcefd15 648 "Return specializers of the method @var{obj}.")
398d8ee1 649#define FUNC_NAME s_scm_method_specializers
80662eda 650{
398d8ee1 651 SCM_VALIDATE_METHOD (1, obj);
4a655e50 652 return scm_slot_ref (obj, scm_from_latin1_symbol ("specializers"));
80662eda 653}
398d8ee1 654#undef FUNC_NAME
80662eda 655
398d8ee1
KN
656SCM_DEFINE (scm_method_procedure, "method-procedure", 1, 0, 0,
657 (SCM obj),
6bcefd15 658 "Return the procedure of the method @var{obj}.")
398d8ee1 659#define FUNC_NAME s_scm_method_procedure
80662eda 660{
398d8ee1 661 SCM_VALIDATE_METHOD (1, obj);
6b80d352 662 return scm_slot_ref (obj, sym_procedure);
80662eda 663}
398d8ee1 664#undef FUNC_NAME
80662eda 665
80662eda
MD
666/******************************************************************************
667 *
668 * S l o t a c c e s s
669 *
670 ******************************************************************************/
671
398d8ee1
KN
672SCM_DEFINE (scm_make_unbound, "make-unbound", 0, 0, 0,
673 (),
6bcefd15 674 "Return the unbound value.")
398d8ee1 675#define FUNC_NAME s_scm_make_unbound
80662eda
MD
676{
677 return SCM_GOOPS_UNBOUND;
678}
398d8ee1 679#undef FUNC_NAME
80662eda 680
398d8ee1
KN
681SCM_DEFINE (scm_unbound_p, "unbound?", 1, 0, 0,
682 (SCM obj),
6bcefd15 683 "Return @code{#t} if @var{obj} is unbound.")
398d8ee1 684#define FUNC_NAME s_scm_unbound_p
80662eda
MD
685{
686 return SCM_GOOPS_UNBOUNDP (obj) ? SCM_BOOL_T : SCM_BOOL_F;
687}
398d8ee1 688#undef FUNC_NAME
80662eda 689
80662eda 690
4d0949ea 691\f
80662eda
MD
692/** Utilities **/
693
694/* In the future, this function will return the effective slot
695 * definition associated with SLOT_NAME. Now it just returns some of
696 * the information which will be stored in the effective slot
697 * definition.
698 */
699
700static SCM
701slot_definition_using_name (SCM class, SCM slot_name)
702{
703 register SCM slots = SCM_SLOT (class, scm_si_getters_n_setters);
d2e53ed6 704 for (; !scm_is_null (slots); slots = SCM_CDR (slots))
d223c3fc 705 if (scm_is_eq (SCM_CAAR (slots), slot_name))
80662eda
MD
706 return SCM_CAR (slots);
707 return SCM_BOOL_F;
708}
709
710static SCM
e81d98ec 711get_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef)
54ee7cdf 712#define FUNC_NAME "%get-slot-value"
80662eda
MD
713{
714 SCM access = SCM_CDDR (slotdef);
715 /* Two cases here:
716 * - access is an integer (the offset of this slot in the slots vector)
717 * - otherwise (car access) is the getter function to apply
e11e83f3
MV
718 *
719 * Instances have never more than SCM_MOST_POSITIVE_FIXNUM slots, so
720 * we can just assume fixnums here.
23437298 721 */
e11e83f3 722 if (SCM_I_INUMP (access))
54ee7cdf
AW
723 /* Don't poke at the slots directly, because scm_struct_ref handles the
724 access bits for us. */
725 return scm_struct_ref (obj, access);
80662eda 726 else
9d019f9b 727 return scm_call_1 (SCM_CAR (access), obj);
80662eda 728}
54ee7cdf 729#undef FUNC_NAME
80662eda
MD
730
731static SCM
732get_slot_value_using_name (SCM class, SCM obj, SCM slot_name)
733{
734 SCM slotdef = slot_definition_using_name (class, slot_name);
7888309b 735 if (scm_is_true (slotdef))
80662eda
MD
736 return get_slot_value (class, obj, slotdef);
737 else
bef95911 738 return scm_call_3 (SCM_VARIABLE_REF (var_slot_missing), class, obj, slot_name);
80662eda
MD
739}
740
741static SCM
e81d98ec 742set_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef, SCM value)
54ee7cdf 743#define FUNC_NAME "%set-slot-value"
80662eda
MD
744{
745 SCM access = SCM_CDDR (slotdef);
746 /* Two cases here:
747 * - access is an integer (the offset of this slot in the slots vector)
748 * - otherwise (cadr access) is the setter function to apply
e11e83f3
MV
749 *
750 * Instances have never more than SCM_MOST_POSITIVE_FIXNUM slots, so
751 * we can just assume fixnums here.
80662eda 752 */
e11e83f3 753 if (SCM_I_INUMP (access))
54ee7cdf
AW
754 /* obey permissions bits via going through struct-set! */
755 scm_struct_set_x (obj, access, value);
80662eda 756 else
9d019f9b
AW
757 /* ((cadr l) obj value) */
758 scm_call_2 (SCM_CADR (access), obj, value);
80662eda
MD
759 return SCM_UNSPECIFIED;
760}
54ee7cdf 761#undef FUNC_NAME
80662eda
MD
762
763static SCM
764set_slot_value_using_name (SCM class, SCM obj, SCM slot_name, SCM value)
765{
766 SCM slotdef = slot_definition_using_name (class, slot_name);
7888309b 767 if (scm_is_true (slotdef))
80662eda
MD
768 return set_slot_value (class, obj, slotdef, value);
769 else
bef95911 770 return scm_call_4 (SCM_VARIABLE_REF (var_slot_missing), class, obj, slot_name, value);
80662eda
MD
771}
772
773static SCM
e81d98ec 774test_slot_existence (SCM class SCM_UNUSED, SCM obj, SCM slot_name)
80662eda
MD
775{
776 register SCM l;
777
d2e53ed6 778 for (l = SCM_ACCESSORS_OF (obj); !scm_is_null (l); l = SCM_CDR (l))
bc36d050 779 if (scm_is_eq (SCM_CAAR (l), slot_name))
80662eda
MD
780 return SCM_BOOL_T;
781
782 return SCM_BOOL_F;
783}
784
80662eda
MD
785 /* ======================================== */
786
23437298
DH
787SCM_DEFINE (scm_slot_ref_using_class, "slot-ref-using-class", 3, 0, 0,
788 (SCM class, SCM obj, SCM slot_name),
789 "")
790#define FUNC_NAME s_scm_slot_ref_using_class
80662eda
MD
791{
792 SCM res;
793
398d8ee1
KN
794 SCM_VALIDATE_CLASS (1, class);
795 SCM_VALIDATE_INSTANCE (2, obj);
796 SCM_VALIDATE_SYMBOL (3, slot_name);
80662eda
MD
797
798 res = get_slot_value_using_name (class, obj, slot_name);
799 if (SCM_GOOPS_UNBOUNDP (res))
bef95911 800 return scm_call_3 (SCM_VARIABLE_REF (var_slot_unbound), class, obj, slot_name);
80662eda
MD
801 return res;
802}
23437298 803#undef FUNC_NAME
80662eda 804
23437298
DH
805
806SCM_DEFINE (scm_slot_set_using_class_x, "slot-set-using-class!", 4, 0, 0,
807 (SCM class, SCM obj, SCM slot_name, SCM value),
808 "")
809#define FUNC_NAME s_scm_slot_set_using_class_x
80662eda 810{
398d8ee1
KN
811 SCM_VALIDATE_CLASS (1, class);
812 SCM_VALIDATE_INSTANCE (2, obj);
813 SCM_VALIDATE_SYMBOL (3, slot_name);
23437298 814
80662eda
MD
815 return set_slot_value_using_name (class, obj, slot_name, value);
816}
23437298
DH
817#undef FUNC_NAME
818
80662eda 819
398d8ee1
KN
820SCM_DEFINE (scm_slot_bound_using_class_p, "slot-bound-using-class?", 3, 0, 0,
821 (SCM class, SCM obj, SCM slot_name),
822 "")
823#define FUNC_NAME s_scm_slot_bound_using_class_p
80662eda 824{
398d8ee1
KN
825 SCM_VALIDATE_CLASS (1, class);
826 SCM_VALIDATE_INSTANCE (2, obj);
827 SCM_VALIDATE_SYMBOL (3, slot_name);
80662eda
MD
828
829 return (SCM_GOOPS_UNBOUNDP (get_slot_value_using_name (class, obj, slot_name))
830 ? SCM_BOOL_F
831 : SCM_BOOL_T);
832}
398d8ee1 833#undef FUNC_NAME
80662eda 834
398d8ee1
KN
835SCM_DEFINE (scm_slot_exists_using_class_p, "slot-exists-using-class?", 3, 0, 0,
836 (SCM class, SCM obj, SCM slot_name),
837 "")
838#define FUNC_NAME s_scm_slot_exists_using_class_p
839{
840 SCM_VALIDATE_CLASS (1, class);
841 SCM_VALIDATE_INSTANCE (2, obj);
842 SCM_VALIDATE_SYMBOL (3, slot_name);
80662eda
MD
843 return test_slot_existence (class, obj, slot_name);
844}
398d8ee1 845#undef FUNC_NAME
80662eda
MD
846
847
848 /* ======================================== */
849
398d8ee1
KN
850SCM_DEFINE (scm_slot_ref, "slot-ref", 2, 0, 0,
851 (SCM obj, SCM slot_name),
6bcefd15
MG
852 "Return the value from @var{obj}'s slot with the name\n"
853 "@var{slot_name}.")
398d8ee1 854#define FUNC_NAME s_scm_slot_ref
80662eda
MD
855{
856 SCM res, class;
857
398d8ee1 858 SCM_VALIDATE_INSTANCE (1, obj);
80662eda
MD
859 TEST_CHANGE_CLASS (obj, class);
860
861 res = get_slot_value_using_name (class, obj, slot_name);
862 if (SCM_GOOPS_UNBOUNDP (res))
bef95911 863 return scm_call_3 (SCM_VARIABLE_REF (var_slot_unbound), class, obj, slot_name);
80662eda
MD
864 return res;
865}
398d8ee1 866#undef FUNC_NAME
80662eda 867
398d8ee1
KN
868SCM_DEFINE (scm_slot_set_x, "slot-set!", 3, 0, 0,
869 (SCM obj, SCM slot_name, SCM value),
6bcefd15 870 "Set the slot named @var{slot_name} of @var{obj} to @var{value}.")
398d8ee1 871#define FUNC_NAME s_scm_slot_set_x
80662eda
MD
872{
873 SCM class;
874
398d8ee1 875 SCM_VALIDATE_INSTANCE (1, obj);
80662eda
MD
876 TEST_CHANGE_CLASS(obj, class);
877
878 return set_slot_value_using_name (class, obj, slot_name, value);
879}
398d8ee1 880#undef FUNC_NAME
80662eda 881
398d8ee1
KN
882SCM_DEFINE (scm_slot_bound_p, "slot-bound?", 2, 0, 0,
883 (SCM obj, SCM slot_name),
6bcefd15
MG
884 "Return @code{#t} if the slot named @var{slot_name} of @var{obj}\n"
885 "is bound.")
398d8ee1 886#define FUNC_NAME s_scm_slot_bound_p
80662eda
MD
887{
888 SCM class;
889
398d8ee1 890 SCM_VALIDATE_INSTANCE (1, obj);
80662eda
MD
891 TEST_CHANGE_CLASS(obj, class);
892
893 return (SCM_GOOPS_UNBOUNDP (get_slot_value_using_name (class,
894 obj,
895 slot_name))
896 ? SCM_BOOL_F
897 : SCM_BOOL_T);
898}
398d8ee1 899#undef FUNC_NAME
80662eda 900
6d77c894 901SCM_DEFINE (scm_slot_exists_p, "slot-exists?", 2, 0, 0,
398d8ee1 902 (SCM obj, SCM slot_name),
6bcefd15 903 "Return @code{#t} if @var{obj} has a slot named @var{slot_name}.")
6d77c894 904#define FUNC_NAME s_scm_slot_exists_p
80662eda
MD
905{
906 SCM class;
907
398d8ee1
KN
908 SCM_VALIDATE_INSTANCE (1, obj);
909 SCM_VALIDATE_SYMBOL (2, slot_name);
80662eda
MD
910 TEST_CHANGE_CLASS (obj, class);
911
912 return test_slot_existence (class, obj, slot_name);
913}
398d8ee1 914#undef FUNC_NAME
80662eda
MD
915
916
917/******************************************************************************
918 *
919 * %allocate-instance (the low level instance allocation primitive)
920 *
921 ******************************************************************************/
922
398d8ee1
KN
923SCM_DEFINE (scm_sys_allocate_instance, "%allocate-instance", 2, 0, 0,
924 (SCM class, SCM initargs),
6bcefd15
MG
925 "Create a new instance of class @var{class} and initialize it\n"
926 "from the arguments @var{initargs}.")
398d8ee1 927#define FUNC_NAME s_scm_sys_allocate_instance
80662eda 928{
b6cf4d02 929 SCM obj;
e25f3727 930 scm_t_signed_bits n, i;
b6cf4d02 931 SCM layout;
80662eda 932
398d8ee1 933 SCM_VALIDATE_CLASS (1, class);
80662eda 934
b6cf4d02 935 /* FIXME: duplicates some of scm_make_struct. */
80662eda 936
e11e83f3 937 n = SCM_I_INUM (SCM_SLOT (class, scm_si_nfields));
96a44c1c 938 obj = scm_i_alloc_struct (SCM_STRUCT_DATA (class), n);
6d77c894 939
b6cf4d02
AW
940 layout = SCM_VTABLE_LAYOUT (class);
941
942 /* Set all SCM-holding slots to unbound */
943 for (i = 0; i < n; i++)
71fc6438
AW
944 {
945 scm_t_wchar c = scm_i_symbol_ref (layout, i*2);
b6cf4d02
AW
946 if (c == 'p')
947 SCM_STRUCT_DATA (obj)[i] = SCM_UNPACK (SCM_GOOPS_UNBOUND);
948 else if (c == 's')
949 SCM_STRUCT_DATA (obj)[i] = SCM_UNPACK (obj);
950 else
951 SCM_STRUCT_DATA (obj)[i] = 0;
80662eda 952 }
6d77c894 953
b6cf4d02 954 return obj;
80662eda 955}
398d8ee1 956#undef FUNC_NAME
80662eda 957
80662eda
MD
958/******************************************************************************
959 *
960 * %modify-instance (used by change-class to modify in place)
6d77c894 961 *
80662eda
MD
962 ******************************************************************************/
963
398d8ee1
KN
964SCM_DEFINE (scm_sys_modify_instance, "%modify-instance", 2, 0, 0,
965 (SCM old, SCM new),
966 "")
967#define FUNC_NAME s_scm_sys_modify_instance
80662eda 968{
398d8ee1
KN
969 SCM_VALIDATE_INSTANCE (1, old);
970 SCM_VALIDATE_INSTANCE (2, new);
80662eda 971
6d77c894 972 /* Exchange the data contained in old and new. We exchange rather than
80662eda
MD
973 * scratch the old value with new to be correct with GC.
974 * See "Class redefinition protocol above".
975 */
9de87eea 976 SCM_CRITICAL_SECTION_START;
80662eda 977 {
32b12f40
KR
978 scm_t_bits word0, word1;
979 word0 = SCM_CELL_WORD_0 (old);
980 word1 = SCM_CELL_WORD_1 (old);
981 SCM_SET_CELL_WORD_0 (old, SCM_CELL_WORD_0 (new));
982 SCM_SET_CELL_WORD_1 (old, SCM_CELL_WORD_1 (new));
983 SCM_SET_CELL_WORD_0 (new, word0);
984 SCM_SET_CELL_WORD_1 (new, word1);
80662eda 985 }
9de87eea 986 SCM_CRITICAL_SECTION_END;
80662eda
MD
987 return SCM_UNSPECIFIED;
988}
398d8ee1 989#undef FUNC_NAME
80662eda 990
398d8ee1
KN
991SCM_DEFINE (scm_sys_modify_class, "%modify-class", 2, 0, 0,
992 (SCM old, SCM new),
993 "")
994#define FUNC_NAME s_scm_sys_modify_class
80662eda 995{
398d8ee1
KN
996 SCM_VALIDATE_CLASS (1, old);
997 SCM_VALIDATE_CLASS (2, new);
80662eda 998
9de87eea 999 SCM_CRITICAL_SECTION_START;
80662eda 1000 {
32b12f40
KR
1001 scm_t_bits word0, word1;
1002 word0 = SCM_CELL_WORD_0 (old);
1003 word1 = SCM_CELL_WORD_1 (old);
1004 SCM_SET_CELL_WORD_0 (old, SCM_CELL_WORD_0 (new));
1005 SCM_SET_CELL_WORD_1 (old, SCM_CELL_WORD_1 (new));
b6cf4d02 1006 SCM_STRUCT_DATA (old)[scm_vtable_index_self] = SCM_UNPACK (old);
32b12f40
KR
1007 SCM_SET_CELL_WORD_0 (new, word0);
1008 SCM_SET_CELL_WORD_1 (new, word1);
b6cf4d02 1009 SCM_STRUCT_DATA (new)[scm_vtable_index_self] = SCM_UNPACK (new);
80662eda 1010 }
9de87eea 1011 SCM_CRITICAL_SECTION_END;
80662eda
MD
1012 return SCM_UNSPECIFIED;
1013}
398d8ee1 1014#undef FUNC_NAME
80662eda 1015
398d8ee1
KN
1016SCM_DEFINE (scm_sys_invalidate_class, "%invalidate-class", 1, 0, 0,
1017 (SCM class),
1018 "")
1019#define FUNC_NAME s_scm_sys_invalidate_class
80662eda 1020{
398d8ee1 1021 SCM_VALIDATE_CLASS (1, class);
80662eda
MD
1022 SCM_CLEAR_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_VALID);
1023 return SCM_UNSPECIFIED;
1024}
398d8ee1 1025#undef FUNC_NAME
80662eda
MD
1026
1027/* When instances change class, they finally get a new body, but
1028 * before that, they go through purgatory in hell. Odd as it may
1029 * seem, this data structure saves us from eternal suffering in
1030 * infinite recursions.
1031 */
1032
92c2555f 1033static scm_t_bits **hell;
c014a02e
ML
1034static long n_hell = 1; /* one place for the evil one himself */
1035static long hell_size = 4;
2132f0d2 1036static SCM hell_mutex;
80662eda 1037
c014a02e 1038static long
80662eda
MD
1039burnin (SCM o)
1040{
c014a02e 1041 long i;
80662eda 1042 for (i = 1; i < n_hell; ++i)
6b80d352 1043 if (SCM_STRUCT_DATA (o) == hell[i])
80662eda
MD
1044 return i;
1045 return 0;
1046}
1047
1048static void
1049go_to_hell (void *o)
1050{
b5df9cda 1051 SCM obj = *(SCM*)o;
2132f0d2 1052 scm_lock_mutex (hell_mutex);
51ef99f7 1053 if (n_hell >= hell_size)
80662eda 1054 {
51ef99f7 1055 hell_size *= 2;
408bcd99 1056 hell = scm_realloc (hell, hell_size * sizeof(*hell));
80662eda 1057 }
6b80d352 1058 hell[n_hell++] = SCM_STRUCT_DATA (obj);
2132f0d2 1059 scm_unlock_mutex (hell_mutex);
80662eda
MD
1060}
1061
1062static void
1063go_to_heaven (void *o)
1064{
b5df9cda 1065 SCM obj = *(SCM*)o;
2132f0d2 1066 scm_lock_mutex (hell_mutex);
b5df9cda 1067 hell[burnin (obj)] = hell[--n_hell];
2132f0d2 1068 scm_unlock_mutex (hell_mutex);
80662eda
MD
1069}
1070
6b80d352
DH
1071
1072SCM_SYMBOL (scm_sym_change_class, "change-class");
1073
80662eda 1074static SCM
b5df9cda 1075purgatory (SCM obj, SCM new_class)
80662eda 1076{
b5df9cda 1077 return scm_call_2 (SCM_VARIABLE_REF (var_change_class), obj, new_class);
80662eda
MD
1078}
1079
38d8927c
MD
1080/* This function calls the generic function change-class for all
1081 * instances which aren't currently undergoing class change.
1082 */
1083
80662eda 1084void
e81d98ec 1085scm_change_object_class (SCM obj, SCM old_class SCM_UNUSED, SCM new_class)
80662eda
MD
1086{
1087 if (!burnin (obj))
b5df9cda
AW
1088 {
1089 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
1090 scm_dynwind_rewind_handler (go_to_hell, &obj, SCM_F_WIND_EXPLICITLY);
1091 scm_dynwind_unwind_handler (go_to_heaven, &obj, SCM_F_WIND_EXPLICITLY);
1092 purgatory (obj, new_class);
1093 scm_dynwind_end ();
1094 }
80662eda
MD
1095}
1096
1097/******************************************************************************
1098 *
6d77c894
TTN
1099 * GGGG FFFFF
1100 * G F
1101 * G GG FFF
1102 * G G F
80662eda
MD
1103 * GGG E N E R I C F U N C T I O N S
1104 *
1105 * This implementation provides
1106 * - generic functions (with class specializers)
1107 * - multi-methods
6d77c894 1108 * - next-method
80662eda
MD
1109 * - a hard-coded MOP for standard gf, which can be overloaded for non-std gf
1110 *
1111 ******************************************************************************/
1112
1113SCM_KEYWORD (k_name, "name");
63c1872f 1114SCM_GLOBAL_SYMBOL (scm_sym_args, "args");
80662eda 1115
398d8ee1
KN
1116SCM_DEFINE (scm_generic_capability_p, "generic-capability?", 1, 0, 0,
1117 (SCM proc),
1118 "")
1119#define FUNC_NAME s_scm_generic_capability_p
80662eda 1120{
7888309b 1121 SCM_ASSERT (scm_is_true (scm_procedure_p (proc)),
398d8ee1 1122 proc, SCM_ARG1, FUNC_NAME);
9fdf9fd3 1123 return (SCM_PRIMITIVE_GENERIC_P (proc) ? SCM_BOOL_T : SCM_BOOL_F);
80662eda 1124}
398d8ee1 1125#undef FUNC_NAME
80662eda 1126
398d8ee1
KN
1127SCM_DEFINE (scm_enable_primitive_generic_x, "enable-primitive-generic!", 0, 0, 1,
1128 (SCM subrs),
1129 "")
1130#define FUNC_NAME s_scm_enable_primitive_generic_x
80662eda 1131{
6b80d352 1132 SCM_VALIDATE_REST_ARGUMENT (subrs);
d2e53ed6 1133 while (!scm_is_null (subrs))
80662eda
MD
1134 {
1135 SCM subr = SCM_CAR (subrs);
9fdf9fd3 1136 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARGn, FUNC_NAME);
52fd9639 1137 SCM_SET_SUBR_GENERIC (subr,
57898597 1138 scm_make (scm_list_3 (class_generic,
52fd9639
AW
1139 k_name,
1140 SCM_SUBR_NAME (subr))));
80662eda
MD
1141 subrs = SCM_CDR (subrs);
1142 }
1143 return SCM_UNSPECIFIED;
1144}
398d8ee1 1145#undef FUNC_NAME
80662eda 1146
9f63ce02
AW
1147SCM_DEFINE (scm_set_primitive_generic_x, "set-primitive-generic!", 2, 0, 0,
1148 (SCM subr, SCM generic),
1149 "")
1150#define FUNC_NAME s_scm_set_primitive_generic_x
1151{
9fdf9fd3 1152 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARG1, FUNC_NAME);
9f63ce02 1153 SCM_ASSERT (SCM_PUREGENERICP (generic), generic, SCM_ARG2, FUNC_NAME);
52fd9639 1154 SCM_SET_SUBR_GENERIC (subr, generic);
9f63ce02
AW
1155 return SCM_UNSPECIFIED;
1156}
1157#undef FUNC_NAME
1158
398d8ee1
KN
1159SCM_DEFINE (scm_primitive_generic_generic, "primitive-generic-generic", 1, 0, 0,
1160 (SCM subr),
1161 "")
1162#define FUNC_NAME s_scm_primitive_generic_generic
80662eda 1163{
9fdf9fd3 1164 if (SCM_PRIMITIVE_GENERIC_P (subr))
80662eda 1165 {
b2b33168 1166 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (subr)))
a48d60b1
MD
1167 scm_enable_primitive_generic_x (scm_list_1 (subr));
1168 return *SCM_SUBR_GENERIC (subr);
80662eda 1169 }
db4b4ca6 1170 SCM_WRONG_TYPE_ARG (SCM_ARG1, subr);
80662eda 1171}
398d8ee1 1172#undef FUNC_NAME
80662eda 1173
a48d60b1
MD
1174typedef struct t_extension {
1175 struct t_extension *next;
1176 SCM extended;
1177 SCM extension;
1178} t_extension;
1179
d0cad249
LC
1180
1181/* Hint for `scm_gc_malloc ()' et al. when allocating `t_extension'
1182 objects. */
1183static const char extension_gc_hint[] = "GOOPS extension";
1184
a48d60b1
MD
1185static t_extension *extensions = 0;
1186
a48d60b1
MD
1187void
1188scm_c_extend_primitive_generic (SCM extended, SCM extension)
1189{
1190 if (goops_loaded_p)
1191 {
1192 SCM gf, gext;
b2b33168 1193 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (extended)))
a48d60b1
MD
1194 scm_enable_primitive_generic_x (scm_list_1 (extended));
1195 gf = *SCM_SUBR_GENERIC (extended);
1196 gext = scm_call_2 (SCM_VARIABLE_REF (scm_var_make_extended_generic),
1197 gf,
ce471ab8 1198 SCM_SUBR_NAME (extension));
feccd2d3 1199 SCM_SET_SUBR_GENERIC (extension, gext);
a48d60b1
MD
1200 }
1201 else
1202 {
d0cad249
LC
1203 t_extension *e = scm_gc_malloc (sizeof (t_extension),
1204 extension_gc_hint);
a48d60b1
MD
1205 t_extension **loc = &extensions;
1206 /* Make sure that extensions are placed before their own
1207 * extensions in the extensions list. O(N^2) algorithm, but
1208 * extensions of primitive generics are rare.
1209 */
d223c3fc 1210 while (*loc && !scm_is_eq (extension, (*loc)->extended))
a48d60b1
MD
1211 loc = &(*loc)->next;
1212 e->next = *loc;
1213 e->extended = extended;
1214 e->extension = extension;
1215 *loc = e;
1216 }
1217}
1218
1219static void
1220setup_extended_primitive_generics ()
1221{
1222 while (extensions)
1223 {
1224 t_extension *e = extensions;
1225 scm_c_extend_primitive_generic (e->extended, e->extension);
1226 extensions = e->next;
a48d60b1
MD
1227 }
1228}
1229
fa075d40
AW
1230/* Dirk:FIXME:: In all of these scm_wta_dispatch_* routines it is
1231 * assumed that 'gf' is zero if uninitialized. It would be cleaner if
1232 * some valid SCM value like SCM_BOOL_F or SCM_UNDEFINED were chosen.
1233 */
1234
1235SCM
1236scm_wta_dispatch_0 (SCM gf, const char *subr)
1237{
1238 if (!SCM_UNPACK (gf))
1239 scm_error_num_args_subr (subr);
1240
1241 return scm_call_0 (gf);
1242}
1243
1244SCM
1245scm_wta_dispatch_1 (SCM gf, SCM a1, int pos, const char *subr)
1246{
1247 if (!SCM_UNPACK (gf))
1248 scm_wrong_type_arg (subr, pos, a1);
1249
1250 return scm_call_1 (gf, a1);
1251}
1252
1253SCM
1254scm_wta_dispatch_2 (SCM gf, SCM a1, SCM a2, int pos, const char *subr)
1255{
1256 if (!SCM_UNPACK (gf))
1257 scm_wrong_type_arg (subr, pos, (pos == SCM_ARG1) ? a1 : a2);
1258
1259 return scm_call_2 (gf, a1, a2);
1260}
1261
1262SCM
1263scm_wta_dispatch_n (SCM gf, SCM args, int pos, const char *subr)
1264{
1265 if (!SCM_UNPACK (gf))
1266 scm_wrong_type_arg (subr, pos, scm_list_ref (args, scm_from_int (pos)));
1267
1268 return scm_apply_0 (gf, args);
1269}
1270
80662eda 1271/******************************************************************************
6d77c894 1272 *
80662eda 1273 * Protocol for calling a generic fumction
6d77c894 1274 * This protocol is roughly equivalent to (parameter are a little bit different
80662eda
MD
1275 * for efficiency reasons):
1276 *
1277 * + apply-generic (gf args)
1278 * + compute-applicable-methods (gf args ...)
1279 * + sort-applicable-methods (methods args)
1280 * + apply-methods (gf methods args)
6d77c894
TTN
1281 *
1282 * apply-methods calls make-next-method to build the "continuation" of a a
80662eda
MD
1283 * method. Applying a next-method will call apply-next-method which in
1284 * turn will call apply again to call effectively the following method.
1285 *
1286 ******************************************************************************/
1287
398d8ee1
KN
1288SCM_DEFINE (scm_make, "make", 0, 0, 1,
1289 (SCM args),
27c37006 1290 "Make a new object. @var{args} must contain the class and\n"
6bcefd15 1291 "all necessary initialization information.")
398d8ee1 1292#define FUNC_NAME s_scm_make
80662eda 1293{
e0590e7c 1294 return scm_apply_0 (scm_variable_ref (var_make), args);
80662eda 1295}
398d8ee1 1296#undef FUNC_NAME
80662eda 1297
80662eda 1298
80662eda
MD
1299/**********************************************************************
1300 *
1301 * Smob classes
1302 *
1303 **********************************************************************/
1304
1305static SCM
2e0b6934 1306make_class_name (const char *prefix, const char *type_name, const char *suffix)
80662eda 1307{
2e0b6934
AW
1308 if (!type_name)
1309 type_name = "";
1310 return scm_string_to_symbol (scm_string_append
1311 (scm_list_3 (scm_from_utf8_string (prefix),
1312 scm_from_utf8_string (type_name),
1313 scm_from_utf8_string (suffix))));
80662eda
MD
1314}
1315
1316SCM
da0e6c2b 1317scm_make_extended_class (char const *type_name, int applicablep)
80662eda 1318{
2e0b6934
AW
1319 SCM name, meta, supers;
1320
1321 name = make_class_name ("<", type_name, ">");
1322 meta = class_class;
1323
1324 if (applicablep)
1325 supers = scm_list_1 (class_applicable);
1326 else
1327 supers = scm_list_1 (class_top);
1328
1329 return scm_make_standard_class (meta, name, supers, SCM_EOL);
74b6d6e4
MD
1330}
1331
1332void
1333scm_i_inherit_applicable (SCM c)
1334{
57898597 1335 if (!SCM_SUBCLASSP (c, class_applicable))
74b6d6e4
MD
1336 {
1337 SCM dsupers = SCM_SLOT (c, scm_si_direct_supers);
1338 SCM cpl = SCM_SLOT (c, scm_si_cpl);
57898597
AW
1339 /* patch class_applicable into direct-supers */
1340 SCM top = scm_c_memq (class_top, dsupers);
7888309b 1341 if (scm_is_false (top))
74b6d6e4 1342 dsupers = scm_append (scm_list_2 (dsupers,
57898597 1343 scm_list_1 (class_applicable)));
74b6d6e4
MD
1344 else
1345 {
57898597
AW
1346 SCM_SETCAR (top, class_applicable);
1347 SCM_SETCDR (top, scm_cons (class_top, SCM_CDR (top)));
74b6d6e4
MD
1348 }
1349 SCM_SET_SLOT (c, scm_si_direct_supers, dsupers);
57898597
AW
1350 /* patch class_applicable into cpl */
1351 top = scm_c_memq (class_top, cpl);
7888309b 1352 if (scm_is_false (top))
74b6d6e4
MD
1353 abort ();
1354 else
1355 {
57898597
AW
1356 SCM_SETCAR (top, class_applicable);
1357 SCM_SETCDR (top, scm_cons (class_top, SCM_CDR (top)));
74b6d6e4 1358 }
57898597
AW
1359 /* add class to direct-subclasses of class_applicable */
1360 SCM_SET_SLOT (class_applicable,
74b6d6e4 1361 scm_si_direct_subclasses,
57898597 1362 scm_cons (c, SCM_SLOT (class_applicable,
74b6d6e4
MD
1363 scm_si_direct_subclasses)));
1364 }
80662eda
MD
1365}
1366
1367static void
1368create_smob_classes (void)
1369{
c014a02e 1370 long i;
80662eda 1371
c891a40e 1372 for (i = 0; i < SCM_I_MAX_SMOB_TYPE_COUNT; ++i)
57898597 1373 scm_i_smob_class[i] = SCM_BOOL_F;
80662eda 1374
80662eda 1375 for (i = 0; i < scm_numsmob; ++i)
57898597
AW
1376 if (scm_is_false (scm_i_smob_class[i]))
1377 scm_i_smob_class[i] = scm_make_extended_class (SCM_SMOBNAME (i),
1378 scm_smobs[i].apply != 0);
80662eda
MD
1379}
1380
1381void
c014a02e 1382scm_make_port_classes (long ptobnum, char *type_name)
80662eda 1383{
2e0b6934
AW
1384 SCM name, meta, super, supers;
1385
1386 meta = class_class;
1387
1388 name = make_class_name ("<", type_name, "-port>");
1389 supers = scm_list_1 (class_port);
1390 super = scm_make_standard_class (meta, name, supers, SCM_EOL);
1391
1392 name = make_class_name ("<", type_name, "-input-port>");
1393 supers = scm_list_2 (super, class_input_port);
57898597 1394 scm_i_port_class[SCM_IN_PCLASS_INDEX + ptobnum]
2e0b6934
AW
1395 = scm_make_standard_class (meta, name, supers, SCM_EOL);
1396
1397 name = make_class_name ("<", type_name, "-output-port>");
1398 supers = scm_list_2 (super, class_output_port);
57898597 1399 scm_i_port_class[SCM_OUT_PCLASS_INDEX + ptobnum]
2e0b6934
AW
1400 = scm_make_standard_class (meta, name, supers, SCM_EOL);
1401
1402 name = make_class_name ("<", type_name, "-input-output-port>");
1403 supers = scm_list_2 (super, class_input_output_port);
57898597 1404 scm_i_port_class[SCM_INOUT_PCLASS_INDEX + ptobnum]
2e0b6934 1405 = scm_make_standard_class (meta, name, supers, SCM_EOL);
80662eda
MD
1406}
1407
1408static void
1409create_port_classes (void)
1410{
c014a02e 1411 long i;
80662eda 1412
62bd5d66 1413 for (i = scm_c_num_port_types () - 1; i >= 0; i--)
80662eda
MD
1414 scm_make_port_classes (i, SCM_PTOBNAME (i));
1415}
1416
6c7dd9eb
AW
1417SCM
1418scm_i_define_class_for_vtable (SCM vtable)
1419{
1420 SCM class;
1421
1422 scm_i_pthread_mutex_lock (&scm_i_misc_mutex);
1423 if (scm_is_false (vtable_class_map))
1424 vtable_class_map = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
1425 scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
1426
1427 if (scm_is_false (scm_struct_vtable_p (vtable)))
1428 abort ();
1429
1430 class = scm_weak_table_refq (vtable_class_map, vtable, SCM_BOOL_F);
1431
1432 if (scm_is_false (class))
1433 {
57898597 1434 if (SCM_UNPACK (class_class))
6c7dd9eb
AW
1435 {
1436 SCM name, meta, supers;
1437
1438 name = SCM_VTABLE_NAME (vtable);
1439 if (scm_is_symbol (name))
1440 name = scm_string_to_symbol
1441 (scm_string_append
1442 (scm_list_3 (scm_from_latin1_string ("<"),
1443 scm_symbol_to_string (name),
1444 scm_from_latin1_string (">"))));
1445 else
1446 name = scm_from_latin1_symbol ("<>");
1447
1448 if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SETTER))
1449 {
57898597
AW
1450 meta = class_applicable_struct_with_setter_class;
1451 supers = scm_list_1 (class_applicable_struct_with_setter);
6c7dd9eb
AW
1452 }
1453 else if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable,
1454 SCM_VTABLE_FLAG_APPLICABLE))
1455 {
57898597
AW
1456 meta = class_applicable_struct_class;
1457 supers = scm_list_1 (class_applicable_struct);
6c7dd9eb
AW
1458 }
1459 else
1460 {
57898597
AW
1461 meta = class_class;
1462 supers = scm_list_1 (class_top);
6c7dd9eb
AW
1463 }
1464
1465 return scm_make_standard_class (meta, name, supers, SCM_EOL);
1466 }
1467 else
1468 /* `create_struct_classes' will fill this in later. */
1469 class = SCM_BOOL_F;
1470
1471 /* Don't worry about races. This only happens when creating a
1472 vtable, which happens by definition in one thread. */
1473 scm_weak_table_putq_x (vtable_class_map, vtable, class);
1474 }
1475
1476 return class;
1477}
1478
80662eda 1479static SCM
74b6d6e4
MD
1480make_struct_class (void *closure SCM_UNUSED,
1481 SCM vtable, SCM data, SCM prev SCM_UNUSED)
80662eda 1482{
f3c6a02c
AW
1483 if (scm_is_false (data))
1484 scm_i_define_class_for_vtable (vtable);
80662eda
MD
1485 return SCM_UNSPECIFIED;
1486}
1487
1488static void
1489create_struct_classes (void)
1490{
ea742d29 1491 /* FIXME: take the vtable_class_map while initializing goops? */
f3c6a02c
AW
1492 scm_internal_hash_fold (make_struct_class, 0, SCM_BOOL_F,
1493 vtable_class_map);
80662eda
MD
1494}
1495
1496/**********************************************************************
1497 *
1498 * C interface
1499 *
1500 **********************************************************************/
1501
1502void
1503scm_load_goops ()
1504{
1505 if (!goops_loaded_p)
abd28220 1506 scm_c_resolve_module ("oop goops");
80662eda
MD
1507}
1508
e11208ca 1509
e0590e7c
AW
1510SCM_KEYWORD (k_setter, "setter");
1511
80662eda
MD
1512SCM
1513scm_ensure_accessor (SCM name)
1514{
3f48638c
AW
1515 SCM var, gf;
1516
1517 var = scm_module_variable (scm_current_module (), name);
1518 if (SCM_VARIABLEP (var) && !SCM_UNBNDP (SCM_VARIABLE_REF (var)))
1519 gf = SCM_VARIABLE_REF (var);
1520 else
1521 gf = SCM_BOOL_F;
1522
57898597 1523 if (!SCM_IS_A_P (gf, class_accessor))
80662eda 1524 {
57898597
AW
1525 gf = scm_make (scm_list_3 (class_generic, k_name, name));
1526 gf = scm_make (scm_list_5 (class_accessor,
1afff620 1527 k_name, name, k_setter, gf));
80662eda 1528 }
3f48638c 1529
80662eda
MD
1530 return gf;
1531}
1532
80662eda
MD
1533#ifdef GUILE_DEBUG
1534/*
1535 * Debugging utilities
1536 */
1537
398d8ee1
KN
1538SCM_DEFINE (scm_pure_generic_p, "pure-generic?", 1, 0, 0,
1539 (SCM obj),
6bcefd15 1540 "Return @code{#t} if @var{obj} is a pure generic.")
398d8ee1 1541#define FUNC_NAME s_scm_pure_generic_p
80662eda 1542{
7888309b 1543 return scm_from_bool (SCM_PUREGENERICP (obj));
80662eda 1544}
398d8ee1 1545#undef FUNC_NAME
80662eda
MD
1546
1547#endif /* GUILE_DEBUG */
1548
1549/*
1550 * Initialization
1551 */
1552
6c7dd9eb
AW
1553SCM_DEFINE (scm_sys_bless_applicable_struct_vtables_x, "%bless-applicable-struct-vtables!", 2, 0, 0,
1554 (SCM applicable, SCM setter),
51fd1cd6 1555 "")
6c7dd9eb 1556#define FUNC_NAME s_scm_sys_bless_applicable_struct_vtables_x
51fd1cd6 1557{
6c7dd9eb
AW
1558 SCM_VALIDATE_CLASS (1, applicable);
1559 SCM_VALIDATE_CLASS (2, setter);
1560 SCM_SET_VTABLE_FLAGS (applicable, SCM_VTABLE_FLAG_APPLICABLE_VTABLE);
1561 SCM_SET_VTABLE_FLAGS (setter, SCM_VTABLE_FLAG_SETTER_VTABLE);
51fd1cd6
AW
1562 return SCM_UNSPECIFIED;
1563}
1564#undef FUNC_NAME
1565
1566SCM_DEFINE (scm_sys_bless_pure_generic_vtable_x, "%bless-pure-generic-vtable!", 1, 0, 0,
1567 (SCM vtable),
1568 "")
1569#define FUNC_NAME s_scm_sys_bless_pure_generic_vtable_x
1570{
1571 SCM_VALIDATE_CLASS (1, vtable);
1572 SCM_SET_CLASS_FLAGS (vtable, SCM_CLASSF_PURE_GENERIC);
1573 return SCM_UNSPECIFIED;
1574}
1575#undef FUNC_NAME
1576
82ab5090
AW
1577SCM_DEFINE (scm_sys_goops_early_init, "%goops-early-init", 0, 0, 0,
1578 (),
1579 "")
1580#define FUNC_NAME s_scm_sys_goops_early_init
1581{
51fd1cd6 1582 var_make_standard_class = scm_c_lookup ("make-standard-class");
e0590e7c 1583 var_make = scm_c_lookup ("make");
70dd6000
AW
1584 var_class_name = scm_c_lookup ("class-name");
1585 var_class_direct_supers = scm_c_lookup ("class-direct-supers");
1586 var_class_direct_slots = scm_c_lookup ("class-direct-slots");
1587 var_class_direct_subclasses = scm_c_lookup ("class-direct-subclasses");
1588 var_class_direct_methods = scm_c_lookup ("class-direct-methods");
1589 var_class_precedence_list = scm_c_lookup ("class-precedence-list");
1590 var_class_slots = scm_c_lookup ("class-slots");
51fd1cd6 1591
57898597
AW
1592 class_class = scm_variable_ref (scm_c_lookup ("<class>"));
1593 class_top = scm_variable_ref (scm_c_lookup ("<top>"));
1594 class_object = scm_variable_ref (scm_c_lookup ("<object>"));
1595
1596 class_foreign_slot = scm_variable_ref (scm_c_lookup ("<foreign-slot>"));
1597 class_protected = scm_variable_ref (scm_c_lookup ("<protected-slot>"));
1598 class_hidden = scm_variable_ref (scm_c_lookup ("<hidden-slot>"));
1599 class_opaque = scm_variable_ref (scm_c_lookup ("<opaque-slot>"));
1600 class_read_only = scm_variable_ref (scm_c_lookup ("<read-only-slot>"));
1601 class_self = scm_variable_ref (scm_c_lookup ("<self-slot>"));
1602 class_protected_opaque = scm_variable_ref (scm_c_lookup ("<protected-opaque-slot>"));
1603 class_protected_hidden = scm_variable_ref (scm_c_lookup ("<protected-hidden-slot>"));
1604 class_protected_read_only = scm_variable_ref (scm_c_lookup ("<protected-read-only-slot>"));
1605 class_scm = scm_variable_ref (scm_c_lookup ("<scm-slot>"));
1606 class_int = scm_variable_ref (scm_c_lookup ("<int-slot>"));
1607 class_float = scm_variable_ref (scm_c_lookup ("<float-slot>"));
1608 class_double = scm_variable_ref (scm_c_lookup ("<double-slot>"));
1609
1610 /* Applicables */
1611 class_procedure_class = scm_variable_ref (scm_c_lookup ("<procedure-class>"));
1612 class_applicable_struct_class = scm_variable_ref (scm_c_lookup ("<applicable-struct-class>"));
1613 class_applicable_struct_with_setter_class =
6c7dd9eb 1614 scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter-class>"));
51fd1cd6 1615
57898597
AW
1616 class_method = scm_variable_ref (scm_c_lookup ("<method>"));
1617 class_accessor_method = scm_variable_ref (scm_c_lookup ("<accessor-method>"));
1618 class_applicable = scm_variable_ref (scm_c_lookup ("<applicable>"));
1619 class_applicable_struct = scm_variable_ref (scm_c_lookup ("<applicable-struct>"));
1620 class_applicable_struct_with_setter = scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter>"));
1621 class_generic = scm_variable_ref (scm_c_lookup ("<generic>"));
1622 class_extended_generic = scm_variable_ref (scm_c_lookup ("<extended-generic>"));
1623 class_generic_with_setter = scm_variable_ref (scm_c_lookup ("<generic-with-setter>"));
1624 class_accessor = scm_variable_ref (scm_c_lookup ("<accessor>"));
1625 class_extended_generic_with_setter = scm_variable_ref (scm_c_lookup ("<extended-generic-with-setter>"));
1626 class_extended_accessor = scm_variable_ref (scm_c_lookup ("<extended-accessor>"));
51fd1cd6
AW
1627
1628 /* Primitive types classes */
57898597
AW
1629 class_boolean = scm_variable_ref (scm_c_lookup ("<boolean>"));
1630 class_char = scm_variable_ref (scm_c_lookup ("<char>"));
1631 class_list = scm_variable_ref (scm_c_lookup ("<list>"));
1632 class_pair = scm_variable_ref (scm_c_lookup ("<pair>"));
1633 class_null = scm_variable_ref (scm_c_lookup ("<null>"));
1634 class_string = scm_variable_ref (scm_c_lookup ("<string>"));
1635 class_symbol = scm_variable_ref (scm_c_lookup ("<symbol>"));
1636 class_vector = scm_variable_ref (scm_c_lookup ("<vector>"));
51fd1cd6
AW
1637 class_foreign = scm_variable_ref (scm_c_lookup ("<foreign>"));
1638 class_hashtable = scm_variable_ref (scm_c_lookup ("<hashtable>"));
1639 class_fluid = scm_variable_ref (scm_c_lookup ("<fluid>"));
1640 class_dynamic_state = scm_variable_ref (scm_c_lookup ("<dynamic-state>"));
1641 class_frame = scm_variable_ref (scm_c_lookup ("<frame>"));
1642 class_vm_cont = scm_variable_ref (scm_c_lookup ("<vm-continuation>"));
1643 class_bytevector = scm_variable_ref (scm_c_lookup ("<bytevector>"));
1644 class_uvec = scm_variable_ref (scm_c_lookup ("<uvec>"));
1645 class_array = scm_variable_ref (scm_c_lookup ("<array>"));
1646 class_bitvector = scm_variable_ref (scm_c_lookup ("<bitvector>"));
57898597
AW
1647 class_number = scm_variable_ref (scm_c_lookup ("<number>"));
1648 class_complex = scm_variable_ref (scm_c_lookup ("<complex>"));
1649 class_real = scm_variable_ref (scm_c_lookup ("<real>"));
1650 class_integer = scm_variable_ref (scm_c_lookup ("<integer>"));
1651 class_fraction = scm_variable_ref (scm_c_lookup ("<fraction>"));
1652 class_keyword = scm_variable_ref (scm_c_lookup ("<keyword>"));
1653 class_unknown = scm_variable_ref (scm_c_lookup ("<unknown>"));
1654 class_procedure = scm_variable_ref (scm_c_lookup ("<procedure>"));
1655 class_primitive_generic = scm_variable_ref (scm_c_lookup ("<primitive-generic>"));
1656 class_port = scm_variable_ref (scm_c_lookup ("<port>"));
1657 class_input_port = scm_variable_ref (scm_c_lookup ("<input-port>"));
1658 class_output_port = scm_variable_ref (scm_c_lookup ("<output-port>"));
1659 class_input_output_port = scm_variable_ref (scm_c_lookup ("<input-output-port>"));
51fd1cd6 1660
82ab5090
AW
1661 create_smob_classes ();
1662 create_struct_classes ();
1663 create_port_classes ();
1664
82ab5090
AW
1665 return SCM_UNSPECIFIED;
1666}
1667#undef FUNC_NAME
1668
398d8ee1
KN
1669SCM_DEFINE (scm_sys_goops_loaded, "%goops-loaded", 0, 0, 0,
1670 (),
6bcefd15
MG
1671 "Announce that GOOPS is loaded and perform initialization\n"
1672 "on the C level which depends on the loaded GOOPS modules.")
398d8ee1 1673#define FUNC_NAME s_scm_sys_goops_loaded
80662eda
MD
1674{
1675 goops_loaded_p = 1;
bef95911 1676 var_slot_unbound =
f39448c5 1677 scm_module_variable (scm_module_goops, sym_slot_unbound);
bef95911 1678 var_slot_missing =
f39448c5 1679 scm_module_variable (scm_module_goops, sym_slot_missing);
bef95911 1680 var_change_class =
f39448c5 1681 scm_module_variable (scm_module_goops, sym_change_class);
a48d60b1 1682 setup_extended_primitive_generics ();
623559f3
AW
1683
1684#if (SCM_ENABLE_DEPRECATED == 1)
1685 scm_init_deprecated_goops ();
1686#endif
1687
80662eda
MD
1688 return SCM_UNSPECIFIED;
1689}
398d8ee1 1690#undef FUNC_NAME
80662eda
MD
1691
1692SCM scm_module_goops;
1693
6ab19396
AW
1694static void
1695scm_init_goops_builtins (void *unused)
80662eda 1696{
abd28220 1697 scm_module_goops = scm_current_module ();
80662eda 1698
bb764c0e 1699 hell = scm_calloc (hell_size * sizeof (*hell));
f39448c5 1700 hell_mutex = scm_make_mutex ();
80662eda 1701
82ab5090 1702#include "libguile/goops.x"
80662eda
MD
1703}
1704
1705void
abd28220 1706scm_init_goops ()
80662eda 1707{
6ab19396
AW
1708 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
1709 "scm_init_goops_builtins", scm_init_goops_builtins,
1710 NULL);
80662eda 1711}
23437298
DH
1712
1713/*
1714 Local Variables:
1715 c-file-style: "gnu"
1716 End:
1717*/