%init-goops-builtins is an extension, not a global
[bpt/guile.git] / libguile / goops.c
CommitLineData
e2fafeb9 1/* Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2008,2009,2010,2011,2012,2013,2014,2015
366ecaec 2 * Free Software Foundation, Inc.
6d77c894 3 *
73be1d9e 4 * This library is free software; you can redistribute it and/or
53befeb7
NJ
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation; either version 3 of
7 * the License, or (at your option) any later version.
6d77c894 8 *
53befeb7
NJ
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
6d77c894 13 *
73be1d9e
MV
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
53befeb7
NJ
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA
73be1d9e 18 */
80662eda
MD
19\f
20
21/* This software is a derivative work of other copyrighted softwares; the
22 * copyright notices of these softwares are placed in the file COPYRIGHTS
23 *
24 * This file is based upon stklos.c from the STk distribution by
25 * Erick Gallesio <eg@unice.fr>.
26 */
27
dbb605f5
LC
28#ifdef HAVE_CONFIG_H
29# include <config.h>
30#endif
31
80662eda
MD
32#include <stdio.h>
33
34#include "libguile/_scm.h"
35#include "libguile/alist.h"
4e047c3e 36#include "libguile/async.h"
539d5410 37#include "libguile/chars.h"
80662eda
MD
38#include "libguile/debug.h"
39#include "libguile/dynl.h"
40#include "libguile/dynwind.h"
41#include "libguile/eval.h"
9fdf9fd3 42#include "libguile/gsubr.h"
80662eda
MD
43#include "libguile/hashtab.h"
44#include "libguile/keywords.h"
45#include "libguile/macros.h"
46#include "libguile/modules.h"
80662eda
MD
47#include "libguile/ports.h"
48#include "libguile/procprop.h"
efcebb5b 49#include "libguile/programs.h"
80662eda 50#include "libguile/random.h"
fdc28395 51#include "libguile/root.h"
80662eda
MD
52#include "libguile/smob.h"
53#include "libguile/strings.h"
54#include "libguile/strports.h"
55#include "libguile/vectors.h"
efcebb5b 56#include "libguile/vm.h"
80662eda 57
ca83b028 58#include "libguile/validate.h"
80662eda
MD
59#include "libguile/goops.h"
60
efcebb5b
AW
61/* Port classes */
62#define SCM_IN_PCLASS_INDEX 0
63#define SCM_OUT_PCLASS_INDEX SCM_I_MAX_PORT_TYPE_COUNT
64#define SCM_INOUT_PCLASS_INDEX (2 * SCM_I_MAX_PORT_TYPE_COUNT)
65
bef95911
AW
66/* this file is a mess. in theory, though, we shouldn't have many SCM references
67 -- most of the references should be to vars. */
68
69static SCM var_slot_unbound = SCM_BOOL_F;
70static SCM var_slot_missing = SCM_BOOL_F;
71static SCM var_compute_cpl = SCM_BOOL_F;
72static SCM var_no_applicable_method = SCM_BOOL_F;
bef95911
AW
73static SCM var_change_class = SCM_BOOL_F;
74
75SCM_SYMBOL (sym_slot_unbound, "slot-unbound");
76SCM_SYMBOL (sym_slot_missing, "slot-missing");
77SCM_SYMBOL (sym_compute_cpl, "compute-cpl");
78SCM_SYMBOL (sym_no_applicable_method, "no-applicable-method");
79SCM_SYMBOL (sym_memoize_method_x, "memoize-method!");
80SCM_SYMBOL (sym_change_class, "change-class");
81
82SCM_VARIABLE (scm_var_make_extended_generic, "make-extended-generic");
83
84
80662eda
MD
85/* Class redefinition protocol:
86
87 A class is represented by a heap header h1 which points to a
88 malloc:ed memory block m1.
89
90 When a new version of a class is created, a new header h2 and
91 memory block m2 are allocated. The headers h1 and h2 then switch
92 pointers so that h1 refers to m2 and h2 to m1. In this way, names
93 bound to h1 will point to the new class at the same time as h2 will
7346de61 94 be a handle which the GC will use to free m1.
80662eda
MD
95
96 The `redefined' slot of m1 will be set to point to h1. An old
7346de61 97 instance will have its class pointer (the CAR of the heap header)
80662eda
MD
98 pointing to m1. The non-immediate `redefined'-slot in m1 indicates
99 the class modification and the new class pointer can be found via
100 h1.
101*/
102
0fd7dcd3
MD
103#define TEST_CHANGE_CLASS(obj, class) \
104 { \
105 class = SCM_CLASS_OF (obj); \
7888309b 106 if (scm_is_true (SCM_OBJ_CLASS_REDEF (obj))) \
0fd7dcd3
MD
107 { \
108 scm_change_object_class (obj, class, SCM_OBJ_CLASS_REDEF (obj));\
109 class = SCM_CLASS_OF (obj); \
110 } \
80662eda
MD
111 }
112
80662eda 113#define SCM_GOOPS_UNBOUND SCM_UNBOUND
d223c3fc 114#define SCM_GOOPS_UNBOUNDP(x) (scm_is_eq (x, SCM_GOOPS_UNBOUND))
80662eda
MD
115
116static int goops_loaded_p = 0;
92c2555f 117static scm_t_rstate *goops_rstate;
80662eda 118
539d5410
MV
119/* These variables are filled in by the object system when loaded. */
120SCM scm_class_boolean, scm_class_char, scm_class_pair;
121SCM scm_class_procedure, scm_class_string, scm_class_symbol;
ea68d342 122SCM scm_class_primitive_generic;
9ea31741 123SCM scm_class_vector, scm_class_null;
539d5410
MV
124SCM scm_class_integer, scm_class_real, scm_class_complex, scm_class_fraction;
125SCM scm_class_unknown;
80662eda 126SCM scm_class_top, scm_class_object, scm_class_class;
74b6d6e4 127SCM scm_class_applicable;
51f66c91 128SCM scm_class_applicable_struct, scm_class_applicable_struct_with_setter;
bbf8d523 129SCM scm_class_generic, scm_class_generic_with_setter;
f8af5c6d 130SCM scm_class_accessor;
bbf8d523 131SCM scm_class_extended_generic, scm_class_extended_generic_with_setter;
74b6d6e4 132SCM scm_class_extended_accessor;
bbf8d523 133SCM scm_class_method;
51f66c91 134SCM scm_class_accessor_method;
80662eda 135SCM scm_class_procedure_class;
51f66c91 136SCM scm_class_applicable_struct_class;
80662eda
MD
137SCM scm_class_number, scm_class_list;
138SCM scm_class_keyword;
139SCM scm_class_port, scm_class_input_output_port;
140SCM scm_class_input_port, scm_class_output_port;
80662eda
MD
141SCM scm_class_foreign_slot;
142SCM scm_class_self, scm_class_protected;
b6cf4d02
AW
143SCM scm_class_hidden, scm_class_opaque, scm_class_read_only;
144SCM scm_class_protected_hidden, scm_class_protected_opaque, scm_class_protected_read_only;
80662eda
MD
145SCM scm_class_scm;
146SCM scm_class_int, scm_class_float, scm_class_double;
147
e2c2a699 148static SCM class_foreign;
9ea31741
AW
149static SCM class_hashtable;
150static SCM class_fluid;
151static SCM class_dynamic_state;
6f3b0cc2 152static SCM class_frame;
6f3b0cc2 153static SCM class_vm_cont;
f826a886
AW
154static SCM class_bytevector;
155static SCM class_uvec;
b2637c98 156static SCM class_array;
ff1feca9 157static SCM class_bitvector;
9ea31741 158
f3c6a02c
AW
159static SCM vtable_class_map = SCM_BOOL_F;
160
63385df2
LC
161/* Port classes. Allocate 3 times the maximum number of port types so that
162 input ports, output ports, and in/out ports can be stored at different
163 offsets. See `SCM_IN_PCLASS_INDEX' et al. */
164SCM scm_port_class[3 * SCM_I_MAX_PORT_TYPE_COUNT];
165
166/* SMOB classes. */
47455469 167SCM scm_smob_class[SCM_I_MAX_SMOB_TYPE_COUNT];
539d5410
MV
168
169SCM scm_no_applicable_method;
170
80662eda
MD
171static SCM scm_make_unbound (void);
172static SCM scm_unbound_p (SCM obj);
398d8ee1
KN
173static SCM scm_assert_bound (SCM value, SCM obj);
174static SCM scm_at_assert_bound_ref (SCM obj, SCM index);
175static SCM scm_sys_goops_loaded (void);
9db8cf16
MG
176static SCM scm_make_extended_class_from_symbol (SCM type_name_sym,
177 int applicablep);
80662eda 178
f3c6a02c
AW
179
180SCM
181scm_i_define_class_for_vtable (SCM vtable)
182{
183 SCM class;
184
203a92b6 185 scm_i_pthread_mutex_lock (&scm_i_misc_mutex);
f3c6a02c 186 if (scm_is_false (vtable_class_map))
203a92b6
AW
187 vtable_class_map = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
188 scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
f3c6a02c
AW
189
190 if (scm_is_false (scm_struct_vtable_p (vtable)))
191 abort ();
192
203a92b6 193 class = scm_weak_table_refq (vtable_class_map, vtable, SCM_BOOL_F);
ea742d29 194
f3c6a02c
AW
195 if (scm_is_false (class))
196 {
197 if (SCM_UNPACK (scm_class_class))
198 {
199 SCM name = SCM_VTABLE_NAME (vtable);
200 if (!scm_is_symbol (name))
201 name = scm_string_to_symbol (scm_nullstr);
202
203 class = scm_make_extended_class_from_symbol
204 (name, SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_APPLICABLE));
205 }
206 else
207 /* `create_struct_classes' will fill this in later. */
208 class = SCM_BOOL_F;
ea742d29
AW
209
210 /* Don't worry about races. This only happens when creating a
211 vtable, which happens by definition in one thread. */
203a92b6 212 scm_weak_table_putq_x (vtable_class_map, vtable, class);
f3c6a02c
AW
213 }
214
215 return class;
216}
217
539d5410
MV
218/* This function is used for efficient type dispatch. */
219SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0,
220 (SCM x),
221 "Return the class of @var{x}.")
222#define FUNC_NAME s_scm_class_of
223{
224 switch (SCM_ITAG3 (x))
225 {
226 case scm_tc3_int_1:
227 case scm_tc3_int_2:
228 return scm_class_integer;
229
230 case scm_tc3_imm24:
231 if (SCM_CHARP (x))
232 return scm_class_char;
233 else if (scm_is_bool (x))
234 return scm_class_boolean;
235 else if (scm_is_null (x))
236 return scm_class_null;
237 else
238 return scm_class_unknown;
239
240 case scm_tc3_cons:
241 switch (SCM_TYP7 (x))
242 {
243 case scm_tcs_cons_nimcar:
244 return scm_class_pair;
539d5410
MV
245 case scm_tc7_symbol:
246 return scm_class_symbol;
247 case scm_tc7_vector:
248 case scm_tc7_wvect:
249 return scm_class_vector;
5b46a8c2 250 case scm_tc7_pointer:
e2c2a699 251 return class_foreign;
c99de5aa 252 case scm_tc7_hashtable:
9ea31741
AW
253 return class_hashtable;
254 case scm_tc7_fluid:
255 return class_fluid;
256 case scm_tc7_dynamic_state:
257 return class_dynamic_state;
6f3b0cc2
AW
258 case scm_tc7_frame:
259 return class_frame;
e2fafeb9
AW
260 case scm_tc7_keyword:
261 return scm_class_keyword;
6f3b0cc2
AW
262 case scm_tc7_vm_cont:
263 return class_vm_cont;
f826a886
AW
264 case scm_tc7_bytevector:
265 if (SCM_BYTEVECTOR_ELEMENT_TYPE (x) == SCM_ARRAY_ELEMENT_TYPE_VU8)
266 return class_bytevector;
267 else
268 return class_uvec;
b2637c98
AW
269 case scm_tc7_array:
270 return class_array;
ff1feca9
AW
271 case scm_tc7_bitvector:
272 return class_bitvector;
539d5410
MV
273 case scm_tc7_string:
274 return scm_class_string;
275 case scm_tc7_number:
276 switch SCM_TYP16 (x) {
277 case scm_tc16_big:
278 return scm_class_integer;
279 case scm_tc16_real:
280 return scm_class_real;
281 case scm_tc16_complex:
282 return scm_class_complex;
283 case scm_tc16_fraction:
284 return scm_class_fraction;
285 }
e0755cd1 286 case scm_tc7_program:
b2b33168
AW
287 if (SCM_PROGRAM_IS_PRIMITIVE_GENERIC (x)
288 && SCM_UNPACK (*SCM_SUBR_GENERIC (x)))
fd12a19a
AW
289 return scm_class_primitive_generic;
290 else
291 return scm_class_procedure;
539d5410
MV
292
293 case scm_tc7_smob:
294 {
295 scm_t_bits type = SCM_TYP16 (x);
296 if (type != scm_tc16_port_with_ps)
297 return scm_smob_class[SCM_TC2SMOBNUM (type)];
298 x = SCM_PORT_WITH_PS_PORT (x);
299 /* fall through to ports */
300 }
301 case scm_tc7_port:
302 return scm_port_class[(SCM_WRTNG & SCM_CELL_WORD_0 (x)
303 ? (SCM_RDNG & SCM_CELL_WORD_0 (x)
304 ? SCM_INOUT_PCLASS_INDEX | SCM_PTOBNUM (x)
305 : SCM_OUT_PCLASS_INDEX | SCM_PTOBNUM (x))
306 : SCM_IN_PCLASS_INDEX | SCM_PTOBNUM (x))];
307 case scm_tcs_struct:
308 if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS_VALID)
309 return SCM_CLASS_OF (x);
310 else if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS)
311 {
312 /* Goops object */
313 if (! scm_is_false (SCM_OBJ_CLASS_REDEF (x)))
314 scm_change_object_class (x,
315 SCM_CLASS_OF (x), /* old */
316 SCM_OBJ_CLASS_REDEF (x)); /* new */
317 return SCM_CLASS_OF (x);
318 }
319 else
f3c6a02c 320 return scm_i_define_class_for_vtable (SCM_CLASS_OF (x));
539d5410
MV
321 default:
322 if (scm_is_pair (x))
323 return scm_class_pair;
324 else
325 return scm_class_unknown;
326 }
327
328 case scm_tc3_struct:
329 case scm_tc3_tc7_1:
330 case scm_tc3_tc7_2:
314b8716 331 /* case scm_tc3_unused: */
539d5410
MV
332 /* Never reached */
333 break;
334 }
335 return scm_class_unknown;
336}
337#undef FUNC_NAME
338
80662eda
MD
339/******************************************************************************
340 *
341 * compute-slots
342 *
343 ******************************************************************************/
344
345static SCM
346remove_duplicate_slots (SCM l, SCM res, SCM slots_already_seen)
347{
348 SCM tmp;
349
13d807b7 350 if (!scm_is_pair (l))
80662eda
MD
351 return res;
352
353 tmp = SCM_CAAR (l);
cc95e00a 354 if (!scm_is_symbol (tmp))
1afff620 355 scm_misc_error ("%compute-slots", "bad slot name ~S", scm_list_1 (tmp));
6d77c894 356
7888309b 357 if (scm_is_false (scm_c_memq (tmp, slots_already_seen))) {
80662eda
MD
358 res = scm_cons (SCM_CAR (l), res);
359 slots_already_seen = scm_cons (tmp, slots_already_seen);
360 }
6d77c894 361
80662eda
MD
362 return remove_duplicate_slots (SCM_CDR (l), res, slots_already_seen);
363}
364
13d807b7
AW
365static void
366check_cpl (SCM slots, SCM bslots)
367{
368 for (; scm_is_pair (bslots); bslots = SCM_CDR (bslots))
369 if (scm_is_true (scm_assq (SCM_CAAR (bslots), slots)))
370 scm_misc_error ("init-object", "a predefined <class> inherited "
371 "field cannot be redefined", SCM_EOL);
372}
373
9167e0b8
AW
374enum build_class_class_slots_mode { BOOT_SLOTS, FINAL_SLOTS };
375static SCM build_class_class_slots (enum build_class_class_slots_mode mode);
13d807b7 376
80662eda
MD
377static SCM
378build_slots_list (SCM dslots, SCM cpl)
379{
13d807b7
AW
380 SCM bslots, class_slots;
381 int classp;
382 SCM res = dslots;
383
384 class_slots = SCM_EOL;
385 classp = scm_is_true (scm_memq (scm_class_class, cpl));
386
387 if (classp)
388 {
9167e0b8 389 bslots = build_class_class_slots (FINAL_SLOTS);
13d807b7
AW
390 check_cpl (res, bslots);
391 }
392 else
393 bslots = SCM_EOL;
394
395 if (scm_is_pair (cpl))
396 {
397 for (cpl = SCM_CDR (cpl); scm_is_pair (cpl); cpl = SCM_CDR (cpl))
398 {
399 SCM new_slots = SCM_SLOT (SCM_CAR (cpl),
400 scm_si_direct_slots);
401 if (classp)
402 {
403 if (!scm_is_eq (SCM_CAR (cpl), scm_class_class))
404 check_cpl (new_slots, bslots);
405 else
406 {
407 /* Move class slots to the head of the list. */
408 class_slots = new_slots;
409 continue;
410 }
411 }
412 res = scm_append (scm_list_2 (new_slots, res));
413 }
414 }
415 else
416 scm_misc_error ("%compute-slots", "malformed cpl argument in "
417 "build_slots_list", SCM_EOL);
80662eda 418
13d807b7
AW
419 /* make sure to add the <class> slots to the head of the list */
420 if (classp)
421 res = scm_append (scm_list_2 (class_slots, res));
80662eda
MD
422
423 /* res contains a list of slots. Remove slots which appears more than once */
424 return remove_duplicate_slots (scm_reverse (res), SCM_EOL, SCM_EOL);
425}
426
427static SCM
428maplist (SCM ls)
429{
430 SCM orig = ls;
d2e53ed6 431 while (!scm_is_null (ls))
80662eda 432 {
13d807b7
AW
433 if (!scm_is_pair (ls))
434 scm_misc_error ("%compute-slots", "malformed ls argument in "
435 "maplist", SCM_EOL);
d2e53ed6 436 if (!scm_is_pair (SCM_CAR (ls)))
13d807b7 437 SCM_SETCAR (ls, scm_cons (SCM_CAR (ls), SCM_EOL));
80662eda
MD
438 ls = SCM_CDR (ls);
439 }
440 return orig;
441}
442
80662eda 443
23437298
DH
444SCM_DEFINE (scm_sys_compute_slots, "%compute-slots", 1, 0, 0,
445 (SCM class),
5352393c
MG
446 "Return a list consisting of the names of all slots belonging to\n"
447 "class @var{class}, i. e. the slots of @var{class} and of all of\n"
6d77c894 448 "its superclasses.")
23437298 449#define FUNC_NAME s_scm_sys_compute_slots
80662eda 450{
398d8ee1 451 SCM_VALIDATE_CLASS (1, class);
80662eda
MD
452 return build_slots_list (SCM_SLOT (class, scm_si_direct_slots),
453 SCM_SLOT (class, scm_si_cpl));
454}
23437298
DH
455#undef FUNC_NAME
456
80662eda
MD
457
458/******************************************************************************
459 *
460 * compute-getters-n-setters
6d77c894
TTN
461 *
462 * This version doesn't handle slot options. It serves only for booting
dcb410ec 463 * classes and will be overloaded in Scheme.
80662eda
MD
464 *
465 ******************************************************************************/
466
467SCM_KEYWORD (k_init_value, "init-value");
468SCM_KEYWORD (k_init_thunk, "init-thunk");
469
470static SCM
471compute_getters_n_setters (SCM slots)
472{
473 SCM res = SCM_EOL;
474 SCM *cdrloc = &res;
c014a02e 475 long i = 0;
80662eda 476
d2e53ed6 477 for ( ; !scm_is_null (slots); slots = SCM_CDR (slots))
80662eda
MD
478 {
479 SCM init = SCM_BOOL_F;
480 SCM options = SCM_CDAR (slots);
d2e53ed6 481 if (!scm_is_null (options))
80662eda 482 {
b2b33168
AW
483 init = scm_get_keyword (k_init_value, options, SCM_PACK (0));
484 if (SCM_UNPACK (init))
366ecaec 485 {
9d019f9b
AW
486 init = scm_primitive_eval (scm_list_3 (scm_sym_lambda,
487 SCM_EOL,
488 scm_list_2 (scm_sym_quote,
489 init)));
366ecaec 490 }
80662eda
MD
491 else
492 init = scm_get_keyword (k_init_thunk, options, SCM_BOOL_F);
493 }
494 *cdrloc = scm_cons (scm_cons (SCM_CAAR (slots),
495 scm_cons (init,
e11e83f3 496 scm_from_int (i++))),
80662eda
MD
497 SCM_EOL);
498 cdrloc = SCM_CDRLOC (*cdrloc);
499 }
500 return res;
501}
502
503/******************************************************************************
504 *
505 * initialize-object
506 *
507 ******************************************************************************/
508
509/*fixme* Manufacture keywords in advance */
510SCM
c014a02e 511scm_i_get_keyword (SCM key, SCM l, long len, SCM default_value, const char *subr)
80662eda 512{
c014a02e 513 long i;
23437298
DH
514
515 for (i = 0; i != len; i += 2)
80662eda 516 {
23437298
DH
517 SCM obj = SCM_CAR (l);
518
c598539a 519 if (!scm_is_keyword (obj))
1afff620 520 scm_misc_error (subr, "bad keyword: ~S", scm_list_1 (obj));
bc36d050 521 else if (scm_is_eq (obj, key))
80662eda 522 return SCM_CADR (l);
23437298
DH
523 else
524 l = SCM_CDDR (l);
80662eda 525 }
23437298 526
80662eda
MD
527 return default_value;
528}
529
80662eda 530
23437298
DH
531SCM_DEFINE (scm_get_keyword, "get-keyword", 3, 0, 0,
532 (SCM key, SCM l, SCM default_value),
5352393c
MG
533 "Determine an associated value for the keyword @var{key} from\n"
534 "the list @var{l}. The list @var{l} has to consist of an even\n"
535 "number of elements, where, starting with the first, every\n"
536 "second element is a keyword, followed by its associated value.\n"
537 "If @var{l} does not hold a value for @var{key}, the value\n"
538 "@var{default_value} is returned.")
23437298 539#define FUNC_NAME s_scm_get_keyword
80662eda 540{
c014a02e 541 long len;
23437298 542
c598539a 543 SCM_ASSERT (scm_is_keyword (key), key, SCM_ARG1, FUNC_NAME);
80662eda 544 len = scm_ilength (l);
b6311c08 545 if (len < 0 || len % 2 == 1)
1afff620 546 scm_misc_error (FUNC_NAME, "Bad keyword-value list: ~S", scm_list_1 (l));
23437298
DH
547
548 return scm_i_get_keyword (key, l, len, default_value, FUNC_NAME);
80662eda 549}
23437298
DH
550#undef FUNC_NAME
551
80662eda 552
80662eda
MD
553SCM_KEYWORD (k_init_keyword, "init-keyword");
554
555static SCM get_slot_value (SCM class, SCM obj, SCM slotdef);
556static SCM set_slot_value (SCM class, SCM obj, SCM slotdef, SCM value);
557
398d8ee1
KN
558SCM_DEFINE (scm_sys_initialize_object, "%initialize-object", 2, 0, 0,
559 (SCM obj, SCM initargs),
6bcefd15
MG
560 "Initialize the object @var{obj} with the given arguments\n"
561 "@var{initargs}.")
398d8ee1 562#define FUNC_NAME s_scm_sys_initialize_object
80662eda
MD
563{
564 SCM tmp, get_n_set, slots;
565 SCM class = SCM_CLASS_OF (obj);
c014a02e 566 long n_initargs;
80662eda 567
398d8ee1 568 SCM_VALIDATE_INSTANCE (1, obj);
80662eda 569 n_initargs = scm_ilength (initargs);
398d8ee1 570 SCM_ASSERT ((n_initargs & 1) == 0, initargs, SCM_ARG2, FUNC_NAME);
6d77c894 571
80662eda
MD
572 get_n_set = SCM_SLOT (class, scm_si_getters_n_setters);
573 slots = SCM_SLOT (class, scm_si_slots);
6d77c894 574
80662eda
MD
575 /* See for each slot how it must be initialized */
576 for (;
d2e53ed6 577 !scm_is_null (slots);
80662eda
MD
578 get_n_set = SCM_CDR (get_n_set), slots = SCM_CDR (slots))
579 {
580 SCM slot_name = SCM_CAR (slots);
48ad85fb 581 SCM slot_value = SCM_GOOPS_UNBOUND;
6d77c894 582
d2e53ed6 583 if (!scm_is_null (SCM_CDR (slot_name)))
80662eda
MD
584 {
585 /* This slot admits (perhaps) to be initialized at creation time */
c014a02e 586 long n = scm_ilength (SCM_CDR (slot_name));
80662eda 587 if (n & 1) /* odd or -1 */
398d8ee1 588 SCM_MISC_ERROR ("class contains bogus slot definition: ~S",
1afff620 589 scm_list_1 (slot_name));
80662eda
MD
590 tmp = scm_i_get_keyword (k_init_keyword,
591 SCM_CDR (slot_name),
592 n,
b2b33168 593 SCM_PACK (0),
398d8ee1 594 FUNC_NAME);
80662eda 595 slot_name = SCM_CAR (slot_name);
b2b33168 596 if (SCM_UNPACK (tmp))
80662eda
MD
597 {
598 /* an initarg was provided for this slot */
c598539a 599 if (!scm_is_keyword (tmp))
398d8ee1 600 SCM_MISC_ERROR ("initarg must be a keyword. It was ~S",
1afff620 601 scm_list_1 (tmp));
80662eda
MD
602 slot_value = scm_i_get_keyword (tmp,
603 initargs,
604 n_initargs,
48ad85fb 605 SCM_GOOPS_UNBOUND,
398d8ee1 606 FUNC_NAME);
80662eda
MD
607 }
608 }
609
48ad85fb 610 if (!SCM_GOOPS_UNBOUNDP (slot_value))
80662eda
MD
611 /* set slot to provided value */
612 set_slot_value (class, obj, SCM_CAR (get_n_set), slot_value);
613 else
614 {
615 /* set slot to its :init-form if it exists */
616 tmp = SCM_CADAR (get_n_set);
7888309b 617 if (scm_is_true (tmp))
48ad85fb
AW
618 set_slot_value (class,
619 obj,
620 SCM_CAR (get_n_set),
621 scm_call_0 (tmp));
80662eda
MD
622 }
623 }
6d77c894 624
80662eda
MD
625 return obj;
626}
398d8ee1 627#undef FUNC_NAME
80662eda 628
21ab2aeb
MD
629/* NOTE: The following macros are interdependent with code
630 * in goops.scm:compute-getters-n-setters
631 */
632#define SCM_GNS_INSTANCE_ALLOCATED_P(gns) \
e11e83f3 633 (SCM_I_INUMP (SCM_CDDR (gns)) \
d2e53ed6
MV
634 || (scm_is_pair (SCM_CDDR (gns)) \
635 && scm_is_pair (SCM_CDDDR (gns)) \
636 && scm_is_pair (SCM_CDDDDR (gns))))
21ab2aeb 637#define SCM_GNS_INDEX(gns) \
e11e83f3
MV
638 (SCM_I_INUMP (SCM_CDDR (gns)) \
639 ? SCM_I_INUM (SCM_CDDR (gns)) \
640 : scm_to_long (SCM_CAR (SCM_CDDDDR (gns))))
21ab2aeb 641#define SCM_GNS_SIZE(gns) \
e11e83f3 642 (SCM_I_INUMP (SCM_CDDR (gns)) \
21ab2aeb 643 ? 1 \
e11e83f3 644 : scm_to_long (SCM_CADR (SCM_CDDDDR (gns))))
80662eda
MD
645
646SCM_KEYWORD (k_class, "class");
b46fae00
MD
647SCM_KEYWORD (k_allocation, "allocation");
648SCM_KEYWORD (k_instance, "instance");
80662eda 649
398d8ee1
KN
650SCM_DEFINE (scm_sys_prep_layout_x, "%prep-layout!", 1, 0, 0,
651 (SCM class),
652 "")
653#define FUNC_NAME s_scm_sys_prep_layout_x
80662eda 654{
21ab2aeb 655 SCM slots, getters_n_setters, nfields;
6b80d352
DH
656 unsigned long int n, i;
657 char *s;
cc95e00a 658 SCM layout;
80662eda 659
398d8ee1 660 SCM_VALIDATE_INSTANCE (1, class);
80662eda 661 slots = SCM_SLOT (class, scm_si_slots);
21ab2aeb 662 getters_n_setters = SCM_SLOT (class, scm_si_getters_n_setters);
80662eda 663 nfields = SCM_SLOT (class, scm_si_nfields);
e11e83f3 664 if (!SCM_I_INUMP (nfields) || SCM_I_INUM (nfields) < 0)
398d8ee1 665 SCM_MISC_ERROR ("bad value in nfields slot: ~S",
1afff620 666 scm_list_1 (nfields));
e11e83f3 667 n = 2 * SCM_I_INUM (nfields);
80662eda
MD
668 if (n < sizeof (SCM_CLASS_CLASS_LAYOUT) - 1
669 && SCM_SUBCLASSP (class, scm_class_class))
398d8ee1 670 SCM_MISC_ERROR ("class object doesn't have enough fields: ~S",
1afff620 671 scm_list_1 (nfields));
6d77c894 672
190d4b0d 673 layout = scm_i_make_string (n, &s, 0);
21ab2aeb 674 i = 0;
d2e53ed6 675 while (scm_is_pair (getters_n_setters))
80662eda 676 {
21ab2aeb 677 if (SCM_GNS_INSTANCE_ALLOCATED_P (SCM_CAR (getters_n_setters)))
b46fae00 678 {
21ab2aeb
MD
679 SCM type;
680 int len, index, size;
681 char p, a;
682
d2e53ed6 683 if (i >= n || !scm_is_pair (slots))
21ab2aeb
MD
684 goto inconsistent;
685
686 /* extract slot type */
b46fae00 687 len = scm_ilength (SCM_CDAR (slots));
21ab2aeb
MD
688 type = scm_i_get_keyword (k_class, SCM_CDAR (slots),
689 len, SCM_BOOL_F, FUNC_NAME);
690 /* determine slot GC protection and access mode */
7888309b 691 if (scm_is_false (type))
6b80d352 692 {
21ab2aeb
MD
693 p = 'p';
694 a = 'w';
6b80d352
DH
695 }
696 else
697 {
21ab2aeb 698 if (!SCM_CLASSP (type))
cc95e00a 699 SCM_MISC_ERROR ("bad slot class", SCM_EOL);
21ab2aeb
MD
700 else if (SCM_SUBCLASSP (type, scm_class_foreign_slot))
701 {
702 if (SCM_SUBCLASSP (type, scm_class_self))
703 p = 's';
704 else if (SCM_SUBCLASSP (type, scm_class_protected))
705 p = 'p';
706 else
707 p = 'u';
708
709 if (SCM_SUBCLASSP (type, scm_class_opaque))
710 a = 'o';
711 else if (SCM_SUBCLASSP (type, scm_class_read_only))
712 a = 'r';
b6cf4d02
AW
713 else if (SCM_SUBCLASSP (type, scm_class_hidden))
714 a = 'h';
21ab2aeb
MD
715 else
716 a = 'w';
717 }
718 else
719 {
720 p = 'p';
721 a = 'w';
722 }
723 }
724
725 index = SCM_GNS_INDEX (SCM_CAR (getters_n_setters));
726 if (index != (i >> 1))
727 goto inconsistent;
728 size = SCM_GNS_SIZE (SCM_CAR (getters_n_setters));
729 while (size)
730 {
731 s[i++] = p;
732 s[i++] = a;
733 --size;
6b80d352 734 }
80662eda 735 }
80662eda 736 slots = SCM_CDR (slots);
21ab2aeb
MD
737 getters_n_setters = SCM_CDR (getters_n_setters);
738 }
d2e53ed6 739 if (!scm_is_null (slots))
21ab2aeb
MD
740 {
741 inconsistent:
21ab2aeb 742 SCM_MISC_ERROR ("inconsistent getters-n-setters", SCM_EOL);
80662eda 743 }
b6cf4d02 744 SCM_SET_VTABLE_LAYOUT (class, scm_string_to_symbol (layout));
80662eda
MD
745 return SCM_UNSPECIFIED;
746}
398d8ee1 747#undef FUNC_NAME
80662eda
MD
748
749static void prep_hashsets (SCM);
750
398d8ee1
KN
751SCM_DEFINE (scm_sys_inherit_magic_x, "%inherit-magic!", 2, 0, 0,
752 (SCM class, SCM dsupers),
753 "")
754#define FUNC_NAME s_scm_sys_inherit_magic_x
80662eda 755{
398d8ee1 756 SCM_VALIDATE_INSTANCE (1, class);
51f66c91
AW
757 scm_i_struct_inherit_vtable_magic (SCM_CLASS_OF (class), class);
758 SCM_SET_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_OR_VALID);
80662eda
MD
759
760 prep_hashsets (class);
6d77c894 761
80662eda
MD
762 return SCM_UNSPECIFIED;
763}
398d8ee1 764#undef FUNC_NAME
80662eda 765
63c1872f 766static void
80662eda
MD
767prep_hashsets (SCM class)
768{
dcb410ec 769 unsigned int i;
80662eda 770
e161c9f8 771 for (i = 0; i < 8; ++i)
dcb410ec 772 SCM_SET_HASHSET (class, i, scm_c_uniform32 (goops_rstate));
80662eda
MD
773}
774
775/******************************************************************************/
776
777SCM
778scm_basic_basic_make_class (SCM class, SCM name, SCM dsupers, SCM dslots)
779{
780 SCM z, cpl, slots, nfields, g_n_s;
781
782 /* Allocate one instance */
783 z = scm_make_struct (class, SCM_INUM0, SCM_EOL);
784
785 /* Initialize its slots */
dcb410ec 786 SCM_SET_SLOT (z, scm_si_direct_supers, dsupers);
9167e0b8 787 cpl = scm_call_1 (SCM_VARIABLE_REF (var_compute_cpl), z);
80662eda 788 slots = build_slots_list (maplist (dslots), cpl);
e11e83f3 789 nfields = scm_from_int (scm_ilength (slots));
80662eda
MD
790 g_n_s = compute_getters_n_setters (slots);
791
b6cf4d02 792 SCM_SET_SLOT (z, scm_vtable_index_name, name);
dcb410ec
DH
793 SCM_SET_SLOT (z, scm_si_direct_slots, dslots);
794 SCM_SET_SLOT (z, scm_si_direct_subclasses, SCM_EOL);
795 SCM_SET_SLOT (z, scm_si_direct_methods, SCM_EOL);
796 SCM_SET_SLOT (z, scm_si_cpl, cpl);
797 SCM_SET_SLOT (z, scm_si_slots, slots);
798 SCM_SET_SLOT (z, scm_si_nfields, nfields);
799 SCM_SET_SLOT (z, scm_si_getters_n_setters, g_n_s);
800 SCM_SET_SLOT (z, scm_si_redefined, SCM_BOOL_F);
80662eda
MD
801
802 /* Add this class in the direct-subclasses slot of dsupers */
803 {
804 SCM tmp;
d2e53ed6 805 for (tmp = dsupers; !scm_is_null (tmp); tmp = SCM_CDR (tmp))
dcb410ec
DH
806 SCM_SET_SLOT (SCM_CAR (tmp), scm_si_direct_subclasses,
807 scm_cons (z, SCM_SLOT (SCM_CAR (tmp),
808 scm_si_direct_subclasses)));
80662eda
MD
809 }
810
80662eda
MD
811 return z;
812}
813
814SCM
815scm_basic_make_class (SCM class, SCM name, SCM dsupers, SCM dslots)
816{
817 SCM z = scm_basic_basic_make_class (class, name, dsupers, dslots);
80662eda 818 scm_sys_prep_layout_x (z);
51f66c91 819 scm_sys_inherit_magic_x (z, dsupers);
80662eda
MD
820 return z;
821}
822
823/******************************************************************************/
824
6b80d352 825SCM_SYMBOL (sym_layout, "layout");
b6cf4d02
AW
826SCM_SYMBOL (sym_flags, "flags");
827SCM_SYMBOL (sym_self, "%self");
828SCM_SYMBOL (sym_instance_finalizer, "instance-finalizer");
829SCM_SYMBOL (sym_reserved_0, "%reserved-0");
830SCM_SYMBOL (sym_reserved_1, "%reserved-1");
6b80d352
DH
831SCM_SYMBOL (sym_print, "print");
832SCM_SYMBOL (sym_procedure, "procedure");
833SCM_SYMBOL (sym_setter, "setter");
834SCM_SYMBOL (sym_redefined, "redefined");
835SCM_SYMBOL (sym_h0, "h0");
836SCM_SYMBOL (sym_h1, "h1");
837SCM_SYMBOL (sym_h2, "h2");
838SCM_SYMBOL (sym_h3, "h3");
839SCM_SYMBOL (sym_h4, "h4");
840SCM_SYMBOL (sym_h5, "h5");
841SCM_SYMBOL (sym_h6, "h6");
842SCM_SYMBOL (sym_h7, "h7");
843SCM_SYMBOL (sym_name, "name");
844SCM_SYMBOL (sym_direct_supers, "direct-supers");
845SCM_SYMBOL (sym_direct_slots, "direct-slots");
846SCM_SYMBOL (sym_direct_subclasses, "direct-subclasses");
847SCM_SYMBOL (sym_direct_methods, "direct-methods");
848SCM_SYMBOL (sym_cpl, "cpl");
849SCM_SYMBOL (sym_default_slot_definition_class, "default-slot-definition-class");
850SCM_SYMBOL (sym_slots, "slots");
851SCM_SYMBOL (sym_getters_n_setters, "getters-n-setters");
6b80d352 852SCM_SYMBOL (sym_nfields, "nfields");
6b80d352
DH
853
854
9167e0b8
AW
855static int specialized_slots_initialized = 0;
856
80662eda 857static SCM
9167e0b8 858build_class_class_slots (enum build_class_class_slots_mode mode)
80662eda 859{
9167e0b8
AW
860#define SPECIALIZED_SLOT(name, class) \
861 (mode == BOOT_SLOTS ? scm_list_1 (name) : scm_list_3 (name, k_class, class))
862
863 if (mode == FINAL_SLOTS && !specialized_slots_initialized)
864 abort ();
865
b6cf4d02
AW
866 /* has to be kept in sync with SCM_VTABLE_BASE_LAYOUT and
867 SCM_CLASS_CLASS_LAYOUT */
6b80d352 868 return scm_list_n (
9167e0b8
AW
869 SPECIALIZED_SLOT (sym_layout, scm_class_protected_read_only),
870 SPECIALIZED_SLOT (sym_flags, scm_class_hidden),
871 SPECIALIZED_SLOT (sym_self, scm_class_self),
872 SPECIALIZED_SLOT (sym_instance_finalizer, scm_class_hidden),
6b80d352 873 scm_list_1 (sym_print),
9167e0b8
AW
874 SPECIALIZED_SLOT (sym_name, scm_class_protected_hidden),
875 SPECIALIZED_SLOT (sym_reserved_0, scm_class_hidden),
876 SPECIALIZED_SLOT (sym_reserved_1, scm_class_hidden),
6b80d352 877 scm_list_1 (sym_redefined),
9167e0b8
AW
878 SPECIALIZED_SLOT (sym_h0, scm_class_int),
879 SPECIALIZED_SLOT (sym_h1, scm_class_int),
880 SPECIALIZED_SLOT (sym_h2, scm_class_int),
881 SPECIALIZED_SLOT (sym_h3, scm_class_int),
882 SPECIALIZED_SLOT (sym_h4, scm_class_int),
883 SPECIALIZED_SLOT (sym_h5, scm_class_int),
884 SPECIALIZED_SLOT (sym_h6, scm_class_int),
885 SPECIALIZED_SLOT (sym_h7, scm_class_int),
6b80d352
DH
886 scm_list_1 (sym_direct_supers),
887 scm_list_1 (sym_direct_slots),
888 scm_list_1 (sym_direct_subclasses),
889 scm_list_1 (sym_direct_methods),
890 scm_list_1 (sym_cpl),
891 scm_list_1 (sym_default_slot_definition_class),
892 scm_list_1 (sym_slots),
893 scm_list_1 (sym_getters_n_setters),
6b80d352 894 scm_list_1 (sym_nfields),
6b80d352 895 SCM_UNDEFINED);
80662eda
MD
896}
897
898static void
899create_basic_classes (void)
900{
9167e0b8 901 SCM slots_of_class = build_class_class_slots (BOOT_SLOTS);
80662eda 902
b6cf4d02
AW
903 /**** <class> ****/
904 SCM cs = scm_from_locale_string (SCM_CLASS_CLASS_LAYOUT);
4a655e50 905 SCM name = scm_from_latin1_symbol ("<class>");
0818837f 906 scm_class_class = scm_i_make_vtable_vtable (cs);
80662eda
MD
907 SCM_SET_CLASS_FLAGS (scm_class_class, (SCM_CLASSF_GOOPS_OR_VALID
908 | SCM_CLASSF_METACLASS));
909
b6cf4d02 910 SCM_SET_SLOT (scm_class_class, scm_vtable_index_name, name);
dcb410ec 911 SCM_SET_SLOT (scm_class_class, scm_si_direct_supers, SCM_EOL); /* will be changed */
9167e0b8 912 SCM_SET_SLOT (scm_class_class, scm_si_direct_slots, slots_of_class); /* will be changed */
dcb410ec 913 SCM_SET_SLOT (scm_class_class, scm_si_direct_subclasses, SCM_EOL);
6d77c894 914 SCM_SET_SLOT (scm_class_class, scm_si_direct_methods, SCM_EOL);
dcb410ec 915 SCM_SET_SLOT (scm_class_class, scm_si_cpl, SCM_EOL); /* will be changed */
9167e0b8 916 SCM_SET_SLOT (scm_class_class, scm_si_slots, slots_of_class); /* will be changed */
e11e83f3 917 SCM_SET_SLOT (scm_class_class, scm_si_nfields, scm_from_int (SCM_N_CLASS_SLOTS));
9167e0b8
AW
918 SCM_SET_SLOT (scm_class_class, scm_si_getters_n_setters,
919 compute_getters_n_setters (slots_of_class)); /* will be changed */
dcb410ec 920 SCM_SET_SLOT (scm_class_class, scm_si_redefined, SCM_BOOL_F);
80662eda
MD
921
922 prep_hashsets (scm_class_class);
923
28d0871b 924 scm_module_define (scm_module_goops, name, scm_class_class);
80662eda 925
51f66c91 926 /**** <top> ****/
4a655e50 927 name = scm_from_latin1_symbol ("<top>");
f39448c5
AW
928 scm_class_top = scm_basic_make_class (scm_class_class, name,
929 SCM_EOL, SCM_EOL);
80662eda 930
28d0871b 931 scm_module_define (scm_module_goops, name, scm_class_top);
6d77c894 932
51f66c91 933 /**** <object> ****/
4a655e50 934 name = scm_from_latin1_symbol ("<object>");
f39448c5
AW
935 scm_class_object = scm_basic_make_class (scm_class_class, name,
936 scm_list_1 (scm_class_top), SCM_EOL);
80662eda 937
28d0871b 938 scm_module_define (scm_module_goops, name, scm_class_object);
80662eda
MD
939
940 /* <top> <object> and <class> were partially initialized. Correct them here */
1afff620 941 SCM_SET_SLOT (scm_class_object, scm_si_direct_subclasses, scm_list_1 (scm_class_class));
80662eda 942
1afff620
KN
943 SCM_SET_SLOT (scm_class_class, scm_si_direct_supers, scm_list_1 (scm_class_object));
944 SCM_SET_SLOT (scm_class_class, scm_si_cpl, scm_list_3 (scm_class_class, scm_class_object, scm_class_top));
80662eda
MD
945}
946
947/******************************************************************************/
948
398d8ee1
KN
949SCM_DEFINE (scm_instance_p, "instance?", 1, 0, 0,
950 (SCM obj),
6bcefd15 951 "Return @code{#t} if @var{obj} is an instance.")
398d8ee1 952#define FUNC_NAME s_scm_instance_p
80662eda 953{
7888309b 954 return scm_from_bool (SCM_INSTANCEP (obj));
80662eda 955}
398d8ee1 956#undef FUNC_NAME
80662eda 957
80662eda
MD
958
959/******************************************************************************
6d77c894 960 *
80662eda
MD
961 * Meta object accessors
962 *
963 ******************************************************************************/
398d8ee1
KN
964SCM_DEFINE (scm_class_name, "class-name", 1, 0, 0,
965 (SCM obj),
6bcefd15 966 "Return the class name of @var{obj}.")
398d8ee1 967#define FUNC_NAME s_scm_class_name
80662eda 968{
398d8ee1 969 SCM_VALIDATE_CLASS (1, obj);
6b80d352 970 return scm_slot_ref (obj, sym_name);
80662eda 971}
398d8ee1 972#undef FUNC_NAME
80662eda 973
398d8ee1
KN
974SCM_DEFINE (scm_class_direct_supers, "class-direct-supers", 1, 0, 0,
975 (SCM obj),
6bcefd15 976 "Return the direct superclasses of the class @var{obj}.")
398d8ee1 977#define FUNC_NAME s_scm_class_direct_supers
80662eda 978{
398d8ee1 979 SCM_VALIDATE_CLASS (1, obj);
6b80d352 980 return scm_slot_ref (obj, sym_direct_supers);
80662eda 981}
398d8ee1 982#undef FUNC_NAME
80662eda 983
398d8ee1
KN
984SCM_DEFINE (scm_class_direct_slots, "class-direct-slots", 1, 0, 0,
985 (SCM obj),
6bcefd15 986 "Return the direct slots of the class @var{obj}.")
398d8ee1 987#define FUNC_NAME s_scm_class_direct_slots
80662eda 988{
398d8ee1 989 SCM_VALIDATE_CLASS (1, obj);
6b80d352 990 return scm_slot_ref (obj, sym_direct_slots);
80662eda 991}
398d8ee1 992#undef FUNC_NAME
80662eda 993
398d8ee1
KN
994SCM_DEFINE (scm_class_direct_subclasses, "class-direct-subclasses", 1, 0, 0,
995 (SCM obj),
6bcefd15 996 "Return the direct subclasses of the class @var{obj}.")
398d8ee1 997#define FUNC_NAME s_scm_class_direct_subclasses
80662eda 998{
398d8ee1 999 SCM_VALIDATE_CLASS (1, obj);
6b80d352 1000 return scm_slot_ref(obj, sym_direct_subclasses);
80662eda 1001}
398d8ee1 1002#undef FUNC_NAME
80662eda 1003
398d8ee1
KN
1004SCM_DEFINE (scm_class_direct_methods, "class-direct-methods", 1, 0, 0,
1005 (SCM obj),
6bcefd15 1006 "Return the direct methods of the class @var{obj}")
398d8ee1 1007#define FUNC_NAME s_scm_class_direct_methods
80662eda 1008{
398d8ee1 1009 SCM_VALIDATE_CLASS (1, obj);
6b80d352 1010 return scm_slot_ref (obj, sym_direct_methods);
80662eda 1011}
398d8ee1 1012#undef FUNC_NAME
80662eda 1013
398d8ee1
KN
1014SCM_DEFINE (scm_class_precedence_list, "class-precedence-list", 1, 0, 0,
1015 (SCM obj),
6bcefd15 1016 "Return the class precedence list of the class @var{obj}.")
398d8ee1 1017#define FUNC_NAME s_scm_class_precedence_list
80662eda 1018{
398d8ee1 1019 SCM_VALIDATE_CLASS (1, obj);
6b80d352 1020 return scm_slot_ref (obj, sym_cpl);
80662eda 1021}
398d8ee1 1022#undef FUNC_NAME
80662eda 1023
398d8ee1
KN
1024SCM_DEFINE (scm_class_slots, "class-slots", 1, 0, 0,
1025 (SCM obj),
6bcefd15 1026 "Return the slot list of the class @var{obj}.")
398d8ee1 1027#define FUNC_NAME s_scm_class_slots
80662eda 1028{
398d8ee1 1029 SCM_VALIDATE_CLASS (1, obj);
6b80d352 1030 return scm_slot_ref (obj, sym_slots);
80662eda 1031}
398d8ee1 1032#undef FUNC_NAME
80662eda 1033
398d8ee1
KN
1034SCM_DEFINE (scm_generic_function_name, "generic-function-name", 1, 0, 0,
1035 (SCM obj),
6bcefd15 1036 "Return the name of the generic function @var{obj}.")
398d8ee1 1037#define FUNC_NAME s_scm_generic_function_name
80662eda 1038{
398d8ee1 1039 SCM_VALIDATE_GENERIC (1, obj);
80662eda
MD
1040 return scm_procedure_property (obj, scm_sym_name);
1041}
398d8ee1 1042#undef FUNC_NAME
80662eda 1043
bbf8d523
MD
1044SCM_SYMBOL (sym_methods, "methods");
1045SCM_SYMBOL (sym_extended_by, "extended-by");
1046SCM_SYMBOL (sym_extends, "extends");
1047
1048static
1049SCM fold_downward_gf_methods (SCM method_lists, SCM gf)
1050{
1051 SCM gfs = scm_slot_ref (gf, sym_extended_by);
1052 method_lists = scm_cons (scm_slot_ref (gf, sym_methods), method_lists);
d2e53ed6 1053 while (!scm_is_null (gfs))
bbf8d523
MD
1054 {
1055 method_lists = fold_downward_gf_methods (method_lists, SCM_CAR (gfs));
1056 gfs = SCM_CDR (gfs);
1057 }
1058 return method_lists;
1059}
1060
1061static
1062SCM fold_upward_gf_methods (SCM method_lists, SCM gf)
1063{
1064 if (SCM_IS_A_P (gf, scm_class_extended_generic))
1065 {
1066 SCM gfs = scm_slot_ref (gf, sym_extends);
d2e53ed6 1067 while (!scm_is_null (gfs))
bbf8d523
MD
1068 {
1069 SCM methods = scm_slot_ref (SCM_CAR (gfs), sym_methods);
1070 method_lists = fold_upward_gf_methods (scm_cons (methods,
1071 method_lists),
1072 SCM_CAR (gfs));
1073 gfs = SCM_CDR (gfs);
1074 }
1075 }
1076 return method_lists;
1077}
1078
398d8ee1
KN
1079SCM_DEFINE (scm_generic_function_methods, "generic-function-methods", 1, 0, 0,
1080 (SCM obj),
6bcefd15 1081 "Return the methods of the generic function @var{obj}.")
398d8ee1 1082#define FUNC_NAME s_scm_generic_function_methods
80662eda 1083{
bbf8d523 1084 SCM methods;
398d8ee1 1085 SCM_VALIDATE_GENERIC (1, obj);
bbf8d523
MD
1086 methods = fold_upward_gf_methods (SCM_EOL, obj);
1087 methods = fold_downward_gf_methods (methods, obj);
1088 return scm_append (methods);
80662eda 1089}
398d8ee1 1090#undef FUNC_NAME
80662eda 1091
398d8ee1
KN
1092SCM_DEFINE (scm_method_generic_function, "method-generic-function", 1, 0, 0,
1093 (SCM obj),
bb2c02f2 1094 "Return the generic function for the method @var{obj}.")
398d8ee1 1095#define FUNC_NAME s_scm_method_generic_function
80662eda 1096{
398d8ee1 1097 SCM_VALIDATE_METHOD (1, obj);
4a655e50 1098 return scm_slot_ref (obj, scm_from_latin1_symbol ("generic-function"));
80662eda 1099}
398d8ee1 1100#undef FUNC_NAME
80662eda 1101
398d8ee1
KN
1102SCM_DEFINE (scm_method_specializers, "method-specializers", 1, 0, 0,
1103 (SCM obj),
6bcefd15 1104 "Return specializers of the method @var{obj}.")
398d8ee1 1105#define FUNC_NAME s_scm_method_specializers
80662eda 1106{
398d8ee1 1107 SCM_VALIDATE_METHOD (1, obj);
4a655e50 1108 return scm_slot_ref (obj, scm_from_latin1_symbol ("specializers"));
80662eda 1109}
398d8ee1 1110#undef FUNC_NAME
80662eda 1111
398d8ee1
KN
1112SCM_DEFINE (scm_method_procedure, "method-procedure", 1, 0, 0,
1113 (SCM obj),
6bcefd15 1114 "Return the procedure of the method @var{obj}.")
398d8ee1 1115#define FUNC_NAME s_scm_method_procedure
80662eda 1116{
398d8ee1 1117 SCM_VALIDATE_METHOD (1, obj);
6b80d352 1118 return scm_slot_ref (obj, sym_procedure);
80662eda 1119}
398d8ee1 1120#undef FUNC_NAME
80662eda 1121
80662eda
MD
1122/******************************************************************************
1123 *
1124 * S l o t a c c e s s
1125 *
1126 ******************************************************************************/
1127
398d8ee1
KN
1128SCM_DEFINE (scm_make_unbound, "make-unbound", 0, 0, 0,
1129 (),
6bcefd15 1130 "Return the unbound value.")
398d8ee1 1131#define FUNC_NAME s_scm_make_unbound
80662eda
MD
1132{
1133 return SCM_GOOPS_UNBOUND;
1134}
398d8ee1 1135#undef FUNC_NAME
80662eda 1136
398d8ee1
KN
1137SCM_DEFINE (scm_unbound_p, "unbound?", 1, 0, 0,
1138 (SCM obj),
6bcefd15 1139 "Return @code{#t} if @var{obj} is unbound.")
398d8ee1 1140#define FUNC_NAME s_scm_unbound_p
80662eda
MD
1141{
1142 return SCM_GOOPS_UNBOUNDP (obj) ? SCM_BOOL_T : SCM_BOOL_F;
1143}
398d8ee1 1144#undef FUNC_NAME
80662eda 1145
398d8ee1
KN
1146SCM_DEFINE (scm_assert_bound, "assert-bound", 2, 0, 0,
1147 (SCM value, SCM obj),
6bcefd15
MG
1148 "Return @var{value} if it is bound, and invoke the\n"
1149 "@var{slot-unbound} method of @var{obj} if it is not.")
398d8ee1 1150#define FUNC_NAME s_scm_assert_bound
80662eda
MD
1151{
1152 if (SCM_GOOPS_UNBOUNDP (value))
bef95911 1153 return scm_call_1 (SCM_VARIABLE_REF (var_slot_unbound), obj);
80662eda
MD
1154 return value;
1155}
398d8ee1 1156#undef FUNC_NAME
80662eda 1157
398d8ee1
KN
1158SCM_DEFINE (scm_at_assert_bound_ref, "@assert-bound-ref", 2, 0, 0,
1159 (SCM obj, SCM index),
6bcefd15
MG
1160 "Like @code{assert-bound}, but use @var{index} for accessing\n"
1161 "the value from @var{obj}.")
398d8ee1 1162#define FUNC_NAME s_scm_at_assert_bound_ref
80662eda 1163{
e11e83f3 1164 SCM value = SCM_SLOT (obj, scm_to_int (index));
80662eda 1165 if (SCM_GOOPS_UNBOUNDP (value))
bef95911 1166 return scm_call_1 (SCM_VARIABLE_REF (var_slot_unbound), obj);
80662eda
MD
1167 return value;
1168}
398d8ee1 1169#undef FUNC_NAME
80662eda 1170
398d8ee1
KN
1171SCM_DEFINE (scm_sys_fast_slot_ref, "%fast-slot-ref", 2, 0, 0,
1172 (SCM obj, SCM index),
6bcefd15 1173 "Return the slot value with index @var{index} from @var{obj}.")
398d8ee1 1174#define FUNC_NAME s_scm_sys_fast_slot_ref
80662eda 1175{
e25f3727 1176 scm_t_bits i;
80662eda 1177
398d8ee1 1178 SCM_VALIDATE_INSTANCE (1, obj);
a9931e4e
NJ
1179 i = scm_to_unsigned_integer (index, 0,
1180 SCM_I_INUM (SCM_SLOT (SCM_CLASS_OF (obj),
1181 scm_si_nfields))
1182 - 1);
58241edc 1183 return SCM_SLOT (obj, i);
80662eda 1184}
ca83b028
DH
1185#undef FUNC_NAME
1186
398d8ee1
KN
1187SCM_DEFINE (scm_sys_fast_slot_set_x, "%fast-slot-set!", 3, 0, 0,
1188 (SCM obj, SCM index, SCM value),
6bcefd15
MG
1189 "Set the slot with index @var{index} in @var{obj} to\n"
1190 "@var{value}.")
398d8ee1 1191#define FUNC_NAME s_scm_sys_fast_slot_set_x
80662eda 1192{
e25f3727 1193 scm_t_bits i;
80662eda 1194
398d8ee1 1195 SCM_VALIDATE_INSTANCE (1, obj);
a9931e4e
NJ
1196 i = scm_to_unsigned_integer (index, 0,
1197 SCM_I_INUM (SCM_SLOT (SCM_CLASS_OF (obj),
1198 scm_si_nfields))
1199 - 1);
6b80d352 1200
dcb410ec 1201 SCM_SET_SLOT (obj, i, value);
ca83b028 1202
80662eda
MD
1203 return SCM_UNSPECIFIED;
1204}
ca83b028
DH
1205#undef FUNC_NAME
1206
80662eda 1207
4d0949ea 1208\f
80662eda
MD
1209/** Utilities **/
1210
1211/* In the future, this function will return the effective slot
1212 * definition associated with SLOT_NAME. Now it just returns some of
1213 * the information which will be stored in the effective slot
1214 * definition.
1215 */
1216
1217static SCM
1218slot_definition_using_name (SCM class, SCM slot_name)
1219{
1220 register SCM slots = SCM_SLOT (class, scm_si_getters_n_setters);
d2e53ed6 1221 for (; !scm_is_null (slots); slots = SCM_CDR (slots))
d223c3fc 1222 if (scm_is_eq (SCM_CAAR (slots), slot_name))
80662eda
MD
1223 return SCM_CAR (slots);
1224 return SCM_BOOL_F;
1225}
1226
1227static SCM
e81d98ec 1228get_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef)
54ee7cdf 1229#define FUNC_NAME "%get-slot-value"
80662eda
MD
1230{
1231 SCM access = SCM_CDDR (slotdef);
1232 /* Two cases here:
1233 * - access is an integer (the offset of this slot in the slots vector)
1234 * - otherwise (car access) is the getter function to apply
e11e83f3
MV
1235 *
1236 * Instances have never more than SCM_MOST_POSITIVE_FIXNUM slots, so
1237 * we can just assume fixnums here.
23437298 1238 */
e11e83f3 1239 if (SCM_I_INUMP (access))
54ee7cdf
AW
1240 /* Don't poke at the slots directly, because scm_struct_ref handles the
1241 access bits for us. */
1242 return scm_struct_ref (obj, access);
80662eda 1243 else
9d019f9b 1244 return scm_call_1 (SCM_CAR (access), obj);
80662eda 1245}
54ee7cdf 1246#undef FUNC_NAME
80662eda
MD
1247
1248static SCM
1249get_slot_value_using_name (SCM class, SCM obj, SCM slot_name)
1250{
1251 SCM slotdef = slot_definition_using_name (class, slot_name);
7888309b 1252 if (scm_is_true (slotdef))
80662eda
MD
1253 return get_slot_value (class, obj, slotdef);
1254 else
bef95911 1255 return scm_call_3 (SCM_VARIABLE_REF (var_slot_missing), class, obj, slot_name);
80662eda
MD
1256}
1257
1258static SCM
e81d98ec 1259set_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef, SCM value)
54ee7cdf 1260#define FUNC_NAME "%set-slot-value"
80662eda
MD
1261{
1262 SCM access = SCM_CDDR (slotdef);
1263 /* Two cases here:
1264 * - access is an integer (the offset of this slot in the slots vector)
1265 * - otherwise (cadr access) is the setter function to apply
e11e83f3
MV
1266 *
1267 * Instances have never more than SCM_MOST_POSITIVE_FIXNUM slots, so
1268 * we can just assume fixnums here.
80662eda 1269 */
e11e83f3 1270 if (SCM_I_INUMP (access))
54ee7cdf
AW
1271 /* obey permissions bits via going through struct-set! */
1272 scm_struct_set_x (obj, access, value);
80662eda 1273 else
9d019f9b
AW
1274 /* ((cadr l) obj value) */
1275 scm_call_2 (SCM_CADR (access), obj, value);
80662eda
MD
1276 return SCM_UNSPECIFIED;
1277}
54ee7cdf 1278#undef FUNC_NAME
80662eda
MD
1279
1280static SCM
1281set_slot_value_using_name (SCM class, SCM obj, SCM slot_name, SCM value)
1282{
1283 SCM slotdef = slot_definition_using_name (class, slot_name);
7888309b 1284 if (scm_is_true (slotdef))
80662eda
MD
1285 return set_slot_value (class, obj, slotdef, value);
1286 else
bef95911 1287 return scm_call_4 (SCM_VARIABLE_REF (var_slot_missing), class, obj, slot_name, value);
80662eda
MD
1288}
1289
1290static SCM
e81d98ec 1291test_slot_existence (SCM class SCM_UNUSED, SCM obj, SCM slot_name)
80662eda
MD
1292{
1293 register SCM l;
1294
d2e53ed6 1295 for (l = SCM_ACCESSORS_OF (obj); !scm_is_null (l); l = SCM_CDR (l))
bc36d050 1296 if (scm_is_eq (SCM_CAAR (l), slot_name))
80662eda
MD
1297 return SCM_BOOL_T;
1298
1299 return SCM_BOOL_F;
1300}
1301
80662eda
MD
1302 /* ======================================== */
1303
23437298
DH
1304SCM_DEFINE (scm_slot_ref_using_class, "slot-ref-using-class", 3, 0, 0,
1305 (SCM class, SCM obj, SCM slot_name),
1306 "")
1307#define FUNC_NAME s_scm_slot_ref_using_class
80662eda
MD
1308{
1309 SCM res;
1310
398d8ee1
KN
1311 SCM_VALIDATE_CLASS (1, class);
1312 SCM_VALIDATE_INSTANCE (2, obj);
1313 SCM_VALIDATE_SYMBOL (3, slot_name);
80662eda
MD
1314
1315 res = get_slot_value_using_name (class, obj, slot_name);
1316 if (SCM_GOOPS_UNBOUNDP (res))
bef95911 1317 return scm_call_3 (SCM_VARIABLE_REF (var_slot_unbound), class, obj, slot_name);
80662eda
MD
1318 return res;
1319}
23437298 1320#undef FUNC_NAME
80662eda 1321
23437298
DH
1322
1323SCM_DEFINE (scm_slot_set_using_class_x, "slot-set-using-class!", 4, 0, 0,
1324 (SCM class, SCM obj, SCM slot_name, SCM value),
1325 "")
1326#define FUNC_NAME s_scm_slot_set_using_class_x
80662eda 1327{
398d8ee1
KN
1328 SCM_VALIDATE_CLASS (1, class);
1329 SCM_VALIDATE_INSTANCE (2, obj);
1330 SCM_VALIDATE_SYMBOL (3, slot_name);
23437298 1331
80662eda
MD
1332 return set_slot_value_using_name (class, obj, slot_name, value);
1333}
23437298
DH
1334#undef FUNC_NAME
1335
80662eda 1336
398d8ee1
KN
1337SCM_DEFINE (scm_slot_bound_using_class_p, "slot-bound-using-class?", 3, 0, 0,
1338 (SCM class, SCM obj, SCM slot_name),
1339 "")
1340#define FUNC_NAME s_scm_slot_bound_using_class_p
80662eda 1341{
398d8ee1
KN
1342 SCM_VALIDATE_CLASS (1, class);
1343 SCM_VALIDATE_INSTANCE (2, obj);
1344 SCM_VALIDATE_SYMBOL (3, slot_name);
80662eda
MD
1345
1346 return (SCM_GOOPS_UNBOUNDP (get_slot_value_using_name (class, obj, slot_name))
1347 ? SCM_BOOL_F
1348 : SCM_BOOL_T);
1349}
398d8ee1 1350#undef FUNC_NAME
80662eda 1351
398d8ee1
KN
1352SCM_DEFINE (scm_slot_exists_using_class_p, "slot-exists-using-class?", 3, 0, 0,
1353 (SCM class, SCM obj, SCM slot_name),
1354 "")
1355#define FUNC_NAME s_scm_slot_exists_using_class_p
1356{
1357 SCM_VALIDATE_CLASS (1, class);
1358 SCM_VALIDATE_INSTANCE (2, obj);
1359 SCM_VALIDATE_SYMBOL (3, slot_name);
80662eda
MD
1360 return test_slot_existence (class, obj, slot_name);
1361}
398d8ee1 1362#undef FUNC_NAME
80662eda
MD
1363
1364
1365 /* ======================================== */
1366
398d8ee1
KN
1367SCM_DEFINE (scm_slot_ref, "slot-ref", 2, 0, 0,
1368 (SCM obj, SCM slot_name),
6bcefd15
MG
1369 "Return the value from @var{obj}'s slot with the name\n"
1370 "@var{slot_name}.")
398d8ee1 1371#define FUNC_NAME s_scm_slot_ref
80662eda
MD
1372{
1373 SCM res, class;
1374
398d8ee1 1375 SCM_VALIDATE_INSTANCE (1, obj);
80662eda
MD
1376 TEST_CHANGE_CLASS (obj, class);
1377
1378 res = get_slot_value_using_name (class, obj, slot_name);
1379 if (SCM_GOOPS_UNBOUNDP (res))
bef95911 1380 return scm_call_3 (SCM_VARIABLE_REF (var_slot_unbound), class, obj, slot_name);
80662eda
MD
1381 return res;
1382}
398d8ee1 1383#undef FUNC_NAME
80662eda 1384
398d8ee1
KN
1385SCM_DEFINE (scm_slot_set_x, "slot-set!", 3, 0, 0,
1386 (SCM obj, SCM slot_name, SCM value),
6bcefd15 1387 "Set the slot named @var{slot_name} of @var{obj} to @var{value}.")
398d8ee1 1388#define FUNC_NAME s_scm_slot_set_x
80662eda
MD
1389{
1390 SCM class;
1391
398d8ee1 1392 SCM_VALIDATE_INSTANCE (1, obj);
80662eda
MD
1393 TEST_CHANGE_CLASS(obj, class);
1394
1395 return set_slot_value_using_name (class, obj, slot_name, value);
1396}
398d8ee1 1397#undef FUNC_NAME
80662eda 1398
398d8ee1 1399const char *scm_s_slot_set_x = s_scm_slot_set_x;
80662eda 1400
398d8ee1
KN
1401SCM_DEFINE (scm_slot_bound_p, "slot-bound?", 2, 0, 0,
1402 (SCM obj, SCM slot_name),
6bcefd15
MG
1403 "Return @code{#t} if the slot named @var{slot_name} of @var{obj}\n"
1404 "is bound.")
398d8ee1 1405#define FUNC_NAME s_scm_slot_bound_p
80662eda
MD
1406{
1407 SCM class;
1408
398d8ee1 1409 SCM_VALIDATE_INSTANCE (1, obj);
80662eda
MD
1410 TEST_CHANGE_CLASS(obj, class);
1411
1412 return (SCM_GOOPS_UNBOUNDP (get_slot_value_using_name (class,
1413 obj,
1414 slot_name))
1415 ? SCM_BOOL_F
1416 : SCM_BOOL_T);
1417}
398d8ee1 1418#undef FUNC_NAME
80662eda 1419
6d77c894 1420SCM_DEFINE (scm_slot_exists_p, "slot-exists?", 2, 0, 0,
398d8ee1 1421 (SCM obj, SCM slot_name),
6bcefd15 1422 "Return @code{#t} if @var{obj} has a slot named @var{slot_name}.")
6d77c894 1423#define FUNC_NAME s_scm_slot_exists_p
80662eda
MD
1424{
1425 SCM class;
1426
398d8ee1
KN
1427 SCM_VALIDATE_INSTANCE (1, obj);
1428 SCM_VALIDATE_SYMBOL (2, slot_name);
80662eda
MD
1429 TEST_CHANGE_CLASS (obj, class);
1430
1431 return test_slot_existence (class, obj, slot_name);
1432}
398d8ee1 1433#undef FUNC_NAME
80662eda
MD
1434
1435
1436/******************************************************************************
1437 *
1438 * %allocate-instance (the low level instance allocation primitive)
1439 *
1440 ******************************************************************************/
1441
1442static void clear_method_cache (SCM);
1443
398d8ee1
KN
1444SCM_DEFINE (scm_sys_allocate_instance, "%allocate-instance", 2, 0, 0,
1445 (SCM class, SCM initargs),
6bcefd15
MG
1446 "Create a new instance of class @var{class} and initialize it\n"
1447 "from the arguments @var{initargs}.")
398d8ee1 1448#define FUNC_NAME s_scm_sys_allocate_instance
80662eda 1449{
b6cf4d02 1450 SCM obj;
e25f3727 1451 scm_t_signed_bits n, i;
b6cf4d02 1452 SCM layout;
80662eda 1453
398d8ee1 1454 SCM_VALIDATE_CLASS (1, class);
80662eda 1455
b6cf4d02 1456 /* FIXME: duplicates some of scm_make_struct. */
80662eda 1457
e11e83f3 1458 n = SCM_I_INUM (SCM_SLOT (class, scm_si_nfields));
96a44c1c 1459 obj = scm_i_alloc_struct (SCM_STRUCT_DATA (class), n);
6d77c894 1460
b6cf4d02
AW
1461 layout = SCM_VTABLE_LAYOUT (class);
1462
1463 /* Set all SCM-holding slots to unbound */
1464 for (i = 0; i < n; i++)
71fc6438
AW
1465 {
1466 scm_t_wchar c = scm_i_symbol_ref (layout, i*2);
b6cf4d02
AW
1467 if (c == 'p')
1468 SCM_STRUCT_DATA (obj)[i] = SCM_UNPACK (SCM_GOOPS_UNBOUND);
1469 else if (c == 's')
1470 SCM_STRUCT_DATA (obj)[i] = SCM_UNPACK (obj);
1471 else
1472 SCM_STRUCT_DATA (obj)[i] = 0;
80662eda 1473 }
6d77c894 1474
b6cf4d02
AW
1475 if (SCM_CLASS_FLAGS (class) & SCM_CLASSF_PURE_GENERIC)
1476 clear_method_cache (obj);
80662eda 1477
b6cf4d02 1478 return obj;
80662eda 1479}
398d8ee1 1480#undef FUNC_NAME
80662eda 1481
398d8ee1
KN
1482SCM_DEFINE (scm_sys_set_object_setter_x, "%set-object-setter!", 2, 0, 0,
1483 (SCM obj, SCM setter),
1484 "")
1485#define FUNC_NAME s_scm_sys_set_object_setter_x
80662eda 1486{
11561496
AW
1487 SCM_ASSERT (SCM_STRUCTP (obj)
1488 && (SCM_OBJ_CLASS_FLAGS (obj) & SCM_CLASSF_PURE_GENERIC),
80662eda
MD
1489 obj,
1490 SCM_ARG1,
398d8ee1 1491 FUNC_NAME);
11561496 1492 SCM_SET_GENERIC_SETTER (obj, setter);
80662eda
MD
1493 return SCM_UNSPECIFIED;
1494}
398d8ee1 1495#undef FUNC_NAME
80662eda
MD
1496
1497/******************************************************************************
1498 *
1499 * %modify-instance (used by change-class to modify in place)
6d77c894 1500 *
80662eda
MD
1501 ******************************************************************************/
1502
398d8ee1
KN
1503SCM_DEFINE (scm_sys_modify_instance, "%modify-instance", 2, 0, 0,
1504 (SCM old, SCM new),
1505 "")
1506#define FUNC_NAME s_scm_sys_modify_instance
80662eda 1507{
398d8ee1
KN
1508 SCM_VALIDATE_INSTANCE (1, old);
1509 SCM_VALIDATE_INSTANCE (2, new);
80662eda 1510
6d77c894 1511 /* Exchange the data contained in old and new. We exchange rather than
80662eda
MD
1512 * scratch the old value with new to be correct with GC.
1513 * See "Class redefinition protocol above".
1514 */
9de87eea 1515 SCM_CRITICAL_SECTION_START;
80662eda 1516 {
32b12f40
KR
1517 scm_t_bits word0, word1;
1518 word0 = SCM_CELL_WORD_0 (old);
1519 word1 = SCM_CELL_WORD_1 (old);
1520 SCM_SET_CELL_WORD_0 (old, SCM_CELL_WORD_0 (new));
1521 SCM_SET_CELL_WORD_1 (old, SCM_CELL_WORD_1 (new));
1522 SCM_SET_CELL_WORD_0 (new, word0);
1523 SCM_SET_CELL_WORD_1 (new, word1);
80662eda 1524 }
9de87eea 1525 SCM_CRITICAL_SECTION_END;
80662eda
MD
1526 return SCM_UNSPECIFIED;
1527}
398d8ee1 1528#undef FUNC_NAME
80662eda 1529
398d8ee1
KN
1530SCM_DEFINE (scm_sys_modify_class, "%modify-class", 2, 0, 0,
1531 (SCM old, SCM new),
1532 "")
1533#define FUNC_NAME s_scm_sys_modify_class
80662eda 1534{
398d8ee1
KN
1535 SCM_VALIDATE_CLASS (1, old);
1536 SCM_VALIDATE_CLASS (2, new);
80662eda 1537
9de87eea 1538 SCM_CRITICAL_SECTION_START;
80662eda 1539 {
32b12f40
KR
1540 scm_t_bits word0, word1;
1541 word0 = SCM_CELL_WORD_0 (old);
1542 word1 = SCM_CELL_WORD_1 (old);
1543 SCM_SET_CELL_WORD_0 (old, SCM_CELL_WORD_0 (new));
1544 SCM_SET_CELL_WORD_1 (old, SCM_CELL_WORD_1 (new));
b6cf4d02 1545 SCM_STRUCT_DATA (old)[scm_vtable_index_self] = SCM_UNPACK (old);
32b12f40
KR
1546 SCM_SET_CELL_WORD_0 (new, word0);
1547 SCM_SET_CELL_WORD_1 (new, word1);
b6cf4d02 1548 SCM_STRUCT_DATA (new)[scm_vtable_index_self] = SCM_UNPACK (new);
80662eda 1549 }
9de87eea 1550 SCM_CRITICAL_SECTION_END;
80662eda
MD
1551 return SCM_UNSPECIFIED;
1552}
398d8ee1 1553#undef FUNC_NAME
80662eda 1554
398d8ee1
KN
1555SCM_DEFINE (scm_sys_invalidate_class, "%invalidate-class", 1, 0, 0,
1556 (SCM class),
1557 "")
1558#define FUNC_NAME s_scm_sys_invalidate_class
80662eda 1559{
398d8ee1 1560 SCM_VALIDATE_CLASS (1, class);
80662eda
MD
1561 SCM_CLEAR_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_VALID);
1562 return SCM_UNSPECIFIED;
1563}
398d8ee1 1564#undef FUNC_NAME
80662eda
MD
1565
1566/* When instances change class, they finally get a new body, but
1567 * before that, they go through purgatory in hell. Odd as it may
1568 * seem, this data structure saves us from eternal suffering in
1569 * infinite recursions.
1570 */
1571
92c2555f 1572static scm_t_bits **hell;
c014a02e
ML
1573static long n_hell = 1; /* one place for the evil one himself */
1574static long hell_size = 4;
2132f0d2 1575static SCM hell_mutex;
80662eda 1576
c014a02e 1577static long
80662eda
MD
1578burnin (SCM o)
1579{
c014a02e 1580 long i;
80662eda 1581 for (i = 1; i < n_hell; ++i)
6b80d352 1582 if (SCM_STRUCT_DATA (o) == hell[i])
80662eda
MD
1583 return i;
1584 return 0;
1585}
1586
1587static void
1588go_to_hell (void *o)
1589{
b5df9cda 1590 SCM obj = *(SCM*)o;
2132f0d2 1591 scm_lock_mutex (hell_mutex);
51ef99f7 1592 if (n_hell >= hell_size)
80662eda 1593 {
51ef99f7 1594 hell_size *= 2;
408bcd99 1595 hell = scm_realloc (hell, hell_size * sizeof(*hell));
80662eda 1596 }
6b80d352 1597 hell[n_hell++] = SCM_STRUCT_DATA (obj);
2132f0d2 1598 scm_unlock_mutex (hell_mutex);
80662eda
MD
1599}
1600
1601static void
1602go_to_heaven (void *o)
1603{
b5df9cda 1604 SCM obj = *(SCM*)o;
2132f0d2 1605 scm_lock_mutex (hell_mutex);
b5df9cda 1606 hell[burnin (obj)] = hell[--n_hell];
2132f0d2 1607 scm_unlock_mutex (hell_mutex);
80662eda
MD
1608}
1609
6b80d352
DH
1610
1611SCM_SYMBOL (scm_sym_change_class, "change-class");
1612
80662eda 1613static SCM
b5df9cda 1614purgatory (SCM obj, SCM new_class)
80662eda 1615{
b5df9cda 1616 return scm_call_2 (SCM_VARIABLE_REF (var_change_class), obj, new_class);
80662eda
MD
1617}
1618
38d8927c
MD
1619/* This function calls the generic function change-class for all
1620 * instances which aren't currently undergoing class change.
1621 */
1622
80662eda 1623void
e81d98ec 1624scm_change_object_class (SCM obj, SCM old_class SCM_UNUSED, SCM new_class)
80662eda
MD
1625{
1626 if (!burnin (obj))
b5df9cda
AW
1627 {
1628 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
1629 scm_dynwind_rewind_handler (go_to_hell, &obj, SCM_F_WIND_EXPLICITLY);
1630 scm_dynwind_unwind_handler (go_to_heaven, &obj, SCM_F_WIND_EXPLICITLY);
1631 purgatory (obj, new_class);
1632 scm_dynwind_end ();
1633 }
80662eda
MD
1634}
1635
1636/******************************************************************************
1637 *
6d77c894
TTN
1638 * GGGG FFFFF
1639 * G F
1640 * G GG FFF
1641 * G G F
80662eda
MD
1642 * GGG E N E R I C F U N C T I O N S
1643 *
1644 * This implementation provides
1645 * - generic functions (with class specializers)
1646 * - multi-methods
6d77c894 1647 * - next-method
80662eda
MD
1648 * - a hard-coded MOP for standard gf, which can be overloaded for non-std gf
1649 *
1650 ******************************************************************************/
1651
1652SCM_KEYWORD (k_name, "name");
1653
63c1872f 1654SCM_GLOBAL_SYMBOL (scm_sym_args, "args");
80662eda 1655
e29db33c 1656SCM_SYMBOL (sym_delayed_compile, "delayed-compile");
efcebb5b 1657
60617d81
MW
1658static SCM delayed_compile_var;
1659
1660static void
1661init_delayed_compile_var (void)
1662{
1663 delayed_compile_var
1664 = scm_c_private_lookup ("oop goops dispatch", "delayed-compile");
1665}
1666
e29db33c
AW
1667static SCM
1668make_dispatch_procedure (SCM gf)
1669{
60617d81
MW
1670 static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
1671 scm_i_pthread_once (&once, init_delayed_compile_var);
1672
1673 return scm_call_1 (scm_variable_ref (delayed_compile_var), gf);
e29db33c
AW
1674}
1675
80662eda
MD
1676static void
1677clear_method_cache (SCM gf)
1678{
e29db33c 1679 SCM_SET_GENERIC_DISPATCH_PROCEDURE (gf, make_dispatch_procedure (gf));
a9a90a88 1680 SCM_CLEAR_GENERIC_EFFECTIVE_METHODS (gf);
80662eda
MD
1681}
1682
398d8ee1
KN
1683SCM_DEFINE (scm_sys_invalidate_method_cache_x, "%invalidate-method-cache!", 1, 0, 0,
1684 (SCM gf),
1685 "")
1686#define FUNC_NAME s_scm_sys_invalidate_method_cache_x
80662eda 1687{
25ba37df 1688 SCM_ASSERT (SCM_PUREGENERICP (gf), gf, SCM_ARG1, FUNC_NAME);
6d33e90f 1689 clear_method_cache (gf);
80662eda
MD
1690 return SCM_UNSPECIFIED;
1691}
398d8ee1 1692#undef FUNC_NAME
80662eda 1693
398d8ee1
KN
1694SCM_DEFINE (scm_generic_capability_p, "generic-capability?", 1, 0, 0,
1695 (SCM proc),
1696 "")
1697#define FUNC_NAME s_scm_generic_capability_p
80662eda 1698{
7888309b 1699 SCM_ASSERT (scm_is_true (scm_procedure_p (proc)),
398d8ee1 1700 proc, SCM_ARG1, FUNC_NAME);
9fdf9fd3 1701 return (SCM_PRIMITIVE_GENERIC_P (proc) ? SCM_BOOL_T : SCM_BOOL_F);
80662eda 1702}
398d8ee1 1703#undef FUNC_NAME
80662eda 1704
398d8ee1
KN
1705SCM_DEFINE (scm_enable_primitive_generic_x, "enable-primitive-generic!", 0, 0, 1,
1706 (SCM subrs),
1707 "")
1708#define FUNC_NAME s_scm_enable_primitive_generic_x
80662eda 1709{
6b80d352 1710 SCM_VALIDATE_REST_ARGUMENT (subrs);
d2e53ed6 1711 while (!scm_is_null (subrs))
80662eda
MD
1712 {
1713 SCM subr = SCM_CAR (subrs);
9fdf9fd3 1714 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARGn, FUNC_NAME);
52fd9639
AW
1715 SCM_SET_SUBR_GENERIC (subr,
1716 scm_make (scm_list_3 (scm_class_generic,
1717 k_name,
1718 SCM_SUBR_NAME (subr))));
80662eda
MD
1719 subrs = SCM_CDR (subrs);
1720 }
1721 return SCM_UNSPECIFIED;
1722}
398d8ee1 1723#undef FUNC_NAME
80662eda 1724
9f63ce02
AW
1725SCM_DEFINE (scm_set_primitive_generic_x, "set-primitive-generic!", 2, 0, 0,
1726 (SCM subr, SCM generic),
1727 "")
1728#define FUNC_NAME s_scm_set_primitive_generic_x
1729{
9fdf9fd3 1730 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARG1, FUNC_NAME);
9f63ce02 1731 SCM_ASSERT (SCM_PUREGENERICP (generic), generic, SCM_ARG2, FUNC_NAME);
52fd9639 1732 SCM_SET_SUBR_GENERIC (subr, generic);
9f63ce02
AW
1733 return SCM_UNSPECIFIED;
1734}
1735#undef FUNC_NAME
1736
398d8ee1
KN
1737SCM_DEFINE (scm_primitive_generic_generic, "primitive-generic-generic", 1, 0, 0,
1738 (SCM subr),
1739 "")
1740#define FUNC_NAME s_scm_primitive_generic_generic
80662eda 1741{
9fdf9fd3 1742 if (SCM_PRIMITIVE_GENERIC_P (subr))
80662eda 1743 {
b2b33168 1744 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (subr)))
a48d60b1
MD
1745 scm_enable_primitive_generic_x (scm_list_1 (subr));
1746 return *SCM_SUBR_GENERIC (subr);
80662eda 1747 }
db4b4ca6 1748 SCM_WRONG_TYPE_ARG (SCM_ARG1, subr);
80662eda 1749}
398d8ee1 1750#undef FUNC_NAME
80662eda 1751
a48d60b1
MD
1752typedef struct t_extension {
1753 struct t_extension *next;
1754 SCM extended;
1755 SCM extension;
1756} t_extension;
1757
d0cad249
LC
1758
1759/* Hint for `scm_gc_malloc ()' et al. when allocating `t_extension'
1760 objects. */
1761static const char extension_gc_hint[] = "GOOPS extension";
1762
a48d60b1
MD
1763static t_extension *extensions = 0;
1764
a48d60b1
MD
1765void
1766scm_c_extend_primitive_generic (SCM extended, SCM extension)
1767{
1768 if (goops_loaded_p)
1769 {
1770 SCM gf, gext;
b2b33168 1771 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (extended)))
a48d60b1
MD
1772 scm_enable_primitive_generic_x (scm_list_1 (extended));
1773 gf = *SCM_SUBR_GENERIC (extended);
1774 gext = scm_call_2 (SCM_VARIABLE_REF (scm_var_make_extended_generic),
1775 gf,
ce471ab8 1776 SCM_SUBR_NAME (extension));
feccd2d3 1777 SCM_SET_SUBR_GENERIC (extension, gext);
a48d60b1
MD
1778 }
1779 else
1780 {
d0cad249
LC
1781 t_extension *e = scm_gc_malloc (sizeof (t_extension),
1782 extension_gc_hint);
a48d60b1
MD
1783 t_extension **loc = &extensions;
1784 /* Make sure that extensions are placed before their own
1785 * extensions in the extensions list. O(N^2) algorithm, but
1786 * extensions of primitive generics are rare.
1787 */
d223c3fc 1788 while (*loc && !scm_is_eq (extension, (*loc)->extended))
a48d60b1
MD
1789 loc = &(*loc)->next;
1790 e->next = *loc;
1791 e->extended = extended;
1792 e->extension = extension;
1793 *loc = e;
1794 }
1795}
1796
1797static void
1798setup_extended_primitive_generics ()
1799{
1800 while (extensions)
1801 {
1802 t_extension *e = extensions;
1803 scm_c_extend_primitive_generic (e->extended, e->extension);
1804 extensions = e->next;
a48d60b1
MD
1805 }
1806}
1807
fa075d40
AW
1808/* Dirk:FIXME:: In all of these scm_wta_dispatch_* routines it is
1809 * assumed that 'gf' is zero if uninitialized. It would be cleaner if
1810 * some valid SCM value like SCM_BOOL_F or SCM_UNDEFINED were chosen.
1811 */
1812
1813SCM
1814scm_wta_dispatch_0 (SCM gf, const char *subr)
1815{
1816 if (!SCM_UNPACK (gf))
1817 scm_error_num_args_subr (subr);
1818
1819 return scm_call_0 (gf);
1820}
1821
1822SCM
1823scm_wta_dispatch_1 (SCM gf, SCM a1, int pos, const char *subr)
1824{
1825 if (!SCM_UNPACK (gf))
1826 scm_wrong_type_arg (subr, pos, a1);
1827
1828 return scm_call_1 (gf, a1);
1829}
1830
1831SCM
1832scm_wta_dispatch_2 (SCM gf, SCM a1, SCM a2, int pos, const char *subr)
1833{
1834 if (!SCM_UNPACK (gf))
1835 scm_wrong_type_arg (subr, pos, (pos == SCM_ARG1) ? a1 : a2);
1836
1837 return scm_call_2 (gf, a1, a2);
1838}
1839
1840SCM
1841scm_wta_dispatch_n (SCM gf, SCM args, int pos, const char *subr)
1842{
1843 if (!SCM_UNPACK (gf))
1844 scm_wrong_type_arg (subr, pos, scm_list_ref (args, scm_from_int (pos)));
1845
1846 return scm_apply_0 (gf, args);
1847}
1848
80662eda 1849/******************************************************************************
6d77c894 1850 *
80662eda 1851 * Protocol for calling a generic fumction
6d77c894 1852 * This protocol is roughly equivalent to (parameter are a little bit different
80662eda
MD
1853 * for efficiency reasons):
1854 *
1855 * + apply-generic (gf args)
1856 * + compute-applicable-methods (gf args ...)
1857 * + sort-applicable-methods (methods args)
1858 * + apply-methods (gf methods args)
6d77c894
TTN
1859 *
1860 * apply-methods calls make-next-method to build the "continuation" of a a
80662eda
MD
1861 * method. Applying a next-method will call apply-next-method which in
1862 * turn will call apply again to call effectively the following method.
1863 *
1864 ******************************************************************************/
1865
80662eda
MD
1866/******************************************************************************
1867 *
1868 * A simple make (which will be redefined later in Scheme)
1869 * This version handles only creation of gf, methods and classes (no instances)
1870 *
6d77c894 1871 * Since this code will disappear when Goops will be fully booted,
80662eda
MD
1872 * no precaution is taken to be efficient.
1873 *
1874 ******************************************************************************/
1875
1876SCM_KEYWORD (k_setter, "setter");
1877SCM_KEYWORD (k_specializers, "specializers");
1878SCM_KEYWORD (k_procedure, "procedure");
5487977b
AW
1879SCM_KEYWORD (k_formals, "formals");
1880SCM_KEYWORD (k_body, "body");
e177058b 1881SCM_KEYWORD (k_make_procedure, "make-procedure");
80662eda
MD
1882SCM_KEYWORD (k_dsupers, "dsupers");
1883SCM_KEYWORD (k_slots, "slots");
1884SCM_KEYWORD (k_gf, "generic-function");
1885
398d8ee1
KN
1886SCM_DEFINE (scm_make, "make", 0, 0, 1,
1887 (SCM args),
27c37006 1888 "Make a new object. @var{args} must contain the class and\n"
6bcefd15 1889 "all necessary initialization information.")
398d8ee1 1890#define FUNC_NAME s_scm_make
80662eda
MD
1891{
1892 SCM class, z;
c014a02e 1893 long len = scm_ilength (args);
80662eda
MD
1894
1895 if (len <= 0 || (len & 1) == 0)
398d8ee1 1896 SCM_WRONG_NUM_ARGS ();
80662eda
MD
1897
1898 class = SCM_CAR(args);
1899 args = SCM_CDR(args);
1900
d223c3fc
AW
1901 if (scm_is_eq (class, scm_class_generic)
1902 || scm_is_eq (class, scm_class_accessor))
80662eda 1903 {
80662eda 1904 z = scm_make_struct (class, SCM_INUM0,
72d2e7e6 1905 scm_list_4 (SCM_BOOL_F,
51f66c91 1906 SCM_EOL,
1afff620 1907 SCM_INUM0,
bbf8d523 1908 SCM_EOL));
80662eda
MD
1909 scm_set_procedure_property_x (z, scm_sym_name,
1910 scm_get_keyword (k_name,
1911 args,
1912 SCM_BOOL_F));
1913 clear_method_cache (z);
d223c3fc 1914 if (scm_is_eq (class, scm_class_accessor))
80662eda
MD
1915 {
1916 SCM setter = scm_get_keyword (k_setter, args, SCM_BOOL_F);
7888309b 1917 if (scm_is_true (setter))
80662eda
MD
1918 scm_sys_set_object_setter_x (z, setter);
1919 }
1920 }
1921 else
1922 {
1923 z = scm_sys_allocate_instance (class, args);
1924
d223c3fc
AW
1925 if (scm_is_eq (class, scm_class_method)
1926 || scm_is_eq (class, scm_class_accessor_method))
80662eda 1927 {
6d77c894 1928 SCM_SET_SLOT (z, scm_si_generic_function,
80662eda
MD
1929 scm_i_get_keyword (k_gf,
1930 args,
1931 len - 1,
1932 SCM_BOOL_F,
dcb410ec 1933 FUNC_NAME));
6d77c894 1934 SCM_SET_SLOT (z, scm_si_specializers,
80662eda
MD
1935 scm_i_get_keyword (k_specializers,
1936 args,
1937 len - 1,
1938 SCM_EOL,
dcb410ec 1939 FUNC_NAME));
6d77c894 1940 SCM_SET_SLOT (z, scm_si_procedure,
80662eda
MD
1941 scm_i_get_keyword (k_procedure,
1942 args,
1943 len - 1,
e177058b 1944 SCM_BOOL_F,
dcb410ec 1945 FUNC_NAME));
5487977b
AW
1946 SCM_SET_SLOT (z, scm_si_formals,
1947 scm_i_get_keyword (k_formals,
1948 args,
1949 len - 1,
1950 SCM_EOL,
1951 FUNC_NAME));
1952 SCM_SET_SLOT (z, scm_si_body,
1953 scm_i_get_keyword (k_body,
1954 args,
1955 len - 1,
1956 SCM_EOL,
1957 FUNC_NAME));
e177058b
AW
1958 SCM_SET_SLOT (z, scm_si_make_procedure,
1959 scm_i_get_keyword (k_make_procedure,
5487977b
AW
1960 args,
1961 len - 1,
1962 SCM_BOOL_F,
1963 FUNC_NAME));
80662eda
MD
1964 }
1965 else
1966 {
1967 /* In all the others case, make a new class .... No instance here */
b6cf4d02 1968 SCM_SET_SLOT (z, scm_vtable_index_name,
80662eda
MD
1969 scm_i_get_keyword (k_name,
1970 args,
1971 len - 1,
4a655e50 1972 scm_from_latin1_symbol ("???"),
dcb410ec 1973 FUNC_NAME));
6d77c894 1974 SCM_SET_SLOT (z, scm_si_direct_supers,
80662eda
MD
1975 scm_i_get_keyword (k_dsupers,
1976 args,
1977 len - 1,
1978 SCM_EOL,
dcb410ec 1979 FUNC_NAME));
6d77c894 1980 SCM_SET_SLOT (z, scm_si_direct_slots,
80662eda
MD
1981 scm_i_get_keyword (k_slots,
1982 args,
1983 len - 1,
1984 SCM_EOL,
dcb410ec 1985 FUNC_NAME));
80662eda
MD
1986 }
1987 }
1988 return z;
1989}
398d8ee1 1990#undef FUNC_NAME
80662eda 1991
80662eda
MD
1992
1993/******************************************************************************
1994 *
6d77c894 1995 * Initializations
80662eda
MD
1996 *
1997 ******************************************************************************/
1998
80662eda
MD
1999static void
2000make_stdcls (SCM *var, char *name, SCM meta, SCM super, SCM slots)
2001{
25d50a05 2002 SCM tmp = scm_from_utf8_symbol (name);
6d77c894 2003
f39448c5
AW
2004 *var = scm_basic_make_class (meta, tmp,
2005 scm_is_pair (super) ? super : scm_list_1 (super),
2006 slots);
28d0871b 2007 scm_module_define (scm_module_goops, tmp, *var);
80662eda
MD
2008}
2009
2010
2011SCM_KEYWORD (k_slot_definition, "slot-definition");
2012
2013static void
2014create_standard_classes (void)
2015{
2016 SCM slots;
4a655e50
AW
2017 SCM method_slots = scm_list_n (scm_from_latin1_symbol ("generic-function"),
2018 scm_from_latin1_symbol ("specializers"),
6b80d352 2019 sym_procedure,
4a655e50
AW
2020 scm_from_latin1_symbol ("formals"),
2021 scm_from_latin1_symbol ("body"),
2022 scm_from_latin1_symbol ("make-procedure"),
21497600 2023 SCM_UNDEFINED);
4a655e50 2024 SCM amethod_slots = scm_list_1 (scm_list_3 (scm_from_latin1_symbol ("slot-definition"),
1afff620
KN
2025 k_init_keyword,
2026 k_slot_definition));
4a655e50
AW
2027 SCM gf_slots = scm_list_4 (scm_from_latin1_symbol ("methods"),
2028 scm_list_3 (scm_from_latin1_symbol ("n-specialized"),
1afff620
KN
2029 k_init_value,
2030 SCM_INUM0),
4a655e50 2031 scm_list_3 (scm_from_latin1_symbol ("extended-by"),
bbf8d523 2032 k_init_value,
b6cf4d02 2033 SCM_EOL),
4a655e50 2034 scm_from_latin1_symbol ("effective-methods"));
a9a90a88 2035 SCM setter_slots = scm_list_1 (sym_setter);
4a655e50 2036 SCM egf_slots = scm_list_1 (scm_list_3 (scm_from_latin1_symbol ("extends"),
bbf8d523
MD
2037 k_init_value,
2038 SCM_EOL));
80662eda
MD
2039 /* Foreign class slot classes */
2040 make_stdcls (&scm_class_foreign_slot, "<foreign-slot>",
2041 scm_class_class, scm_class_top, SCM_EOL);
2042 make_stdcls (&scm_class_protected, "<protected-slot>",
2043 scm_class_class, scm_class_foreign_slot, SCM_EOL);
b6cf4d02
AW
2044 make_stdcls (&scm_class_hidden, "<hidden-slot>",
2045 scm_class_class, scm_class_foreign_slot, SCM_EOL);
80662eda
MD
2046 make_stdcls (&scm_class_opaque, "<opaque-slot>",
2047 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2048 make_stdcls (&scm_class_read_only, "<read-only-slot>",
2049 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2050 make_stdcls (&scm_class_self, "<self-slot>",
b6cf4d02 2051 scm_class_class, scm_class_read_only, SCM_EOL);
80662eda
MD
2052 make_stdcls (&scm_class_protected_opaque, "<protected-opaque-slot>",
2053 scm_class_class,
1afff620 2054 scm_list_2 (scm_class_protected, scm_class_opaque),
80662eda 2055 SCM_EOL);
b6cf4d02
AW
2056 make_stdcls (&scm_class_protected_hidden, "<protected-hidden-slot>",
2057 scm_class_class,
2058 scm_list_2 (scm_class_protected, scm_class_hidden),
2059 SCM_EOL);
80662eda
MD
2060 make_stdcls (&scm_class_protected_read_only, "<protected-read-only-slot>",
2061 scm_class_class,
1afff620 2062 scm_list_2 (scm_class_protected, scm_class_read_only),
80662eda
MD
2063 SCM_EOL);
2064 make_stdcls (&scm_class_scm, "<scm-slot>",
2065 scm_class_class, scm_class_protected, SCM_EOL);
2066 make_stdcls (&scm_class_int, "<int-slot>",
2067 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2068 make_stdcls (&scm_class_float, "<float-slot>",
2069 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2070 make_stdcls (&scm_class_double, "<double-slot>",
2071 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2072
9167e0b8 2073 specialized_slots_initialized = 1;
6d77c894 2074
9167e0b8
AW
2075 /* Finish initialization of class <class> */
2076
2077 slots = build_class_class_slots (FINAL_SLOTS);
dcb410ec
DH
2078 SCM_SET_SLOT (scm_class_class, scm_si_direct_slots, slots);
2079 SCM_SET_SLOT (scm_class_class, scm_si_slots, slots);
2080 SCM_SET_SLOT (scm_class_class, scm_si_getters_n_setters,
2081 compute_getters_n_setters (slots));
6d77c894 2082
80662eda
MD
2083 /* scm_class_generic functions classes */
2084 make_stdcls (&scm_class_procedure_class, "<procedure-class>",
2085 scm_class_class, scm_class_class, SCM_EOL);
51f66c91 2086 make_stdcls (&scm_class_applicable_struct_class, "<applicable-struct-class>",
80662eda 2087 scm_class_class, scm_class_procedure_class, SCM_EOL);
2f652c68 2088 SCM_SET_VTABLE_FLAGS (scm_class_applicable_struct_class, SCM_VTABLE_FLAG_APPLICABLE_VTABLE);
80662eda
MD
2089 make_stdcls (&scm_class_method, "<method>",
2090 scm_class_class, scm_class_object, method_slots);
f8af5c6d 2091 make_stdcls (&scm_class_accessor_method, "<accessor-method>",
51f66c91 2092 scm_class_class, scm_class_method, amethod_slots);
74b6d6e4
MD
2093 make_stdcls (&scm_class_applicable, "<applicable>",
2094 scm_class_class, scm_class_top, SCM_EOL);
51f66c91
AW
2095 make_stdcls (&scm_class_applicable_struct, "<applicable-struct>",
2096 scm_class_applicable_struct_class,
74b6d6e4 2097 scm_list_2 (scm_class_object, scm_class_applicable),
51f66c91 2098 scm_list_1 (sym_procedure));
80662eda 2099 make_stdcls (&scm_class_generic, "<generic>",
51f66c91 2100 scm_class_applicable_struct_class, scm_class_applicable_struct, gf_slots);
80662eda 2101 SCM_SET_CLASS_FLAGS (scm_class_generic, SCM_CLASSF_PURE_GENERIC);
bbf8d523 2102 make_stdcls (&scm_class_extended_generic, "<extended-generic>",
51f66c91 2103 scm_class_applicable_struct_class, scm_class_generic, egf_slots);
bbf8d523 2104 SCM_SET_CLASS_FLAGS (scm_class_extended_generic, SCM_CLASSF_PURE_GENERIC);
80662eda 2105 make_stdcls (&scm_class_generic_with_setter, "<generic-with-setter>",
51f66c91 2106 scm_class_applicable_struct_class, scm_class_generic, setter_slots);
80662eda 2107 SCM_SET_CLASS_FLAGS (scm_class_generic_with_setter, SCM_CLASSF_PURE_GENERIC);
f8af5c6d 2108 make_stdcls (&scm_class_accessor, "<accessor>",
51f66c91 2109 scm_class_applicable_struct_class, scm_class_generic_with_setter, SCM_EOL);
f8af5c6d 2110 SCM_SET_CLASS_FLAGS (scm_class_accessor, SCM_CLASSF_PURE_GENERIC);
bbf8d523
MD
2111 make_stdcls (&scm_class_extended_generic_with_setter,
2112 "<extended-generic-with-setter>",
51f66c91 2113 scm_class_applicable_struct_class,
ae88d9bc
AW
2114 scm_list_2 (scm_class_extended_generic,
2115 scm_class_generic_with_setter),
bbf8d523
MD
2116 SCM_EOL);
2117 SCM_SET_CLASS_FLAGS (scm_class_extended_generic_with_setter,
2118 SCM_CLASSF_PURE_GENERIC);
74b6d6e4 2119 make_stdcls (&scm_class_extended_accessor, "<extended-accessor>",
51f66c91 2120 scm_class_applicable_struct_class,
74b6d6e4
MD
2121 scm_list_2 (scm_class_accessor,
2122 scm_class_extended_generic_with_setter),
2123 SCM_EOL);
74b6d6e4 2124 SCM_SET_CLASS_FLAGS (scm_class_extended_accessor, SCM_CLASSF_PURE_GENERIC);
80662eda
MD
2125
2126 /* Primitive types classes */
2127 make_stdcls (&scm_class_boolean, "<boolean>",
2128 scm_class_class, scm_class_top, SCM_EOL);
2129 make_stdcls (&scm_class_char, "<char>",
2130 scm_class_class, scm_class_top, SCM_EOL);
2131 make_stdcls (&scm_class_list, "<list>",
2132 scm_class_class, scm_class_top, SCM_EOL);
2133 make_stdcls (&scm_class_pair, "<pair>",
2134 scm_class_class, scm_class_list, SCM_EOL);
2135 make_stdcls (&scm_class_null, "<null>",
2136 scm_class_class, scm_class_list, SCM_EOL);
2137 make_stdcls (&scm_class_string, "<string>",
2138 scm_class_class, scm_class_top, SCM_EOL);
2139 make_stdcls (&scm_class_symbol, "<symbol>",
2140 scm_class_class, scm_class_top, SCM_EOL);
2141 make_stdcls (&scm_class_vector, "<vector>",
2142 scm_class_class, scm_class_top, SCM_EOL);
e2c2a699
AW
2143 make_stdcls (&class_foreign, "<foreign>",
2144 scm_class_class, scm_class_top, SCM_EOL);
9ea31741
AW
2145 make_stdcls (&class_hashtable, "<hashtable>",
2146 scm_class_class, scm_class_top, SCM_EOL);
2147 make_stdcls (&class_fluid, "<fluid>",
2148 scm_class_class, scm_class_top, SCM_EOL);
2149 make_stdcls (&class_dynamic_state, "<dynamic-state>",
c99de5aa 2150 scm_class_class, scm_class_top, SCM_EOL);
6f3b0cc2
AW
2151 make_stdcls (&class_frame, "<frame>",
2152 scm_class_class, scm_class_top, SCM_EOL);
6f3b0cc2
AW
2153 make_stdcls (&class_vm_cont, "<vm-continuation>",
2154 scm_class_class, scm_class_top, SCM_EOL);
f826a886
AW
2155 make_stdcls (&class_bytevector, "<bytevector>",
2156 scm_class_class, scm_class_top, SCM_EOL);
2157 make_stdcls (&class_uvec, "<uvec>",
2158 scm_class_class, class_bytevector, SCM_EOL);
b2637c98
AW
2159 make_stdcls (&class_array, "<array>",
2160 scm_class_class, scm_class_top, SCM_EOL);
ff1feca9
AW
2161 make_stdcls (&class_bitvector, "<bitvector>",
2162 scm_class_class, scm_class_top, SCM_EOL);
80662eda
MD
2163 make_stdcls (&scm_class_number, "<number>",
2164 scm_class_class, scm_class_top, SCM_EOL);
2165 make_stdcls (&scm_class_complex, "<complex>",
2166 scm_class_class, scm_class_number, SCM_EOL);
2167 make_stdcls (&scm_class_real, "<real>",
2168 scm_class_class, scm_class_complex, SCM_EOL);
2169 make_stdcls (&scm_class_integer, "<integer>",
2170 scm_class_class, scm_class_real, SCM_EOL);
f92e85f7
MV
2171 make_stdcls (&scm_class_fraction, "<fraction>",
2172 scm_class_class, scm_class_real, SCM_EOL);
80662eda
MD
2173 make_stdcls (&scm_class_keyword, "<keyword>",
2174 scm_class_class, scm_class_top, SCM_EOL);
2175 make_stdcls (&scm_class_unknown, "<unknown>",
2176 scm_class_class, scm_class_top, SCM_EOL);
2177 make_stdcls (&scm_class_procedure, "<procedure>",
74b6d6e4 2178 scm_class_procedure_class, scm_class_applicable, SCM_EOL);
80662eda
MD
2179 make_stdcls (&scm_class_primitive_generic, "<primitive-generic>",
2180 scm_class_procedure_class, scm_class_procedure, SCM_EOL);
2181 make_stdcls (&scm_class_port, "<port>",
2182 scm_class_class, scm_class_top, SCM_EOL);
2183 make_stdcls (&scm_class_input_port, "<input-port>",
2184 scm_class_class, scm_class_port, SCM_EOL);
2185 make_stdcls (&scm_class_output_port, "<output-port>",
2186 scm_class_class, scm_class_port, SCM_EOL);
2187 make_stdcls (&scm_class_input_output_port, "<input-output-port>",
2188 scm_class_class,
1afff620 2189 scm_list_2 (scm_class_input_port, scm_class_output_port),
80662eda
MD
2190 SCM_EOL);
2191}
2192
2193/**********************************************************************
2194 *
2195 * Smob classes
2196 *
2197 **********************************************************************/
2198
2199static SCM
da0e6c2b 2200make_class_from_template (char const *template, char const *type_name, SCM supers, int applicablep)
80662eda 2201{
28d0871b 2202 SCM name;
80662eda
MD
2203 if (type_name)
2204 {
2205 char buffer[100];
2206 sprintf (buffer, template, type_name);
25d50a05 2207 name = scm_from_utf8_symbol (buffer);
80662eda
MD
2208 }
2209 else
2210 name = SCM_GOOPS_UNBOUND;
2211
28d0871b
AW
2212 return scm_basic_make_class (applicablep ? scm_class_procedure_class : scm_class_class,
2213 name, supers, SCM_EOL);
80662eda
MD
2214}
2215
9db8cf16
MG
2216static SCM
2217make_class_from_symbol (SCM type_name_sym, SCM supers, int applicablep)
2218{
28d0871b
AW
2219 SCM name;
2220
393baa8a 2221 if (scm_is_true (type_name_sym))
9db8cf16
MG
2222 {
2223 name = scm_string_append (scm_list_3 (scm_from_locale_string ("<"),
2224 scm_symbol_to_string (type_name_sym),
2225 scm_from_locale_string (">")));
2226 name = scm_string_to_symbol (name);
2227 }
2228 else
2229 name = SCM_GOOPS_UNBOUND;
2230
28d0871b
AW
2231 return scm_basic_make_class (applicablep ? scm_class_procedure_class : scm_class_class,
2232 name, supers, SCM_EOL);
9db8cf16
MG
2233}
2234
80662eda 2235SCM
da0e6c2b 2236scm_make_extended_class (char const *type_name, int applicablep)
80662eda
MD
2237{
2238 return make_class_from_template ("<%s>",
2239 type_name,
74b6d6e4
MD
2240 scm_list_1 (applicablep
2241 ? scm_class_applicable
2242 : scm_class_top),
2243 applicablep);
2244}
2245
9db8cf16
MG
2246static SCM
2247scm_make_extended_class_from_symbol (SCM type_name_sym, int applicablep)
2248{
2249 return make_class_from_symbol (type_name_sym,
2250 scm_list_1 (applicablep
2251 ? scm_class_applicable
2252 : scm_class_top),
2253 applicablep);
2254}
2255
74b6d6e4
MD
2256void
2257scm_i_inherit_applicable (SCM c)
2258{
2259 if (!SCM_SUBCLASSP (c, scm_class_applicable))
2260 {
2261 SCM dsupers = SCM_SLOT (c, scm_si_direct_supers);
2262 SCM cpl = SCM_SLOT (c, scm_si_cpl);
2263 /* patch scm_class_applicable into direct-supers */
2264 SCM top = scm_c_memq (scm_class_top, dsupers);
7888309b 2265 if (scm_is_false (top))
74b6d6e4
MD
2266 dsupers = scm_append (scm_list_2 (dsupers,
2267 scm_list_1 (scm_class_applicable)));
2268 else
2269 {
2270 SCM_SETCAR (top, scm_class_applicable);
2271 SCM_SETCDR (top, scm_cons (scm_class_top, SCM_CDR (top)));
2272 }
2273 SCM_SET_SLOT (c, scm_si_direct_supers, dsupers);
2274 /* patch scm_class_applicable into cpl */
2275 top = scm_c_memq (scm_class_top, cpl);
7888309b 2276 if (scm_is_false (top))
74b6d6e4
MD
2277 abort ();
2278 else
2279 {
2280 SCM_SETCAR (top, scm_class_applicable);
2281 SCM_SETCDR (top, scm_cons (scm_class_top, SCM_CDR (top)));
2282 }
2283 /* add class to direct-subclasses of scm_class_applicable */
2284 SCM_SET_SLOT (scm_class_applicable,
2285 scm_si_direct_subclasses,
2286 scm_cons (c, SCM_SLOT (scm_class_applicable,
2287 scm_si_direct_subclasses)));
2288 }
80662eda
MD
2289}
2290
2291static void
2292create_smob_classes (void)
2293{
c014a02e 2294 long i;
80662eda 2295
c891a40e 2296 for (i = 0; i < SCM_I_MAX_SMOB_TYPE_COUNT; ++i)
393baa8a 2297 scm_smob_class[i] = SCM_BOOL_F;
80662eda 2298
80662eda 2299 for (i = 0; i < scm_numsmob; ++i)
393baa8a 2300 if (scm_is_false (scm_smob_class[i]))
74b6d6e4
MD
2301 scm_smob_class[i] = scm_make_extended_class (SCM_SMOBNAME (i),
2302 scm_smobs[i].apply != 0);
80662eda
MD
2303}
2304
2305void
c014a02e 2306scm_make_port_classes (long ptobnum, char *type_name)
80662eda
MD
2307{
2308 SCM c, class = make_class_from_template ("<%s-port>",
2309 type_name,
74b6d6e4
MD
2310 scm_list_1 (scm_class_port),
2311 0);
80662eda
MD
2312 scm_port_class[SCM_IN_PCLASS_INDEX + ptobnum]
2313 = make_class_from_template ("<%s-input-port>",
2314 type_name,
74b6d6e4
MD
2315 scm_list_2 (class, scm_class_input_port),
2316 0);
80662eda
MD
2317 scm_port_class[SCM_OUT_PCLASS_INDEX + ptobnum]
2318 = make_class_from_template ("<%s-output-port>",
2319 type_name,
74b6d6e4
MD
2320 scm_list_2 (class, scm_class_output_port),
2321 0);
80662eda
MD
2322 scm_port_class[SCM_INOUT_PCLASS_INDEX + ptobnum]
2323 = c
2324 = make_class_from_template ("<%s-input-output-port>",
2325 type_name,
74b6d6e4
MD
2326 scm_list_2 (class, scm_class_input_output_port),
2327 0);
80662eda 2328 /* Patch cpl (since this tree is too complex for the C level compute-cpl) */
dcb410ec
DH
2329 SCM_SET_SLOT (c, scm_si_cpl,
2330 scm_cons2 (c, class, SCM_SLOT (scm_class_input_output_port, scm_si_cpl)));
80662eda
MD
2331}
2332
2333static void
2334create_port_classes (void)
2335{
c014a02e 2336 long i;
80662eda 2337
62bd5d66 2338 for (i = scm_c_num_port_types () - 1; i >= 0; i--)
80662eda
MD
2339 scm_make_port_classes (i, SCM_PTOBNAME (i));
2340}
2341
2342static SCM
74b6d6e4
MD
2343make_struct_class (void *closure SCM_UNUSED,
2344 SCM vtable, SCM data, SCM prev SCM_UNUSED)
80662eda 2345{
f3c6a02c
AW
2346 if (scm_is_false (data))
2347 scm_i_define_class_for_vtable (vtable);
80662eda
MD
2348 return SCM_UNSPECIFIED;
2349}
2350
2351static void
2352create_struct_classes (void)
2353{
ea742d29 2354 /* FIXME: take the vtable_class_map while initializing goops? */
f3c6a02c
AW
2355 scm_internal_hash_fold (make_struct_class, 0, SCM_BOOL_F,
2356 vtable_class_map);
80662eda
MD
2357}
2358
2359/**********************************************************************
2360 *
2361 * C interface
2362 *
2363 **********************************************************************/
2364
2365void
2366scm_load_goops ()
2367{
2368 if (!goops_loaded_p)
abd28220 2369 scm_c_resolve_module ("oop goops");
80662eda
MD
2370}
2371
e11208ca 2372
80662eda
MD
2373SCM_SYMBOL (sym_o, "o");
2374SCM_SYMBOL (sym_x, "x");
2375
2376SCM_KEYWORD (k_accessor, "accessor");
2377SCM_KEYWORD (k_getter, "getter");
2378
80662eda
MD
2379SCM
2380scm_ensure_accessor (SCM name)
2381{
3f48638c
AW
2382 SCM var, gf;
2383
2384 var = scm_module_variable (scm_current_module (), name);
2385 if (SCM_VARIABLEP (var) && !SCM_UNBNDP (SCM_VARIABLE_REF (var)))
2386 gf = SCM_VARIABLE_REF (var);
2387 else
2388 gf = SCM_BOOL_F;
2389
f8af5c6d 2390 if (!SCM_IS_A_P (gf, scm_class_accessor))
80662eda 2391 {
1afff620 2392 gf = scm_make (scm_list_3 (scm_class_generic, k_name, name));
f8af5c6d 2393 gf = scm_make (scm_list_5 (scm_class_accessor,
1afff620 2394 k_name, name, k_setter, gf));
80662eda 2395 }
3f48638c 2396
80662eda
MD
2397 return gf;
2398}
2399
80662eda
MD
2400#ifdef GUILE_DEBUG
2401/*
2402 * Debugging utilities
2403 */
2404
398d8ee1
KN
2405SCM_DEFINE (scm_pure_generic_p, "pure-generic?", 1, 0, 0,
2406 (SCM obj),
6bcefd15 2407 "Return @code{#t} if @var{obj} is a pure generic.")
398d8ee1 2408#define FUNC_NAME s_scm_pure_generic_p
80662eda 2409{
7888309b 2410 return scm_from_bool (SCM_PUREGENERICP (obj));
80662eda 2411}
398d8ee1 2412#undef FUNC_NAME
80662eda
MD
2413
2414#endif /* GUILE_DEBUG */
2415
2416/*
2417 * Initialization
2418 */
2419
398d8ee1
KN
2420SCM_DEFINE (scm_sys_goops_loaded, "%goops-loaded", 0, 0, 0,
2421 (),
6bcefd15
MG
2422 "Announce that GOOPS is loaded and perform initialization\n"
2423 "on the C level which depends on the loaded GOOPS modules.")
398d8ee1 2424#define FUNC_NAME s_scm_sys_goops_loaded
80662eda
MD
2425{
2426 goops_loaded_p = 1;
bef95911 2427 var_slot_unbound =
f39448c5 2428 scm_module_variable (scm_module_goops, sym_slot_unbound);
bef95911 2429 var_slot_missing =
f39448c5 2430 scm_module_variable (scm_module_goops, sym_slot_missing);
bef95911 2431 var_no_applicable_method =
f39448c5 2432 scm_module_variable (scm_module_goops, sym_no_applicable_method);
bef95911 2433 var_change_class =
f39448c5 2434 scm_module_variable (scm_module_goops, sym_change_class);
a48d60b1 2435 setup_extended_primitive_generics ();
80662eda
MD
2436 return SCM_UNSPECIFIED;
2437}
398d8ee1 2438#undef FUNC_NAME
80662eda
MD
2439
2440SCM scm_module_goops;
2441
6ab19396
AW
2442static void
2443scm_init_goops_builtins (void *unused)
80662eda 2444{
abd28220 2445 scm_module_goops = scm_current_module ();
80662eda 2446
80662eda
MD
2447 goops_rstate = scm_c_make_rstate ("GOOPS", 5);
2448
2449#include "libguile/goops.x"
2450
9167e0b8
AW
2451 var_compute_cpl =
2452 scm_module_variable (scm_module_goops, sym_compute_cpl);
2453
bb764c0e 2454 hell = scm_calloc (hell_size * sizeof (*hell));
f39448c5 2455 hell_mutex = scm_make_mutex ();
80662eda
MD
2456
2457 create_basic_classes ();
2458 create_standard_classes ();
2459 create_smob_classes ();
2460 create_struct_classes ();
2461 create_port_classes ();
2462
2463 {
4a655e50 2464 SCM name = scm_from_latin1_symbol ("no-applicable-method");
f39448c5
AW
2465 scm_no_applicable_method =
2466 scm_make (scm_list_3 (scm_class_generic, k_name, name));
28d0871b 2467 scm_module_define (scm_module_goops, name, scm_no_applicable_method);
80662eda 2468 }
80662eda
MD
2469}
2470
2471void
abd28220 2472scm_init_goops ()
80662eda 2473{
6ab19396
AW
2474 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
2475 "scm_init_goops_builtins", scm_init_goops_builtins,
2476 NULL);
80662eda 2477}
23437298
DH
2478
2479/*
2480 Local Variables:
2481 c-file-style: "gnu"
2482 End:
2483*/