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