simpos tweak
[bpt/guile.git] / libguile / goops.c
CommitLineData
e2c2a699 1/* Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2008,2009,2010
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
cc95e00a 673 layout = scm_i_make_string (n, &s);
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);
cc95e00a 899 SCM name = scm_from_locale_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> ****/
cc95e00a 921 name = scm_from_locale_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> ****/
cc95e00a 928 name = scm_from_locale_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);
cc95e00a 1092 return scm_slot_ref (obj, scm_from_locale_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);
cc95e00a 1102 return scm_slot_ref (obj, scm_from_locale_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{
6b80d352 1170 unsigned long int 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{
6b80d352 1187 unsigned long int 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;
c014a02e 1445 long n;
b6cf4d02
AW
1446 long i;
1447 SCM layout;
80662eda 1448
398d8ee1 1449 SCM_VALIDATE_CLASS (1, class);
80662eda 1450
b6cf4d02 1451 /* FIXME: duplicates some of scm_make_struct. */
80662eda 1452
e11e83f3 1453 n = SCM_I_INUM (SCM_SLOT (class, scm_si_nfields));
96a44c1c 1454 obj = scm_i_alloc_struct (SCM_STRUCT_DATA (class), n);
6d77c894 1455
b6cf4d02
AW
1456 layout = SCM_VTABLE_LAYOUT (class);
1457
1458 /* Set all SCM-holding slots to unbound */
1459 for (i = 0; i < n; i++)
71fc6438
AW
1460 {
1461 scm_t_wchar c = scm_i_symbol_ref (layout, i*2);
b6cf4d02
AW
1462 if (c == 'p')
1463 SCM_STRUCT_DATA (obj)[i] = SCM_UNPACK (SCM_GOOPS_UNBOUND);
1464 else if (c == 's')
1465 SCM_STRUCT_DATA (obj)[i] = SCM_UNPACK (obj);
1466 else
1467 SCM_STRUCT_DATA (obj)[i] = 0;
80662eda 1468 }
6d77c894 1469
b6cf4d02
AW
1470 if (SCM_CLASS_FLAGS (class) & SCM_CLASSF_PURE_GENERIC)
1471 clear_method_cache (obj);
80662eda 1472
b6cf4d02 1473 return obj;
80662eda 1474}
398d8ee1 1475#undef FUNC_NAME
80662eda 1476
398d8ee1
KN
1477SCM_DEFINE (scm_sys_set_object_setter_x, "%set-object-setter!", 2, 0, 0,
1478 (SCM obj, SCM setter),
1479 "")
1480#define FUNC_NAME s_scm_sys_set_object_setter_x
80662eda 1481{
11561496
AW
1482 SCM_ASSERT (SCM_STRUCTP (obj)
1483 && (SCM_OBJ_CLASS_FLAGS (obj) & SCM_CLASSF_PURE_GENERIC),
80662eda
MD
1484 obj,
1485 SCM_ARG1,
398d8ee1 1486 FUNC_NAME);
11561496 1487 SCM_SET_GENERIC_SETTER (obj, setter);
80662eda
MD
1488 return SCM_UNSPECIFIED;
1489}
398d8ee1 1490#undef FUNC_NAME
80662eda
MD
1491
1492/******************************************************************************
1493 *
1494 * %modify-instance (used by change-class to modify in place)
6d77c894 1495 *
80662eda
MD
1496 ******************************************************************************/
1497
398d8ee1
KN
1498SCM_DEFINE (scm_sys_modify_instance, "%modify-instance", 2, 0, 0,
1499 (SCM old, SCM new),
1500 "")
1501#define FUNC_NAME s_scm_sys_modify_instance
80662eda 1502{
398d8ee1
KN
1503 SCM_VALIDATE_INSTANCE (1, old);
1504 SCM_VALIDATE_INSTANCE (2, new);
80662eda 1505
6d77c894 1506 /* Exchange the data contained in old and new. We exchange rather than
80662eda
MD
1507 * scratch the old value with new to be correct with GC.
1508 * See "Class redefinition protocol above".
1509 */
9de87eea 1510 SCM_CRITICAL_SECTION_START;
80662eda 1511 {
32b12f40
KR
1512 scm_t_bits word0, word1;
1513 word0 = SCM_CELL_WORD_0 (old);
1514 word1 = SCM_CELL_WORD_1 (old);
1515 SCM_SET_CELL_WORD_0 (old, SCM_CELL_WORD_0 (new));
1516 SCM_SET_CELL_WORD_1 (old, SCM_CELL_WORD_1 (new));
1517 SCM_SET_CELL_WORD_0 (new, word0);
1518 SCM_SET_CELL_WORD_1 (new, word1);
80662eda 1519 }
9de87eea 1520 SCM_CRITICAL_SECTION_END;
80662eda
MD
1521 return SCM_UNSPECIFIED;
1522}
398d8ee1 1523#undef FUNC_NAME
80662eda 1524
398d8ee1
KN
1525SCM_DEFINE (scm_sys_modify_class, "%modify-class", 2, 0, 0,
1526 (SCM old, SCM new),
1527 "")
1528#define FUNC_NAME s_scm_sys_modify_class
80662eda 1529{
398d8ee1
KN
1530 SCM_VALIDATE_CLASS (1, old);
1531 SCM_VALIDATE_CLASS (2, new);
80662eda 1532
9de87eea 1533 SCM_CRITICAL_SECTION_START;
80662eda 1534 {
32b12f40
KR
1535 scm_t_bits word0, word1;
1536 word0 = SCM_CELL_WORD_0 (old);
1537 word1 = SCM_CELL_WORD_1 (old);
1538 SCM_SET_CELL_WORD_0 (old, SCM_CELL_WORD_0 (new));
1539 SCM_SET_CELL_WORD_1 (old, SCM_CELL_WORD_1 (new));
b6cf4d02 1540 SCM_STRUCT_DATA (old)[scm_vtable_index_self] = SCM_UNPACK (old);
32b12f40
KR
1541 SCM_SET_CELL_WORD_0 (new, word0);
1542 SCM_SET_CELL_WORD_1 (new, word1);
b6cf4d02 1543 SCM_STRUCT_DATA (new)[scm_vtable_index_self] = SCM_UNPACK (new);
80662eda 1544 }
9de87eea 1545 SCM_CRITICAL_SECTION_END;
80662eda
MD
1546 return SCM_UNSPECIFIED;
1547}
398d8ee1 1548#undef FUNC_NAME
80662eda 1549
398d8ee1
KN
1550SCM_DEFINE (scm_sys_invalidate_class, "%invalidate-class", 1, 0, 0,
1551 (SCM class),
1552 "")
1553#define FUNC_NAME s_scm_sys_invalidate_class
80662eda 1554{
398d8ee1 1555 SCM_VALIDATE_CLASS (1, class);
80662eda
MD
1556 SCM_CLEAR_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_VALID);
1557 return SCM_UNSPECIFIED;
1558}
398d8ee1 1559#undef FUNC_NAME
80662eda
MD
1560
1561/* When instances change class, they finally get a new body, but
1562 * before that, they go through purgatory in hell. Odd as it may
1563 * seem, this data structure saves us from eternal suffering in
1564 * infinite recursions.
1565 */
1566
92c2555f 1567static scm_t_bits **hell;
c014a02e
ML
1568static long n_hell = 1; /* one place for the evil one himself */
1569static long hell_size = 4;
2132f0d2 1570static SCM hell_mutex;
80662eda 1571
c014a02e 1572static long
80662eda
MD
1573burnin (SCM o)
1574{
c014a02e 1575 long i;
80662eda 1576 for (i = 1; i < n_hell; ++i)
6b80d352 1577 if (SCM_STRUCT_DATA (o) == hell[i])
80662eda
MD
1578 return i;
1579 return 0;
1580}
1581
1582static void
1583go_to_hell (void *o)
1584{
6b80d352 1585 SCM obj = SCM_PACK ((scm_t_bits) o);
2132f0d2 1586 scm_lock_mutex (hell_mutex);
51ef99f7 1587 if (n_hell >= hell_size)
80662eda 1588 {
51ef99f7 1589 hell_size *= 2;
408bcd99 1590 hell = scm_realloc (hell, hell_size * sizeof(*hell));
80662eda 1591 }
6b80d352 1592 hell[n_hell++] = SCM_STRUCT_DATA (obj);
2132f0d2 1593 scm_unlock_mutex (hell_mutex);
80662eda
MD
1594}
1595
1596static void
1597go_to_heaven (void *o)
1598{
2132f0d2 1599 scm_lock_mutex (hell_mutex);
6b80d352 1600 hell[burnin (SCM_PACK ((scm_t_bits) o))] = hell[--n_hell];
2132f0d2 1601 scm_unlock_mutex (hell_mutex);
80662eda
MD
1602}
1603
6b80d352
DH
1604
1605SCM_SYMBOL (scm_sym_change_class, "change-class");
1606
80662eda
MD
1607static SCM
1608purgatory (void *args)
1609{
bef95911 1610 return scm_apply_0 (SCM_VARIABLE_REF (var_change_class),
6b80d352 1611 SCM_PACK ((scm_t_bits) args));
80662eda
MD
1612}
1613
38d8927c
MD
1614/* This function calls the generic function change-class for all
1615 * instances which aren't currently undergoing class change.
1616 */
1617
80662eda 1618void
e81d98ec 1619scm_change_object_class (SCM obj, SCM old_class SCM_UNUSED, SCM new_class)
80662eda
MD
1620{
1621 if (!burnin (obj))
1622 scm_internal_dynamic_wind (go_to_hell, purgatory, go_to_heaven,
6b80d352
DH
1623 (void *) SCM_UNPACK (scm_list_2 (obj, new_class)),
1624 (void *) SCM_UNPACK (obj));
80662eda
MD
1625}
1626
1627/******************************************************************************
1628 *
6d77c894
TTN
1629 * GGGG FFFFF
1630 * G F
1631 * G GG FFF
1632 * G G F
80662eda
MD
1633 * GGG E N E R I C F U N C T I O N S
1634 *
1635 * This implementation provides
1636 * - generic functions (with class specializers)
1637 * - multi-methods
6d77c894 1638 * - next-method
80662eda
MD
1639 * - a hard-coded MOP for standard gf, which can be overloaded for non-std gf
1640 *
1641 ******************************************************************************/
1642
1643SCM_KEYWORD (k_name, "name");
1644
63c1872f 1645SCM_GLOBAL_SYMBOL (scm_sym_args, "args");
80662eda 1646
a4aa2134 1647
efcebb5b
AW
1648SCM
1649scm_apply_generic (SCM gf, SCM args)
1650{
2f652c68 1651 return scm_apply (SCM_STRUCT_PROCEDURE (gf), args, SCM_EOL);
efcebb5b
AW
1652}
1653
1654SCM
1655scm_call_generic_0 (SCM gf)
1656{
2f652c68 1657 return scm_call_0 (SCM_STRUCT_PROCEDURE (gf));
efcebb5b
AW
1658}
1659
1660SCM
1661scm_call_generic_1 (SCM gf, SCM a1)
1662{
2f652c68 1663 return scm_call_1 (SCM_STRUCT_PROCEDURE (gf), a1);
efcebb5b
AW
1664}
1665
1666SCM
1667scm_call_generic_2 (SCM gf, SCM a1, SCM a2)
1668{
2f652c68 1669 return scm_call_2 (SCM_STRUCT_PROCEDURE (gf), a1, a2);
efcebb5b
AW
1670}
1671
1672SCM
1673scm_call_generic_3 (SCM gf, SCM a1, SCM a2, SCM a3)
1674{
2f652c68 1675 return scm_call_3 (SCM_STRUCT_PROCEDURE (gf), a1, a2, a3);
efcebb5b
AW
1676}
1677
e29db33c
AW
1678SCM_SYMBOL (sym_delayed_compile, "delayed-compile");
1679static SCM
1680make_dispatch_procedure (SCM gf)
1681{
1682 static SCM var = SCM_BOOL_F;
1683 if (var == SCM_BOOL_F)
1684 var = scm_module_variable (scm_c_resolve_module ("oop goops dispatch"),
1685 sym_delayed_compile);
1686 return scm_call_1 (SCM_VARIABLE_REF (var), gf);
1687}
1688
80662eda
MD
1689static void
1690clear_method_cache (SCM gf)
1691{
e29db33c 1692 SCM_SET_GENERIC_DISPATCH_PROCEDURE (gf, make_dispatch_procedure (gf));
a9a90a88 1693 SCM_CLEAR_GENERIC_EFFECTIVE_METHODS (gf);
80662eda
MD
1694}
1695
398d8ee1
KN
1696SCM_DEFINE (scm_sys_invalidate_method_cache_x, "%invalidate-method-cache!", 1, 0, 0,
1697 (SCM gf),
1698 "")
1699#define FUNC_NAME s_scm_sys_invalidate_method_cache_x
80662eda 1700{
25ba37df 1701 SCM_ASSERT (SCM_PUREGENERICP (gf), gf, SCM_ARG1, FUNC_NAME);
6d33e90f 1702 clear_method_cache (gf);
80662eda
MD
1703 return SCM_UNSPECIFIED;
1704}
398d8ee1 1705#undef FUNC_NAME
80662eda 1706
398d8ee1
KN
1707SCM_DEFINE (scm_generic_capability_p, "generic-capability?", 1, 0, 0,
1708 (SCM proc),
1709 "")
1710#define FUNC_NAME s_scm_generic_capability_p
80662eda 1711{
7888309b 1712 SCM_ASSERT (scm_is_true (scm_procedure_p (proc)),
398d8ee1 1713 proc, SCM_ARG1, FUNC_NAME);
9fdf9fd3 1714 return (SCM_PRIMITIVE_GENERIC_P (proc) ? SCM_BOOL_T : SCM_BOOL_F);
80662eda 1715}
398d8ee1 1716#undef FUNC_NAME
80662eda 1717
398d8ee1
KN
1718SCM_DEFINE (scm_enable_primitive_generic_x, "enable-primitive-generic!", 0, 0, 1,
1719 (SCM subrs),
1720 "")
1721#define FUNC_NAME s_scm_enable_primitive_generic_x
80662eda 1722{
6b80d352 1723 SCM_VALIDATE_REST_ARGUMENT (subrs);
d2e53ed6 1724 while (!scm_is_null (subrs))
80662eda
MD
1725 {
1726 SCM subr = SCM_CAR (subrs);
9fdf9fd3 1727 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARGn, FUNC_NAME);
52fd9639
AW
1728 SCM_SET_SUBR_GENERIC (subr,
1729 scm_make (scm_list_3 (scm_class_generic,
1730 k_name,
1731 SCM_SUBR_NAME (subr))));
80662eda
MD
1732 subrs = SCM_CDR (subrs);
1733 }
1734 return SCM_UNSPECIFIED;
1735}
398d8ee1 1736#undef FUNC_NAME
80662eda 1737
9f63ce02
AW
1738SCM_DEFINE (scm_set_primitive_generic_x, "set-primitive-generic!", 2, 0, 0,
1739 (SCM subr, SCM generic),
1740 "")
1741#define FUNC_NAME s_scm_set_primitive_generic_x
1742{
9fdf9fd3 1743 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARG1, FUNC_NAME);
9f63ce02 1744 SCM_ASSERT (SCM_PUREGENERICP (generic), generic, SCM_ARG2, FUNC_NAME);
52fd9639 1745 SCM_SET_SUBR_GENERIC (subr, generic);
9f63ce02
AW
1746 return SCM_UNSPECIFIED;
1747}
1748#undef FUNC_NAME
1749
398d8ee1
KN
1750SCM_DEFINE (scm_primitive_generic_generic, "primitive-generic-generic", 1, 0, 0,
1751 (SCM subr),
1752 "")
1753#define FUNC_NAME s_scm_primitive_generic_generic
80662eda 1754{
9fdf9fd3 1755 if (SCM_PRIMITIVE_GENERIC_P (subr))
80662eda 1756 {
a48d60b1
MD
1757 if (!*SCM_SUBR_GENERIC (subr))
1758 scm_enable_primitive_generic_x (scm_list_1 (subr));
1759 return *SCM_SUBR_GENERIC (subr);
80662eda 1760 }
db4b4ca6 1761 SCM_WRONG_TYPE_ARG (SCM_ARG1, subr);
80662eda 1762}
398d8ee1 1763#undef FUNC_NAME
80662eda 1764
a48d60b1
MD
1765typedef struct t_extension {
1766 struct t_extension *next;
1767 SCM extended;
1768 SCM extension;
1769} t_extension;
1770
d0cad249
LC
1771
1772/* Hint for `scm_gc_malloc ()' et al. when allocating `t_extension'
1773 objects. */
1774static const char extension_gc_hint[] = "GOOPS extension";
1775
a48d60b1
MD
1776static t_extension *extensions = 0;
1777
a48d60b1
MD
1778void
1779scm_c_extend_primitive_generic (SCM extended, SCM extension)
1780{
1781 if (goops_loaded_p)
1782 {
1783 SCM gf, gext;
1784 if (!*SCM_SUBR_GENERIC (extended))
1785 scm_enable_primitive_generic_x (scm_list_1 (extended));
1786 gf = *SCM_SUBR_GENERIC (extended);
1787 gext = scm_call_2 (SCM_VARIABLE_REF (scm_var_make_extended_generic),
1788 gf,
ce471ab8 1789 SCM_SUBR_NAME (extension));
feccd2d3 1790 SCM_SET_SUBR_GENERIC (extension, gext);
a48d60b1
MD
1791 }
1792 else
1793 {
d0cad249
LC
1794 t_extension *e = scm_gc_malloc (sizeof (t_extension),
1795 extension_gc_hint);
a48d60b1
MD
1796 t_extension **loc = &extensions;
1797 /* Make sure that extensions are placed before their own
1798 * extensions in the extensions list. O(N^2) algorithm, but
1799 * extensions of primitive generics are rare.
1800 */
1801 while (*loc && extension != (*loc)->extended)
1802 loc = &(*loc)->next;
1803 e->next = *loc;
1804 e->extended = extended;
1805 e->extension = extension;
1806 *loc = e;
1807 }
1808}
1809
1810static void
1811setup_extended_primitive_generics ()
1812{
1813 while (extensions)
1814 {
1815 t_extension *e = extensions;
1816 scm_c_extend_primitive_generic (e->extended, e->extension);
1817 extensions = e->next;
a48d60b1
MD
1818 }
1819}
1820
80662eda 1821/******************************************************************************
6d77c894 1822 *
80662eda 1823 * Protocol for calling a generic fumction
6d77c894 1824 * This protocol is roughly equivalent to (parameter are a little bit different
80662eda
MD
1825 * for efficiency reasons):
1826 *
1827 * + apply-generic (gf args)
1828 * + compute-applicable-methods (gf args ...)
1829 * + sort-applicable-methods (methods args)
1830 * + apply-methods (gf methods args)
6d77c894
TTN
1831 *
1832 * apply-methods calls make-next-method to build the "continuation" of a a
80662eda
MD
1833 * method. Applying a next-method will call apply-next-method which in
1834 * turn will call apply again to call effectively the following method.
1835 *
1836 ******************************************************************************/
1837
1838static int
1839applicablep (SCM actual, SCM formal)
1840{
79a3dafe 1841 /* We already know that the cpl is well formed. */
7888309b 1842 return scm_is_true (scm_c_memq (formal, SCM_SLOT (actual, scm_si_cpl)));
80662eda
MD
1843}
1844
1845static int
34d19ef6 1846more_specificp (SCM m1, SCM m2, SCM const *targs)
80662eda
MD
1847{
1848 register SCM s1, s2;
c014a02e 1849 register long i;
6d77c894
TTN
1850 /*
1851 * Note:
1852 * m1 and m2 can have != length (i.e. one can be one element longer than the
80662eda
MD
1853 * other when we have a dotted parameter list). For instance, with the call
1854 * (M 1)
1855 * with
1856 * (define-method M (a . l) ....)
6d77c894 1857 * (define-method M (a) ....)
80662eda
MD
1858 *
1859 * we consider that the second method is more specific.
1860 *
1861 * BTW, targs is an array of types. We don't need it's size since
1862 * we already know that m1 and m2 are applicable (no risk to go past
1863 * the end of this array).
1864 *
1865 */
34d19ef6 1866 for (i=0, s1=SPEC_OF(m1), s2=SPEC_OF(m2); ; i++, s1=SCM_CDR(s1), s2=SCM_CDR(s2)) {
d2e53ed6
MV
1867 if (scm_is_null(s1)) return 1;
1868 if (scm_is_null(s2)) return 0;
80662eda
MD
1869 if (SCM_CAR(s1) != SCM_CAR(s2)) {
1870 register SCM l, cs1 = SCM_CAR(s1), cs2 = SCM_CAR(s2);
6d77c894 1871
dcb410ec 1872 for (l = SCM_SLOT (targs[i], scm_si_cpl); ; l = SCM_CDR(l)) {
80662eda
MD
1873 if (cs1 == SCM_CAR(l))
1874 return 1;
1875 if (cs2 == SCM_CAR(l))
1876 return 0;
1877 }
1878 return 0;/* should not occur! */
1879 }
1880 }
1881 return 0; /* should not occur! */
1882}
1883
1884#define BUFFSIZE 32 /* big enough for most uses */
1885
1886static SCM
c014a02e 1887scm_i_vector2list (SCM l, long len)
80662eda 1888{
c014a02e 1889 long j;
00ffa0e7 1890 SCM z = scm_c_make_vector (len, SCM_UNDEFINED);
6d77c894 1891
80662eda 1892 for (j = 0; j < len; j++, l = SCM_CDR (l)) {
4057a3e0 1893 SCM_SIMPLE_VECTOR_SET (z, j, SCM_CAR (l));
80662eda
MD
1894 }
1895 return z;
1896}
1897
1898static SCM
34d19ef6 1899sort_applicable_methods (SCM method_list, long size, SCM const *targs)
80662eda 1900{
c014a02e 1901 long i, j, incr;
80662eda
MD
1902 SCM *v, vector = SCM_EOL;
1903 SCM buffer[BUFFSIZE];
1904 SCM save = method_list;
4057a3e0 1905 scm_t_array_handle handle;
80662eda
MD
1906
1907 /* For reasonably sized method_lists we can try to avoid all the
1908 * consing and reorder the list in place...
1909 * This idea is due to David McClain <Dave_McClain@msn.com>
1910 */
1911 if (size <= BUFFSIZE)
1912 {
1913 for (i = 0; i < size; i++)
1914 {
1915 buffer[i] = SCM_CAR (method_list);
1916 method_list = SCM_CDR (method_list);
1917 }
1918 v = buffer;
6d77c894 1919 }
80662eda
MD
1920 else
1921 {
1922 /* Too many elements in method_list to keep everything locally */
1923 vector = scm_i_vector2list (save, size);
4057a3e0 1924 v = scm_vector_writable_elements (vector, &handle, NULL, NULL);
80662eda
MD
1925 }
1926
6d77c894 1927 /* Use a simple shell sort since it is generally faster than qsort on
80662eda
MD
1928 * small vectors (which is probably mostly the case when we have to
1929 * sort a list of applicable methods).
1930 */
1931 for (incr = size / 2; incr; incr /= 2)
1932 {
1933 for (i = incr; i < size; i++)
1934 {
1935 for (j = i - incr; j >= 0; j -= incr)
1936 {
1937 if (more_specificp (v[j], v[j+incr], targs))
1938 break;
1939 else
1940 {
1941 SCM tmp = v[j + incr];
1942 v[j + incr] = v[j];
1943 v[j] = tmp;
1944 }
1945 }
1946 }
1947 }
1948
1949 if (size <= BUFFSIZE)
1950 {
1951 /* We did it in locally, so restore the original list (reordered) in-place */
1952 for (i = 0, method_list = save; i < size; i++, v++)
1953 {
1954 SCM_SETCAR (method_list, *v);
1955 method_list = SCM_CDR (method_list);
1956 }
1957 return save;
1958 }
4057a3e0 1959
6d77c894 1960 /* If we are here, that's that we did it the hard way... */
c8857a4d 1961 scm_array_handle_release (&handle);
80662eda
MD
1962 return scm_vector_to_list (vector);
1963}
1964
1965SCM
c014a02e 1966scm_compute_applicable_methods (SCM gf, SCM args, long len, int find_method_p)
80662eda 1967{
c014a02e
ML
1968 register long i;
1969 long count = 0;
80662eda
MD
1970 SCM l, fl, applicable = SCM_EOL;
1971 SCM save = args;
34d19ef6
HWN
1972 SCM buffer[BUFFSIZE];
1973 SCM const *types;
1974 SCM *p;
1975 SCM tmp = SCM_EOL;
4057a3e0 1976 scm_t_array_handle handle;
6d77c894 1977
80662eda 1978 /* Build the list of arguments types */
4057a3e0
MV
1979 if (len >= BUFFSIZE)
1980 {
1981 tmp = scm_c_make_vector (len, SCM_UNDEFINED);
1982 types = p = scm_vector_writable_elements (tmp, &handle, NULL, NULL);
34d19ef6
HWN
1983
1984 /*
1985 note that we don't have to work to reset the generation
1986 count. TMP is a new vector anyway, and it is found
1987 conservatively.
1988 */
4057a3e0 1989 }
80662eda
MD
1990 else
1991 types = p = buffer;
6d77c894 1992
d2e53ed6 1993 for ( ; !scm_is_null (args); args = SCM_CDR (args))
80662eda 1994 *p++ = scm_class_of (SCM_CAR (args));
34d19ef6 1995
80662eda 1996 /* Build a list of all applicable methods */
d2e53ed6 1997 for (l = scm_generic_function_methods (gf); !scm_is_null (l); l = SCM_CDR (l))
80662eda
MD
1998 {
1999 fl = SPEC_OF (SCM_CAR (l));
80662eda
MD
2000 for (i = 0; ; i++, fl = SCM_CDR (fl))
2001 {
c312aca7 2002 if (SCM_INSTANCEP (fl)
80662eda 2003 /* We have a dotted argument list */
d2e53ed6 2004 || (i >= len && scm_is_null (fl)))
80662eda
MD
2005 { /* both list exhausted */
2006 applicable = scm_cons (SCM_CAR (l), applicable);
2007 count += 1;
2008 break;
2009 }
2010 if (i >= len
d2e53ed6 2011 || scm_is_null (fl)
80662eda
MD
2012 || !applicablep (types[i], SCM_CAR (fl)))
2013 break;
2014 }
2015 }
2016
c8857a4d
MV
2017 if (len >= BUFFSIZE)
2018 scm_array_handle_release (&handle);
2019
80662eda
MD
2020 if (count == 0)
2021 {
2022 if (find_method_p)
2023 return SCM_BOOL_F;
bef95911 2024 scm_call_2 (SCM_VARIABLE_REF (var_no_applicable_method), gf, save);
80662eda
MD
2025 /* if we are here, it's because no-applicable-method hasn't signaled an error */
2026 return SCM_BOOL_F;
2027 }
34d19ef6 2028
80662eda
MD
2029 return (count == 1
2030 ? applicable
2031 : sort_applicable_methods (applicable, count, types));
2032}
2033
2034#if 0
2035SCM_PROC (s_sys_compute_applicable_methods, "%compute-applicable-methods", 2, 0, 0, scm_sys_compute_applicable_methods);
2036#endif
2037
2038static const char s_sys_compute_applicable_methods[] = "%compute-applicable-methods";
2039
2040SCM
2041scm_sys_compute_applicable_methods (SCM gf, SCM args)
398d8ee1 2042#define FUNC_NAME s_sys_compute_applicable_methods
80662eda 2043{
c014a02e 2044 long n;
398d8ee1 2045 SCM_VALIDATE_GENERIC (1, gf);
80662eda 2046 n = scm_ilength (args);
398d8ee1 2047 SCM_ASSERT (n >= 0, args, SCM_ARG2, FUNC_NAME);
80662eda
MD
2048 return scm_compute_applicable_methods (gf, args, n, 1);
2049}
398d8ee1 2050#undef FUNC_NAME
80662eda 2051
86d31dfe 2052SCM_SYMBOL (sym_compute_applicable_methods, "compute-applicable-methods");
cc7005bc
AW
2053SCM_VARIABLE_INIT (var_compute_applicable_methods, "compute-applicable-methods",
2054 scm_c_define_gsubr (s_sys_compute_applicable_methods, 2, 0, 0,
2055 scm_sys_compute_applicable_methods));
80662eda 2056
80662eda
MD
2057/******************************************************************************
2058 *
2059 * A simple make (which will be redefined later in Scheme)
2060 * This version handles only creation of gf, methods and classes (no instances)
2061 *
6d77c894 2062 * Since this code will disappear when Goops will be fully booted,
80662eda
MD
2063 * no precaution is taken to be efficient.
2064 *
2065 ******************************************************************************/
2066
2067SCM_KEYWORD (k_setter, "setter");
2068SCM_KEYWORD (k_specializers, "specializers");
2069SCM_KEYWORD (k_procedure, "procedure");
5487977b
AW
2070SCM_KEYWORD (k_formals, "formals");
2071SCM_KEYWORD (k_body, "body");
e177058b 2072SCM_KEYWORD (k_make_procedure, "make-procedure");
80662eda
MD
2073SCM_KEYWORD (k_dsupers, "dsupers");
2074SCM_KEYWORD (k_slots, "slots");
2075SCM_KEYWORD (k_gf, "generic-function");
2076
398d8ee1
KN
2077SCM_DEFINE (scm_make, "make", 0, 0, 1,
2078 (SCM args),
27c37006 2079 "Make a new object. @var{args} must contain the class and\n"
6bcefd15 2080 "all necessary initialization information.")
398d8ee1 2081#define FUNC_NAME s_scm_make
80662eda
MD
2082{
2083 SCM class, z;
c014a02e 2084 long len = scm_ilength (args);
80662eda
MD
2085
2086 if (len <= 0 || (len & 1) == 0)
398d8ee1 2087 SCM_WRONG_NUM_ARGS ();
80662eda
MD
2088
2089 class = SCM_CAR(args);
2090 args = SCM_CDR(args);
2091
f8af5c6d 2092 if (class == scm_class_generic || class == scm_class_accessor)
80662eda 2093 {
80662eda 2094 z = scm_make_struct (class, SCM_INUM0,
72d2e7e6 2095 scm_list_4 (SCM_BOOL_F,
51f66c91 2096 SCM_EOL,
1afff620 2097 SCM_INUM0,
bbf8d523 2098 SCM_EOL));
80662eda
MD
2099 scm_set_procedure_property_x (z, scm_sym_name,
2100 scm_get_keyword (k_name,
2101 args,
2102 SCM_BOOL_F));
2103 clear_method_cache (z);
f8af5c6d 2104 if (class == scm_class_accessor)
80662eda
MD
2105 {
2106 SCM setter = scm_get_keyword (k_setter, args, SCM_BOOL_F);
7888309b 2107 if (scm_is_true (setter))
80662eda
MD
2108 scm_sys_set_object_setter_x (z, setter);
2109 }
2110 }
2111 else
2112 {
2113 z = scm_sys_allocate_instance (class, args);
2114
2115 if (class == scm_class_method
f8af5c6d 2116 || class == scm_class_accessor_method)
80662eda 2117 {
6d77c894 2118 SCM_SET_SLOT (z, scm_si_generic_function,
80662eda
MD
2119 scm_i_get_keyword (k_gf,
2120 args,
2121 len - 1,
2122 SCM_BOOL_F,
dcb410ec 2123 FUNC_NAME));
6d77c894 2124 SCM_SET_SLOT (z, scm_si_specializers,
80662eda
MD
2125 scm_i_get_keyword (k_specializers,
2126 args,
2127 len - 1,
2128 SCM_EOL,
dcb410ec 2129 FUNC_NAME));
6d77c894 2130 SCM_SET_SLOT (z, scm_si_procedure,
80662eda
MD
2131 scm_i_get_keyword (k_procedure,
2132 args,
2133 len - 1,
e177058b 2134 SCM_BOOL_F,
dcb410ec 2135 FUNC_NAME));
5487977b
AW
2136 SCM_SET_SLOT (z, scm_si_formals,
2137 scm_i_get_keyword (k_formals,
2138 args,
2139 len - 1,
2140 SCM_EOL,
2141 FUNC_NAME));
2142 SCM_SET_SLOT (z, scm_si_body,
2143 scm_i_get_keyword (k_body,
2144 args,
2145 len - 1,
2146 SCM_EOL,
2147 FUNC_NAME));
e177058b
AW
2148 SCM_SET_SLOT (z, scm_si_make_procedure,
2149 scm_i_get_keyword (k_make_procedure,
5487977b
AW
2150 args,
2151 len - 1,
2152 SCM_BOOL_F,
2153 FUNC_NAME));
80662eda
MD
2154 }
2155 else
2156 {
2157 /* In all the others case, make a new class .... No instance here */
b6cf4d02 2158 SCM_SET_SLOT (z, scm_vtable_index_name,
80662eda
MD
2159 scm_i_get_keyword (k_name,
2160 args,
2161 len - 1,
cc95e00a 2162 scm_from_locale_symbol ("???"),
dcb410ec 2163 FUNC_NAME));
6d77c894 2164 SCM_SET_SLOT (z, scm_si_direct_supers,
80662eda
MD
2165 scm_i_get_keyword (k_dsupers,
2166 args,
2167 len - 1,
2168 SCM_EOL,
dcb410ec 2169 FUNC_NAME));
6d77c894 2170 SCM_SET_SLOT (z, scm_si_direct_slots,
80662eda
MD
2171 scm_i_get_keyword (k_slots,
2172 args,
2173 len - 1,
2174 SCM_EOL,
dcb410ec 2175 FUNC_NAME));
80662eda
MD
2176 }
2177 }
2178 return z;
2179}
398d8ee1 2180#undef FUNC_NAME
80662eda 2181
398d8ee1
KN
2182SCM_DEFINE (scm_find_method, "find-method", 0, 0, 1,
2183 (SCM l),
2184 "")
2185#define FUNC_NAME s_scm_find_method
80662eda
MD
2186{
2187 SCM gf;
c014a02e 2188 long len = scm_ilength (l);
80662eda
MD
2189
2190 if (len == 0)
398d8ee1 2191 SCM_WRONG_NUM_ARGS ();
80662eda
MD
2192
2193 gf = SCM_CAR(l); l = SCM_CDR(l);
398d8ee1 2194 SCM_VALIDATE_GENERIC (1, gf);
d2e53ed6 2195 if (scm_is_null (SCM_SLOT (gf, scm_si_methods)))
1afff620 2196 SCM_MISC_ERROR ("no methods for generic ~S", scm_list_1 (gf));
80662eda
MD
2197
2198 return scm_compute_applicable_methods (gf, l, len - 1, 1);
2199}
398d8ee1 2200#undef FUNC_NAME
80662eda 2201
398d8ee1
KN
2202SCM_DEFINE (scm_sys_method_more_specific_p, "%method-more-specific?", 3, 0, 0,
2203 (SCM m1, SCM m2, SCM targs),
b1f57ea4
LC
2204 "Return true if method @var{m1} is more specific than @var{m2} "
2205 "given the argument types (classes) listed in @var{targs}.")
398d8ee1 2206#define FUNC_NAME s_scm_sys_method_more_specific_p
80662eda 2207{
4057a3e0
MV
2208 SCM l, v, result;
2209 SCM *v_elts;
b1f57ea4 2210 long i, len, m1_specs, m2_specs;
4057a3e0 2211 scm_t_array_handle handle;
80662eda 2212
398d8ee1
KN
2213 SCM_VALIDATE_METHOD (1, m1);
2214 SCM_VALIDATE_METHOD (2, m2);
80662eda 2215
b1f57ea4
LC
2216 len = scm_ilength (targs);
2217 m1_specs = scm_ilength (SPEC_OF (m1));
2218 m2_specs = scm_ilength (SPEC_OF (m2));
2219 SCM_ASSERT ((len >= m1_specs) || (len >= m2_specs),
2220 targs, SCM_ARG3, FUNC_NAME);
2221
2222 /* Verify that all the arguments of TARGS are classes and place them
2223 in a vector. */
4057a3e0 2224
00ffa0e7 2225 v = scm_c_make_vector (len, SCM_EOL);
4057a3e0 2226 v_elts = scm_vector_writable_elements (v, &handle, NULL, NULL);
80662eda 2227
b1f57ea4
LC
2228 for (i = 0, l = targs;
2229 i < len && scm_is_pair (l);
2230 i++, l = SCM_CDR (l))
4057a3e0
MV
2231 {
2232 SCM_ASSERT (SCM_CLASSP (SCM_CAR (l)), targs, SCM_ARG3, FUNC_NAME);
b1f57ea4 2233 v_elts[i] = SCM_CAR (l);
4057a3e0 2234 }
4057a3e0 2235 result = more_specificp (m1, m2, v_elts) ? SCM_BOOL_T: SCM_BOOL_F;
c8857a4d
MV
2236
2237 scm_array_handle_release (&handle);
2238
4057a3e0 2239 return result;
80662eda 2240}
398d8ee1 2241#undef FUNC_NAME
6d77c894
TTN
2242
2243
80662eda
MD
2244
2245/******************************************************************************
2246 *
6d77c894 2247 * Initializations
80662eda
MD
2248 *
2249 ******************************************************************************/
2250
74b6d6e4
MD
2251static void
2252fix_cpl (SCM c, SCM before, SCM after)
2253{
2254 SCM cpl = SCM_SLOT (c, scm_si_cpl);
2255 SCM ls = scm_c_memq (after, cpl);
2256 SCM tail = scm_delq1_x (before, SCM_CDR (ls));
7888309b 2257 if (scm_is_false (ls))
74b6d6e4
MD
2258 /* if this condition occurs, fix_cpl should not be applied this way */
2259 abort ();
2260 SCM_SETCAR (ls, before);
2261 SCM_SETCDR (ls, scm_cons (after, tail));
2262 {
2263 SCM dslots = SCM_SLOT (c, scm_si_direct_slots);
2264 SCM slots = build_slots_list (maplist (dslots), cpl);
2265 SCM g_n_s = compute_getters_n_setters (slots);
2266 SCM_SET_SLOT (c, scm_si_slots, slots);
2267 SCM_SET_SLOT (c, scm_si_getters_n_setters, g_n_s);
2268 }
2269}
2270
80662eda
MD
2271
2272static void
2273make_stdcls (SCM *var, char *name, SCM meta, SCM super, SCM slots)
2274{
cc95e00a 2275 SCM tmp = scm_from_locale_symbol (name);
6d77c894 2276
f39448c5
AW
2277 *var = scm_basic_make_class (meta, tmp,
2278 scm_is_pair (super) ? super : scm_list_1 (super),
2279 slots);
80662eda
MD
2280 DEFVAR(tmp, *var);
2281}
2282
2283
2284SCM_KEYWORD (k_slot_definition, "slot-definition");
2285
2286static void
2287create_standard_classes (void)
2288{
2289 SCM slots;
21497600 2290 SCM method_slots = scm_list_n (scm_from_locale_symbol ("generic-function"),
cc95e00a 2291 scm_from_locale_symbol ("specializers"),
6b80d352 2292 sym_procedure,
21497600
AW
2293 scm_from_locale_symbol ("formals"),
2294 scm_from_locale_symbol ("body"),
e177058b 2295 scm_from_locale_symbol ("make-procedure"),
21497600 2296 SCM_UNDEFINED);
cc95e00a 2297 SCM amethod_slots = scm_list_1 (scm_list_3 (scm_from_locale_symbol ("slot-definition"),
1afff620
KN
2298 k_init_keyword,
2299 k_slot_definition));
c06e3eb0 2300 SCM gf_slots = scm_list_4 (scm_from_locale_symbol ("methods"),
cc95e00a 2301 scm_list_3 (scm_from_locale_symbol ("n-specialized"),
1afff620
KN
2302 k_init_value,
2303 SCM_INUM0),
cc95e00a 2304 scm_list_3 (scm_from_locale_symbol ("extended-by"),
bbf8d523 2305 k_init_value,
b6cf4d02 2306 SCM_EOL),
72d2e7e6 2307 scm_from_locale_symbol ("effective-methods"));
a9a90a88 2308 SCM setter_slots = scm_list_1 (sym_setter);
cc95e00a 2309 SCM egf_slots = scm_list_1 (scm_list_3 (scm_from_locale_symbol ("extends"),
bbf8d523
MD
2310 k_init_value,
2311 SCM_EOL));
80662eda
MD
2312 /* Foreign class slot classes */
2313 make_stdcls (&scm_class_foreign_slot, "<foreign-slot>",
2314 scm_class_class, scm_class_top, SCM_EOL);
2315 make_stdcls (&scm_class_protected, "<protected-slot>",
2316 scm_class_class, scm_class_foreign_slot, SCM_EOL);
b6cf4d02
AW
2317 make_stdcls (&scm_class_hidden, "<hidden-slot>",
2318 scm_class_class, scm_class_foreign_slot, SCM_EOL);
80662eda
MD
2319 make_stdcls (&scm_class_opaque, "<opaque-slot>",
2320 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2321 make_stdcls (&scm_class_read_only, "<read-only-slot>",
2322 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2323 make_stdcls (&scm_class_self, "<self-slot>",
b6cf4d02 2324 scm_class_class, scm_class_read_only, SCM_EOL);
80662eda
MD
2325 make_stdcls (&scm_class_protected_opaque, "<protected-opaque-slot>",
2326 scm_class_class,
1afff620 2327 scm_list_2 (scm_class_protected, scm_class_opaque),
80662eda 2328 SCM_EOL);
b6cf4d02
AW
2329 make_stdcls (&scm_class_protected_hidden, "<protected-hidden-slot>",
2330 scm_class_class,
2331 scm_list_2 (scm_class_protected, scm_class_hidden),
2332 SCM_EOL);
80662eda
MD
2333 make_stdcls (&scm_class_protected_read_only, "<protected-read-only-slot>",
2334 scm_class_class,
1afff620 2335 scm_list_2 (scm_class_protected, scm_class_read_only),
80662eda
MD
2336 SCM_EOL);
2337 make_stdcls (&scm_class_scm, "<scm-slot>",
2338 scm_class_class, scm_class_protected, SCM_EOL);
2339 make_stdcls (&scm_class_int, "<int-slot>",
2340 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2341 make_stdcls (&scm_class_float, "<float-slot>",
2342 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2343 make_stdcls (&scm_class_double, "<double-slot>",
2344 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2345
2346 /* Continue initialization of class <class> */
6d77c894 2347
80662eda 2348 slots = build_class_class_slots ();
dcb410ec
DH
2349 SCM_SET_SLOT (scm_class_class, scm_si_direct_slots, slots);
2350 SCM_SET_SLOT (scm_class_class, scm_si_slots, slots);
2351 SCM_SET_SLOT (scm_class_class, scm_si_getters_n_setters,
2352 compute_getters_n_setters (slots));
6d77c894 2353
80662eda
MD
2354 /* scm_class_generic functions classes */
2355 make_stdcls (&scm_class_procedure_class, "<procedure-class>",
2356 scm_class_class, scm_class_class, SCM_EOL);
51f66c91 2357 make_stdcls (&scm_class_applicable_struct_class, "<applicable-struct-class>",
80662eda 2358 scm_class_class, scm_class_procedure_class, SCM_EOL);
2f652c68 2359 SCM_SET_VTABLE_FLAGS (scm_class_applicable_struct_class, SCM_VTABLE_FLAG_APPLICABLE_VTABLE);
80662eda
MD
2360 make_stdcls (&scm_class_method, "<method>",
2361 scm_class_class, scm_class_object, method_slots);
f8af5c6d 2362 make_stdcls (&scm_class_accessor_method, "<accessor-method>",
51f66c91 2363 scm_class_class, scm_class_method, amethod_slots);
74b6d6e4
MD
2364 make_stdcls (&scm_class_applicable, "<applicable>",
2365 scm_class_class, scm_class_top, SCM_EOL);
51f66c91
AW
2366 make_stdcls (&scm_class_applicable_struct, "<applicable-struct>",
2367 scm_class_applicable_struct_class,
74b6d6e4 2368 scm_list_2 (scm_class_object, scm_class_applicable),
51f66c91 2369 scm_list_1 (sym_procedure));
80662eda 2370 make_stdcls (&scm_class_generic, "<generic>",
51f66c91 2371 scm_class_applicable_struct_class, scm_class_applicable_struct, gf_slots);
80662eda 2372 SCM_SET_CLASS_FLAGS (scm_class_generic, SCM_CLASSF_PURE_GENERIC);
bbf8d523 2373 make_stdcls (&scm_class_extended_generic, "<extended-generic>",
51f66c91 2374 scm_class_applicable_struct_class, scm_class_generic, egf_slots);
bbf8d523 2375 SCM_SET_CLASS_FLAGS (scm_class_extended_generic, SCM_CLASSF_PURE_GENERIC);
80662eda 2376 make_stdcls (&scm_class_generic_with_setter, "<generic-with-setter>",
51f66c91 2377 scm_class_applicable_struct_class, scm_class_generic, setter_slots);
80662eda 2378 SCM_SET_CLASS_FLAGS (scm_class_generic_with_setter, SCM_CLASSF_PURE_GENERIC);
f8af5c6d 2379 make_stdcls (&scm_class_accessor, "<accessor>",
51f66c91 2380 scm_class_applicable_struct_class, scm_class_generic_with_setter, SCM_EOL);
f8af5c6d 2381 SCM_SET_CLASS_FLAGS (scm_class_accessor, SCM_CLASSF_PURE_GENERIC);
bbf8d523
MD
2382 make_stdcls (&scm_class_extended_generic_with_setter,
2383 "<extended-generic-with-setter>",
51f66c91 2384 scm_class_applicable_struct_class,
74b6d6e4
MD
2385 scm_list_2 (scm_class_generic_with_setter,
2386 scm_class_extended_generic),
bbf8d523
MD
2387 SCM_EOL);
2388 SCM_SET_CLASS_FLAGS (scm_class_extended_generic_with_setter,
2389 SCM_CLASSF_PURE_GENERIC);
74b6d6e4 2390 make_stdcls (&scm_class_extended_accessor, "<extended-accessor>",
51f66c91 2391 scm_class_applicable_struct_class,
74b6d6e4
MD
2392 scm_list_2 (scm_class_accessor,
2393 scm_class_extended_generic_with_setter),
2394 SCM_EOL);
2395 fix_cpl (scm_class_extended_accessor,
2396 scm_class_extended_generic, scm_class_generic);
2397 SCM_SET_CLASS_FLAGS (scm_class_extended_accessor, SCM_CLASSF_PURE_GENERIC);
80662eda
MD
2398
2399 /* Primitive types classes */
2400 make_stdcls (&scm_class_boolean, "<boolean>",
2401 scm_class_class, scm_class_top, SCM_EOL);
2402 make_stdcls (&scm_class_char, "<char>",
2403 scm_class_class, scm_class_top, SCM_EOL);
2404 make_stdcls (&scm_class_list, "<list>",
2405 scm_class_class, scm_class_top, SCM_EOL);
2406 make_stdcls (&scm_class_pair, "<pair>",
2407 scm_class_class, scm_class_list, SCM_EOL);
2408 make_stdcls (&scm_class_null, "<null>",
2409 scm_class_class, scm_class_list, SCM_EOL);
2410 make_stdcls (&scm_class_string, "<string>",
2411 scm_class_class, scm_class_top, SCM_EOL);
2412 make_stdcls (&scm_class_symbol, "<symbol>",
2413 scm_class_class, scm_class_top, SCM_EOL);
2414 make_stdcls (&scm_class_vector, "<vector>",
2415 scm_class_class, scm_class_top, SCM_EOL);
e2c2a699
AW
2416 make_stdcls (&class_foreign, "<foreign>",
2417 scm_class_class, scm_class_top, SCM_EOL);
9ea31741
AW
2418 make_stdcls (&class_hashtable, "<hashtable>",
2419 scm_class_class, scm_class_top, SCM_EOL);
2420 make_stdcls (&class_fluid, "<fluid>",
2421 scm_class_class, scm_class_top, SCM_EOL);
2422 make_stdcls (&class_dynamic_state, "<dynamic-state>",
c99de5aa 2423 scm_class_class, scm_class_top, SCM_EOL);
6f3b0cc2
AW
2424 make_stdcls (&class_frame, "<frame>",
2425 scm_class_class, scm_class_top, SCM_EOL);
2426 make_stdcls (&class_objcode, "<objcode>",
2427 scm_class_class, scm_class_top, SCM_EOL);
2428 make_stdcls (&class_vm, "<vm>",
2429 scm_class_class, scm_class_top, SCM_EOL);
2430 make_stdcls (&class_vm_cont, "<vm-continuation>",
2431 scm_class_class, scm_class_top, SCM_EOL);
f826a886
AW
2432 make_stdcls (&class_bytevector, "<bytevector>",
2433 scm_class_class, scm_class_top, SCM_EOL);
2434 make_stdcls (&class_uvec, "<uvec>",
2435 scm_class_class, class_bytevector, SCM_EOL);
80662eda
MD
2436 make_stdcls (&scm_class_number, "<number>",
2437 scm_class_class, scm_class_top, SCM_EOL);
2438 make_stdcls (&scm_class_complex, "<complex>",
2439 scm_class_class, scm_class_number, SCM_EOL);
2440 make_stdcls (&scm_class_real, "<real>",
2441 scm_class_class, scm_class_complex, SCM_EOL);
2442 make_stdcls (&scm_class_integer, "<integer>",
2443 scm_class_class, scm_class_real, SCM_EOL);
f92e85f7
MV
2444 make_stdcls (&scm_class_fraction, "<fraction>",
2445 scm_class_class, scm_class_real, SCM_EOL);
80662eda
MD
2446 make_stdcls (&scm_class_keyword, "<keyword>",
2447 scm_class_class, scm_class_top, SCM_EOL);
2448 make_stdcls (&scm_class_unknown, "<unknown>",
2449 scm_class_class, scm_class_top, SCM_EOL);
2450 make_stdcls (&scm_class_procedure, "<procedure>",
74b6d6e4 2451 scm_class_procedure_class, scm_class_applicable, SCM_EOL);
80662eda
MD
2452 make_stdcls (&scm_class_primitive_generic, "<primitive-generic>",
2453 scm_class_procedure_class, scm_class_procedure, SCM_EOL);
2454 make_stdcls (&scm_class_port, "<port>",
2455 scm_class_class, scm_class_top, SCM_EOL);
2456 make_stdcls (&scm_class_input_port, "<input-port>",
2457 scm_class_class, scm_class_port, SCM_EOL);
2458 make_stdcls (&scm_class_output_port, "<output-port>",
2459 scm_class_class, scm_class_port, SCM_EOL);
2460 make_stdcls (&scm_class_input_output_port, "<input-output-port>",
2461 scm_class_class,
1afff620 2462 scm_list_2 (scm_class_input_port, scm_class_output_port),
80662eda
MD
2463 SCM_EOL);
2464}
2465
2466/**********************************************************************
2467 *
2468 * Smob classes
2469 *
2470 **********************************************************************/
2471
2472static SCM
da0e6c2b 2473make_class_from_template (char const *template, char const *type_name, SCM supers, int applicablep)
80662eda
MD
2474{
2475 SCM class, name;
2476 if (type_name)
2477 {
2478 char buffer[100];
2479 sprintf (buffer, template, type_name);
cc95e00a 2480 name = scm_from_locale_symbol (buffer);
80662eda
MD
2481 }
2482 else
2483 name = SCM_GOOPS_UNBOUND;
2484
f39448c5
AW
2485 class = scm_basic_make_class (applicablep ? scm_class_procedure_class : scm_class_class,
2486 name, supers, SCM_EOL);
80662eda
MD
2487
2488 /* Only define name if doesn't already exist. */
2489 if (!SCM_GOOPS_UNBOUNDP (name)
bef95911 2490 && scm_is_false (scm_module_variable (scm_module_goops, name)))
0ba8a0a5 2491 DEFVAR (name, class);
80662eda
MD
2492 return class;
2493}
2494
9db8cf16
MG
2495static SCM
2496make_class_from_symbol (SCM type_name_sym, SCM supers, int applicablep)
2497{
2498 SCM class, name;
2499 if (type_name_sym != SCM_BOOL_F)
2500 {
2501 name = scm_string_append (scm_list_3 (scm_from_locale_string ("<"),
2502 scm_symbol_to_string (type_name_sym),
2503 scm_from_locale_string (">")));
2504 name = scm_string_to_symbol (name);
2505 }
2506 else
2507 name = SCM_GOOPS_UNBOUND;
2508
f39448c5
AW
2509 class = scm_basic_make_class (applicablep ? scm_class_procedure_class : scm_class_class,
2510 name, supers, SCM_EOL);
9db8cf16
MG
2511
2512 /* Only define name if doesn't already exist. */
2513 if (!SCM_GOOPS_UNBOUNDP (name)
2514 && scm_is_false (scm_module_variable (scm_module_goops, name)))
2515 DEFVAR (name, class);
2516 return class;
2517}
2518
80662eda 2519SCM
da0e6c2b 2520scm_make_extended_class (char const *type_name, int applicablep)
80662eda
MD
2521{
2522 return make_class_from_template ("<%s>",
2523 type_name,
74b6d6e4
MD
2524 scm_list_1 (applicablep
2525 ? scm_class_applicable
2526 : scm_class_top),
2527 applicablep);
2528}
2529
9db8cf16
MG
2530static SCM
2531scm_make_extended_class_from_symbol (SCM type_name_sym, int applicablep)
2532{
2533 return make_class_from_symbol (type_name_sym,
2534 scm_list_1 (applicablep
2535 ? scm_class_applicable
2536 : scm_class_top),
2537 applicablep);
2538}
2539
74b6d6e4
MD
2540void
2541scm_i_inherit_applicable (SCM c)
2542{
2543 if (!SCM_SUBCLASSP (c, scm_class_applicable))
2544 {
2545 SCM dsupers = SCM_SLOT (c, scm_si_direct_supers);
2546 SCM cpl = SCM_SLOT (c, scm_si_cpl);
2547 /* patch scm_class_applicable into direct-supers */
2548 SCM top = scm_c_memq (scm_class_top, dsupers);
7888309b 2549 if (scm_is_false (top))
74b6d6e4
MD
2550 dsupers = scm_append (scm_list_2 (dsupers,
2551 scm_list_1 (scm_class_applicable)));
2552 else
2553 {
2554 SCM_SETCAR (top, scm_class_applicable);
2555 SCM_SETCDR (top, scm_cons (scm_class_top, SCM_CDR (top)));
2556 }
2557 SCM_SET_SLOT (c, scm_si_direct_supers, dsupers);
2558 /* patch scm_class_applicable into cpl */
2559 top = scm_c_memq (scm_class_top, cpl);
7888309b 2560 if (scm_is_false (top))
74b6d6e4
MD
2561 abort ();
2562 else
2563 {
2564 SCM_SETCAR (top, scm_class_applicable);
2565 SCM_SETCDR (top, scm_cons (scm_class_top, SCM_CDR (top)));
2566 }
2567 /* add class to direct-subclasses of scm_class_applicable */
2568 SCM_SET_SLOT (scm_class_applicable,
2569 scm_si_direct_subclasses,
2570 scm_cons (c, SCM_SLOT (scm_class_applicable,
2571 scm_si_direct_subclasses)));
2572 }
80662eda
MD
2573}
2574
2575static void
2576create_smob_classes (void)
2577{
c014a02e 2578 long i;
80662eda 2579
c891a40e 2580 for (i = 0; i < SCM_I_MAX_SMOB_TYPE_COUNT; ++i)
80662eda
MD
2581 scm_smob_class[i] = 0;
2582
80662eda 2583 scm_smob_class[SCM_TC2SMOBNUM (scm_tc16_keyword)] = scm_class_keyword;
6d77c894 2584
80662eda
MD
2585 for (i = 0; i < scm_numsmob; ++i)
2586 if (!scm_smob_class[i])
74b6d6e4
MD
2587 scm_smob_class[i] = scm_make_extended_class (SCM_SMOBNAME (i),
2588 scm_smobs[i].apply != 0);
80662eda
MD
2589}
2590
2591void
c014a02e 2592scm_make_port_classes (long ptobnum, char *type_name)
80662eda
MD
2593{
2594 SCM c, class = make_class_from_template ("<%s-port>",
2595 type_name,
74b6d6e4
MD
2596 scm_list_1 (scm_class_port),
2597 0);
80662eda
MD
2598 scm_port_class[SCM_IN_PCLASS_INDEX + ptobnum]
2599 = make_class_from_template ("<%s-input-port>",
2600 type_name,
74b6d6e4
MD
2601 scm_list_2 (class, scm_class_input_port),
2602 0);
80662eda
MD
2603 scm_port_class[SCM_OUT_PCLASS_INDEX + ptobnum]
2604 = make_class_from_template ("<%s-output-port>",
2605 type_name,
74b6d6e4
MD
2606 scm_list_2 (class, scm_class_output_port),
2607 0);
80662eda
MD
2608 scm_port_class[SCM_INOUT_PCLASS_INDEX + ptobnum]
2609 = c
2610 = make_class_from_template ("<%s-input-output-port>",
2611 type_name,
74b6d6e4
MD
2612 scm_list_2 (class, scm_class_input_output_port),
2613 0);
80662eda 2614 /* Patch cpl (since this tree is too complex for the C level compute-cpl) */
dcb410ec
DH
2615 SCM_SET_SLOT (c, scm_si_cpl,
2616 scm_cons2 (c, class, SCM_SLOT (scm_class_input_output_port, scm_si_cpl)));
80662eda
MD
2617}
2618
2619static void
2620create_port_classes (void)
2621{
c014a02e 2622 long i;
80662eda 2623
80662eda
MD
2624 for (i = 0; i < scm_numptob; ++i)
2625 scm_make_port_classes (i, SCM_PTOBNAME (i));
2626}
2627
2628static SCM
74b6d6e4
MD
2629make_struct_class (void *closure SCM_UNUSED,
2630 SCM vtable, SCM data, SCM prev SCM_UNUSED)
80662eda 2631{
9db8cf16
MG
2632 SCM sym = SCM_STRUCT_TABLE_NAME (data);
2633 if (scm_is_true (sym))
2634 {
b6cf4d02 2635 int applicablep = SCM_CLASS_FLAGS (vtable) & SCM_VTABLE_FLAG_APPLICABLE;
9db8cf16
MG
2636
2637 SCM_SET_STRUCT_TABLE_CLASS (data,
2638 scm_make_extended_class_from_symbol (sym, applicablep));
2639 }
2640
2641 scm_remember_upto_here_2 (data, vtable);
80662eda
MD
2642 return SCM_UNSPECIFIED;
2643}
2644
2645static void
2646create_struct_classes (void)
2647{
2648 scm_internal_hash_fold (make_struct_class, 0, SCM_BOOL_F, scm_struct_table);
2649}
2650
2651/**********************************************************************
2652 *
2653 * C interface
2654 *
2655 **********************************************************************/
2656
2657void
2658scm_load_goops ()
2659{
2660 if (!goops_loaded_p)
abd28220 2661 scm_c_resolve_module ("oop goops");
80662eda
MD
2662}
2663
e11208ca 2664
80662eda
MD
2665SCM_SYMBOL (sym_o, "o");
2666SCM_SYMBOL (sym_x, "x");
2667
2668SCM_KEYWORD (k_accessor, "accessor");
2669SCM_KEYWORD (k_getter, "getter");
2670
80662eda
MD
2671SCM
2672scm_ensure_accessor (SCM name)
2673{
fdc28395 2674 SCM gf = scm_call_2 (SCM_TOP_LEVEL_LOOKUP_CLOSURE, name, SCM_BOOL_F);
f8af5c6d 2675 if (!SCM_IS_A_P (gf, scm_class_accessor))
80662eda 2676 {
1afff620 2677 gf = scm_make (scm_list_3 (scm_class_generic, k_name, name));
f8af5c6d 2678 gf = scm_make (scm_list_5 (scm_class_accessor,
1afff620 2679 k_name, name, k_setter, gf));
80662eda
MD
2680 }
2681 return gf;
2682}
2683
80662eda
MD
2684#ifdef GUILE_DEBUG
2685/*
2686 * Debugging utilities
2687 */
2688
398d8ee1
KN
2689SCM_DEFINE (scm_pure_generic_p, "pure-generic?", 1, 0, 0,
2690 (SCM obj),
6bcefd15 2691 "Return @code{#t} if @var{obj} is a pure generic.")
398d8ee1 2692#define FUNC_NAME s_scm_pure_generic_p
80662eda 2693{
7888309b 2694 return scm_from_bool (SCM_PUREGENERICP (obj));
80662eda 2695}
398d8ee1 2696#undef FUNC_NAME
80662eda
MD
2697
2698#endif /* GUILE_DEBUG */
2699
2700/*
2701 * Initialization
2702 */
2703
398d8ee1
KN
2704SCM_DEFINE (scm_sys_goops_loaded, "%goops-loaded", 0, 0, 0,
2705 (),
6bcefd15
MG
2706 "Announce that GOOPS is loaded and perform initialization\n"
2707 "on the C level which depends on the loaded GOOPS modules.")
398d8ee1 2708#define FUNC_NAME s_scm_sys_goops_loaded
80662eda
MD
2709{
2710 goops_loaded_p = 1;
86d31dfe 2711 var_compute_applicable_methods =
f39448c5 2712 scm_module_variable (scm_module_goops, sym_compute_applicable_methods);
bef95911 2713 var_slot_unbound =
f39448c5 2714 scm_module_variable (scm_module_goops, sym_slot_unbound);
bef95911 2715 var_slot_missing =
f39448c5 2716 scm_module_variable (scm_module_goops, sym_slot_missing);
bef95911 2717 var_compute_cpl =
f39448c5 2718 scm_module_variable (scm_module_goops, sym_compute_cpl);
bef95911 2719 var_no_applicable_method =
f39448c5 2720 scm_module_variable (scm_module_goops, sym_no_applicable_method);
bef95911 2721 var_change_class =
f39448c5 2722 scm_module_variable (scm_module_goops, sym_change_class);
a48d60b1 2723 setup_extended_primitive_generics ();
80662eda
MD
2724 return SCM_UNSPECIFIED;
2725}
398d8ee1 2726#undef FUNC_NAME
80662eda
MD
2727
2728SCM scm_module_goops;
2729
abd28220
MV
2730SCM
2731scm_init_goops_builtins (void)
80662eda 2732{
abd28220 2733 scm_module_goops = scm_current_module ();
80662eda 2734
80662eda
MD
2735 goops_rstate = scm_c_make_rstate ("GOOPS", 5);
2736
2737#include "libguile/goops.x"
2738
bb764c0e 2739 hell = scm_calloc (hell_size * sizeof (*hell));
f39448c5 2740 hell_mutex = scm_make_mutex ();
80662eda
MD
2741
2742 create_basic_classes ();
2743 create_standard_classes ();
2744 create_smob_classes ();
2745 create_struct_classes ();
2746 create_port_classes ();
2747
2748 {
cc95e00a 2749 SCM name = scm_from_locale_symbol ("no-applicable-method");
f39448c5
AW
2750 scm_no_applicable_method =
2751 scm_make (scm_list_3 (scm_class_generic, k_name, name));
80662eda
MD
2752 DEFVAR (name, scm_no_applicable_method);
2753 }
abd28220
MV
2754
2755 return SCM_UNSPECIFIED;
80662eda
MD
2756}
2757
2758void
abd28220 2759scm_init_goops ()
80662eda 2760{
9a441ddb
MV
2761 scm_c_define_gsubr ("%init-goops-builtins", 0, 0, 0,
2762 scm_init_goops_builtins);
80662eda 2763}
23437298
DH
2764
2765/*
2766 Local Variables:
2767 c-file-style: "gnu"
2768 End:
2769*/