More goops.c cleanups, and fix a security issue
[bpt/guile.git] / libguile / goops.c
1 /* Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2008,2009,2010,2011,2012,2013,2014,2015
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 License
6 * as published by the Free Software Foundation; either version 3 of
7 * the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful, but
10 * 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
17 * 02110-1301 USA
18 */
19 \f
20
21 /* This software is a derivative work of other copyrighted softwares; the
22 * copyright notices of these softwares are placed in the file COPYRIGHTS
23 *
24 * This file is based upon stklos.c from the STk distribution by
25 * Erick Gallesio <eg@unice.fr>.
26 */
27
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
31
32 #include "libguile/_scm.h"
33 #include "libguile/async.h"
34 #include "libguile/chars.h"
35 #include "libguile/dynwind.h"
36 #include "libguile/eval.h"
37 #include "libguile/gsubr.h"
38 #include "libguile/hashtab.h"
39 #include "libguile/keywords.h"
40 #include "libguile/macros.h"
41 #include "libguile/modules.h"
42 #include "libguile/ports.h"
43 #include "libguile/procprop.h"
44 #include "libguile/programs.h"
45 #include "libguile/smob.h"
46 #include "libguile/strings.h"
47 #include "libguile/strports.h"
48 #include "libguile/vectors.h"
49
50 #include "libguile/validate.h"
51 #include "libguile/goops.h"
52
53 /* Port classes */
54 #define SCM_IN_PCLASS_INDEX 0
55 #define SCM_OUT_PCLASS_INDEX SCM_I_MAX_PORT_TYPE_COUNT
56 #define SCM_INOUT_PCLASS_INDEX (2 * SCM_I_MAX_PORT_TYPE_COUNT)
57
58 /* Objects have identity, so references to classes and instances are by
59 value, not by reference. Redefinition of a class or modification of
60 an instance causes in-place update; you can think of GOOPS as
61 building in its own indirection, and for that reason referring to
62 GOOPS values by variable reference is unnecessary.
63
64 References to ordinary procedures is by reference (by variable),
65 though, as in the rest of Guile. */
66
67 static SCM var_make_standard_class = SCM_BOOL_F;
68 static SCM var_slot_unbound = SCM_BOOL_F;
69 static SCM var_slot_missing = SCM_BOOL_F;
70 static SCM var_change_class = SCM_BOOL_F;
71 static SCM var_make = SCM_BOOL_F;
72
73 SCM_SYMBOL (sym_slot_unbound, "slot-unbound");
74 SCM_SYMBOL (sym_slot_missing, "slot-missing");
75 SCM_SYMBOL (sym_change_class, "change-class");
76
77 SCM_VARIABLE (scm_var_make_extended_generic, "make-extended-generic");
78
79
80 /* Class redefinition protocol:
81
82 A class is represented by a heap header h1 which points to a
83 malloc:ed memory block m1.
84
85 When a new version of a class is created, a new header h2 and
86 memory block m2 are allocated. The headers h1 and h2 then switch
87 pointers so that h1 refers to m2 and h2 to m1. In this way, names
88 bound to h1 will point to the new class at the same time as h2 will
89 be a handle which the GC will use to free m1.
90
91 The `redefined' slot of m1 will be set to point to h1. An old
92 instance will have its class pointer (the CAR of the heap header)
93 pointing to m1. The non-immediate `redefined'-slot in m1 indicates
94 the class modification and the new class pointer can be found via
95 h1.
96 */
97
98 #define TEST_CHANGE_CLASS(obj, class) \
99 { \
100 class = SCM_CLASS_OF (obj); \
101 if (scm_is_true (SCM_OBJ_CLASS_REDEF (obj))) \
102 { \
103 scm_change_object_class (obj, class, SCM_OBJ_CLASS_REDEF (obj));\
104 class = SCM_CLASS_OF (obj); \
105 } \
106 }
107
108 #define SCM_GOOPS_UNBOUND SCM_UNBOUND
109 #define SCM_GOOPS_UNBOUNDP(x) (scm_is_eq (x, SCM_GOOPS_UNBOUND))
110
111 static int goops_loaded_p = 0;
112 static scm_t_rstate *goops_rstate;
113
114 /* These variables are filled in by the object system when loaded. */
115 static SCM class_boolean, class_char, class_pair;
116 static SCM class_procedure, class_string, class_symbol;
117 static SCM class_primitive_generic;
118 static SCM class_vector, class_null;
119 static SCM class_integer, class_real, class_complex, class_fraction;
120 static SCM class_unknown;
121 static SCM class_top, class_object, class_class;
122 static SCM class_applicable;
123 static SCM class_applicable_struct, class_applicable_struct_with_setter;
124 static SCM class_generic, class_generic_with_setter;
125 static SCM class_accessor;
126 static SCM class_extended_generic, class_extended_generic_with_setter;
127 static SCM class_extended_accessor;
128 static SCM class_method;
129 static SCM class_accessor_method;
130 static SCM class_procedure_class;
131 static SCM class_applicable_struct_class;
132 static SCM class_applicable_struct_with_setter_class;
133 static SCM class_number, class_list;
134 static SCM class_keyword;
135 static SCM class_port, class_input_output_port;
136 static SCM class_input_port, class_output_port;
137 static SCM class_foreign_slot;
138 static SCM class_self, class_protected;
139 static SCM class_hidden, class_opaque, class_read_only;
140 static SCM class_protected_hidden, class_protected_opaque, class_protected_read_only;
141 static SCM class_scm;
142 static SCM class_int, class_float, class_double;
143
144 static SCM class_foreign;
145 static SCM class_hashtable;
146 static SCM class_fluid;
147 static SCM class_dynamic_state;
148 static SCM class_frame;
149 static SCM class_vm_cont;
150 static SCM class_bytevector;
151 static SCM class_uvec;
152 static SCM class_array;
153 static SCM class_bitvector;
154
155 static SCM vtable_class_map = SCM_BOOL_F;
156
157 /* Port classes. Allocate 3 times the maximum number of port types so that
158 input ports, output ports, and in/out ports can be stored at different
159 offsets. See `SCM_IN_PCLASS_INDEX' et al. */
160 SCM scm_i_port_class[3 * SCM_I_MAX_PORT_TYPE_COUNT];
161
162 /* SMOB classes. */
163 SCM scm_i_smob_class[SCM_I_MAX_SMOB_TYPE_COUNT];
164
165 static SCM scm_make_unbound (void);
166 static SCM scm_unbound_p (SCM obj);
167 static SCM scm_sys_bless_applicable_struct_vtables_x (SCM applicable,
168 SCM setter);
169 static SCM scm_sys_bless_pure_generic_vtable_x (SCM vtable);
170 static SCM scm_sys_make_root_class (SCM name, SCM dslots,
171 SCM getters_n_setters);
172 static SCM scm_sys_init_layout_x (SCM class, SCM layout);
173 static SCM scm_sys_goops_early_init (void);
174 static SCM scm_sys_goops_loaded (void);
175
176
177 /* This function is used for efficient type dispatch. */
178 SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0,
179 (SCM x),
180 "Return the class of @var{x}.")
181 #define FUNC_NAME s_scm_class_of
182 {
183 switch (SCM_ITAG3 (x))
184 {
185 case scm_tc3_int_1:
186 case scm_tc3_int_2:
187 return class_integer;
188
189 case scm_tc3_imm24:
190 if (SCM_CHARP (x))
191 return class_char;
192 else if (scm_is_bool (x))
193 return class_boolean;
194 else if (scm_is_null (x))
195 return class_null;
196 else
197 return class_unknown;
198
199 case scm_tc3_cons:
200 switch (SCM_TYP7 (x))
201 {
202 case scm_tcs_cons_nimcar:
203 return class_pair;
204 case scm_tc7_symbol:
205 return class_symbol;
206 case scm_tc7_vector:
207 case scm_tc7_wvect:
208 return class_vector;
209 case scm_tc7_pointer:
210 return class_foreign;
211 case scm_tc7_hashtable:
212 return class_hashtable;
213 case scm_tc7_fluid:
214 return class_fluid;
215 case scm_tc7_dynamic_state:
216 return class_dynamic_state;
217 case scm_tc7_frame:
218 return class_frame;
219 case scm_tc7_keyword:
220 return class_keyword;
221 case scm_tc7_vm_cont:
222 return class_vm_cont;
223 case scm_tc7_bytevector:
224 if (SCM_BYTEVECTOR_ELEMENT_TYPE (x) == SCM_ARRAY_ELEMENT_TYPE_VU8)
225 return class_bytevector;
226 else
227 return class_uvec;
228 case scm_tc7_array:
229 return class_array;
230 case scm_tc7_bitvector:
231 return class_bitvector;
232 case scm_tc7_string:
233 return class_string;
234 case scm_tc7_number:
235 switch SCM_TYP16 (x) {
236 case scm_tc16_big:
237 return class_integer;
238 case scm_tc16_real:
239 return class_real;
240 case scm_tc16_complex:
241 return class_complex;
242 case scm_tc16_fraction:
243 return class_fraction;
244 }
245 case scm_tc7_program:
246 if (SCM_PROGRAM_IS_PRIMITIVE_GENERIC (x)
247 && SCM_UNPACK (*SCM_SUBR_GENERIC (x)))
248 return class_primitive_generic;
249 else
250 return class_procedure;
251
252 case scm_tc7_smob:
253 {
254 scm_t_bits type = SCM_TYP16 (x);
255 if (type != scm_tc16_port_with_ps)
256 return scm_i_smob_class[SCM_TC2SMOBNUM (type)];
257 x = SCM_PORT_WITH_PS_PORT (x);
258 /* fall through to ports */
259 }
260 case scm_tc7_port:
261 return scm_i_port_class[(SCM_WRTNG & SCM_CELL_WORD_0 (x)
262 ? (SCM_RDNG & SCM_CELL_WORD_0 (x)
263 ? SCM_INOUT_PCLASS_INDEX | SCM_PTOBNUM (x)
264 : SCM_OUT_PCLASS_INDEX | SCM_PTOBNUM (x))
265 : SCM_IN_PCLASS_INDEX | SCM_PTOBNUM (x))];
266 case scm_tcs_struct:
267 if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS_VALID)
268 return SCM_CLASS_OF (x);
269 else if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS)
270 {
271 /* Goops object */
272 if (! scm_is_false (SCM_OBJ_CLASS_REDEF (x)))
273 scm_change_object_class (x,
274 SCM_CLASS_OF (x), /* old */
275 SCM_OBJ_CLASS_REDEF (x)); /* new */
276 return SCM_CLASS_OF (x);
277 }
278 else
279 return scm_i_define_class_for_vtable (SCM_CLASS_OF (x));
280 default:
281 if (scm_is_pair (x))
282 return class_pair;
283 else
284 return class_unknown;
285 }
286
287 case scm_tc3_struct:
288 case scm_tc3_tc7_1:
289 case scm_tc3_tc7_2:
290 /* case scm_tc3_unused: */
291 /* Never reached */
292 break;
293 }
294 return class_unknown;
295 }
296 #undef FUNC_NAME
297
298 /******************************************************************************
299 *
300 * initialize-object
301 *
302 ******************************************************************************/
303
304 /*fixme* Manufacture keywords in advance */
305 SCM
306 scm_i_get_keyword (SCM key, SCM l, long len, SCM default_value, const char *subr)
307 {
308 long i;
309
310 for (i = 0; i != len; i += 2)
311 {
312 SCM obj = SCM_CAR (l);
313
314 if (!scm_is_keyword (obj))
315 scm_misc_error (subr, "bad keyword: ~S", scm_list_1 (obj));
316 else if (scm_is_eq (obj, key))
317 return SCM_CADR (l);
318 else
319 l = SCM_CDDR (l);
320 }
321
322 return default_value;
323 }
324
325
326 SCM_DEFINE (scm_get_keyword, "get-keyword", 3, 0, 0,
327 (SCM key, SCM l, SCM default_value),
328 "Determine an associated value for the keyword @var{key} from\n"
329 "the list @var{l}. The list @var{l} has to consist of an even\n"
330 "number of elements, where, starting with the first, every\n"
331 "second element is a keyword, followed by its associated value.\n"
332 "If @var{l} does not hold a value for @var{key}, the value\n"
333 "@var{default_value} is returned.")
334 #define FUNC_NAME s_scm_get_keyword
335 {
336 long len;
337
338 SCM_ASSERT (scm_is_keyword (key), key, SCM_ARG1, FUNC_NAME);
339 len = scm_ilength (l);
340 if (len < 0 || len % 2 == 1)
341 scm_misc_error (FUNC_NAME, "Bad keyword-value list: ~S", scm_list_1 (l));
342
343 return scm_i_get_keyword (key, l, len, default_value, FUNC_NAME);
344 }
345 #undef FUNC_NAME
346
347
348 SCM_KEYWORD (k_init_keyword, "init-keyword");
349
350 static SCM get_slot_value (SCM class, SCM obj, SCM slotdef);
351 static SCM set_slot_value (SCM class, SCM obj, SCM slotdef, SCM value);
352
353 SCM_DEFINE (scm_sys_initialize_object, "%initialize-object", 2, 0, 0,
354 (SCM obj, SCM initargs),
355 "Initialize the object @var{obj} with the given arguments\n"
356 "@var{initargs}.")
357 #define FUNC_NAME s_scm_sys_initialize_object
358 {
359 SCM tmp, get_n_set, slots;
360 SCM class = SCM_CLASS_OF (obj);
361 long n_initargs;
362
363 SCM_VALIDATE_INSTANCE (1, obj);
364 n_initargs = scm_ilength (initargs);
365 SCM_ASSERT ((n_initargs & 1) == 0, initargs, SCM_ARG2, FUNC_NAME);
366
367 get_n_set = SCM_SLOT (class, scm_si_getters_n_setters);
368 slots = SCM_SLOT (class, scm_si_slots);
369
370 /* See for each slot how it must be initialized */
371 for (;
372 !scm_is_null (slots);
373 get_n_set = SCM_CDR (get_n_set), slots = SCM_CDR (slots))
374 {
375 SCM slot_name = SCM_CAR (slots);
376 SCM slot_value = SCM_GOOPS_UNBOUND;
377
378 if (!scm_is_null (SCM_CDR (slot_name)))
379 {
380 /* This slot admits (perhaps) to be initialized at creation time */
381 long n = scm_ilength (SCM_CDR (slot_name));
382 if (n & 1) /* odd or -1 */
383 SCM_MISC_ERROR ("class contains bogus slot definition: ~S",
384 scm_list_1 (slot_name));
385 tmp = scm_i_get_keyword (k_init_keyword,
386 SCM_CDR (slot_name),
387 n,
388 SCM_PACK (0),
389 FUNC_NAME);
390 slot_name = SCM_CAR (slot_name);
391 if (SCM_UNPACK (tmp))
392 {
393 /* an initarg was provided for this slot */
394 if (!scm_is_keyword (tmp))
395 SCM_MISC_ERROR ("initarg must be a keyword. It was ~S",
396 scm_list_1 (tmp));
397 slot_value = scm_i_get_keyword (tmp,
398 initargs,
399 n_initargs,
400 SCM_GOOPS_UNBOUND,
401 FUNC_NAME);
402 }
403 }
404
405 if (!SCM_GOOPS_UNBOUNDP (slot_value))
406 /* set slot to provided value */
407 set_slot_value (class, obj, SCM_CAR (get_n_set), slot_value);
408 else
409 {
410 /* set slot to its :init-form if it exists */
411 tmp = SCM_CADAR (get_n_set);
412 if (scm_is_true (tmp))
413 set_slot_value (class,
414 obj,
415 SCM_CAR (get_n_set),
416 scm_call_0 (tmp));
417 }
418 }
419
420 return obj;
421 }
422 #undef FUNC_NAME
423
424 SCM_DEFINE (scm_sys_init_layout_x, "%init-layout!", 2, 0, 0,
425 (SCM class, SCM layout),
426 "")
427 #define FUNC_NAME s_scm_sys_init_layout_x
428 {
429 SCM_VALIDATE_INSTANCE (1, class);
430 SCM_ASSERT (!scm_is_symbol (SCM_VTABLE_LAYOUT (class)), class, 1, FUNC_NAME);
431 SCM_VALIDATE_STRING (2, layout);
432
433 SCM_SET_VTABLE_LAYOUT (class, scm_make_struct_layout (layout));
434 return SCM_UNSPECIFIED;
435 }
436 #undef FUNC_NAME
437
438 SCM_DEFINE (scm_sys_inherit_magic_x, "%inherit-magic!", 2, 0, 0,
439 (SCM class, SCM dsupers),
440 "")
441 #define FUNC_NAME s_scm_sys_inherit_magic_x
442 {
443 SCM_VALIDATE_INSTANCE (1, class);
444 scm_i_struct_inherit_vtable_magic (SCM_CLASS_OF (class), class);
445 SCM_SET_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_OR_VALID);
446
447 return SCM_UNSPECIFIED;
448 }
449 #undef FUNC_NAME
450
451 /******************************************************************************/
452
453 SCM
454 scm_make_standard_class (SCM meta, SCM name, SCM dsupers, SCM dslots)
455 {
456 return scm_call_4 (scm_variable_ref (var_make_standard_class),
457 meta, name, dsupers, dslots);
458 }
459
460 /******************************************************************************/
461
462 SCM_DEFINE (scm_sys_make_root_class, "%make-root-class", 3, 0, 0,
463 (SCM name, SCM dslots, SCM getters_n_setters),
464 "")
465 #define FUNC_NAME s_scm_sys_make_root_class
466 {
467 SCM cs, z;
468
469 cs = scm_from_locale_string (SCM_CLASS_CLASS_LAYOUT);
470 z = scm_i_make_vtable_vtable (cs);
471 SCM_SET_CLASS_FLAGS (z, (SCM_CLASSF_GOOPS_OR_VALID
472 | SCM_CLASSF_METACLASS));
473
474 SCM_SET_SLOT (z, scm_vtable_index_name, name);
475 SCM_SET_SLOT (z, scm_si_direct_supers, SCM_EOL); /* will be changed */
476 SCM_SET_SLOT (z, scm_si_direct_slots, dslots); /* will be changed */
477 SCM_SET_SLOT (z, scm_si_direct_subclasses, SCM_EOL);
478 SCM_SET_SLOT (z, scm_si_direct_methods, SCM_EOL);
479 SCM_SET_SLOT (z, scm_si_cpl, SCM_EOL); /* will be changed */
480 SCM_SET_SLOT (z, scm_si_slots, dslots); /* will be changed */
481 SCM_SET_SLOT (z, scm_si_nfields, scm_from_int (SCM_N_CLASS_SLOTS));
482 SCM_SET_SLOT (z, scm_si_getters_n_setters, getters_n_setters); /* will be changed */
483 SCM_SET_SLOT (z, scm_si_redefined, SCM_BOOL_F);
484
485 return z;
486 }
487 #undef FUNC_NAME
488
489 /******************************************************************************/
490
491 SCM_DEFINE (scm_instance_p, "instance?", 1, 0, 0,
492 (SCM obj),
493 "Return @code{#t} if @var{obj} is an instance.")
494 #define FUNC_NAME s_scm_instance_p
495 {
496 return scm_from_bool (SCM_INSTANCEP (obj));
497 }
498 #undef FUNC_NAME
499
500 int
501 scm_is_generic (SCM x)
502 {
503 return SCM_INSTANCEP (x) && SCM_SUBCLASSP (SCM_CLASS_OF (x), class_generic);
504 }
505
506 int
507 scm_is_method (SCM x)
508 {
509 return SCM_INSTANCEP (x) && SCM_SUBCLASSP (SCM_CLASS_OF (x), class_method);
510 }
511
512 /******************************************************************************
513 *
514 * Meta object accessors
515 *
516 ******************************************************************************/
517
518 SCM_SYMBOL (sym_procedure, "procedure");
519 SCM_SYMBOL (sym_direct_supers, "direct-supers");
520 SCM_SYMBOL (sym_direct_slots, "direct-slots");
521 SCM_SYMBOL (sym_direct_subclasses, "direct-subclasses");
522 SCM_SYMBOL (sym_direct_methods, "direct-methods");
523 SCM_SYMBOL (sym_cpl, "cpl");
524 SCM_SYMBOL (sym_slots, "slots");
525
526 SCM_DEFINE (scm_class_name, "class-name", 1, 0, 0,
527 (SCM obj),
528 "Return the class name of @var{obj}.")
529 #define FUNC_NAME s_scm_class_name
530 {
531 SCM_VALIDATE_CLASS (1, obj);
532 return scm_slot_ref (obj, scm_sym_name);
533 }
534 #undef FUNC_NAME
535
536 SCM_DEFINE (scm_class_direct_supers, "class-direct-supers", 1, 0, 0,
537 (SCM obj),
538 "Return the direct superclasses of the class @var{obj}.")
539 #define FUNC_NAME s_scm_class_direct_supers
540 {
541 SCM_VALIDATE_CLASS (1, obj);
542 return scm_slot_ref (obj, sym_direct_supers);
543 }
544 #undef FUNC_NAME
545
546 SCM_DEFINE (scm_class_direct_slots, "class-direct-slots", 1, 0, 0,
547 (SCM obj),
548 "Return the direct slots of the class @var{obj}.")
549 #define FUNC_NAME s_scm_class_direct_slots
550 {
551 SCM_VALIDATE_CLASS (1, obj);
552 return scm_slot_ref (obj, sym_direct_slots);
553 }
554 #undef FUNC_NAME
555
556 SCM_DEFINE (scm_class_direct_subclasses, "class-direct-subclasses", 1, 0, 0,
557 (SCM obj),
558 "Return the direct subclasses of the class @var{obj}.")
559 #define FUNC_NAME s_scm_class_direct_subclasses
560 {
561 SCM_VALIDATE_CLASS (1, obj);
562 return scm_slot_ref(obj, sym_direct_subclasses);
563 }
564 #undef FUNC_NAME
565
566 SCM_DEFINE (scm_class_direct_methods, "class-direct-methods", 1, 0, 0,
567 (SCM obj),
568 "Return the direct methods of the class @var{obj}")
569 #define FUNC_NAME s_scm_class_direct_methods
570 {
571 SCM_VALIDATE_CLASS (1, obj);
572 return scm_slot_ref (obj, sym_direct_methods);
573 }
574 #undef FUNC_NAME
575
576 SCM_DEFINE (scm_class_precedence_list, "class-precedence-list", 1, 0, 0,
577 (SCM obj),
578 "Return the class precedence list of the class @var{obj}.")
579 #define FUNC_NAME s_scm_class_precedence_list
580 {
581 SCM_VALIDATE_CLASS (1, obj);
582 return scm_slot_ref (obj, sym_cpl);
583 }
584 #undef FUNC_NAME
585
586 SCM_DEFINE (scm_class_slots, "class-slots", 1, 0, 0,
587 (SCM obj),
588 "Return the slot list of the class @var{obj}.")
589 #define FUNC_NAME s_scm_class_slots
590 {
591 SCM_VALIDATE_CLASS (1, obj);
592 return scm_slot_ref (obj, sym_slots);
593 }
594 #undef FUNC_NAME
595
596 SCM_DEFINE (scm_generic_function_name, "generic-function-name", 1, 0, 0,
597 (SCM obj),
598 "Return the name of the generic function @var{obj}.")
599 #define FUNC_NAME s_scm_generic_function_name
600 {
601 SCM_VALIDATE_GENERIC (1, obj);
602 return scm_procedure_property (obj, scm_sym_name);
603 }
604 #undef FUNC_NAME
605
606 SCM_SYMBOL (sym_methods, "methods");
607 SCM_SYMBOL (sym_extended_by, "extended-by");
608 SCM_SYMBOL (sym_extends, "extends");
609
610 static
611 SCM fold_downward_gf_methods (SCM method_lists, SCM gf)
612 {
613 SCM gfs = scm_slot_ref (gf, sym_extended_by);
614 method_lists = scm_cons (scm_slot_ref (gf, sym_methods), method_lists);
615 while (!scm_is_null (gfs))
616 {
617 method_lists = fold_downward_gf_methods (method_lists, SCM_CAR (gfs));
618 gfs = SCM_CDR (gfs);
619 }
620 return method_lists;
621 }
622
623 static
624 SCM fold_upward_gf_methods (SCM method_lists, SCM gf)
625 {
626 if (SCM_IS_A_P (gf, class_extended_generic))
627 {
628 SCM gfs = scm_slot_ref (gf, sym_extends);
629 while (!scm_is_null (gfs))
630 {
631 SCM methods = scm_slot_ref (SCM_CAR (gfs), sym_methods);
632 method_lists = fold_upward_gf_methods (scm_cons (methods,
633 method_lists),
634 SCM_CAR (gfs));
635 gfs = SCM_CDR (gfs);
636 }
637 }
638 return method_lists;
639 }
640
641 SCM_DEFINE (scm_generic_function_methods, "generic-function-methods", 1, 0, 0,
642 (SCM obj),
643 "Return the methods of the generic function @var{obj}.")
644 #define FUNC_NAME s_scm_generic_function_methods
645 {
646 SCM methods;
647 SCM_VALIDATE_GENERIC (1, obj);
648 methods = fold_upward_gf_methods (SCM_EOL, obj);
649 methods = fold_downward_gf_methods (methods, obj);
650 return scm_append (methods);
651 }
652 #undef FUNC_NAME
653
654 SCM_DEFINE (scm_method_generic_function, "method-generic-function", 1, 0, 0,
655 (SCM obj),
656 "Return the generic function for the method @var{obj}.")
657 #define FUNC_NAME s_scm_method_generic_function
658 {
659 SCM_VALIDATE_METHOD (1, obj);
660 return scm_slot_ref (obj, scm_from_latin1_symbol ("generic-function"));
661 }
662 #undef FUNC_NAME
663
664 SCM_DEFINE (scm_method_specializers, "method-specializers", 1, 0, 0,
665 (SCM obj),
666 "Return specializers of the method @var{obj}.")
667 #define FUNC_NAME s_scm_method_specializers
668 {
669 SCM_VALIDATE_METHOD (1, obj);
670 return scm_slot_ref (obj, scm_from_latin1_symbol ("specializers"));
671 }
672 #undef FUNC_NAME
673
674 SCM_DEFINE (scm_method_procedure, "method-procedure", 1, 0, 0,
675 (SCM obj),
676 "Return the procedure of the method @var{obj}.")
677 #define FUNC_NAME s_scm_method_procedure
678 {
679 SCM_VALIDATE_METHOD (1, obj);
680 return scm_slot_ref (obj, sym_procedure);
681 }
682 #undef FUNC_NAME
683
684 /******************************************************************************
685 *
686 * S l o t a c c e s s
687 *
688 ******************************************************************************/
689
690 SCM_DEFINE (scm_make_unbound, "make-unbound", 0, 0, 0,
691 (),
692 "Return the unbound value.")
693 #define FUNC_NAME s_scm_make_unbound
694 {
695 return SCM_GOOPS_UNBOUND;
696 }
697 #undef FUNC_NAME
698
699 SCM_DEFINE (scm_unbound_p, "unbound?", 1, 0, 0,
700 (SCM obj),
701 "Return @code{#t} if @var{obj} is unbound.")
702 #define FUNC_NAME s_scm_unbound_p
703 {
704 return SCM_GOOPS_UNBOUNDP (obj) ? SCM_BOOL_T : SCM_BOOL_F;
705 }
706 #undef FUNC_NAME
707
708
709 \f
710 /** Utilities **/
711
712 /* In the future, this function will return the effective slot
713 * definition associated with SLOT_NAME. Now it just returns some of
714 * the information which will be stored in the effective slot
715 * definition.
716 */
717
718 static SCM
719 slot_definition_using_name (SCM class, SCM slot_name)
720 {
721 register SCM slots = SCM_SLOT (class, scm_si_getters_n_setters);
722 for (; !scm_is_null (slots); slots = SCM_CDR (slots))
723 if (scm_is_eq (SCM_CAAR (slots), slot_name))
724 return SCM_CAR (slots);
725 return SCM_BOOL_F;
726 }
727
728 static SCM
729 get_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef)
730 #define FUNC_NAME "%get-slot-value"
731 {
732 SCM access = SCM_CDDR (slotdef);
733 /* Two cases here:
734 * - access is an integer (the offset of this slot in the slots vector)
735 * - otherwise (car access) is the getter function to apply
736 *
737 * Instances have never more than SCM_MOST_POSITIVE_FIXNUM slots, so
738 * we can just assume fixnums here.
739 */
740 if (SCM_I_INUMP (access))
741 /* Don't poke at the slots directly, because scm_struct_ref handles the
742 access bits for us. */
743 return scm_struct_ref (obj, access);
744 else
745 return scm_call_1 (SCM_CAR (access), obj);
746 }
747 #undef FUNC_NAME
748
749 static SCM
750 get_slot_value_using_name (SCM class, SCM obj, SCM slot_name)
751 {
752 SCM slotdef = slot_definition_using_name (class, slot_name);
753 if (scm_is_true (slotdef))
754 return get_slot_value (class, obj, slotdef);
755 else
756 return scm_call_3 (SCM_VARIABLE_REF (var_slot_missing), class, obj, slot_name);
757 }
758
759 static SCM
760 set_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef, SCM value)
761 #define FUNC_NAME "%set-slot-value"
762 {
763 SCM access = SCM_CDDR (slotdef);
764 /* Two cases here:
765 * - access is an integer (the offset of this slot in the slots vector)
766 * - otherwise (cadr access) is the setter function to apply
767 *
768 * Instances have never more than SCM_MOST_POSITIVE_FIXNUM slots, so
769 * we can just assume fixnums here.
770 */
771 if (SCM_I_INUMP (access))
772 /* obey permissions bits via going through struct-set! */
773 scm_struct_set_x (obj, access, value);
774 else
775 /* ((cadr l) obj value) */
776 scm_call_2 (SCM_CADR (access), obj, value);
777 return SCM_UNSPECIFIED;
778 }
779 #undef FUNC_NAME
780
781 static SCM
782 set_slot_value_using_name (SCM class, SCM obj, SCM slot_name, SCM value)
783 {
784 SCM slotdef = slot_definition_using_name (class, slot_name);
785 if (scm_is_true (slotdef))
786 return set_slot_value (class, obj, slotdef, value);
787 else
788 return scm_call_4 (SCM_VARIABLE_REF (var_slot_missing), class, obj, slot_name, value);
789 }
790
791 static SCM
792 test_slot_existence (SCM class SCM_UNUSED, SCM obj, SCM slot_name)
793 {
794 register SCM l;
795
796 for (l = SCM_ACCESSORS_OF (obj); !scm_is_null (l); l = SCM_CDR (l))
797 if (scm_is_eq (SCM_CAAR (l), slot_name))
798 return SCM_BOOL_T;
799
800 return SCM_BOOL_F;
801 }
802
803 /* ======================================== */
804
805 SCM_DEFINE (scm_slot_ref_using_class, "slot-ref-using-class", 3, 0, 0,
806 (SCM class, SCM obj, SCM slot_name),
807 "")
808 #define FUNC_NAME s_scm_slot_ref_using_class
809 {
810 SCM res;
811
812 SCM_VALIDATE_CLASS (1, class);
813 SCM_VALIDATE_INSTANCE (2, obj);
814 SCM_VALIDATE_SYMBOL (3, slot_name);
815
816 res = get_slot_value_using_name (class, obj, slot_name);
817 if (SCM_GOOPS_UNBOUNDP (res))
818 return scm_call_3 (SCM_VARIABLE_REF (var_slot_unbound), class, obj, slot_name);
819 return res;
820 }
821 #undef FUNC_NAME
822
823
824 SCM_DEFINE (scm_slot_set_using_class_x, "slot-set-using-class!", 4, 0, 0,
825 (SCM class, SCM obj, SCM slot_name, SCM value),
826 "")
827 #define FUNC_NAME s_scm_slot_set_using_class_x
828 {
829 SCM_VALIDATE_CLASS (1, class);
830 SCM_VALIDATE_INSTANCE (2, obj);
831 SCM_VALIDATE_SYMBOL (3, slot_name);
832
833 return set_slot_value_using_name (class, obj, slot_name, value);
834 }
835 #undef FUNC_NAME
836
837
838 SCM_DEFINE (scm_slot_bound_using_class_p, "slot-bound-using-class?", 3, 0, 0,
839 (SCM class, SCM obj, SCM slot_name),
840 "")
841 #define FUNC_NAME s_scm_slot_bound_using_class_p
842 {
843 SCM_VALIDATE_CLASS (1, class);
844 SCM_VALIDATE_INSTANCE (2, obj);
845 SCM_VALIDATE_SYMBOL (3, slot_name);
846
847 return (SCM_GOOPS_UNBOUNDP (get_slot_value_using_name (class, obj, slot_name))
848 ? SCM_BOOL_F
849 : SCM_BOOL_T);
850 }
851 #undef FUNC_NAME
852
853 SCM_DEFINE (scm_slot_exists_using_class_p, "slot-exists-using-class?", 3, 0, 0,
854 (SCM class, SCM obj, SCM slot_name),
855 "")
856 #define FUNC_NAME s_scm_slot_exists_using_class_p
857 {
858 SCM_VALIDATE_CLASS (1, class);
859 SCM_VALIDATE_INSTANCE (2, obj);
860 SCM_VALIDATE_SYMBOL (3, slot_name);
861 return test_slot_existence (class, obj, slot_name);
862 }
863 #undef FUNC_NAME
864
865
866 /* ======================================== */
867
868 SCM_DEFINE (scm_slot_ref, "slot-ref", 2, 0, 0,
869 (SCM obj, SCM slot_name),
870 "Return the value from @var{obj}'s slot with the name\n"
871 "@var{slot_name}.")
872 #define FUNC_NAME s_scm_slot_ref
873 {
874 SCM res, class;
875
876 SCM_VALIDATE_INSTANCE (1, obj);
877 TEST_CHANGE_CLASS (obj, class);
878
879 res = get_slot_value_using_name (class, obj, slot_name);
880 if (SCM_GOOPS_UNBOUNDP (res))
881 return scm_call_3 (SCM_VARIABLE_REF (var_slot_unbound), class, obj, slot_name);
882 return res;
883 }
884 #undef FUNC_NAME
885
886 SCM_DEFINE (scm_slot_set_x, "slot-set!", 3, 0, 0,
887 (SCM obj, SCM slot_name, SCM value),
888 "Set the slot named @var{slot_name} of @var{obj} to @var{value}.")
889 #define FUNC_NAME s_scm_slot_set_x
890 {
891 SCM class;
892
893 SCM_VALIDATE_INSTANCE (1, obj);
894 TEST_CHANGE_CLASS(obj, class);
895
896 return set_slot_value_using_name (class, obj, slot_name, value);
897 }
898 #undef FUNC_NAME
899
900 SCM_DEFINE (scm_slot_bound_p, "slot-bound?", 2, 0, 0,
901 (SCM obj, SCM slot_name),
902 "Return @code{#t} if the slot named @var{slot_name} of @var{obj}\n"
903 "is bound.")
904 #define FUNC_NAME s_scm_slot_bound_p
905 {
906 SCM class;
907
908 SCM_VALIDATE_INSTANCE (1, obj);
909 TEST_CHANGE_CLASS(obj, class);
910
911 return (SCM_GOOPS_UNBOUNDP (get_slot_value_using_name (class,
912 obj,
913 slot_name))
914 ? SCM_BOOL_F
915 : SCM_BOOL_T);
916 }
917 #undef FUNC_NAME
918
919 SCM_DEFINE (scm_slot_exists_p, "slot-exists?", 2, 0, 0,
920 (SCM obj, SCM slot_name),
921 "Return @code{#t} if @var{obj} has a slot named @var{slot_name}.")
922 #define FUNC_NAME s_scm_slot_exists_p
923 {
924 SCM class;
925
926 SCM_VALIDATE_INSTANCE (1, obj);
927 SCM_VALIDATE_SYMBOL (2, slot_name);
928 TEST_CHANGE_CLASS (obj, class);
929
930 return test_slot_existence (class, obj, slot_name);
931 }
932 #undef FUNC_NAME
933
934
935 /******************************************************************************
936 *
937 * %allocate-instance (the low level instance allocation primitive)
938 *
939 ******************************************************************************/
940
941 SCM_DEFINE (scm_sys_allocate_instance, "%allocate-instance", 2, 0, 0,
942 (SCM class, SCM initargs),
943 "Create a new instance of class @var{class} and initialize it\n"
944 "from the arguments @var{initargs}.")
945 #define FUNC_NAME s_scm_sys_allocate_instance
946 {
947 SCM obj;
948 scm_t_signed_bits n, i;
949 SCM layout;
950
951 SCM_VALIDATE_CLASS (1, class);
952
953 /* FIXME: duplicates some of scm_make_struct. */
954
955 n = SCM_I_INUM (SCM_SLOT (class, scm_si_nfields));
956 obj = scm_i_alloc_struct (SCM_STRUCT_DATA (class), n);
957
958 layout = SCM_VTABLE_LAYOUT (class);
959
960 /* Set all SCM-holding slots to unbound */
961 for (i = 0; i < n; i++)
962 {
963 scm_t_wchar c = scm_i_symbol_ref (layout, i*2);
964 if (c == 'p')
965 SCM_STRUCT_DATA (obj)[i] = SCM_UNPACK (SCM_GOOPS_UNBOUND);
966 else if (c == 's')
967 SCM_STRUCT_DATA (obj)[i] = SCM_UNPACK (obj);
968 else
969 SCM_STRUCT_DATA (obj)[i] = 0;
970 }
971
972 return obj;
973 }
974 #undef FUNC_NAME
975
976 /******************************************************************************
977 *
978 * %modify-instance (used by change-class to modify in place)
979 *
980 ******************************************************************************/
981
982 SCM_DEFINE (scm_sys_modify_instance, "%modify-instance", 2, 0, 0,
983 (SCM old, SCM new),
984 "")
985 #define FUNC_NAME s_scm_sys_modify_instance
986 {
987 SCM_VALIDATE_INSTANCE (1, old);
988 SCM_VALIDATE_INSTANCE (2, new);
989
990 /* Exchange the data contained in old and new. We exchange rather than
991 * scratch the old value with new to be correct with GC.
992 * See "Class redefinition protocol above".
993 */
994 SCM_CRITICAL_SECTION_START;
995 {
996 scm_t_bits word0, word1;
997 word0 = SCM_CELL_WORD_0 (old);
998 word1 = SCM_CELL_WORD_1 (old);
999 SCM_SET_CELL_WORD_0 (old, SCM_CELL_WORD_0 (new));
1000 SCM_SET_CELL_WORD_1 (old, SCM_CELL_WORD_1 (new));
1001 SCM_SET_CELL_WORD_0 (new, word0);
1002 SCM_SET_CELL_WORD_1 (new, word1);
1003 }
1004 SCM_CRITICAL_SECTION_END;
1005 return SCM_UNSPECIFIED;
1006 }
1007 #undef FUNC_NAME
1008
1009 SCM_DEFINE (scm_sys_modify_class, "%modify-class", 2, 0, 0,
1010 (SCM old, SCM new),
1011 "")
1012 #define FUNC_NAME s_scm_sys_modify_class
1013 {
1014 SCM_VALIDATE_CLASS (1, old);
1015 SCM_VALIDATE_CLASS (2, new);
1016
1017 SCM_CRITICAL_SECTION_START;
1018 {
1019 scm_t_bits word0, word1;
1020 word0 = SCM_CELL_WORD_0 (old);
1021 word1 = SCM_CELL_WORD_1 (old);
1022 SCM_SET_CELL_WORD_0 (old, SCM_CELL_WORD_0 (new));
1023 SCM_SET_CELL_WORD_1 (old, SCM_CELL_WORD_1 (new));
1024 SCM_STRUCT_DATA (old)[scm_vtable_index_self] = SCM_UNPACK (old);
1025 SCM_SET_CELL_WORD_0 (new, word0);
1026 SCM_SET_CELL_WORD_1 (new, word1);
1027 SCM_STRUCT_DATA (new)[scm_vtable_index_self] = SCM_UNPACK (new);
1028 }
1029 SCM_CRITICAL_SECTION_END;
1030 return SCM_UNSPECIFIED;
1031 }
1032 #undef FUNC_NAME
1033
1034 SCM_DEFINE (scm_sys_invalidate_class, "%invalidate-class", 1, 0, 0,
1035 (SCM class),
1036 "")
1037 #define FUNC_NAME s_scm_sys_invalidate_class
1038 {
1039 SCM_VALIDATE_CLASS (1, class);
1040 SCM_CLEAR_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_VALID);
1041 return SCM_UNSPECIFIED;
1042 }
1043 #undef FUNC_NAME
1044
1045 /* When instances change class, they finally get a new body, but
1046 * before that, they go through purgatory in hell. Odd as it may
1047 * seem, this data structure saves us from eternal suffering in
1048 * infinite recursions.
1049 */
1050
1051 static scm_t_bits **hell;
1052 static long n_hell = 1; /* one place for the evil one himself */
1053 static long hell_size = 4;
1054 static SCM hell_mutex;
1055
1056 static long
1057 burnin (SCM o)
1058 {
1059 long i;
1060 for (i = 1; i < n_hell; ++i)
1061 if (SCM_STRUCT_DATA (o) == hell[i])
1062 return i;
1063 return 0;
1064 }
1065
1066 static void
1067 go_to_hell (void *o)
1068 {
1069 SCM obj = *(SCM*)o;
1070 scm_lock_mutex (hell_mutex);
1071 if (n_hell >= hell_size)
1072 {
1073 hell_size *= 2;
1074 hell = scm_realloc (hell, hell_size * sizeof(*hell));
1075 }
1076 hell[n_hell++] = SCM_STRUCT_DATA (obj);
1077 scm_unlock_mutex (hell_mutex);
1078 }
1079
1080 static void
1081 go_to_heaven (void *o)
1082 {
1083 SCM obj = *(SCM*)o;
1084 scm_lock_mutex (hell_mutex);
1085 hell[burnin (obj)] = hell[--n_hell];
1086 scm_unlock_mutex (hell_mutex);
1087 }
1088
1089
1090 SCM_SYMBOL (scm_sym_change_class, "change-class");
1091
1092 static SCM
1093 purgatory (SCM obj, SCM new_class)
1094 {
1095 return scm_call_2 (SCM_VARIABLE_REF (var_change_class), obj, new_class);
1096 }
1097
1098 /* This function calls the generic function change-class for all
1099 * instances which aren't currently undergoing class change.
1100 */
1101
1102 void
1103 scm_change_object_class (SCM obj, SCM old_class SCM_UNUSED, SCM new_class)
1104 {
1105 if (!burnin (obj))
1106 {
1107 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
1108 scm_dynwind_rewind_handler (go_to_hell, &obj, SCM_F_WIND_EXPLICITLY);
1109 scm_dynwind_unwind_handler (go_to_heaven, &obj, SCM_F_WIND_EXPLICITLY);
1110 purgatory (obj, new_class);
1111 scm_dynwind_end ();
1112 }
1113 }
1114
1115 /******************************************************************************
1116 *
1117 * GGGG FFFFF
1118 * G F
1119 * G GG FFF
1120 * G G F
1121 * GGG E N E R I C F U N C T I O N S
1122 *
1123 * This implementation provides
1124 * - generic functions (with class specializers)
1125 * - multi-methods
1126 * - next-method
1127 * - a hard-coded MOP for standard gf, which can be overloaded for non-std gf
1128 *
1129 ******************************************************************************/
1130
1131 SCM_KEYWORD (k_name, "name");
1132 SCM_GLOBAL_SYMBOL (scm_sym_args, "args");
1133
1134 SCM_DEFINE (scm_generic_capability_p, "generic-capability?", 1, 0, 0,
1135 (SCM proc),
1136 "")
1137 #define FUNC_NAME s_scm_generic_capability_p
1138 {
1139 SCM_ASSERT (scm_is_true (scm_procedure_p (proc)),
1140 proc, SCM_ARG1, FUNC_NAME);
1141 return (SCM_PRIMITIVE_GENERIC_P (proc) ? SCM_BOOL_T : SCM_BOOL_F);
1142 }
1143 #undef FUNC_NAME
1144
1145 SCM_DEFINE (scm_enable_primitive_generic_x, "enable-primitive-generic!", 0, 0, 1,
1146 (SCM subrs),
1147 "")
1148 #define FUNC_NAME s_scm_enable_primitive_generic_x
1149 {
1150 SCM_VALIDATE_REST_ARGUMENT (subrs);
1151 while (!scm_is_null (subrs))
1152 {
1153 SCM subr = SCM_CAR (subrs);
1154 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARGn, FUNC_NAME);
1155 SCM_SET_SUBR_GENERIC (subr,
1156 scm_make (scm_list_3 (class_generic,
1157 k_name,
1158 SCM_SUBR_NAME (subr))));
1159 subrs = SCM_CDR (subrs);
1160 }
1161 return SCM_UNSPECIFIED;
1162 }
1163 #undef FUNC_NAME
1164
1165 SCM_DEFINE (scm_set_primitive_generic_x, "set-primitive-generic!", 2, 0, 0,
1166 (SCM subr, SCM generic),
1167 "")
1168 #define FUNC_NAME s_scm_set_primitive_generic_x
1169 {
1170 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARG1, FUNC_NAME);
1171 SCM_ASSERT (SCM_PUREGENERICP (generic), generic, SCM_ARG2, FUNC_NAME);
1172 SCM_SET_SUBR_GENERIC (subr, generic);
1173 return SCM_UNSPECIFIED;
1174 }
1175 #undef FUNC_NAME
1176
1177 SCM_DEFINE (scm_primitive_generic_generic, "primitive-generic-generic", 1, 0, 0,
1178 (SCM subr),
1179 "")
1180 #define FUNC_NAME s_scm_primitive_generic_generic
1181 {
1182 if (SCM_PRIMITIVE_GENERIC_P (subr))
1183 {
1184 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (subr)))
1185 scm_enable_primitive_generic_x (scm_list_1 (subr));
1186 return *SCM_SUBR_GENERIC (subr);
1187 }
1188 SCM_WRONG_TYPE_ARG (SCM_ARG1, subr);
1189 }
1190 #undef FUNC_NAME
1191
1192 typedef struct t_extension {
1193 struct t_extension *next;
1194 SCM extended;
1195 SCM extension;
1196 } t_extension;
1197
1198
1199 /* Hint for `scm_gc_malloc ()' et al. when allocating `t_extension'
1200 objects. */
1201 static const char extension_gc_hint[] = "GOOPS extension";
1202
1203 static t_extension *extensions = 0;
1204
1205 void
1206 scm_c_extend_primitive_generic (SCM extended, SCM extension)
1207 {
1208 if (goops_loaded_p)
1209 {
1210 SCM gf, gext;
1211 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (extended)))
1212 scm_enable_primitive_generic_x (scm_list_1 (extended));
1213 gf = *SCM_SUBR_GENERIC (extended);
1214 gext = scm_call_2 (SCM_VARIABLE_REF (scm_var_make_extended_generic),
1215 gf,
1216 SCM_SUBR_NAME (extension));
1217 SCM_SET_SUBR_GENERIC (extension, gext);
1218 }
1219 else
1220 {
1221 t_extension *e = scm_gc_malloc (sizeof (t_extension),
1222 extension_gc_hint);
1223 t_extension **loc = &extensions;
1224 /* Make sure that extensions are placed before their own
1225 * extensions in the extensions list. O(N^2) algorithm, but
1226 * extensions of primitive generics are rare.
1227 */
1228 while (*loc && !scm_is_eq (extension, (*loc)->extended))
1229 loc = &(*loc)->next;
1230 e->next = *loc;
1231 e->extended = extended;
1232 e->extension = extension;
1233 *loc = e;
1234 }
1235 }
1236
1237 static void
1238 setup_extended_primitive_generics ()
1239 {
1240 while (extensions)
1241 {
1242 t_extension *e = extensions;
1243 scm_c_extend_primitive_generic (e->extended, e->extension);
1244 extensions = e->next;
1245 }
1246 }
1247
1248 /* Dirk:FIXME:: In all of these scm_wta_dispatch_* routines it is
1249 * assumed that 'gf' is zero if uninitialized. It would be cleaner if
1250 * some valid SCM value like SCM_BOOL_F or SCM_UNDEFINED were chosen.
1251 */
1252
1253 SCM
1254 scm_wta_dispatch_0 (SCM gf, const char *subr)
1255 {
1256 if (!SCM_UNPACK (gf))
1257 scm_error_num_args_subr (subr);
1258
1259 return scm_call_0 (gf);
1260 }
1261
1262 SCM
1263 scm_wta_dispatch_1 (SCM gf, SCM a1, int pos, const char *subr)
1264 {
1265 if (!SCM_UNPACK (gf))
1266 scm_wrong_type_arg (subr, pos, a1);
1267
1268 return scm_call_1 (gf, a1);
1269 }
1270
1271 SCM
1272 scm_wta_dispatch_2 (SCM gf, SCM a1, SCM a2, int pos, const char *subr)
1273 {
1274 if (!SCM_UNPACK (gf))
1275 scm_wrong_type_arg (subr, pos, (pos == SCM_ARG1) ? a1 : a2);
1276
1277 return scm_call_2 (gf, a1, a2);
1278 }
1279
1280 SCM
1281 scm_wta_dispatch_n (SCM gf, SCM args, int pos, const char *subr)
1282 {
1283 if (!SCM_UNPACK (gf))
1284 scm_wrong_type_arg (subr, pos, scm_list_ref (args, scm_from_int (pos)));
1285
1286 return scm_apply_0 (gf, args);
1287 }
1288
1289 /******************************************************************************
1290 *
1291 * Protocol for calling a generic fumction
1292 * This protocol is roughly equivalent to (parameter are a little bit different
1293 * for efficiency reasons):
1294 *
1295 * + apply-generic (gf args)
1296 * + compute-applicable-methods (gf args ...)
1297 * + sort-applicable-methods (methods args)
1298 * + apply-methods (gf methods args)
1299 *
1300 * apply-methods calls make-next-method to build the "continuation" of a a
1301 * method. Applying a next-method will call apply-next-method which in
1302 * turn will call apply again to call effectively the following method.
1303 *
1304 ******************************************************************************/
1305
1306 SCM_DEFINE (scm_make, "make", 0, 0, 1,
1307 (SCM args),
1308 "Make a new object. @var{args} must contain the class and\n"
1309 "all necessary initialization information.")
1310 #define FUNC_NAME s_scm_make
1311 {
1312 return scm_apply_0 (scm_variable_ref (var_make), args);
1313 }
1314 #undef FUNC_NAME
1315
1316
1317 /**********************************************************************
1318 *
1319 * Smob classes
1320 *
1321 **********************************************************************/
1322
1323 static SCM
1324 make_class_name (const char *prefix, const char *type_name, const char *suffix)
1325 {
1326 if (!type_name)
1327 type_name = "";
1328 return scm_string_to_symbol (scm_string_append
1329 (scm_list_3 (scm_from_utf8_string (prefix),
1330 scm_from_utf8_string (type_name),
1331 scm_from_utf8_string (suffix))));
1332 }
1333
1334 SCM
1335 scm_make_extended_class (char const *type_name, int applicablep)
1336 {
1337 SCM name, meta, supers;
1338
1339 name = make_class_name ("<", type_name, ">");
1340 meta = class_class;
1341
1342 if (applicablep)
1343 supers = scm_list_1 (class_applicable);
1344 else
1345 supers = scm_list_1 (class_top);
1346
1347 return scm_make_standard_class (meta, name, supers, SCM_EOL);
1348 }
1349
1350 void
1351 scm_i_inherit_applicable (SCM c)
1352 {
1353 if (!SCM_SUBCLASSP (c, class_applicable))
1354 {
1355 SCM dsupers = SCM_SLOT (c, scm_si_direct_supers);
1356 SCM cpl = SCM_SLOT (c, scm_si_cpl);
1357 /* patch class_applicable into direct-supers */
1358 SCM top = scm_c_memq (class_top, dsupers);
1359 if (scm_is_false (top))
1360 dsupers = scm_append (scm_list_2 (dsupers,
1361 scm_list_1 (class_applicable)));
1362 else
1363 {
1364 SCM_SETCAR (top, class_applicable);
1365 SCM_SETCDR (top, scm_cons (class_top, SCM_CDR (top)));
1366 }
1367 SCM_SET_SLOT (c, scm_si_direct_supers, dsupers);
1368 /* patch class_applicable into cpl */
1369 top = scm_c_memq (class_top, cpl);
1370 if (scm_is_false (top))
1371 abort ();
1372 else
1373 {
1374 SCM_SETCAR (top, class_applicable);
1375 SCM_SETCDR (top, scm_cons (class_top, SCM_CDR (top)));
1376 }
1377 /* add class to direct-subclasses of class_applicable */
1378 SCM_SET_SLOT (class_applicable,
1379 scm_si_direct_subclasses,
1380 scm_cons (c, SCM_SLOT (class_applicable,
1381 scm_si_direct_subclasses)));
1382 }
1383 }
1384
1385 static void
1386 create_smob_classes (void)
1387 {
1388 long i;
1389
1390 for (i = 0; i < SCM_I_MAX_SMOB_TYPE_COUNT; ++i)
1391 scm_i_smob_class[i] = SCM_BOOL_F;
1392
1393 for (i = 0; i < scm_numsmob; ++i)
1394 if (scm_is_false (scm_i_smob_class[i]))
1395 scm_i_smob_class[i] = scm_make_extended_class (SCM_SMOBNAME (i),
1396 scm_smobs[i].apply != 0);
1397 }
1398
1399 void
1400 scm_make_port_classes (long ptobnum, char *type_name)
1401 {
1402 SCM name, meta, super, supers;
1403
1404 meta = class_class;
1405
1406 name = make_class_name ("<", type_name, "-port>");
1407 supers = scm_list_1 (class_port);
1408 super = scm_make_standard_class (meta, name, supers, SCM_EOL);
1409
1410 name = make_class_name ("<", type_name, "-input-port>");
1411 supers = scm_list_2 (super, class_input_port);
1412 scm_i_port_class[SCM_IN_PCLASS_INDEX + ptobnum]
1413 = scm_make_standard_class (meta, name, supers, SCM_EOL);
1414
1415 name = make_class_name ("<", type_name, "-output-port>");
1416 supers = scm_list_2 (super, class_output_port);
1417 scm_i_port_class[SCM_OUT_PCLASS_INDEX + ptobnum]
1418 = scm_make_standard_class (meta, name, supers, SCM_EOL);
1419
1420 name = make_class_name ("<", type_name, "-input-output-port>");
1421 supers = scm_list_2 (super, class_input_output_port);
1422 scm_i_port_class[SCM_INOUT_PCLASS_INDEX + ptobnum]
1423 = scm_make_standard_class (meta, name, supers, SCM_EOL);
1424 }
1425
1426 static void
1427 create_port_classes (void)
1428 {
1429 long i;
1430
1431 for (i = scm_c_num_port_types () - 1; i >= 0; i--)
1432 scm_make_port_classes (i, SCM_PTOBNAME (i));
1433 }
1434
1435 SCM
1436 scm_i_define_class_for_vtable (SCM vtable)
1437 {
1438 SCM class;
1439
1440 scm_i_pthread_mutex_lock (&scm_i_misc_mutex);
1441 if (scm_is_false (vtable_class_map))
1442 vtable_class_map = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
1443 scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
1444
1445 if (scm_is_false (scm_struct_vtable_p (vtable)))
1446 abort ();
1447
1448 class = scm_weak_table_refq (vtable_class_map, vtable, SCM_BOOL_F);
1449
1450 if (scm_is_false (class))
1451 {
1452 if (SCM_UNPACK (class_class))
1453 {
1454 SCM name, meta, supers;
1455
1456 name = SCM_VTABLE_NAME (vtable);
1457 if (scm_is_symbol (name))
1458 name = scm_string_to_symbol
1459 (scm_string_append
1460 (scm_list_3 (scm_from_latin1_string ("<"),
1461 scm_symbol_to_string (name),
1462 scm_from_latin1_string (">"))));
1463 else
1464 name = scm_from_latin1_symbol ("<>");
1465
1466 if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SETTER))
1467 {
1468 meta = class_applicable_struct_with_setter_class;
1469 supers = scm_list_1 (class_applicable_struct_with_setter);
1470 }
1471 else if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable,
1472 SCM_VTABLE_FLAG_APPLICABLE))
1473 {
1474 meta = class_applicable_struct_class;
1475 supers = scm_list_1 (class_applicable_struct);
1476 }
1477 else
1478 {
1479 meta = class_class;
1480 supers = scm_list_1 (class_top);
1481 }
1482
1483 return scm_make_standard_class (meta, name, supers, SCM_EOL);
1484 }
1485 else
1486 /* `create_struct_classes' will fill this in later. */
1487 class = SCM_BOOL_F;
1488
1489 /* Don't worry about races. This only happens when creating a
1490 vtable, which happens by definition in one thread. */
1491 scm_weak_table_putq_x (vtable_class_map, vtable, class);
1492 }
1493
1494 return class;
1495 }
1496
1497 static SCM
1498 make_struct_class (void *closure SCM_UNUSED,
1499 SCM vtable, SCM data, SCM prev SCM_UNUSED)
1500 {
1501 if (scm_is_false (data))
1502 scm_i_define_class_for_vtable (vtable);
1503 return SCM_UNSPECIFIED;
1504 }
1505
1506 static void
1507 create_struct_classes (void)
1508 {
1509 /* FIXME: take the vtable_class_map while initializing goops? */
1510 scm_internal_hash_fold (make_struct_class, 0, SCM_BOOL_F,
1511 vtable_class_map);
1512 }
1513
1514 /**********************************************************************
1515 *
1516 * C interface
1517 *
1518 **********************************************************************/
1519
1520 void
1521 scm_load_goops ()
1522 {
1523 if (!goops_loaded_p)
1524 scm_c_resolve_module ("oop goops");
1525 }
1526
1527
1528 SCM_KEYWORD (k_setter, "setter");
1529
1530 SCM
1531 scm_ensure_accessor (SCM name)
1532 {
1533 SCM var, gf;
1534
1535 var = scm_module_variable (scm_current_module (), name);
1536 if (SCM_VARIABLEP (var) && !SCM_UNBNDP (SCM_VARIABLE_REF (var)))
1537 gf = SCM_VARIABLE_REF (var);
1538 else
1539 gf = SCM_BOOL_F;
1540
1541 if (!SCM_IS_A_P (gf, class_accessor))
1542 {
1543 gf = scm_make (scm_list_3 (class_generic, k_name, name));
1544 gf = scm_make (scm_list_5 (class_accessor,
1545 k_name, name, k_setter, gf));
1546 }
1547
1548 return gf;
1549 }
1550
1551 #ifdef GUILE_DEBUG
1552 /*
1553 * Debugging utilities
1554 */
1555
1556 SCM_DEFINE (scm_pure_generic_p, "pure-generic?", 1, 0, 0,
1557 (SCM obj),
1558 "Return @code{#t} if @var{obj} is a pure generic.")
1559 #define FUNC_NAME s_scm_pure_generic_p
1560 {
1561 return scm_from_bool (SCM_PUREGENERICP (obj));
1562 }
1563 #undef FUNC_NAME
1564
1565 #endif /* GUILE_DEBUG */
1566
1567 /*
1568 * Initialization
1569 */
1570
1571 SCM_DEFINE (scm_sys_bless_applicable_struct_vtables_x, "%bless-applicable-struct-vtables!", 2, 0, 0,
1572 (SCM applicable, SCM setter),
1573 "")
1574 #define FUNC_NAME s_scm_sys_bless_applicable_struct_vtables_x
1575 {
1576 SCM_VALIDATE_CLASS (1, applicable);
1577 SCM_VALIDATE_CLASS (2, setter);
1578 SCM_SET_VTABLE_FLAGS (applicable, SCM_VTABLE_FLAG_APPLICABLE_VTABLE);
1579 SCM_SET_VTABLE_FLAGS (setter, SCM_VTABLE_FLAG_SETTER_VTABLE);
1580 return SCM_UNSPECIFIED;
1581 }
1582 #undef FUNC_NAME
1583
1584 SCM_DEFINE (scm_sys_bless_pure_generic_vtable_x, "%bless-pure-generic-vtable!", 1, 0, 0,
1585 (SCM vtable),
1586 "")
1587 #define FUNC_NAME s_scm_sys_bless_pure_generic_vtable_x
1588 {
1589 SCM_VALIDATE_CLASS (1, vtable);
1590 SCM_SET_CLASS_FLAGS (vtable, SCM_CLASSF_PURE_GENERIC);
1591 return SCM_UNSPECIFIED;
1592 }
1593 #undef FUNC_NAME
1594
1595 SCM_DEFINE (scm_sys_goops_early_init, "%goops-early-init", 0, 0, 0,
1596 (),
1597 "")
1598 #define FUNC_NAME s_scm_sys_goops_early_init
1599 {
1600 var_make_standard_class = scm_c_lookup ("make-standard-class");
1601 var_make = scm_c_lookup ("make");
1602
1603 class_class = scm_variable_ref (scm_c_lookup ("<class>"));
1604 class_top = scm_variable_ref (scm_c_lookup ("<top>"));
1605 class_object = scm_variable_ref (scm_c_lookup ("<object>"));
1606
1607 class_foreign_slot = scm_variable_ref (scm_c_lookup ("<foreign-slot>"));
1608 class_protected = scm_variable_ref (scm_c_lookup ("<protected-slot>"));
1609 class_hidden = scm_variable_ref (scm_c_lookup ("<hidden-slot>"));
1610 class_opaque = scm_variable_ref (scm_c_lookup ("<opaque-slot>"));
1611 class_read_only = scm_variable_ref (scm_c_lookup ("<read-only-slot>"));
1612 class_self = scm_variable_ref (scm_c_lookup ("<self-slot>"));
1613 class_protected_opaque = scm_variable_ref (scm_c_lookup ("<protected-opaque-slot>"));
1614 class_protected_hidden = scm_variable_ref (scm_c_lookup ("<protected-hidden-slot>"));
1615 class_protected_read_only = scm_variable_ref (scm_c_lookup ("<protected-read-only-slot>"));
1616 class_scm = scm_variable_ref (scm_c_lookup ("<scm-slot>"));
1617 class_int = scm_variable_ref (scm_c_lookup ("<int-slot>"));
1618 class_float = scm_variable_ref (scm_c_lookup ("<float-slot>"));
1619 class_double = scm_variable_ref (scm_c_lookup ("<double-slot>"));
1620
1621 /* Applicables */
1622 class_procedure_class = scm_variable_ref (scm_c_lookup ("<procedure-class>"));
1623 class_applicable_struct_class = scm_variable_ref (scm_c_lookup ("<applicable-struct-class>"));
1624 class_applicable_struct_with_setter_class =
1625 scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter-class>"));
1626
1627 class_method = scm_variable_ref (scm_c_lookup ("<method>"));
1628 class_accessor_method = scm_variable_ref (scm_c_lookup ("<accessor-method>"));
1629 class_applicable = scm_variable_ref (scm_c_lookup ("<applicable>"));
1630 class_applicable_struct = scm_variable_ref (scm_c_lookup ("<applicable-struct>"));
1631 class_applicable_struct_with_setter = scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter>"));
1632 class_generic = scm_variable_ref (scm_c_lookup ("<generic>"));
1633 class_extended_generic = scm_variable_ref (scm_c_lookup ("<extended-generic>"));
1634 class_generic_with_setter = scm_variable_ref (scm_c_lookup ("<generic-with-setter>"));
1635 class_accessor = scm_variable_ref (scm_c_lookup ("<accessor>"));
1636 class_extended_generic_with_setter = scm_variable_ref (scm_c_lookup ("<extended-generic-with-setter>"));
1637 class_extended_accessor = scm_variable_ref (scm_c_lookup ("<extended-accessor>"));
1638
1639 /* Primitive types classes */
1640 class_boolean = scm_variable_ref (scm_c_lookup ("<boolean>"));
1641 class_char = scm_variable_ref (scm_c_lookup ("<char>"));
1642 class_list = scm_variable_ref (scm_c_lookup ("<list>"));
1643 class_pair = scm_variable_ref (scm_c_lookup ("<pair>"));
1644 class_null = scm_variable_ref (scm_c_lookup ("<null>"));
1645 class_string = scm_variable_ref (scm_c_lookup ("<string>"));
1646 class_symbol = scm_variable_ref (scm_c_lookup ("<symbol>"));
1647 class_vector = scm_variable_ref (scm_c_lookup ("<vector>"));
1648 class_foreign = scm_variable_ref (scm_c_lookup ("<foreign>"));
1649 class_hashtable = scm_variable_ref (scm_c_lookup ("<hashtable>"));
1650 class_fluid = scm_variable_ref (scm_c_lookup ("<fluid>"));
1651 class_dynamic_state = scm_variable_ref (scm_c_lookup ("<dynamic-state>"));
1652 class_frame = scm_variable_ref (scm_c_lookup ("<frame>"));
1653 class_vm_cont = scm_variable_ref (scm_c_lookup ("<vm-continuation>"));
1654 class_bytevector = scm_variable_ref (scm_c_lookup ("<bytevector>"));
1655 class_uvec = scm_variable_ref (scm_c_lookup ("<uvec>"));
1656 class_array = scm_variable_ref (scm_c_lookup ("<array>"));
1657 class_bitvector = scm_variable_ref (scm_c_lookup ("<bitvector>"));
1658 class_number = scm_variable_ref (scm_c_lookup ("<number>"));
1659 class_complex = scm_variable_ref (scm_c_lookup ("<complex>"));
1660 class_real = scm_variable_ref (scm_c_lookup ("<real>"));
1661 class_integer = scm_variable_ref (scm_c_lookup ("<integer>"));
1662 class_fraction = scm_variable_ref (scm_c_lookup ("<fraction>"));
1663 class_keyword = scm_variable_ref (scm_c_lookup ("<keyword>"));
1664 class_unknown = scm_variable_ref (scm_c_lookup ("<unknown>"));
1665 class_procedure = scm_variable_ref (scm_c_lookup ("<procedure>"));
1666 class_primitive_generic = scm_variable_ref (scm_c_lookup ("<primitive-generic>"));
1667 class_port = scm_variable_ref (scm_c_lookup ("<port>"));
1668 class_input_port = scm_variable_ref (scm_c_lookup ("<input-port>"));
1669 class_output_port = scm_variable_ref (scm_c_lookup ("<output-port>"));
1670 class_input_output_port = scm_variable_ref (scm_c_lookup ("<input-output-port>"));
1671
1672 create_smob_classes ();
1673 create_struct_classes ();
1674 create_port_classes ();
1675
1676 return SCM_UNSPECIFIED;
1677 }
1678 #undef FUNC_NAME
1679
1680 SCM_DEFINE (scm_sys_goops_loaded, "%goops-loaded", 0, 0, 0,
1681 (),
1682 "Announce that GOOPS is loaded and perform initialization\n"
1683 "on the C level which depends on the loaded GOOPS modules.")
1684 #define FUNC_NAME s_scm_sys_goops_loaded
1685 {
1686 goops_loaded_p = 1;
1687 var_slot_unbound =
1688 scm_module_variable (scm_module_goops, sym_slot_unbound);
1689 var_slot_missing =
1690 scm_module_variable (scm_module_goops, sym_slot_missing);
1691 var_change_class =
1692 scm_module_variable (scm_module_goops, sym_change_class);
1693 setup_extended_primitive_generics ();
1694
1695 #if (SCM_ENABLE_DEPRECATED == 1)
1696 scm_init_deprecated_goops ();
1697 #endif
1698
1699 return SCM_UNSPECIFIED;
1700 }
1701 #undef FUNC_NAME
1702
1703 SCM scm_module_goops;
1704
1705 static void
1706 scm_init_goops_builtins (void *unused)
1707 {
1708 scm_module_goops = scm_current_module ();
1709
1710 goops_rstate = scm_c_make_rstate ("GOOPS", 5);
1711
1712 hell = scm_calloc (hell_size * sizeof (*hell));
1713 hell_mutex = scm_make_mutex ();
1714
1715 #include "libguile/goops.x"
1716 }
1717
1718 void
1719 scm_init_goops ()
1720 {
1721 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
1722 "scm_init_goops_builtins", scm_init_goops_builtins,
1723 NULL);
1724 }
1725
1726 /*
1727 Local Variables:
1728 c-file-style: "gnu"
1729 End:
1730 */