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