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