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