1 /* Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2008,2009,2010,2011,2012,2013,2014,2015
2 * Free Software Foundation, Inc.
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.
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.
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
21 /* This software is a derivative work of other copyrighted softwares; the
22 * copyright notices of these softwares are placed in the file COPYRIGHTS
24 * This file is based upon stklos.c from the STk distribution by
25 * Erick Gallesio <eg@unice.fr>.
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"
50 #include "libguile/validate.h"
51 #include "libguile/goops.h"
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)
58 #define SCM_GOOPS_UNBOUND SCM_UNBOUND
59 #define SCM_GOOPS_UNBOUNDP(x) (scm_is_eq (x, SCM_GOOPS_UNBOUND))
61 /* Objects have identity, so references to classes and instances are by
62 value, not by reference. Redefinition of a class or modification of
63 an instance causes in-place update; you can think of GOOPS as
64 building in its own indirection, and for that reason referring to
65 GOOPS values by variable reference is unnecessary.
67 References to ordinary procedures is by reference (by variable),
68 though, as in the rest of Guile. */
70 static int goops_loaded_p
= 0;
72 static SCM var_make_standard_class
= SCM_BOOL_F
;
73 static SCM var_change_class
= SCM_BOOL_F
;
74 static SCM var_make
= SCM_BOOL_F
;
75 static SCM var_class_name
= SCM_BOOL_F
;
76 static SCM var_class_direct_supers
= SCM_BOOL_F
;
77 static SCM var_class_direct_slots
= SCM_BOOL_F
;
78 static SCM var_class_direct_subclasses
= SCM_BOOL_F
;
79 static SCM var_class_direct_methods
= SCM_BOOL_F
;
80 static SCM var_class_precedence_list
= SCM_BOOL_F
;
81 static SCM var_class_slots
= SCM_BOOL_F
;
83 static SCM var_generic_function_methods
= SCM_BOOL_F
;
84 static SCM var_method_generic_function
= SCM_BOOL_F
;
85 static SCM var_method_specializers
= SCM_BOOL_F
;
86 static SCM var_method_procedure
= SCM_BOOL_F
;
88 static SCM var_slot_ref_using_class
= SCM_BOOL_F
;
89 static SCM var_slot_set_using_class_x
= SCM_BOOL_F
;
90 static SCM var_slot_bound_using_class_p
= SCM_BOOL_F
;
91 static SCM var_slot_exists_using_class_p
= SCM_BOOL_F
;
93 static SCM var_slot_ref
= SCM_BOOL_F
;
94 static SCM var_slot_set_x
= SCM_BOOL_F
;
95 static SCM var_slot_bound_p
= SCM_BOOL_F
;
96 static SCM var_slot_exists_p
= SCM_BOOL_F
;
98 /* These variables are filled in by the object system when loaded. */
99 static SCM class_boolean
, class_char
, class_pair
;
100 static SCM class_procedure
, class_string
, class_symbol
;
101 static SCM class_primitive_generic
;
102 static SCM class_vector
, class_null
;
103 static SCM class_integer
, class_real
, class_complex
, class_fraction
;
104 static SCM class_unknown
;
105 static SCM class_top
, class_object
, class_class
;
106 static SCM class_applicable
;
107 static SCM class_applicable_struct
, class_applicable_struct_with_setter
;
108 static SCM class_generic
, class_generic_with_setter
;
109 static SCM class_accessor
;
110 static SCM class_extended_generic
, class_extended_generic_with_setter
;
111 static SCM class_extended_accessor
;
112 static SCM class_method
;
113 static SCM class_accessor_method
;
114 static SCM class_procedure_class
;
115 static SCM class_applicable_struct_class
;
116 static SCM class_applicable_struct_with_setter_class
;
117 static SCM class_number
, class_list
;
118 static SCM class_keyword
;
119 static SCM class_port
, class_input_output_port
;
120 static SCM class_input_port
, class_output_port
;
121 static SCM class_foreign_slot
;
122 static SCM class_self
, class_protected
;
123 static SCM class_hidden
, class_opaque
, class_read_only
;
124 static SCM class_protected_hidden
, class_protected_opaque
, class_protected_read_only
;
125 static SCM class_scm
;
126 static SCM class_int
, class_float
, class_double
;
128 static SCM class_foreign
;
129 static SCM class_hashtable
;
130 static SCM class_fluid
;
131 static SCM class_dynamic_state
;
132 static SCM class_frame
;
133 static SCM class_vm_cont
;
134 static SCM class_bytevector
;
135 static SCM class_uvec
;
136 static SCM class_array
;
137 static SCM class_bitvector
;
139 static SCM vtable_class_map
= SCM_BOOL_F
;
141 /* Port classes. Allocate 3 times the maximum number of port types so that
142 input ports, output ports, and in/out ports can be stored at different
143 offsets. See `SCM_IN_PCLASS_INDEX' et al. */
144 SCM scm_i_port_class
[3 * SCM_I_MAX_PORT_TYPE_COUNT
];
147 SCM scm_i_smob_class
[SCM_I_MAX_SMOB_TYPE_COUNT
];
149 static SCM
scm_make_unbound (void);
150 static SCM
scm_unbound_p (SCM obj
);
151 static SCM
scm_class_p (SCM obj
);
152 static SCM
scm_sys_bless_applicable_struct_vtables_x (SCM applicable
,
154 static SCM
scm_sys_make_root_class (SCM name
, SCM dslots
,
155 SCM getters_n_setters
);
156 static SCM
scm_sys_init_layout_x (SCM
class, SCM layout
);
157 static SCM
scm_sys_goops_early_init (void);
158 static SCM
scm_sys_goops_loaded (void);
161 /* This function is used for efficient type dispatch. */
162 SCM_DEFINE (scm_class_of
, "class-of", 1, 0, 0,
164 "Return the class of @var{x}.")
165 #define FUNC_NAME s_scm_class_of
167 switch (SCM_ITAG3 (x
))
171 return class_integer
;
176 else if (scm_is_bool (x
))
177 return class_boolean
;
178 else if (scm_is_null (x
))
181 return class_unknown
;
184 switch (SCM_TYP7 (x
))
186 case scm_tcs_cons_nimcar
:
193 case scm_tc7_pointer
:
194 return class_foreign
;
195 case scm_tc7_hashtable
:
196 return class_hashtable
;
199 case scm_tc7_dynamic_state
:
200 return class_dynamic_state
;
203 case scm_tc7_keyword
:
204 return class_keyword
;
205 case scm_tc7_vm_cont
:
206 return class_vm_cont
;
207 case scm_tc7_bytevector
:
208 if (SCM_BYTEVECTOR_ELEMENT_TYPE (x
) == SCM_ARRAY_ELEMENT_TYPE_VU8
)
209 return class_bytevector
;
214 case scm_tc7_bitvector
:
215 return class_bitvector
;
219 switch SCM_TYP16 (x
) {
221 return class_integer
;
224 case scm_tc16_complex
:
225 return class_complex
;
226 case scm_tc16_fraction
:
227 return class_fraction
;
229 case scm_tc7_program
:
230 if (SCM_PROGRAM_IS_PRIMITIVE_GENERIC (x
)
231 && SCM_UNPACK (*SCM_SUBR_GENERIC (x
)))
232 return class_primitive_generic
;
234 return class_procedure
;
238 scm_t_bits type
= SCM_TYP16 (x
);
239 if (type
!= scm_tc16_port_with_ps
)
240 return scm_i_smob_class
[SCM_TC2SMOBNUM (type
)];
241 x
= SCM_PORT_WITH_PS_PORT (x
);
242 /* fall through to ports */
245 return scm_i_port_class
[(SCM_WRTNG
& SCM_CELL_WORD_0 (x
)
246 ? (SCM_RDNG
& SCM_CELL_WORD_0 (x
)
247 ? SCM_INOUT_PCLASS_INDEX
| SCM_PTOBNUM (x
)
248 : SCM_OUT_PCLASS_INDEX
| SCM_PTOBNUM (x
))
249 : SCM_IN_PCLASS_INDEX
| SCM_PTOBNUM (x
))];
251 if (SCM_OBJ_CLASS_FLAGS (x
) & SCM_CLASSF_GOOPS_VALID
)
252 return SCM_CLASS_OF (x
);
253 else if (SCM_OBJ_CLASS_FLAGS (x
) & SCM_CLASSF_GOOPS
)
256 if (! scm_is_false (SCM_OBJ_CLASS_REDEF (x
)))
257 scm_change_object_class (x
,
258 SCM_CLASS_OF (x
), /* old */
259 SCM_OBJ_CLASS_REDEF (x
)); /* new */
260 return SCM_CLASS_OF (x
);
263 return scm_i_define_class_for_vtable (SCM_CLASS_OF (x
));
268 return class_unknown
;
274 /* case scm_tc3_unused: */
278 return class_unknown
;
282 /******************************************************************************
286 ******************************************************************************/
288 /*fixme* Manufacture keywords in advance */
290 scm_i_get_keyword (SCM key
, SCM l
, long len
, SCM default_value
, const char *subr
)
294 for (i
= 0; i
!= len
; i
+= 2)
296 SCM obj
= SCM_CAR (l
);
298 if (!scm_is_keyword (obj
))
299 scm_misc_error (subr
, "bad keyword: ~S", scm_list_1 (obj
));
300 else if (scm_is_eq (obj
, key
))
306 return default_value
;
310 SCM_DEFINE (scm_get_keyword
, "get-keyword", 3, 0, 0,
311 (SCM key
, SCM l
, SCM default_value
),
312 "Determine an associated value for the keyword @var{key} from\n"
313 "the list @var{l}. The list @var{l} has to consist of an even\n"
314 "number of elements, where, starting with the first, every\n"
315 "second element is a keyword, followed by its associated value.\n"
316 "If @var{l} does not hold a value for @var{key}, the value\n"
317 "@var{default_value} is returned.")
318 #define FUNC_NAME s_scm_get_keyword
322 SCM_ASSERT (scm_is_keyword (key
), key
, SCM_ARG1
, FUNC_NAME
);
323 len
= scm_ilength (l
);
324 if (len
< 0 || len
% 2 == 1)
325 scm_misc_error (FUNC_NAME
, "Bad keyword-value list: ~S", scm_list_1 (l
));
327 return scm_i_get_keyword (key
, l
, len
, default_value
, FUNC_NAME
);
332 SCM_KEYWORD (k_init_keyword
, "init-keyword");
335 SCM_DEFINE (scm_sys_initialize_object
, "%initialize-object", 2, 0, 0,
336 (SCM obj
, SCM initargs
),
337 "Initialize the object @var{obj} with the given arguments\n"
339 #define FUNC_NAME s_scm_sys_initialize_object
341 SCM tmp
, get_n_set
, slots
;
342 SCM
class = SCM_CLASS_OF (obj
);
345 SCM_VALIDATE_INSTANCE (1, obj
);
346 n_initargs
= scm_ilength (initargs
);
347 SCM_ASSERT ((n_initargs
& 1) == 0, initargs
, SCM_ARG2
, FUNC_NAME
);
349 get_n_set
= SCM_SLOT (class, scm_si_getters_n_setters
);
350 slots
= SCM_SLOT (class, scm_si_slots
);
352 /* See for each slot how it must be initialized */
354 !scm_is_null (slots
);
355 get_n_set
= SCM_CDR (get_n_set
), slots
= SCM_CDR (slots
))
357 SCM slot_name
= SCM_CAR (slots
);
358 SCM slot_value
= SCM_GOOPS_UNBOUND
;
360 if (!scm_is_null (SCM_CDR (slot_name
)))
362 /* This slot admits (perhaps) to be initialized at creation time */
363 long n
= scm_ilength (SCM_CDR (slot_name
));
364 if (n
& 1) /* odd or -1 */
365 SCM_MISC_ERROR ("class contains bogus slot definition: ~S",
366 scm_list_1 (slot_name
));
367 tmp
= scm_i_get_keyword (k_init_keyword
,
372 slot_name
= SCM_CAR (slot_name
);
373 if (SCM_UNPACK (tmp
))
375 /* an initarg was provided for this slot */
376 if (!scm_is_keyword (tmp
))
377 SCM_MISC_ERROR ("initarg must be a keyword. It was ~S",
379 slot_value
= scm_i_get_keyword (tmp
,
387 if (!SCM_GOOPS_UNBOUNDP (slot_value
))
388 /* set slot to provided value */
389 scm_slot_set_x (obj
, slot_name
, slot_value
);
392 /* set slot to its :init-form if it exists */
393 tmp
= SCM_CADAR (get_n_set
);
394 if (scm_is_true (tmp
))
395 scm_slot_set_x (obj
, slot_name
, scm_call_0 (tmp
));
403 SCM_DEFINE (scm_sys_init_layout_x
, "%init-layout!", 2, 0, 0,
404 (SCM
class, SCM layout
),
406 #define FUNC_NAME s_scm_sys_init_layout_x
408 SCM_VALIDATE_INSTANCE (1, class);
409 SCM_ASSERT (!scm_is_symbol (SCM_VTABLE_LAYOUT (class)), class, 1, FUNC_NAME
);
410 SCM_VALIDATE_STRING (2, layout
);
412 SCM_SET_VTABLE_LAYOUT (class, scm_make_struct_layout (layout
));
413 return SCM_UNSPECIFIED
;
417 SCM_DEFINE (scm_sys_inherit_magic_x
, "%inherit-magic!", 2, 0, 0,
418 (SCM
class, SCM dsupers
),
420 #define FUNC_NAME s_scm_sys_inherit_magic_x
422 SCM_VALIDATE_INSTANCE (1, class);
423 scm_i_struct_inherit_vtable_magic (SCM_CLASS_OF (class), class);
424 SCM_SET_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_OR_VALID
);
426 return SCM_UNSPECIFIED
;
430 /******************************************************************************/
433 scm_make_standard_class (SCM meta
, SCM name
, SCM dsupers
, SCM dslots
)
435 return scm_call_4 (scm_variable_ref (var_make_standard_class
),
436 meta
, name
, dsupers
, dslots
);
439 /******************************************************************************/
441 SCM_DEFINE (scm_sys_make_root_class
, "%make-root-class", 3, 0, 0,
442 (SCM name
, SCM dslots
, SCM getters_n_setters
),
444 #define FUNC_NAME s_scm_sys_make_root_class
448 cs
= scm_from_locale_string (SCM_CLASS_CLASS_LAYOUT
);
449 z
= scm_i_make_vtable_vtable (cs
);
450 SCM_SET_CLASS_FLAGS (z
, (SCM_CLASSF_GOOPS_OR_VALID
451 | SCM_CLASSF_METACLASS
));
453 SCM_SET_SLOT (z
, scm_vtable_index_name
, name
);
454 SCM_SET_SLOT (z
, scm_si_direct_supers
, SCM_EOL
); /* will be changed */
455 SCM_SET_SLOT (z
, scm_si_direct_slots
, dslots
); /* will be changed */
456 SCM_SET_SLOT (z
, scm_si_direct_subclasses
, SCM_EOL
);
457 SCM_SET_SLOT (z
, scm_si_direct_methods
, SCM_EOL
);
458 SCM_SET_SLOT (z
, scm_si_cpl
, SCM_EOL
); /* will be changed */
459 SCM_SET_SLOT (z
, scm_si_slots
, dslots
); /* will be changed */
460 SCM_SET_SLOT (z
, scm_si_nfields
, scm_from_int (SCM_N_CLASS_SLOTS
));
461 SCM_SET_SLOT (z
, scm_si_getters_n_setters
, getters_n_setters
); /* will be changed */
462 SCM_SET_SLOT (z
, scm_si_redefined
, SCM_BOOL_F
);
468 /******************************************************************************/
470 SCM_DEFINE (scm_instance_p
, "instance?", 1, 0, 0,
472 "Return @code{#t} if @var{obj} is an instance.")
473 #define FUNC_NAME s_scm_instance_p
475 return scm_from_bool (SCM_INSTANCEP (obj
));
479 SCM_DEFINE (scm_class_p
, "class?", 1, 0, 0,
481 "Return @code{#t} if @var{obj} is a class.")
482 #define FUNC_NAME s_scm_class_p
484 return scm_from_bool (SCM_CLASSP (obj
));
489 scm_is_generic (SCM x
)
491 return SCM_INSTANCEP (x
) && SCM_SUBCLASSP (SCM_CLASS_OF (x
), class_generic
);
495 scm_is_method (SCM x
)
497 return SCM_INSTANCEP (x
) && SCM_SUBCLASSP (SCM_CLASS_OF (x
), class_method
);
500 /******************************************************************************
502 * Meta object accessors
504 ******************************************************************************/
507 scm_class_name (SCM obj
)
509 return scm_call_1 (scm_variable_ref (var_class_name
), obj
);
513 scm_class_direct_supers (SCM obj
)
515 return scm_call_1 (scm_variable_ref (var_class_direct_supers
), obj
);
519 scm_class_direct_slots (SCM obj
)
521 return scm_call_1 (scm_variable_ref (var_class_direct_slots
), obj
);
525 scm_class_direct_subclasses (SCM obj
)
527 return scm_call_1 (scm_variable_ref (var_class_direct_subclasses
), obj
);
531 scm_class_direct_methods (SCM obj
)
533 return scm_call_1 (scm_variable_ref (var_class_direct_methods
), obj
);
537 scm_class_precedence_list (SCM obj
)
539 return scm_call_1 (scm_variable_ref (var_class_precedence_list
), obj
);
543 scm_class_slots (SCM obj
)
545 return scm_call_1 (scm_variable_ref (var_class_slots
), obj
);
548 SCM_DEFINE (scm_generic_function_name
, "generic-function-name", 1, 0, 0,
550 "Return the name of the generic function @var{obj}.")
551 #define FUNC_NAME s_scm_generic_function_name
553 SCM_VALIDATE_GENERIC (1, obj
);
554 return scm_procedure_property (obj
, scm_sym_name
);
559 scm_generic_function_methods (SCM obj
)
561 return scm_call_1 (scm_variable_ref (var_generic_function_methods
), obj
);
565 scm_method_generic_function (SCM obj
)
567 return scm_call_1 (scm_variable_ref (var_method_generic_function
), obj
);
571 scm_method_specializers (SCM obj
)
573 return scm_call_1 (scm_variable_ref (var_method_specializers
), obj
);
577 scm_method_procedure (SCM obj
)
579 return scm_call_1 (scm_variable_ref (var_method_procedure
), obj
);
582 /******************************************************************************
584 * S l o t a c c e s s
586 ******************************************************************************/
588 SCM_DEFINE (scm_make_unbound
, "make-unbound", 0, 0, 0,
590 "Return the unbound value.")
591 #define FUNC_NAME s_scm_make_unbound
593 return SCM_GOOPS_UNBOUND
;
597 SCM_DEFINE (scm_unbound_p
, "unbound?", 1, 0, 0,
599 "Return @code{#t} if @var{obj} is unbound.")
600 #define FUNC_NAME s_scm_unbound_p
602 return SCM_GOOPS_UNBOUNDP (obj
) ? SCM_BOOL_T
: SCM_BOOL_F
;
610 scm_slot_ref_using_class (SCM
class, SCM obj
, SCM slot_name
)
612 return scm_call_3 (scm_variable_ref (var_slot_ref_using_class
),
613 class, obj
, slot_name
);
617 scm_slot_set_using_class_x (SCM
class, SCM obj
, SCM slot_name
, SCM value
)
619 return scm_call_4 (scm_variable_ref (var_slot_set_using_class_x
),
620 class, obj
, slot_name
, value
);
624 scm_slot_bound_using_class_p (SCM
class, SCM obj
, SCM slot_name
)
626 return scm_call_3 (scm_variable_ref (var_slot_bound_using_class_p
),
627 class, obj
, slot_name
);
631 scm_slot_exists_using_class_p (SCM
class, SCM obj
, SCM slot_name
)
633 return scm_call_3 (scm_variable_ref (var_slot_exists_using_class_p
),
634 class, obj
, slot_name
);
638 scm_slot_ref (SCM obj
, SCM slot_name
)
640 return scm_call_2 (scm_variable_ref (var_slot_ref
), obj
, slot_name
);
644 scm_slot_set_x (SCM obj
, SCM slot_name
, SCM value
)
646 return scm_call_3 (scm_variable_ref (var_slot_set_x
), obj
, slot_name
, value
);
650 scm_slot_bound_p (SCM obj
, SCM slot_name
)
652 return scm_call_2 (scm_variable_ref (var_slot_bound_p
), obj
, slot_name
);
656 scm_slot_exists_p (SCM obj
, SCM slot_name
)
658 return scm_call_2 (scm_variable_ref (var_slot_exists_p
), obj
, slot_name
);
662 /******************************************************************************
664 * %allocate-instance (the low level instance allocation primitive)
666 ******************************************************************************/
668 SCM_DEFINE (scm_sys_allocate_instance
, "%allocate-instance", 2, 0, 0,
669 (SCM
class, SCM initargs
),
670 "Create a new instance of class @var{class} and initialize it\n"
671 "from the arguments @var{initargs}.")
672 #define FUNC_NAME s_scm_sys_allocate_instance
675 scm_t_signed_bits n
, i
;
678 SCM_VALIDATE_CLASS (1, class);
680 /* FIXME: duplicates some of scm_make_struct. */
682 n
= SCM_I_INUM (SCM_SLOT (class, scm_si_nfields
));
683 obj
= scm_i_alloc_struct (SCM_STRUCT_DATA (class), n
);
685 layout
= SCM_VTABLE_LAYOUT (class);
687 /* Set all SCM-holding slots to unbound */
688 for (i
= 0; i
< n
; i
++)
690 scm_t_wchar c
= scm_i_symbol_ref (layout
, i
*2);
692 SCM_STRUCT_DATA (obj
)[i
] = SCM_UNPACK (SCM_GOOPS_UNBOUND
);
694 SCM_STRUCT_DATA (obj
)[i
] = SCM_UNPACK (obj
);
696 SCM_STRUCT_DATA (obj
)[i
] = 0;
703 /******************************************************************************
705 * %modify-instance (used by change-class to modify in place)
707 ******************************************************************************/
709 SCM_DEFINE (scm_sys_modify_instance
, "%modify-instance", 2, 0, 0,
712 #define FUNC_NAME s_scm_sys_modify_instance
714 SCM_VALIDATE_INSTANCE (1, old
);
715 SCM_VALIDATE_INSTANCE (2, new);
717 /* Exchange the data contained in old and new. We exchange rather than
718 * scratch the old value with new to be correct with GC.
719 * See "Class redefinition protocol above".
721 SCM_CRITICAL_SECTION_START
;
723 scm_t_bits word0
, word1
;
724 word0
= SCM_CELL_WORD_0 (old
);
725 word1
= SCM_CELL_WORD_1 (old
);
726 SCM_SET_CELL_WORD_0 (old
, SCM_CELL_WORD_0 (new));
727 SCM_SET_CELL_WORD_1 (old
, SCM_CELL_WORD_1 (new));
728 SCM_SET_CELL_WORD_0 (new, word0
);
729 SCM_SET_CELL_WORD_1 (new, word1
);
731 SCM_CRITICAL_SECTION_END
;
732 return SCM_UNSPECIFIED
;
736 SCM_DEFINE (scm_sys_modify_class
, "%modify-class", 2, 0, 0,
739 #define FUNC_NAME s_scm_sys_modify_class
741 SCM_VALIDATE_CLASS (1, old
);
742 SCM_VALIDATE_CLASS (2, new);
744 SCM_CRITICAL_SECTION_START
;
746 scm_t_bits word0
, word1
;
747 word0
= SCM_CELL_WORD_0 (old
);
748 word1
= SCM_CELL_WORD_1 (old
);
749 SCM_SET_CELL_WORD_0 (old
, SCM_CELL_WORD_0 (new));
750 SCM_SET_CELL_WORD_1 (old
, SCM_CELL_WORD_1 (new));
751 SCM_STRUCT_DATA (old
)[scm_vtable_index_self
] = SCM_UNPACK (old
);
752 SCM_SET_CELL_WORD_0 (new, word0
);
753 SCM_SET_CELL_WORD_1 (new, word1
);
754 SCM_STRUCT_DATA (new)[scm_vtable_index_self
] = SCM_UNPACK (new);
756 SCM_CRITICAL_SECTION_END
;
757 return SCM_UNSPECIFIED
;
761 SCM_DEFINE (scm_sys_invalidate_class
, "%invalidate-class", 1, 0, 0,
764 #define FUNC_NAME s_scm_sys_invalidate_class
766 SCM_VALIDATE_CLASS (1, class);
767 SCM_CLEAR_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_VALID
);
768 return SCM_UNSPECIFIED
;
772 /* When instances change class, they finally get a new body, but
773 * before that, they go through purgatory in hell. Odd as it may
774 * seem, this data structure saves us from eternal suffering in
775 * infinite recursions.
778 static scm_t_bits
**hell
;
779 static long n_hell
= 1; /* one place for the evil one himself */
780 static long hell_size
= 4;
781 static SCM hell_mutex
;
787 for (i
= 1; i
< n_hell
; ++i
)
788 if (SCM_STRUCT_DATA (o
) == hell
[i
])
797 scm_lock_mutex (hell_mutex
);
798 if (n_hell
>= hell_size
)
801 hell
= scm_realloc (hell
, hell_size
* sizeof(*hell
));
803 hell
[n_hell
++] = SCM_STRUCT_DATA (obj
);
804 scm_unlock_mutex (hell_mutex
);
808 go_to_heaven (void *o
)
811 scm_lock_mutex (hell_mutex
);
812 hell
[burnin (obj
)] = hell
[--n_hell
];
813 scm_unlock_mutex (hell_mutex
);
818 purgatory (SCM obj
, SCM new_class
)
820 return scm_call_2 (SCM_VARIABLE_REF (var_change_class
), obj
, new_class
);
823 /* This function calls the generic function change-class for all
824 * instances which aren't currently undergoing class change.
828 scm_change_object_class (SCM obj
, SCM old_class SCM_UNUSED
, SCM new_class
)
832 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE
);
833 scm_dynwind_rewind_handler (go_to_hell
, &obj
, SCM_F_WIND_EXPLICITLY
);
834 scm_dynwind_unwind_handler (go_to_heaven
, &obj
, SCM_F_WIND_EXPLICITLY
);
835 purgatory (obj
, new_class
);
840 /******************************************************************************
846 * GGG E N E R I C F U N C T I O N S
848 * This implementation provides
849 * - generic functions (with class specializers)
852 * - a hard-coded MOP for standard gf, which can be overloaded for non-std gf
854 ******************************************************************************/
856 SCM_KEYWORD (k_name
, "name");
857 SCM_GLOBAL_SYMBOL (scm_sym_args
, "args");
859 SCM_DEFINE (scm_generic_capability_p
, "generic-capability?", 1, 0, 0,
862 #define FUNC_NAME s_scm_generic_capability_p
864 SCM_ASSERT (scm_is_true (scm_procedure_p (proc
)),
865 proc
, SCM_ARG1
, FUNC_NAME
);
866 return (SCM_PRIMITIVE_GENERIC_P (proc
) ? SCM_BOOL_T
: SCM_BOOL_F
);
870 SCM_DEFINE (scm_enable_primitive_generic_x
, "enable-primitive-generic!", 0, 0, 1,
873 #define FUNC_NAME s_scm_enable_primitive_generic_x
875 SCM_VALIDATE_REST_ARGUMENT (subrs
);
876 while (!scm_is_null (subrs
))
878 SCM subr
= SCM_CAR (subrs
);
879 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr
), subr
, SCM_ARGn
, FUNC_NAME
);
880 SCM_SET_SUBR_GENERIC (subr
,
881 scm_make (scm_list_3 (class_generic
,
883 SCM_SUBR_NAME (subr
))));
884 subrs
= SCM_CDR (subrs
);
886 return SCM_UNSPECIFIED
;
890 SCM_DEFINE (scm_set_primitive_generic_x
, "set-primitive-generic!", 2, 0, 0,
891 (SCM subr
, SCM generic
),
893 #define FUNC_NAME s_scm_set_primitive_generic_x
895 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr
), subr
, SCM_ARG1
, FUNC_NAME
);
896 SCM_ASSERT (SCM_GENERICP (generic
), generic
, SCM_ARG2
, FUNC_NAME
);
897 SCM_SET_SUBR_GENERIC (subr
, generic
);
898 return SCM_UNSPECIFIED
;
902 SCM_DEFINE (scm_primitive_generic_generic
, "primitive-generic-generic", 1, 0, 0,
905 #define FUNC_NAME s_scm_primitive_generic_generic
907 if (SCM_PRIMITIVE_GENERIC_P (subr
))
909 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (subr
)))
910 scm_enable_primitive_generic_x (scm_list_1 (subr
));
911 return *SCM_SUBR_GENERIC (subr
);
913 SCM_WRONG_TYPE_ARG (SCM_ARG1
, subr
);
917 /* Dirk:FIXME:: In all of these scm_wta_dispatch_* routines it is
918 * assumed that 'gf' is zero if uninitialized. It would be cleaner if
919 * some valid SCM value like SCM_BOOL_F or SCM_UNDEFINED were chosen.
923 scm_wta_dispatch_0 (SCM gf
, const char *subr
)
925 if (!SCM_UNPACK (gf
))
926 scm_error_num_args_subr (subr
);
928 return scm_call_0 (gf
);
932 scm_wta_dispatch_1 (SCM gf
, SCM a1
, int pos
, const char *subr
)
934 if (!SCM_UNPACK (gf
))
935 scm_wrong_type_arg (subr
, pos
, a1
);
937 return scm_call_1 (gf
, a1
);
941 scm_wta_dispatch_2 (SCM gf
, SCM a1
, SCM a2
, int pos
, const char *subr
)
943 if (!SCM_UNPACK (gf
))
944 scm_wrong_type_arg (subr
, pos
, (pos
== SCM_ARG1
) ? a1
: a2
);
946 return scm_call_2 (gf
, a1
, a2
);
950 scm_wta_dispatch_n (SCM gf
, SCM args
, int pos
, const char *subr
)
952 if (!SCM_UNPACK (gf
))
953 scm_wrong_type_arg (subr
, pos
, scm_list_ref (args
, scm_from_int (pos
)));
955 return scm_apply_0 (gf
, args
);
958 /******************************************************************************
960 * Protocol for calling a generic fumction
961 * This protocol is roughly equivalent to (parameter are a little bit different
962 * for efficiency reasons):
964 * + apply-generic (gf args)
965 * + compute-applicable-methods (gf args ...)
966 * + sort-applicable-methods (methods args)
967 * + apply-methods (gf methods args)
969 * apply-methods calls make-next-method to build the "continuation" of a a
970 * method. Applying a next-method will call apply-next-method which in
971 * turn will call apply again to call effectively the following method.
973 ******************************************************************************/
975 SCM_DEFINE (scm_make
, "make", 0, 0, 1,
977 "Make a new object. @var{args} must contain the class and\n"
978 "all necessary initialization information.")
979 #define FUNC_NAME s_scm_make
981 return scm_apply_0 (scm_variable_ref (var_make
), args
);
986 /**********************************************************************
990 **********************************************************************/
993 make_class_name (const char *prefix
, const char *type_name
, const char *suffix
)
997 return scm_string_to_symbol (scm_string_append
998 (scm_list_3 (scm_from_utf8_string (prefix
),
999 scm_from_utf8_string (type_name
),
1000 scm_from_utf8_string (suffix
))));
1004 scm_make_extended_class (char const *type_name
, int applicablep
)
1006 SCM name
, meta
, supers
;
1008 name
= make_class_name ("<", type_name
, ">");
1012 supers
= scm_list_1 (class_applicable
);
1014 supers
= scm_list_1 (class_top
);
1016 return scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
1020 scm_i_inherit_applicable (SCM c
)
1022 if (!SCM_SUBCLASSP (c
, class_applicable
))
1024 SCM dsupers
= SCM_SLOT (c
, scm_si_direct_supers
);
1025 SCM cpl
= SCM_SLOT (c
, scm_si_cpl
);
1026 /* patch class_applicable into direct-supers */
1027 SCM top
= scm_c_memq (class_top
, dsupers
);
1028 if (scm_is_false (top
))
1029 dsupers
= scm_append (scm_list_2 (dsupers
,
1030 scm_list_1 (class_applicable
)));
1033 SCM_SETCAR (top
, class_applicable
);
1034 SCM_SETCDR (top
, scm_cons (class_top
, SCM_CDR (top
)));
1036 SCM_SET_SLOT (c
, scm_si_direct_supers
, dsupers
);
1037 /* patch class_applicable into cpl */
1038 top
= scm_c_memq (class_top
, cpl
);
1039 if (scm_is_false (top
))
1043 SCM_SETCAR (top
, class_applicable
);
1044 SCM_SETCDR (top
, scm_cons (class_top
, SCM_CDR (top
)));
1046 /* add class to direct-subclasses of class_applicable */
1047 SCM_SET_SLOT (class_applicable
,
1048 scm_si_direct_subclasses
,
1049 scm_cons (c
, SCM_SLOT (class_applicable
,
1050 scm_si_direct_subclasses
)));
1055 create_smob_classes (void)
1059 for (i
= 0; i
< SCM_I_MAX_SMOB_TYPE_COUNT
; ++i
)
1060 scm_i_smob_class
[i
] = SCM_BOOL_F
;
1062 for (i
= 0; i
< scm_numsmob
; ++i
)
1063 if (scm_is_false (scm_i_smob_class
[i
]))
1064 scm_i_smob_class
[i
] = scm_make_extended_class (SCM_SMOBNAME (i
),
1065 scm_smobs
[i
].apply
!= 0);
1069 scm_make_port_classes (long ptobnum
, char *type_name
)
1071 SCM name
, meta
, super
, supers
;
1075 name
= make_class_name ("<", type_name
, "-port>");
1076 supers
= scm_list_1 (class_port
);
1077 super
= scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
1079 name
= make_class_name ("<", type_name
, "-input-port>");
1080 supers
= scm_list_2 (super
, class_input_port
);
1081 scm_i_port_class
[SCM_IN_PCLASS_INDEX
+ ptobnum
]
1082 = scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
1084 name
= make_class_name ("<", type_name
, "-output-port>");
1085 supers
= scm_list_2 (super
, class_output_port
);
1086 scm_i_port_class
[SCM_OUT_PCLASS_INDEX
+ ptobnum
]
1087 = scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
1089 name
= make_class_name ("<", type_name
, "-input-output-port>");
1090 supers
= scm_list_2 (super
, class_input_output_port
);
1091 scm_i_port_class
[SCM_INOUT_PCLASS_INDEX
+ ptobnum
]
1092 = scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
1096 create_port_classes (void)
1100 for (i
= scm_c_num_port_types () - 1; i
>= 0; i
--)
1101 scm_make_port_classes (i
, SCM_PTOBNAME (i
));
1105 scm_i_define_class_for_vtable (SCM vtable
)
1109 scm_i_pthread_mutex_lock (&scm_i_misc_mutex
);
1110 if (scm_is_false (vtable_class_map
))
1111 vtable_class_map
= scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY
);
1112 scm_i_pthread_mutex_unlock (&scm_i_misc_mutex
);
1114 if (scm_is_false (scm_struct_vtable_p (vtable
)))
1117 class = scm_weak_table_refq (vtable_class_map
, vtable
, SCM_BOOL_F
);
1119 if (scm_is_false (class))
1121 if (SCM_UNPACK (class_class
))
1123 SCM name
, meta
, supers
;
1125 name
= SCM_VTABLE_NAME (vtable
);
1126 if (scm_is_symbol (name
))
1127 name
= scm_string_to_symbol
1129 (scm_list_3 (scm_from_latin1_string ("<"),
1130 scm_symbol_to_string (name
),
1131 scm_from_latin1_string (">"))));
1133 name
= scm_from_latin1_symbol ("<>");
1135 if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable
, SCM_VTABLE_FLAG_SETTER
))
1137 meta
= class_applicable_struct_with_setter_class
;
1138 supers
= scm_list_1 (class_applicable_struct_with_setter
);
1140 else if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable
,
1141 SCM_VTABLE_FLAG_APPLICABLE
))
1143 meta
= class_applicable_struct_class
;
1144 supers
= scm_list_1 (class_applicable_struct
);
1149 supers
= scm_list_1 (class_top
);
1152 return scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
1155 /* `create_struct_classes' will fill this in later. */
1158 /* Don't worry about races. This only happens when creating a
1159 vtable, which happens by definition in one thread. */
1160 scm_weak_table_putq_x (vtable_class_map
, vtable
, class);
1167 make_struct_class (void *closure SCM_UNUSED
,
1168 SCM vtable
, SCM data
, SCM prev SCM_UNUSED
)
1170 if (scm_is_false (data
))
1171 scm_i_define_class_for_vtable (vtable
);
1172 return SCM_UNSPECIFIED
;
1176 create_struct_classes (void)
1178 /* FIXME: take the vtable_class_map while initializing goops? */
1179 scm_internal_hash_fold (make_struct_class
, 0, SCM_BOOL_F
,
1183 /**********************************************************************
1187 **********************************************************************/
1192 if (!goops_loaded_p
)
1193 scm_c_resolve_module ("oop goops");
1197 SCM_KEYWORD (k_setter
, "setter");
1200 scm_ensure_accessor (SCM name
)
1204 var
= scm_module_variable (scm_current_module (), name
);
1205 if (SCM_VARIABLEP (var
) && !SCM_UNBNDP (SCM_VARIABLE_REF (var
)))
1206 gf
= SCM_VARIABLE_REF (var
);
1210 if (!SCM_IS_A_P (gf
, class_accessor
))
1212 gf
= scm_make (scm_list_3 (class_generic
, k_name
, name
));
1213 gf
= scm_make (scm_list_5 (class_accessor
,
1214 k_name
, name
, k_setter
, gf
));
1224 SCM_DEFINE (scm_sys_bless_applicable_struct_vtables_x
, "%bless-applicable-struct-vtables!", 2, 0, 0,
1225 (SCM applicable
, SCM setter
),
1227 #define FUNC_NAME s_scm_sys_bless_applicable_struct_vtables_x
1229 SCM_VALIDATE_CLASS (1, applicable
);
1230 SCM_VALIDATE_CLASS (2, setter
);
1231 SCM_SET_VTABLE_FLAGS (applicable
, SCM_VTABLE_FLAG_APPLICABLE_VTABLE
);
1232 SCM_SET_VTABLE_FLAGS (setter
, SCM_VTABLE_FLAG_SETTER_VTABLE
);
1233 return SCM_UNSPECIFIED
;
1237 SCM_DEFINE (scm_sys_goops_early_init
, "%goops-early-init", 0, 0, 0,
1240 #define FUNC_NAME s_scm_sys_goops_early_init
1242 var_make_standard_class
= scm_c_lookup ("make-standard-class");
1243 var_make
= scm_c_lookup ("make");
1245 var_slot_ref_using_class
= scm_c_lookup ("slot-ref-using-class");
1246 var_slot_set_using_class_x
= scm_c_lookup ("slot-set-using-class!");
1247 var_slot_bound_using_class_p
= scm_c_lookup ("slot-bound-using-class?");
1248 var_slot_exists_using_class_p
= scm_c_lookup ("slot-exists-using-class?");
1250 var_slot_ref
= scm_c_lookup ("slot-ref");
1251 var_slot_set_x
= scm_c_lookup ("slot-set!");
1252 var_slot_bound_p
= scm_c_lookup ("slot-bound?");
1253 var_slot_exists_p
= scm_c_lookup ("slot-exists?");
1255 class_class
= scm_variable_ref (scm_c_lookup ("<class>"));
1256 class_top
= scm_variable_ref (scm_c_lookup ("<top>"));
1257 class_object
= scm_variable_ref (scm_c_lookup ("<object>"));
1259 class_foreign_slot
= scm_variable_ref (scm_c_lookup ("<foreign-slot>"));
1260 class_protected
= scm_variable_ref (scm_c_lookup ("<protected-slot>"));
1261 class_hidden
= scm_variable_ref (scm_c_lookup ("<hidden-slot>"));
1262 class_opaque
= scm_variable_ref (scm_c_lookup ("<opaque-slot>"));
1263 class_read_only
= scm_variable_ref (scm_c_lookup ("<read-only-slot>"));
1264 class_self
= scm_variable_ref (scm_c_lookup ("<self-slot>"));
1265 class_protected_opaque
= scm_variable_ref (scm_c_lookup ("<protected-opaque-slot>"));
1266 class_protected_hidden
= scm_variable_ref (scm_c_lookup ("<protected-hidden-slot>"));
1267 class_protected_read_only
= scm_variable_ref (scm_c_lookup ("<protected-read-only-slot>"));
1268 class_scm
= scm_variable_ref (scm_c_lookup ("<scm-slot>"));
1269 class_int
= scm_variable_ref (scm_c_lookup ("<int-slot>"));
1270 class_float
= scm_variable_ref (scm_c_lookup ("<float-slot>"));
1271 class_double
= scm_variable_ref (scm_c_lookup ("<double-slot>"));
1274 class_procedure_class
= scm_variable_ref (scm_c_lookup ("<procedure-class>"));
1275 class_applicable_struct_class
= scm_variable_ref (scm_c_lookup ("<applicable-struct-class>"));
1276 class_applicable_struct_with_setter_class
=
1277 scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter-class>"));
1279 class_method
= scm_variable_ref (scm_c_lookup ("<method>"));
1280 class_accessor_method
= scm_variable_ref (scm_c_lookup ("<accessor-method>"));
1281 class_applicable
= scm_variable_ref (scm_c_lookup ("<applicable>"));
1282 class_applicable_struct
= scm_variable_ref (scm_c_lookup ("<applicable-struct>"));
1283 class_applicable_struct_with_setter
= scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter>"));
1284 class_generic
= scm_variable_ref (scm_c_lookup ("<generic>"));
1285 class_extended_generic
= scm_variable_ref (scm_c_lookup ("<extended-generic>"));
1286 class_generic_with_setter
= scm_variable_ref (scm_c_lookup ("<generic-with-setter>"));
1287 class_accessor
= scm_variable_ref (scm_c_lookup ("<accessor>"));
1288 class_extended_generic_with_setter
= scm_variable_ref (scm_c_lookup ("<extended-generic-with-setter>"));
1289 class_extended_accessor
= scm_variable_ref (scm_c_lookup ("<extended-accessor>"));
1291 /* Primitive types classes */
1292 class_boolean
= scm_variable_ref (scm_c_lookup ("<boolean>"));
1293 class_char
= scm_variable_ref (scm_c_lookup ("<char>"));
1294 class_list
= scm_variable_ref (scm_c_lookup ("<list>"));
1295 class_pair
= scm_variable_ref (scm_c_lookup ("<pair>"));
1296 class_null
= scm_variable_ref (scm_c_lookup ("<null>"));
1297 class_string
= scm_variable_ref (scm_c_lookup ("<string>"));
1298 class_symbol
= scm_variable_ref (scm_c_lookup ("<symbol>"));
1299 class_vector
= scm_variable_ref (scm_c_lookup ("<vector>"));
1300 class_foreign
= scm_variable_ref (scm_c_lookup ("<foreign>"));
1301 class_hashtable
= scm_variable_ref (scm_c_lookup ("<hashtable>"));
1302 class_fluid
= scm_variable_ref (scm_c_lookup ("<fluid>"));
1303 class_dynamic_state
= scm_variable_ref (scm_c_lookup ("<dynamic-state>"));
1304 class_frame
= scm_variable_ref (scm_c_lookup ("<frame>"));
1305 class_vm_cont
= scm_variable_ref (scm_c_lookup ("<vm-continuation>"));
1306 class_bytevector
= scm_variable_ref (scm_c_lookup ("<bytevector>"));
1307 class_uvec
= scm_variable_ref (scm_c_lookup ("<uvec>"));
1308 class_array
= scm_variable_ref (scm_c_lookup ("<array>"));
1309 class_bitvector
= scm_variable_ref (scm_c_lookup ("<bitvector>"));
1310 class_number
= scm_variable_ref (scm_c_lookup ("<number>"));
1311 class_complex
= scm_variable_ref (scm_c_lookup ("<complex>"));
1312 class_real
= scm_variable_ref (scm_c_lookup ("<real>"));
1313 class_integer
= scm_variable_ref (scm_c_lookup ("<integer>"));
1314 class_fraction
= scm_variable_ref (scm_c_lookup ("<fraction>"));
1315 class_keyword
= scm_variable_ref (scm_c_lookup ("<keyword>"));
1316 class_unknown
= scm_variable_ref (scm_c_lookup ("<unknown>"));
1317 class_procedure
= scm_variable_ref (scm_c_lookup ("<procedure>"));
1318 class_primitive_generic
= scm_variable_ref (scm_c_lookup ("<primitive-generic>"));
1319 class_port
= scm_variable_ref (scm_c_lookup ("<port>"));
1320 class_input_port
= scm_variable_ref (scm_c_lookup ("<input-port>"));
1321 class_output_port
= scm_variable_ref (scm_c_lookup ("<output-port>"));
1322 class_input_output_port
= scm_variable_ref (scm_c_lookup ("<input-output-port>"));
1324 create_smob_classes ();
1325 create_struct_classes ();
1326 create_port_classes ();
1328 return SCM_UNSPECIFIED
;
1332 SCM_DEFINE (scm_sys_goops_loaded
, "%goops-loaded", 0, 0, 0,
1334 "Announce that GOOPS is loaded and perform initialization\n"
1335 "on the C level which depends on the loaded GOOPS modules.")
1336 #define FUNC_NAME s_scm_sys_goops_loaded
1339 var_class_name
= scm_c_lookup ("class-name");
1340 var_class_direct_supers
= scm_c_lookup ("class-direct-supers");
1341 var_class_direct_slots
= scm_c_lookup ("class-direct-slots");
1342 var_class_direct_subclasses
= scm_c_lookup ("class-direct-subclasses");
1343 var_class_direct_methods
= scm_c_lookup ("class-direct-methods");
1344 var_class_precedence_list
= scm_c_lookup ("class-precedence-list");
1345 var_class_slots
= scm_c_lookup ("class-slots");
1347 var_generic_function_methods
= scm_c_lookup ("generic-function-methods");
1348 var_method_generic_function
= scm_c_lookup ("method-generic-function");
1349 var_method_specializers
= scm_c_lookup ("method-specializers");
1350 var_method_procedure
= scm_c_lookup ("method-procedure");
1352 var_change_class
= scm_c_lookup ("change-class");
1354 #if (SCM_ENABLE_DEPRECATED == 1)
1355 scm_init_deprecated_goops ();
1358 return SCM_UNSPECIFIED
;
1362 SCM scm_module_goops
;
1365 scm_init_goops_builtins (void *unused
)
1367 scm_module_goops
= scm_current_module ();
1369 hell
= scm_calloc (hell_size
* sizeof (*hell
));
1370 hell_mutex
= scm_make_mutex ();
1372 #include "libguile/goops.x"
1378 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION
,
1379 "scm_init_goops_builtins", scm_init_goops_builtins
,