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