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