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