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