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