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