*** empty log message ***
[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 1303{
c014a02e 1304 long i;
80662eda
MD
1305
1306 /* Set all slots to unbound */
1307 for (i = 0; i < n; i++)
1308 m[i] = SCM_GOOPS_UNBOUND;
1309
16d4699b
MV
1310 return scm_alloc_double_cell ((((scm_t_bits) SCM_STRUCT_DATA (class))
1311 | scm_tc3_struct),
1312 (scm_t_bits) m, 0, 0);
80662eda
MD
1313}
1314
398d8ee1
KN
1315SCM_DEFINE (scm_sys_allocate_instance, "%allocate-instance", 2, 0, 0,
1316 (SCM class, SCM initargs),
6bcefd15
MG
1317 "Create a new instance of class @var{class} and initialize it\n"
1318 "from the arguments @var{initargs}.")
398d8ee1 1319#define FUNC_NAME s_scm_sys_allocate_instance
80662eda
MD
1320{
1321 SCM *m;
c014a02e 1322 long n;
80662eda 1323
398d8ee1 1324 SCM_VALIDATE_CLASS (1, class);
80662eda
MD
1325
1326 /* Most instances */
1327 if (SCM_CLASS_FLAGS (class) & SCM_STRUCTF_LIGHT)
1328 {
1329 n = SCM_INUM (SCM_SLOT (class, scm_si_nfields));
1330 m = (SCM *) scm_must_malloc (n * sizeof (SCM), "instance");
1331 return wrap_init (class, m, n);
1332 }
1333
1334 /* Foreign objects */
1335 if (SCM_CLASS_FLAGS (class) & SCM_CLASSF_FOREIGN)
1336 return scm_make_foreign_object (class, initargs);
1337
1338 n = SCM_INUM (SCM_SLOT (class, scm_si_nfields));
1339
1340 /* Entities */
1341 if (SCM_CLASS_FLAGS (class) & SCM_CLASSF_ENTITY)
1342 {
1343 m = (SCM *) scm_alloc_struct (n,
1344 scm_struct_entity_n_extra_words,
1345 "entity");
1346 m[scm_struct_i_setter] = SCM_BOOL_F;
1347 m[scm_struct_i_procedure] = SCM_BOOL_F;
1348 /* Generic functions */
1349 if (SCM_CLASS_FLAGS (class) & SCM_CLASSF_PURE_GENERIC)
1350 {
1351 SCM gf = wrap_init (class, m, n);
1352 clear_method_cache (gf);
1353 return gf;
1354 }
1355 else
1356 return wrap_init (class, m, n);
1357 }
1358
1359 /* Class objects */
1360 if (SCM_CLASS_FLAGS (class) & SCM_CLASSF_METACLASS)
1361 {
c014a02e 1362 long i;
80662eda
MD
1363
1364 /* allocate class object */
1365 SCM z = scm_make_struct (class, SCM_INUM0, SCM_EOL);
1366
dcb410ec 1367 SCM_SET_SLOT (z, scm_si_print, SCM_GOOPS_UNBOUND);
80662eda 1368 for (i = scm_si_goops_fields; i < n; i++)
dcb410ec 1369 SCM_SET_SLOT (z, i, SCM_GOOPS_UNBOUND);
80662eda
MD
1370
1371 if (SCM_SUBCLASSP (class, scm_class_entity_class))
1372 SCM_SET_CLASS_FLAGS (z, SCM_CLASSF_OPERATOR | SCM_CLASSF_ENTITY);
1373 else if (SCM_SUBCLASSP (class, scm_class_operator_class))
1374 SCM_SET_CLASS_FLAGS (z, SCM_CLASSF_OPERATOR);
1375
1376 return z;
1377 }
1378
1379 /* Non-light instances */
1380 {
1381 m = (SCM *) scm_alloc_struct (n,
1382 scm_struct_n_extra_words,
1383 "heavy instance");
1384 return wrap_init (class, m, n);
1385 }
1386}
398d8ee1 1387#undef FUNC_NAME
80662eda 1388
398d8ee1
KN
1389SCM_DEFINE (scm_sys_set_object_setter_x, "%set-object-setter!", 2, 0, 0,
1390 (SCM obj, SCM setter),
1391 "")
1392#define FUNC_NAME s_scm_sys_set_object_setter_x
80662eda 1393{
c312aca7 1394 SCM_ASSERT (SCM_STRUCTP (obj)
80662eda
MD
1395 && ((SCM_CLASS_FLAGS (obj) & SCM_CLASSF_OPERATOR)
1396 || SCM_I_ENTITYP (obj)),
1397 obj,
1398 SCM_ARG1,
398d8ee1 1399 FUNC_NAME);
80662eda 1400 if (SCM_I_ENTITYP (obj))
322ec19d 1401 SCM_SET_ENTITY_SETTER (obj, setter);
80662eda
MD
1402 else
1403 SCM_OPERATOR_CLASS (obj)->setter = setter;
1404 return SCM_UNSPECIFIED;
1405}
398d8ee1 1406#undef FUNC_NAME
80662eda
MD
1407
1408/******************************************************************************
1409 *
1410 * %modify-instance (used by change-class to modify in place)
1411 *
1412 ******************************************************************************/
1413
398d8ee1
KN
1414SCM_DEFINE (scm_sys_modify_instance, "%modify-instance", 2, 0, 0,
1415 (SCM old, SCM new),
1416 "")
1417#define FUNC_NAME s_scm_sys_modify_instance
80662eda 1418{
398d8ee1
KN
1419 SCM_VALIDATE_INSTANCE (1, old);
1420 SCM_VALIDATE_INSTANCE (2, new);
80662eda
MD
1421
1422 /* Exchange the data contained in old and new. We exchange rather than
1423 * scratch the old value with new to be correct with GC.
1424 * See "Class redefinition protocol above".
1425 */
1426 SCM_REDEFER_INTS;
1427 {
1428 SCM car = SCM_CAR (old);
1429 SCM cdr = SCM_CDR (old);
1430 SCM_SETCAR (old, SCM_CAR (new));
1431 SCM_SETCDR (old, SCM_CDR (new));
1432 SCM_SETCAR (new, car);
1433 SCM_SETCDR (new, cdr);
1434 }
1435 SCM_REALLOW_INTS;
1436 return SCM_UNSPECIFIED;
1437}
398d8ee1 1438#undef FUNC_NAME
80662eda 1439
398d8ee1
KN
1440SCM_DEFINE (scm_sys_modify_class, "%modify-class", 2, 0, 0,
1441 (SCM old, SCM new),
1442 "")
1443#define FUNC_NAME s_scm_sys_modify_class
80662eda 1444{
398d8ee1
KN
1445 SCM_VALIDATE_CLASS (1, old);
1446 SCM_VALIDATE_CLASS (2, new);
80662eda
MD
1447
1448 SCM_REDEFER_INTS;
1449 {
1450 SCM car = SCM_CAR (old);
1451 SCM cdr = SCM_CDR (old);
1452 SCM_SETCAR (old, SCM_CAR (new));
1453 SCM_SETCDR (old, SCM_CDR (new));
729dbac3 1454 SCM_STRUCT_DATA (old)[scm_vtable_index_vtable] = SCM_UNPACK (old);
80662eda
MD
1455 SCM_SETCAR (new, car);
1456 SCM_SETCDR (new, cdr);
729dbac3 1457 SCM_STRUCT_DATA (new)[scm_vtable_index_vtable] = SCM_UNPACK (new);
80662eda
MD
1458 }
1459 SCM_REALLOW_INTS;
1460 return SCM_UNSPECIFIED;
1461}
398d8ee1 1462#undef FUNC_NAME
80662eda 1463
398d8ee1
KN
1464SCM_DEFINE (scm_sys_invalidate_class, "%invalidate-class", 1, 0, 0,
1465 (SCM class),
1466 "")
1467#define FUNC_NAME s_scm_sys_invalidate_class
80662eda 1468{
398d8ee1 1469 SCM_VALIDATE_CLASS (1, class);
80662eda
MD
1470 SCM_CLEAR_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_VALID);
1471 return SCM_UNSPECIFIED;
1472}
398d8ee1 1473#undef FUNC_NAME
80662eda
MD
1474
1475/* When instances change class, they finally get a new body, but
1476 * before that, they go through purgatory in hell. Odd as it may
1477 * seem, this data structure saves us from eternal suffering in
1478 * infinite recursions.
1479 */
1480
92c2555f 1481static scm_t_bits **hell;
c014a02e
ML
1482static long n_hell = 1; /* one place for the evil one himself */
1483static long hell_size = 4;
80662eda 1484#ifdef USE_THREADS
92c2555f 1485static scm_t_mutex hell_mutex;
80662eda
MD
1486#endif
1487
c014a02e 1488static long
80662eda
MD
1489burnin (SCM o)
1490{
c014a02e 1491 long i;
80662eda 1492 for (i = 1; i < n_hell; ++i)
6b80d352 1493 if (SCM_STRUCT_DATA (o) == hell[i])
80662eda
MD
1494 return i;
1495 return 0;
1496}
1497
1498static void
1499go_to_hell (void *o)
1500{
6b80d352 1501 SCM obj = SCM_PACK ((scm_t_bits) o);
80662eda
MD
1502#ifdef USE_THREADS
1503 scm_mutex_lock (&hell_mutex);
1504#endif
1505 if (n_hell == hell_size)
1506 {
c014a02e 1507 long new_size = 2 * hell_size;
80662eda
MD
1508 hell = scm_must_realloc (hell, hell_size, new_size, "hell");
1509 hell_size = new_size;
1510 }
6b80d352 1511 hell[n_hell++] = SCM_STRUCT_DATA (obj);
80662eda
MD
1512#ifdef USE_THREADS
1513 scm_mutex_unlock (&hell_mutex);
1514#endif
1515}
1516
1517static void
1518go_to_heaven (void *o)
1519{
1520#ifdef USE_THREADS
1521 scm_mutex_lock (&hell_mutex);
1522#endif
6b80d352 1523 hell[burnin (SCM_PACK ((scm_t_bits) o))] = hell[--n_hell];
80662eda
MD
1524#ifdef USE_THREADS
1525 scm_mutex_unlock (&hell_mutex);
1526#endif
1527}
1528
6b80d352
DH
1529
1530SCM_SYMBOL (scm_sym_change_class, "change-class");
1531
80662eda
MD
1532static SCM
1533purgatory (void *args)
1534{
6b80d352
DH
1535 return scm_apply_0 (GETVAR (scm_sym_change_class),
1536 SCM_PACK ((scm_t_bits) args));
80662eda
MD
1537}
1538
1539void
e81d98ec 1540scm_change_object_class (SCM obj, SCM old_class SCM_UNUSED, SCM new_class)
80662eda
MD
1541{
1542 if (!burnin (obj))
1543 scm_internal_dynamic_wind (go_to_hell, purgatory, go_to_heaven,
6b80d352
DH
1544 (void *) SCM_UNPACK (scm_list_2 (obj, new_class)),
1545 (void *) SCM_UNPACK (obj));
80662eda
MD
1546}
1547
1548/******************************************************************************
1549 *
1550 * GGGG FFFFF
1551 * G F
1552 * G GG FFF
1553 * G G F
1554 * GGG E N E R I C F U N C T I O N S
1555 *
1556 * This implementation provides
1557 * - generic functions (with class specializers)
1558 * - multi-methods
1559 * - next-method
1560 * - a hard-coded MOP for standard gf, which can be overloaded for non-std gf
1561 *
1562 ******************************************************************************/
1563
1564SCM_KEYWORD (k_name, "name");
1565
1566SCM_SYMBOL (sym_no_method, "no-method");
1567
1568static SCM list_of_no_method;
1569
1570SCM_SYMBOL (scm_sym_args, "args");
1571
1572SCM
1573scm_make_method_cache (SCM gf)
1574{
1afff620
KN
1575 return scm_list_5 (SCM_IM_DISPATCH,
1576 scm_sym_args,
1577 SCM_MAKINUM (1),
1578 scm_c_make_vector (SCM_INITIAL_MCACHE_SIZE,
1579 list_of_no_method),
1580 gf);
80662eda
MD
1581}
1582
1583static void
1584clear_method_cache (SCM gf)
1585{
322ec19d
ML
1586 SCM cache = scm_make_method_cache (gf);
1587 SCM_SET_ENTITY_PROCEDURE (gf, cache);
dcb410ec 1588 SCM_SET_SLOT (gf, scm_si_used_by, SCM_BOOL_F);
80662eda
MD
1589}
1590
398d8ee1
KN
1591SCM_DEFINE (scm_sys_invalidate_method_cache_x, "%invalidate-method-cache!", 1, 0, 0,
1592 (SCM gf),
1593 "")
1594#define FUNC_NAME s_scm_sys_invalidate_method_cache_x
80662eda
MD
1595{
1596 SCM used_by;
25ba37df 1597 SCM_ASSERT (SCM_PUREGENERICP (gf), gf, SCM_ARG1, FUNC_NAME);
80662eda 1598 used_by = SCM_SLOT (gf, scm_si_used_by);
6b80d352 1599 if (!SCM_FALSEP (used_by))
80662eda
MD
1600 {
1601 SCM methods = SCM_SLOT (gf, scm_si_methods);
c312aca7 1602 for (; SCM_CONSP (used_by); used_by = SCM_CDR (used_by))
80662eda
MD
1603 scm_sys_invalidate_method_cache_x (SCM_CAR (used_by));
1604 clear_method_cache (gf);
c312aca7 1605 for (; SCM_CONSP (methods); methods = SCM_CDR (methods))
dcb410ec 1606 SCM_SET_SLOT (SCM_CAR (methods), scm_si_code_table, SCM_EOL);
80662eda
MD
1607 }
1608 {
55c4a132 1609 SCM n = SCM_SLOT (gf, scm_si_n_specialized);
80662eda 1610 /* The sign of n is a flag indicating rest args. */
55c4a132 1611 SCM_SET_MCACHE_N_SPECIALIZED (SCM_ENTITY_PROCEDURE (gf), n);
80662eda
MD
1612 }
1613 return SCM_UNSPECIFIED;
1614}
398d8ee1 1615#undef FUNC_NAME
80662eda 1616
398d8ee1
KN
1617SCM_DEFINE (scm_generic_capability_p, "generic-capability?", 1, 0, 0,
1618 (SCM proc),
1619 "")
1620#define FUNC_NAME s_scm_generic_capability_p
80662eda 1621{
6b80d352 1622 SCM_ASSERT (!SCM_FALSEP (scm_procedure_p (proc)),
398d8ee1 1623 proc, SCM_ARG1, FUNC_NAME);
80662eda
MD
1624 return (scm_subr_p (proc) && SCM_SUBR_GENERIC (proc)
1625 ? SCM_BOOL_T
1626 : SCM_BOOL_F);
1627}
398d8ee1 1628#undef FUNC_NAME
80662eda 1629
398d8ee1
KN
1630SCM_DEFINE (scm_enable_primitive_generic_x, "enable-primitive-generic!", 0, 0, 1,
1631 (SCM subrs),
1632 "")
1633#define FUNC_NAME s_scm_enable_primitive_generic_x
80662eda 1634{
6b80d352
DH
1635 SCM_VALIDATE_REST_ARGUMENT (subrs);
1636 while (!SCM_NULLP (subrs))
80662eda
MD
1637 {
1638 SCM subr = SCM_CAR (subrs);
1639 SCM_ASSERT (scm_subr_p (subr) && SCM_SUBR_GENERIC (subr),
398d8ee1 1640 subr, SCM_ARGn, FUNC_NAME);
80662eda 1641 *SCM_SUBR_GENERIC (subr)
1afff620
KN
1642 = scm_make (scm_list_3 (scm_class_generic,
1643 k_name,
1644 SCM_SNAME (subr)));
80662eda
MD
1645 subrs = SCM_CDR (subrs);
1646 }
1647 return SCM_UNSPECIFIED;
1648}
398d8ee1 1649#undef FUNC_NAME
80662eda 1650
398d8ee1
KN
1651SCM_DEFINE (scm_primitive_generic_generic, "primitive-generic-generic", 1, 0, 0,
1652 (SCM subr),
1653 "")
1654#define FUNC_NAME s_scm_primitive_generic_generic
80662eda
MD
1655{
1656 if (scm_subr_p (subr) && SCM_SUBR_GENERIC (subr))
1657 {
1658 SCM gf = *SCM_SUBR_GENERIC (subr);
1659 if (gf)
1660 return gf;
1661 }
db4b4ca6 1662 SCM_WRONG_TYPE_ARG (SCM_ARG1, subr);
80662eda 1663}
398d8ee1 1664#undef FUNC_NAME
80662eda
MD
1665
1666/******************************************************************************
1667 *
1668 * Protocol for calling a generic fumction
1669 * This protocol is roughly equivalent to (parameter are a little bit different
1670 * for efficiency reasons):
1671 *
1672 * + apply-generic (gf args)
1673 * + compute-applicable-methods (gf args ...)
1674 * + sort-applicable-methods (methods args)
1675 * + apply-methods (gf methods args)
1676 *
1677 * apply-methods calls make-next-method to build the "continuation" of a a
1678 * method. Applying a next-method will call apply-next-method which in
1679 * turn will call apply again to call effectively the following method.
1680 *
1681 ******************************************************************************/
1682
1683static int
1684applicablep (SCM actual, SCM formal)
1685{
79a3dafe
DH
1686 /* We already know that the cpl is well formed. */
1687 return !SCM_FALSEP (scm_c_memq (formal, SCM_SLOT (actual, scm_si_cpl)));
80662eda
MD
1688}
1689
1690static int
1691more_specificp (SCM m1, SCM m2, SCM *targs)
1692{
1693 register SCM s1, s2;
c014a02e 1694 register long i;
80662eda
MD
1695 /*
1696 * Note:
1697 * m1 and m2 can have != length (i.e. one can be one element longer than the
1698 * other when we have a dotted parameter list). For instance, with the call
1699 * (M 1)
1700 * with
1701 * (define-method M (a . l) ....)
1702 * (define-method M (a) ....)
1703 *
1704 * we consider that the second method is more specific.
1705 *
1706 * BTW, targs is an array of types. We don't need it's size since
1707 * we already know that m1 and m2 are applicable (no risk to go past
1708 * the end of this array).
1709 *
1710 */
1711 for (i=0,s1=SPEC_OF(m1),s2=SPEC_OF(m2); ; i++,s1=SCM_CDR(s1),s2=SCM_CDR(s2)) {
1712 if (SCM_NULLP(s1)) return 1;
1713 if (SCM_NULLP(s2)) return 0;
1714 if (SCM_CAR(s1) != SCM_CAR(s2)) {
1715 register SCM l, cs1 = SCM_CAR(s1), cs2 = SCM_CAR(s2);
1716
dcb410ec 1717 for (l = SCM_SLOT (targs[i], scm_si_cpl); ; l = SCM_CDR(l)) {
80662eda
MD
1718 if (cs1 == SCM_CAR(l))
1719 return 1;
1720 if (cs2 == SCM_CAR(l))
1721 return 0;
1722 }
1723 return 0;/* should not occur! */
1724 }
1725 }
1726 return 0; /* should not occur! */
1727}
1728
1729#define BUFFSIZE 32 /* big enough for most uses */
1730
1731static SCM
c014a02e 1732scm_i_vector2list (SCM l, long len)
80662eda 1733{
c014a02e 1734 long j;
00ffa0e7 1735 SCM z = scm_c_make_vector (len, SCM_UNDEFINED);
80662eda
MD
1736
1737 for (j = 0; j < len; j++, l = SCM_CDR (l)) {
1738 SCM_VELTS (z)[j] = SCM_CAR (l);
1739 }
1740 return z;
1741}
1742
1743static SCM
c014a02e 1744sort_applicable_methods (SCM method_list, long size, SCM *targs)
80662eda 1745{
c014a02e 1746 long i, j, incr;
80662eda
MD
1747 SCM *v, vector = SCM_EOL;
1748 SCM buffer[BUFFSIZE];
1749 SCM save = method_list;
1750
1751 /* For reasonably sized method_lists we can try to avoid all the
1752 * consing and reorder the list in place...
1753 * This idea is due to David McClain <Dave_McClain@msn.com>
1754 */
1755 if (size <= BUFFSIZE)
1756 {
1757 for (i = 0; i < size; i++)
1758 {
1759 buffer[i] = SCM_CAR (method_list);
1760 method_list = SCM_CDR (method_list);
1761 }
1762 v = buffer;
1763 }
1764 else
1765 {
1766 /* Too many elements in method_list to keep everything locally */
1767 vector = scm_i_vector2list (save, size);
1768 v = SCM_VELTS (vector);
1769 }
1770
1771 /* Use a simple shell sort since it is generally faster than qsort on
1772 * small vectors (which is probably mostly the case when we have to
1773 * sort a list of applicable methods).
1774 */
1775 for (incr = size / 2; incr; incr /= 2)
1776 {
1777 for (i = incr; i < size; i++)
1778 {
1779 for (j = i - incr; j >= 0; j -= incr)
1780 {
1781 if (more_specificp (v[j], v[j+incr], targs))
1782 break;
1783 else
1784 {
1785 SCM tmp = v[j + incr];
1786 v[j + incr] = v[j];
1787 v[j] = tmp;
1788 }
1789 }
1790 }
1791 }
1792
1793 if (size <= BUFFSIZE)
1794 {
1795 /* We did it in locally, so restore the original list (reordered) in-place */
1796 for (i = 0, method_list = save; i < size; i++, v++)
1797 {
1798 SCM_SETCAR (method_list, *v);
1799 method_list = SCM_CDR (method_list);
1800 }
1801 return save;
1802 }
1803 /* If we are here, that's that we did it the hard way... */
1804 return scm_vector_to_list (vector);
1805}
1806
1807SCM
c014a02e 1808scm_compute_applicable_methods (SCM gf, SCM args, long len, int find_method_p)
80662eda 1809{
c014a02e
ML
1810 register long i;
1811 long count = 0;
80662eda
MD
1812 SCM l, fl, applicable = SCM_EOL;
1813 SCM save = args;
1814 SCM buffer[BUFFSIZE], *types, *p;
1815 SCM tmp;
1816
1817 /* Build the list of arguments types */
1818 if (len >= BUFFSIZE) {
00ffa0e7 1819 tmp = scm_c_make_vector (len, SCM_UNDEFINED);
80662eda
MD
1820 /* NOTE: Using pointers to malloced memory won't work if we
1821 1. have preemtive threading, and,
1822 2. have a GC which moves objects. */
1823 types = p = SCM_VELTS(tmp);
1824 }
1825 else
1826 types = p = buffer;
1827
6b80d352 1828 for ( ; !SCM_NULLP (args); args = SCM_CDR (args))
80662eda
MD
1829 *p++ = scm_class_of (SCM_CAR (args));
1830
1831 /* Build a list of all applicable methods */
6b80d352 1832 for (l = SCM_SLOT (gf, scm_si_methods); !SCM_NULLP (l); l = SCM_CDR (l))
80662eda
MD
1833 {
1834 fl = SPEC_OF (SCM_CAR (l));
1835 /* Only accept accessors which match exactly in first arg. */
1836 if (SCM_ACCESSORP (SCM_CAR (l))
6b80d352 1837 && (SCM_NULLP (fl) || types[0] != SCM_CAR (fl)))
80662eda
MD
1838 continue;
1839 for (i = 0; ; i++, fl = SCM_CDR (fl))
1840 {
c312aca7 1841 if (SCM_INSTANCEP (fl)
80662eda
MD
1842 /* We have a dotted argument list */
1843 || (i >= len && SCM_NULLP (fl)))
1844 { /* both list exhausted */
1845 applicable = scm_cons (SCM_CAR (l), applicable);
1846 count += 1;
1847 break;
1848 }
1849 if (i >= len
1850 || SCM_NULLP (fl)
1851 || !applicablep (types[i], SCM_CAR (fl)))
1852 break;
1853 }
1854 }
1855
1856 if (count == 0)
1857 {
1858 if (find_method_p)
1859 return SCM_BOOL_F;
1860 CALL_GF2 ("no-applicable-method", gf, save);
1861 /* if we are here, it's because no-applicable-method hasn't signaled an error */
1862 return SCM_BOOL_F;
1863 }
1864 return (count == 1
1865 ? applicable
1866 : sort_applicable_methods (applicable, count, types));
1867}
1868
1869#if 0
1870SCM_PROC (s_sys_compute_applicable_methods, "%compute-applicable-methods", 2, 0, 0, scm_sys_compute_applicable_methods);
1871#endif
1872
1873static const char s_sys_compute_applicable_methods[] = "%compute-applicable-methods";
1874
1875SCM
1876scm_sys_compute_applicable_methods (SCM gf, SCM args)
398d8ee1 1877#define FUNC_NAME s_sys_compute_applicable_methods
80662eda 1878{
c014a02e 1879 long n;
398d8ee1 1880 SCM_VALIDATE_GENERIC (1, gf);
80662eda 1881 n = scm_ilength (args);
398d8ee1 1882 SCM_ASSERT (n >= 0, args, SCM_ARG2, FUNC_NAME);
80662eda
MD
1883 return scm_compute_applicable_methods (gf, args, n, 1);
1884}
398d8ee1 1885#undef FUNC_NAME
80662eda 1886
86d31dfe 1887SCM_SYMBOL (sym_compute_applicable_methods, "compute-applicable-methods");
9a441ddb 1888SCM_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
1889
1890SCM_SYNTAX (s_atslot_ref, "@slot-ref", scm_makmmacro, scm_m_atslot_ref);
1891
1892SCM
e81d98ec 1893scm_m_atslot_ref (SCM xorig, SCM env SCM_UNUSED)
e11208ca 1894#define FUNC_NAME s_atslot_ref
80662eda
MD
1895{
1896 SCM x = SCM_CDR (xorig);
160bb34a 1897 SCM_ASSYNT (scm_ilength (x) == 2, scm_s_expression, FUNC_NAME);
e11208ca 1898 SCM_VALIDATE_INUM (SCM_ARG2, SCM_CADR (x));
80662eda
MD
1899 return scm_cons (SCM_IM_SLOT_REF, x);
1900}
e11208ca
DH
1901#undef FUNC_NAME
1902
80662eda
MD
1903
1904SCM_SYNTAX (s_atslot_set_x, "@slot-set!", scm_makmmacro, scm_m_atslot_set_x);
1905
1906SCM
e81d98ec 1907scm_m_atslot_set_x (SCM xorig, SCM env SCM_UNUSED)
e11208ca 1908#define FUNC_NAME s_atslot_set_x
80662eda
MD
1909{
1910 SCM x = SCM_CDR (xorig);
160bb34a 1911 SCM_ASSYNT (scm_ilength (x) == 3, scm_s_expression, FUNC_NAME);
e11208ca 1912 SCM_VALIDATE_INUM (SCM_ARG2, SCM_CADR (x));
80662eda
MD
1913 return scm_cons (SCM_IM_SLOT_SET_X, x);
1914}
e11208ca
DH
1915#undef FUNC_NAME
1916
80662eda
MD
1917
1918SCM_SYNTAX (s_atdispatch, "@dispatch", scm_makmmacro, scm_m_atdispatch);
1919
1920SCM_SYMBOL (sym_atdispatch, s_atdispatch);
1921
1922SCM
1923scm_m_atdispatch (SCM xorig, SCM env)
ca83b028 1924#define FUNC_NAME s_atdispatch
80662eda
MD
1925{
1926 SCM args, n, v, gf, x = SCM_CDR (xorig);
160bb34a 1927 SCM_ASSYNT (scm_ilength (x) == 4, scm_s_expression, FUNC_NAME);
80662eda 1928 args = SCM_CAR (x);
e11208ca
DH
1929 if (!SCM_CONSP (args) && !SCM_SYMBOLP (args))
1930 SCM_WRONG_TYPE_ARG (SCM_ARG1, args);
80662eda
MD
1931 x = SCM_CDR (x);
1932 n = SCM_XEVALCAR (x, env);
e11208ca 1933 SCM_VALIDATE_INUM (SCM_ARG2, n);
ca83b028 1934 SCM_ASSERT_RANGE (0, n, SCM_INUM (n) >= 1);
80662eda
MD
1935 x = SCM_CDR (x);
1936 v = SCM_XEVALCAR (x, env);
e11208ca 1937 SCM_VALIDATE_VECTOR (SCM_ARG3, v);
80662eda
MD
1938 x = SCM_CDR (x);
1939 gf = SCM_XEVALCAR (x, env);
e11208ca 1940 SCM_VALIDATE_PUREGENERIC (SCM_ARG4, gf);
1afff620 1941 return scm_list_5 (SCM_IM_DISPATCH, args, n, v, gf);
80662eda 1942}
ca83b028
DH
1943#undef FUNC_NAME
1944
80662eda
MD
1945
1946#ifdef USE_THREADS
1947static void
1948lock_cache_mutex (void *m)
1949{
6b80d352 1950 SCM mutex = SCM_PACK ((scm_t_bits) m);
80662eda
MD
1951 scm_lock_mutex (mutex);
1952}
1953
1954static void
1955unlock_cache_mutex (void *m)
1956{
6b80d352 1957 SCM mutex = SCM_PACK ((scm_t_bits) m);
80662eda
MD
1958 scm_unlock_mutex (mutex);
1959}
1960#endif
1961
1962static SCM
1963call_memoize_method (void *a)
1964{
6b80d352 1965 SCM args = SCM_PACK ((scm_t_bits) a);
80662eda
MD
1966 SCM gf = SCM_CAR (args);
1967 SCM x = SCM_CADR (args);
1968 /* First check if another thread has inserted a method between
1969 * the cache miss and locking the mutex.
1970 */
1971 SCM cmethod = scm_mcache_lookup_cmethod (x, SCM_CDDR (args));
6b80d352 1972 if (!SCM_FALSEP (cmethod))
80662eda
MD
1973 return cmethod;
1974 /*fixme* Use scm_apply */
1975 return CALL_GF3 ("memoize-method!", gf, SCM_CDDR (args), x);
1976}
1977
1978SCM
1979scm_memoize_method (SCM x, SCM args)
1980{
1981 SCM gf = SCM_CAR (scm_last_pair (x));
1982#ifdef USE_THREADS
6b80d352
DH
1983 return scm_internal_dynamic_wind (
1984 lock_cache_mutex,
1985 call_memoize_method,
1986 unlock_cache_mutex,
1987 (void *) SCM_UNPACK (scm_cons2 (gf, x, args)),
1988 (void *) SCM_UNPACK (SCM_SLOT (gf, scm_si_cache_mutex)));
80662eda 1989#else
6b80d352 1990 return call_memoize_method ((void *) SCM_UNPACK (scm_cons2 (gf, x, args)));
80662eda
MD
1991#endif
1992}
1993
1994/******************************************************************************
1995 *
1996 * A simple make (which will be redefined later in Scheme)
1997 * This version handles only creation of gf, methods and classes (no instances)
1998 *
1999 * Since this code will disappear when Goops will be fully booted,
2000 * no precaution is taken to be efficient.
2001 *
2002 ******************************************************************************/
2003
2004SCM_KEYWORD (k_setter, "setter");
2005SCM_KEYWORD (k_specializers, "specializers");
2006SCM_KEYWORD (k_procedure, "procedure");
2007SCM_KEYWORD (k_dsupers, "dsupers");
2008SCM_KEYWORD (k_slots, "slots");
2009SCM_KEYWORD (k_gf, "generic-function");
2010
398d8ee1
KN
2011SCM_DEFINE (scm_make, "make", 0, 0, 1,
2012 (SCM args),
27c37006 2013 "Make a new object. @var{args} must contain the class and\n"
6bcefd15 2014 "all necessary initialization information.")
398d8ee1 2015#define FUNC_NAME s_scm_make
80662eda
MD
2016{
2017 SCM class, z;
c014a02e 2018 long len = scm_ilength (args);
80662eda
MD
2019
2020 if (len <= 0 || (len & 1) == 0)
398d8ee1 2021 SCM_WRONG_NUM_ARGS ();
80662eda
MD
2022
2023 class = SCM_CAR(args);
2024 args = SCM_CDR(args);
2025
2026 if (class == scm_class_generic || class == scm_class_generic_with_setter)
2027 {
2028#ifdef USE_THREADS
2029 z = scm_make_struct (class, SCM_INUM0,
1afff620
KN
2030 scm_list_4 (SCM_EOL,
2031 SCM_INUM0,
2032 SCM_BOOL_F,
2033 scm_make_mutex ()));
80662eda
MD
2034#else
2035 z = scm_make_struct (class, SCM_INUM0,
1afff620 2036 scm_list_3 (SCM_EOL, SCM_INUM0, SCM_BOOL_F));
80662eda
MD
2037#endif
2038 scm_set_procedure_property_x (z, scm_sym_name,
2039 scm_get_keyword (k_name,
2040 args,
2041 SCM_BOOL_F));
2042 clear_method_cache (z);
2043 if (class == scm_class_generic_with_setter)
2044 {
2045 SCM setter = scm_get_keyword (k_setter, args, SCM_BOOL_F);
6b80d352 2046 if (!SCM_FALSEP (setter))
80662eda
MD
2047 scm_sys_set_object_setter_x (z, setter);
2048 }
2049 }
2050 else
2051 {
2052 z = scm_sys_allocate_instance (class, args);
2053
2054 if (class == scm_class_method
2055 || class == scm_class_simple_method
2056 || class == scm_class_accessor)
2057 {
dcb410ec 2058 SCM_SET_SLOT (z, scm_si_generic_function,
80662eda
MD
2059 scm_i_get_keyword (k_gf,
2060 args,
2061 len - 1,
2062 SCM_BOOL_F,
dcb410ec
DH
2063 FUNC_NAME));
2064 SCM_SET_SLOT (z, scm_si_specializers,
80662eda
MD
2065 scm_i_get_keyword (k_specializers,
2066 args,
2067 len - 1,
2068 SCM_EOL,
dcb410ec
DH
2069 FUNC_NAME));
2070 SCM_SET_SLOT (z, scm_si_procedure,
80662eda
MD
2071 scm_i_get_keyword (k_procedure,
2072 args,
2073 len - 1,
2074 SCM_EOL,
dcb410ec
DH
2075 FUNC_NAME));
2076 SCM_SET_SLOT (z, scm_si_code_table, SCM_EOL);
80662eda
MD
2077 }
2078 else
2079 {
2080 /* In all the others case, make a new class .... No instance here */
dcb410ec 2081 SCM_SET_SLOT (z, scm_si_name,
80662eda
MD
2082 scm_i_get_keyword (k_name,
2083 args,
2084 len - 1,
38ae064c 2085 scm_str2symbol ("???"),
dcb410ec
DH
2086 FUNC_NAME));
2087 SCM_SET_SLOT (z, scm_si_direct_supers,
80662eda
MD
2088 scm_i_get_keyword (k_dsupers,
2089 args,
2090 len - 1,
2091 SCM_EOL,
dcb410ec
DH
2092 FUNC_NAME));
2093 SCM_SET_SLOT (z, scm_si_direct_slots,
80662eda
MD
2094 scm_i_get_keyword (k_slots,
2095 args,
2096 len - 1,
2097 SCM_EOL,
dcb410ec 2098 FUNC_NAME));
80662eda
MD
2099 }
2100 }
2101 return z;
2102}
398d8ee1 2103#undef FUNC_NAME
80662eda 2104
398d8ee1
KN
2105SCM_DEFINE (scm_find_method, "find-method", 0, 0, 1,
2106 (SCM l),
2107 "")
2108#define FUNC_NAME s_scm_find_method
80662eda
MD
2109{
2110 SCM gf;
c014a02e 2111 long len = scm_ilength (l);
80662eda
MD
2112
2113 if (len == 0)
398d8ee1 2114 SCM_WRONG_NUM_ARGS ();
80662eda
MD
2115
2116 gf = SCM_CAR(l); l = SCM_CDR(l);
398d8ee1 2117 SCM_VALIDATE_GENERIC (1, gf);
80662eda 2118 if (SCM_NULLP (SCM_SLOT (gf, scm_si_methods)))
1afff620 2119 SCM_MISC_ERROR ("no methods for generic ~S", scm_list_1 (gf));
80662eda
MD
2120
2121 return scm_compute_applicable_methods (gf, l, len - 1, 1);
2122}
398d8ee1 2123#undef FUNC_NAME
80662eda 2124
398d8ee1
KN
2125SCM_DEFINE (scm_sys_method_more_specific_p, "%method-more-specific?", 3, 0, 0,
2126 (SCM m1, SCM m2, SCM targs),
2127 "")
2128#define FUNC_NAME s_scm_sys_method_more_specific_p
80662eda
MD
2129{
2130 SCM l, v;
c014a02e 2131 long i, len;
80662eda 2132
398d8ee1
KN
2133 SCM_VALIDATE_METHOD (1, m1);
2134 SCM_VALIDATE_METHOD (2, m2);
2135 SCM_ASSERT ((len = scm_ilength (targs)) != -1, targs, SCM_ARG3, FUNC_NAME);
80662eda
MD
2136
2137 /* Verify that all the arguments of targs are classes and place them in a vector*/
00ffa0e7 2138 v = scm_c_make_vector (len, SCM_EOL);
80662eda 2139
6b80d352 2140 for (i = 0, l = targs; !SCM_NULLP (l); i++, l = SCM_CDR (l)) {
398d8ee1 2141 SCM_ASSERT (SCM_CLASSP (SCM_CAR (l)), targs, SCM_ARG3, FUNC_NAME);
80662eda
MD
2142 SCM_VELTS(v)[i] = SCM_CAR(l);
2143 }
2144 return more_specificp (m1, m2, SCM_VELTS(v)) ? SCM_BOOL_T: SCM_BOOL_F;
2145}
398d8ee1 2146#undef FUNC_NAME
80662eda
MD
2147
2148
2149
2150/******************************************************************************
2151 *
2152 * Initializations
2153 *
2154 ******************************************************************************/
2155
2156
2157static void
2158make_stdcls (SCM *var, char *name, SCM meta, SCM super, SCM slots)
2159{
38ae064c 2160 SCM tmp = scm_str2symbol (name);
80662eda
MD
2161
2162 *var = scm_permanent_object (scm_basic_make_class (meta,
2163 tmp,
2164 SCM_CONSP (super)
2165 ? super
1afff620 2166 : scm_list_1 (super),
80662eda
MD
2167 slots));
2168 DEFVAR(tmp, *var);
2169}
2170
2171
2172SCM_KEYWORD (k_slot_definition, "slot-definition");
2173
2174static void
2175create_standard_classes (void)
2176{
2177 SCM slots;
1afff620
KN
2178 SCM method_slots = scm_list_4 (scm_str2symbol ("generic-function"),
2179 scm_str2symbol ("specializers"),
6b80d352 2180 sym_procedure,
1afff620
KN
2181 scm_str2symbol ("code-table"));
2182 SCM amethod_slots = scm_list_1 (scm_list_3 (scm_str2symbol ("slot-definition"),
2183 k_init_keyword,
2184 k_slot_definition));
80662eda 2185#ifdef USE_THREADS
1afff620 2186 SCM mutex_slot = scm_list_1 (scm_str2symbol ("make-mutex"));
80662eda
MD
2187#else
2188 SCM mutex_slot = SCM_BOOL_F;
2189#endif
1afff620
KN
2190 SCM gf_slots = scm_list_4 (scm_str2symbol ("methods"),
2191 scm_list_3 (scm_str2symbol ("n-specialized"),
2192 k_init_value,
2193 SCM_INUM0),
2194 scm_list_3 (scm_str2symbol ("used-by"),
2195 k_init_value,
2196 SCM_BOOL_F),
2197 scm_list_3 (scm_str2symbol ("cache-mutex"),
2198 k_init_thunk,
2199 scm_closure (scm_list_2 (SCM_EOL,
2200 mutex_slot),
2201 SCM_EOL)));
80662eda
MD
2202
2203 /* Foreign class slot classes */
2204 make_stdcls (&scm_class_foreign_slot, "<foreign-slot>",
2205 scm_class_class, scm_class_top, SCM_EOL);
2206 make_stdcls (&scm_class_protected, "<protected-slot>",
2207 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2208 make_stdcls (&scm_class_opaque, "<opaque-slot>",
2209 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2210 make_stdcls (&scm_class_read_only, "<read-only-slot>",
2211 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2212 make_stdcls (&scm_class_self, "<self-slot>",
2213 scm_class_class,
1afff620 2214 scm_list_2 (scm_class_foreign_slot, scm_class_read_only),
80662eda
MD
2215 SCM_EOL);
2216 make_stdcls (&scm_class_protected_opaque, "<protected-opaque-slot>",
2217 scm_class_class,
1afff620 2218 scm_list_2 (scm_class_protected, scm_class_opaque),
80662eda
MD
2219 SCM_EOL);
2220 make_stdcls (&scm_class_protected_read_only, "<protected-read-only-slot>",
2221 scm_class_class,
1afff620 2222 scm_list_2 (scm_class_protected, scm_class_read_only),
80662eda
MD
2223 SCM_EOL);
2224 make_stdcls (&scm_class_scm, "<scm-slot>",
2225 scm_class_class, scm_class_protected, SCM_EOL);
2226 make_stdcls (&scm_class_int, "<int-slot>",
2227 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2228 make_stdcls (&scm_class_float, "<float-slot>",
2229 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2230 make_stdcls (&scm_class_double, "<double-slot>",
2231 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2232
2233 /* Continue initialization of class <class> */
2234
2235 slots = build_class_class_slots ();
dcb410ec
DH
2236 SCM_SET_SLOT (scm_class_class, scm_si_direct_slots, slots);
2237 SCM_SET_SLOT (scm_class_class, scm_si_slots, slots);
2238 SCM_SET_SLOT (scm_class_class, scm_si_getters_n_setters,
2239 compute_getters_n_setters (slots));
80662eda
MD
2240
2241 make_stdcls (&scm_class_foreign_class, "<foreign-class>",
2242 scm_class_class, scm_class_class,
1afff620
KN
2243 scm_list_2 (scm_list_3 (scm_str2symbol ("constructor"),
2244 k_class,
2245 scm_class_opaque),
2246 scm_list_3 (scm_str2symbol ("destructor"),
2247 k_class,
2248 scm_class_opaque)));
80662eda
MD
2249 make_stdcls (&scm_class_foreign_object, "<foreign-object>",
2250 scm_class_foreign_class, scm_class_object, SCM_EOL);
2251 SCM_SET_CLASS_FLAGS (scm_class_foreign_object, SCM_CLASSF_FOREIGN);
2252
2253 /* scm_class_generic functions classes */
2254 make_stdcls (&scm_class_procedure_class, "<procedure-class>",
2255 scm_class_class, scm_class_class, SCM_EOL);
2256 make_stdcls (&scm_class_entity_class, "<entity-class>",
2257 scm_class_class, scm_class_procedure_class, SCM_EOL);
2258 make_stdcls (&scm_class_operator_class, "<operator-class>",
2259 scm_class_class, scm_class_procedure_class, SCM_EOL);
2260 make_stdcls (&scm_class_operator_with_setter_class,
2261 "<operator-with-setter-class>",
2262 scm_class_class, scm_class_operator_class, SCM_EOL);
2263 make_stdcls (&scm_class_method, "<method>",
2264 scm_class_class, scm_class_object, method_slots);
2265 make_stdcls (&scm_class_simple_method, "<simple-method>",
2266 scm_class_class, scm_class_method, SCM_EOL);
2267 SCM_SET_CLASS_FLAGS (scm_class_simple_method, SCM_CLASSF_SIMPLE_METHOD);
2268 make_stdcls (&scm_class_accessor, "<accessor-method>",
2269 scm_class_class, scm_class_simple_method, amethod_slots);
2270 SCM_SET_CLASS_FLAGS (scm_class_accessor, SCM_CLASSF_ACCESSOR_METHOD);
2271 make_stdcls (&scm_class_entity, "<entity>",
2272 scm_class_entity_class, scm_class_object, SCM_EOL);
2273 make_stdcls (&scm_class_entity_with_setter, "<entity-with-setter>",
2274 scm_class_entity_class, scm_class_entity, SCM_EOL);
2275 make_stdcls (&scm_class_generic, "<generic>",
2276 scm_class_entity_class, scm_class_entity, gf_slots);
2277 SCM_SET_CLASS_FLAGS (scm_class_generic, SCM_CLASSF_PURE_GENERIC);
2278 make_stdcls (&scm_class_generic_with_setter, "<generic-with-setter>",
2279 scm_class_entity_class,
1afff620 2280 scm_list_2 (scm_class_generic, scm_class_entity_with_setter),
80662eda
MD
2281 SCM_EOL);
2282#if 0
2283 /* Patch cpl since compute_cpl doesn't support multiple inheritance. */
dcb410ec 2284 SCM_SET_SLOT (scm_class_generic_with_setter, scm_si_cpl,
1afff620
KN
2285 scm_append (scm_list_3 (scm_list_2 (scm_class_generic_with_setter,
2286 scm_class_generic),
2287 SCM_SLOT (scm_class_entity_with_setter,
2288 scm_si_cpl),
2289 SCM_EOL)));
80662eda
MD
2290#endif
2291 SCM_SET_CLASS_FLAGS (scm_class_generic_with_setter, SCM_CLASSF_PURE_GENERIC);
2292
2293 /* Primitive types classes */
2294 make_stdcls (&scm_class_boolean, "<boolean>",
2295 scm_class_class, scm_class_top, SCM_EOL);
2296 make_stdcls (&scm_class_char, "<char>",
2297 scm_class_class, scm_class_top, SCM_EOL);
2298 make_stdcls (&scm_class_list, "<list>",
2299 scm_class_class, scm_class_top, SCM_EOL);
2300 make_stdcls (&scm_class_pair, "<pair>",
2301 scm_class_class, scm_class_list, SCM_EOL);
2302 make_stdcls (&scm_class_null, "<null>",
2303 scm_class_class, scm_class_list, SCM_EOL);
2304 make_stdcls (&scm_class_string, "<string>",
2305 scm_class_class, scm_class_top, SCM_EOL);
2306 make_stdcls (&scm_class_symbol, "<symbol>",
2307 scm_class_class, scm_class_top, SCM_EOL);
2308 make_stdcls (&scm_class_vector, "<vector>",
2309 scm_class_class, scm_class_top, SCM_EOL);
2310 make_stdcls (&scm_class_number, "<number>",
2311 scm_class_class, scm_class_top, SCM_EOL);
2312 make_stdcls (&scm_class_complex, "<complex>",
2313 scm_class_class, scm_class_number, SCM_EOL);
2314 make_stdcls (&scm_class_real, "<real>",
2315 scm_class_class, scm_class_complex, SCM_EOL);
2316 make_stdcls (&scm_class_integer, "<integer>",
2317 scm_class_class, scm_class_real, SCM_EOL);
2318 make_stdcls (&scm_class_keyword, "<keyword>",
2319 scm_class_class, scm_class_top, SCM_EOL);
2320 make_stdcls (&scm_class_unknown, "<unknown>",
2321 scm_class_class, scm_class_top, SCM_EOL);
2322 make_stdcls (&scm_class_procedure, "<procedure>",
2323 scm_class_procedure_class, scm_class_top, SCM_EOL);
2324 make_stdcls (&scm_class_procedure_with_setter, "<procedure-with-setter>",
2325 scm_class_procedure_class, scm_class_procedure, SCM_EOL);
2326 make_stdcls (&scm_class_primitive_generic, "<primitive-generic>",
2327 scm_class_procedure_class, scm_class_procedure, SCM_EOL);
2328 make_stdcls (&scm_class_port, "<port>",
2329 scm_class_class, scm_class_top, SCM_EOL);
2330 make_stdcls (&scm_class_input_port, "<input-port>",
2331 scm_class_class, scm_class_port, SCM_EOL);
2332 make_stdcls (&scm_class_output_port, "<output-port>",
2333 scm_class_class, scm_class_port, SCM_EOL);
2334 make_stdcls (&scm_class_input_output_port, "<input-output-port>",
2335 scm_class_class,
1afff620 2336 scm_list_2 (scm_class_input_port, scm_class_output_port),
80662eda
MD
2337 SCM_EOL);
2338}
2339
2340/**********************************************************************
2341 *
2342 * Smob classes
2343 *
2344 **********************************************************************/
2345
2346static SCM
2347make_class_from_template (char *template, char *type_name, SCM supers)
2348{
2349 SCM class, name;
2350 if (type_name)
2351 {
2352 char buffer[100];
2353 sprintf (buffer, template, type_name);
38ae064c 2354 name = scm_str2symbol (buffer);
80662eda
MD
2355 }
2356 else
2357 name = SCM_GOOPS_UNBOUND;
2358
2359 class = scm_permanent_object (scm_basic_make_class (scm_class_class,
2360 name,
2361 supers,
2362 SCM_EOL));
2363
2364 /* Only define name if doesn't already exist. */
2365 if (!SCM_GOOPS_UNBOUNDP (name)
fdc28395 2366 && SCM_FALSEP (scm_call_2 (scm_goops_lookup_closure, name, SCM_BOOL_F)))
0ba8a0a5 2367 DEFVAR (name, class);
80662eda
MD
2368 return class;
2369}
2370
2371SCM
2372scm_make_extended_class (char *type_name)
2373{
2374 return make_class_from_template ("<%s>",
2375 type_name,
1afff620 2376 scm_list_1 (scm_class_top));
80662eda
MD
2377}
2378
2379static void
2380create_smob_classes (void)
2381{
c014a02e 2382 long i;
80662eda
MD
2383
2384 scm_smob_class = (SCM *) malloc (255 * sizeof (SCM));
2385 for (i = 0; i < 255; ++i)
2386 scm_smob_class[i] = 0;
2387
2388 scm_smob_class[SCM_TC2SMOBNUM (scm_tc16_big)] = scm_class_integer;
2389 scm_smob_class[SCM_TC2SMOBNUM (scm_tc16_real)] = scm_class_real;
2390 scm_smob_class[SCM_TC2SMOBNUM (scm_tc16_complex)] = scm_class_complex;
2391 scm_smob_class[SCM_TC2SMOBNUM (scm_tc16_keyword)] = scm_class_keyword;
2392
2393 for (i = 0; i < scm_numsmob; ++i)
2394 if (!scm_smob_class[i])
2395 scm_smob_class[i] = scm_make_extended_class (SCM_SMOBNAME (i));
2396}
2397
2398void
c014a02e 2399scm_make_port_classes (long ptobnum, char *type_name)
80662eda
MD
2400{
2401 SCM c, class = make_class_from_template ("<%s-port>",
2402 type_name,
1afff620 2403 scm_list_1 (scm_class_port));
80662eda
MD
2404 scm_port_class[SCM_IN_PCLASS_INDEX + ptobnum]
2405 = make_class_from_template ("<%s-input-port>",
2406 type_name,
1afff620 2407 scm_list_2 (class, scm_class_input_port));
80662eda
MD
2408 scm_port_class[SCM_OUT_PCLASS_INDEX + ptobnum]
2409 = make_class_from_template ("<%s-output-port>",
2410 type_name,
1afff620 2411 scm_list_2 (class, scm_class_output_port));
80662eda
MD
2412 scm_port_class[SCM_INOUT_PCLASS_INDEX + ptobnum]
2413 = c
2414 = make_class_from_template ("<%s-input-output-port>",
2415 type_name,
1afff620 2416 scm_list_2 (class, scm_class_input_output_port));
80662eda 2417 /* Patch cpl (since this tree is too complex for the C level compute-cpl) */
dcb410ec
DH
2418 SCM_SET_SLOT (c, scm_si_cpl,
2419 scm_cons2 (c, class, SCM_SLOT (scm_class_input_output_port, scm_si_cpl)));
80662eda
MD
2420}
2421
2422static void
2423create_port_classes (void)
2424{
c014a02e 2425 long i;
80662eda
MD
2426
2427 scm_port_class = (SCM *) malloc (3 * 256 * sizeof (SCM));
2428 for (i = 0; i < 3 * 256; ++i)
2429 scm_port_class[i] = 0;
2430
2431 for (i = 0; i < scm_numptob; ++i)
2432 scm_make_port_classes (i, SCM_PTOBNAME (i));
2433}
2434
2435static SCM
e81d98ec
DH
2436make_struct_class (void *closure SCM_UNUSED, SCM key SCM_UNUSED,
2437 SCM data, SCM prev SCM_UNUSED)
80662eda 2438{
6b80d352 2439 if (!SCM_FALSEP (SCM_STRUCT_TABLE_NAME (data)))
80662eda
MD
2440 SCM_SET_STRUCT_TABLE_CLASS (data,
2441 scm_make_extended_class
b24b5e13 2442 (SCM_SYMBOL_CHARS (SCM_STRUCT_TABLE_NAME (data))));
80662eda
MD
2443 return SCM_UNSPECIFIED;
2444}
2445
2446static void
2447create_struct_classes (void)
2448{
2449 scm_internal_hash_fold (make_struct_class, 0, SCM_BOOL_F, scm_struct_table);
2450}
2451
2452/**********************************************************************
2453 *
2454 * C interface
2455 *
2456 **********************************************************************/
2457
2458void
2459scm_load_goops ()
2460{
2461 if (!goops_loaded_p)
abd28220 2462 scm_c_resolve_module ("oop goops");
80662eda
MD
2463}
2464
e11208ca 2465
80662eda
MD
2466SCM
2467scm_make_foreign_object (SCM class, SCM initargs)
e11208ca 2468#define FUNC_NAME s_scm_make
80662eda
MD
2469{
2470 void * (*constructor) (SCM)
2471 = (void * (*) (SCM)) SCM_SLOT (class, scm_si_constructor);
e11208ca 2472 if (constructor == 0)
1afff620 2473 SCM_MISC_ERROR ("Can't make instances of class ~S", scm_list_1 (class));
80662eda
MD
2474 return scm_wrap_object (class, constructor (initargs));
2475}
e11208ca
DH
2476#undef FUNC_NAME
2477
80662eda
MD
2478
2479static size_t
2480scm_free_foreign_object (SCM *class, SCM *data)
2481{
2482 size_t (*destructor) (void *)
2483 = (size_t (*) (void *)) class[scm_si_destructor];
2484 return destructor (data);
2485}
2486
2487SCM
2488scm_make_class (SCM meta, char *s_name, SCM supers, size_t size,
2489 void * (*constructor) (SCM initargs),
2490 size_t (*destructor) (void *))
2491{
2492 SCM name, class;
38ae064c 2493 name = scm_str2symbol (s_name);
6b80d352 2494 if (SCM_NULLP (supers))
1afff620 2495 supers = scm_list_1 (scm_class_foreign_object);
80662eda
MD
2496 class = scm_basic_basic_make_class (meta, name, supers, SCM_EOL);
2497 scm_sys_inherit_magic_x (class, supers);
2498
2499 if (destructor != 0)
2500 {
dcb410ec 2501 SCM_SET_SLOT (class, scm_si_destructor, (SCM) destructor);
80662eda
MD
2502 SCM_SET_CLASS_DESTRUCTOR (class, scm_free_foreign_object);
2503 }
2504 else if (size > 0)
2505 {
2506 SCM_SET_CLASS_DESTRUCTOR (class, scm_struct_free_light);
2507 SCM_SET_CLASS_INSTANCE_SIZE (class, size);
2508 }
2509
dcb410ec
DH
2510 SCM_SET_SLOT (class, scm_si_layout, scm_str2symbol (""));
2511 SCM_SET_SLOT (class, scm_si_constructor, (SCM) constructor);
80662eda
MD
2512
2513 return class;
2514}
2515
2516SCM_SYMBOL (sym_o, "o");
2517SCM_SYMBOL (sym_x, "x");
2518
2519SCM_KEYWORD (k_accessor, "accessor");
2520SCM_KEYWORD (k_getter, "getter");
2521
2522static SCM
e81d98ec 2523default_setter (SCM obj SCM_UNUSED, SCM c SCM_UNUSED)
80662eda
MD
2524{
2525 scm_misc_error ("slot-set!", "read-only slot", SCM_EOL);
2526 return 0;
2527}
2528
2529void
2530scm_add_slot (SCM class, char *slot_name, SCM slot_class,
2531 SCM (*getter) (SCM obj),
2532 SCM (*setter) (SCM obj, SCM x),
2533 char *accessor_name)
2534{
2535 {
9a441ddb
MV
2536 SCM get = scm_c_make_subr ("goops:get", scm_tc7_subr_1, getter);
2537 SCM set = scm_c_make_subr ("goops:set", scm_tc7_subr_2,
2538 setter ? setter : default_setter);
1afff620
KN
2539 SCM getm = scm_closure (scm_list_2 (scm_list_1 (sym_o),
2540 scm_list_2 (get, sym_o)),
80662eda 2541 SCM_EOL);
1afff620
KN
2542 SCM setm = scm_closure (scm_list_2 (scm_list_2 (sym_o, sym_x),
2543 scm_list_3 (set, sym_o, sym_x)),
80662eda
MD
2544 SCM_EOL);
2545 {
38ae064c
DH
2546 SCM name = scm_str2symbol (slot_name);
2547 SCM aname = scm_str2symbol (accessor_name);
80662eda 2548 SCM gf = scm_ensure_accessor (aname);
1afff620
KN
2549 SCM slot = scm_list_5 (name,
2550 k_class,
2551 slot_class,
2552 setter ? k_accessor : k_getter,
2553 gf);
2554 SCM gns = scm_list_4 (name, SCM_BOOL_F, get, set);
2555
2556 scm_add_method (gf, scm_make (scm_list_5 (scm_class_accessor,
2557 k_specializers,
2558 scm_list_1 (class),
2559 k_procedure,
2560 getm)));
80662eda 2561 scm_add_method (scm_setter (gf),
1afff620
KN
2562 scm_make (scm_list_5 (scm_class_accessor,
2563 k_specializers,
2564 scm_list_2 (class, scm_class_top),
2565 k_procedure,
2566 setm)));
80662eda
MD
2567 DEFVAR (aname, gf);
2568
dcb410ec 2569 SCM_SET_SLOT (class, scm_si_slots,
1afff620
KN
2570 scm_append_x (scm_list_2 (SCM_SLOT (class, scm_si_slots),
2571 scm_list_1 (slot))));
dcb410ec 2572 SCM_SET_SLOT (class, scm_si_getters_n_setters,
1afff620
KN
2573 scm_append_x (scm_list_2 (SCM_SLOT (class, scm_si_getters_n_setters),
2574 scm_list_1 (gns))));
80662eda
MD
2575 }
2576 }
2577 {
c014a02e 2578 long n = SCM_INUM (SCM_SLOT (class, scm_si_nfields));
80662eda 2579
dcb410ec 2580 SCM_SET_SLOT (class, scm_si_nfields, SCM_MAKINUM (n + 1));
80662eda
MD
2581 }
2582}
2583
2584SCM
2585scm_wrap_object (SCM class, void *data)
2586{
16d4699b
MV
2587 return scm_alloc_double_cell (SCM_UNPACK (SCM_CDR (class)) | scm_tc3_struct,
2588 (scm_t_bits) data,
2589 0, 0);
80662eda
MD
2590}
2591
2592SCM scm_components;
2593
2594SCM
2595scm_wrap_component (SCM class, SCM container, void *data)
2596{
2597 SCM obj = scm_wrap_object (class, data);
2598 SCM handle = scm_hash_fn_create_handle_x (scm_components,
2599 obj,
2600 SCM_BOOL_F,
2601 scm_struct_ihashq,
2602 scm_sloppy_assq,
2603 0);
2604 SCM_SETCDR (handle, container);
2605 return obj;
2606}
2607
2608SCM
2609scm_ensure_accessor (SCM name)
2610{
fdc28395 2611 SCM gf = scm_call_2 (SCM_TOP_LEVEL_LOOKUP_CLOSURE, name, SCM_BOOL_F);
80662eda
MD
2612 if (!SCM_IS_A_P (gf, scm_class_generic_with_setter))
2613 {
1afff620
KN
2614 gf = scm_make (scm_list_3 (scm_class_generic, k_name, name));
2615 gf = scm_make (scm_list_5 (scm_class_generic_with_setter,
2616 k_name, name, k_setter, gf));
80662eda
MD
2617 }
2618 return gf;
2619}
2620
2621SCM_SYMBOL (sym_internal_add_method_x, "internal-add-method!");
2622
2623void
2624scm_add_method (SCM gf, SCM m)
2625{
1afff620 2626 scm_eval (scm_list_3 (sym_internal_add_method_x, gf, m), scm_module_goops);
80662eda
MD
2627}
2628
2629#ifdef GUILE_DEBUG
2630/*
2631 * Debugging utilities
2632 */
2633
398d8ee1
KN
2634SCM_DEFINE (scm_pure_generic_p, "pure-generic?", 1, 0, 0,
2635 (SCM obj),
6bcefd15 2636 "Return @code{#t} if @var{obj} is a pure generic.")
398d8ee1 2637#define FUNC_NAME s_scm_pure_generic_p
80662eda 2638{
25ba37df 2639 return SCM_BOOL (SCM_PUREGENERICP (obj));
80662eda 2640}
398d8ee1 2641#undef FUNC_NAME
80662eda
MD
2642
2643#endif /* GUILE_DEBUG */
2644
2645/*
2646 * Initialization
2647 */
2648
398d8ee1
KN
2649SCM_DEFINE (scm_sys_goops_loaded, "%goops-loaded", 0, 0, 0,
2650 (),
6bcefd15
MG
2651 "Announce that GOOPS is loaded and perform initialization\n"
2652 "on the C level which depends on the loaded GOOPS modules.")
398d8ee1 2653#define FUNC_NAME s_scm_sys_goops_loaded
80662eda
MD
2654{
2655 goops_loaded_p = 1;
86d31dfe
MV
2656 var_compute_applicable_methods =
2657 scm_sym2var (sym_compute_applicable_methods, scm_goops_lookup_closure,
2658 SCM_BOOL_F);
80662eda
MD
2659 return SCM_UNSPECIFIED;
2660}
398d8ee1 2661#undef FUNC_NAME
80662eda
MD
2662
2663SCM scm_module_goops;
2664
abd28220
MV
2665SCM
2666scm_init_goops_builtins (void)
80662eda 2667{
abd28220 2668 scm_module_goops = scm_current_module ();
80662eda
MD
2669 scm_goops_lookup_closure = scm_module_lookup_closure (scm_module_goops);
2670
0ba8a0a5
MV
2671 /* Not really necessary right now, but who knows...
2672 */
2673 scm_permanent_object (scm_module_goops);
2674 scm_permanent_object (scm_goops_lookup_closure);
2675
80662eda
MD
2676 scm_components = scm_permanent_object (scm_make_weak_key_hash_table
2677 (SCM_MAKINUM (37)));
2678
2679 goops_rstate = scm_c_make_rstate ("GOOPS", 5);
2680
8dc9439f 2681#ifndef SCM_MAGIC_SNARFER
80662eda 2682#include "libguile/goops.x"
8dc9439f 2683#endif
80662eda 2684
1afff620 2685 list_of_no_method = scm_permanent_object (scm_list_1 (sym_no_method));
80662eda
MD
2686
2687 hell = scm_must_malloc (hell_size, "hell");
2688#ifdef USE_THREADS
2689 scm_mutex_init (&hell_mutex);
2690#endif
2691
2692 create_basic_classes ();
2693 create_standard_classes ();
2694 create_smob_classes ();
2695 create_struct_classes ();
2696 create_port_classes ();
2697
2698 {
38ae064c 2699 SCM name = scm_str2symbol ("no-applicable-method");
80662eda 2700 scm_no_applicable_method
1afff620
KN
2701 = scm_permanent_object (scm_make (scm_list_3 (scm_class_generic,
2702 k_name,
2703 name)));
80662eda
MD
2704 DEFVAR (name, scm_no_applicable_method);
2705 }
abd28220
MV
2706
2707 return SCM_UNSPECIFIED;
80662eda
MD
2708}
2709
2710void
abd28220 2711scm_init_goops ()
80662eda 2712{
9a441ddb
MV
2713 scm_c_define_gsubr ("%init-goops-builtins", 0, 0, 0,
2714 scm_init_goops_builtins);
80662eda 2715}
23437298
DH
2716
2717/*
2718 Local Variables:
2719 c-file-style: "gnu"
2720 End:
2721*/