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