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