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