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