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