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