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