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