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 SCM_KEYWORD (k_name
, "name");
71 SCM_KEYWORD (k_setter
, "setter");
72 SCM_SYMBOL (sym_redefined
, "redefined");
73 SCM_GLOBAL_SYMBOL (scm_sym_args
, "args");
75 static int goops_loaded_p
= 0;
77 static SCM var_make_standard_class
= SCM_BOOL_F
;
78 static SCM var_change_class
= SCM_BOOL_F
;
79 static SCM var_make
= SCM_BOOL_F
;
80 static SCM var_inherit_applicable
= SCM_BOOL_F
;
81 static SCM var_class_name
= SCM_BOOL_F
;
82 static SCM var_class_direct_supers
= SCM_BOOL_F
;
83 static SCM var_class_direct_slots
= SCM_BOOL_F
;
84 static SCM var_class_direct_subclasses
= SCM_BOOL_F
;
85 static SCM var_class_direct_methods
= SCM_BOOL_F
;
86 static SCM var_class_precedence_list
= SCM_BOOL_F
;
87 static SCM var_class_slots
= SCM_BOOL_F
;
89 static SCM var_generic_function_methods
= SCM_BOOL_F
;
90 static SCM var_method_generic_function
= SCM_BOOL_F
;
91 static SCM var_method_specializers
= SCM_BOOL_F
;
92 static SCM var_method_procedure
= SCM_BOOL_F
;
94 static SCM var_slot_ref
= SCM_BOOL_F
;
95 static SCM var_slot_set_x
= SCM_BOOL_F
;
96 static SCM var_slot_bound_p
= SCM_BOOL_F
;
97 static SCM var_slot_exists_p
= SCM_BOOL_F
;
99 /* These variables are filled in by the object system when loaded. */
100 static SCM class_boolean
, class_char
, class_pair
;
101 static SCM class_procedure
, class_string
, class_symbol
;
102 static SCM class_primitive_generic
;
103 static SCM class_vector
, class_null
;
104 static SCM class_integer
, class_real
, class_complex
, class_fraction
;
105 static SCM class_unknown
;
106 static SCM class_top
, class_object
, class_class
;
107 static SCM class_applicable
;
108 static SCM class_applicable_struct
, class_applicable_struct_with_setter
;
109 static SCM class_generic
, class_generic_with_setter
;
110 static SCM class_accessor
;
111 static SCM class_extended_generic
, class_extended_generic_with_setter
;
112 static SCM class_extended_accessor
;
113 static SCM class_method
;
114 static SCM class_accessor_method
;
115 static SCM class_procedure_class
;
116 static SCM class_applicable_struct_class
;
117 static SCM class_applicable_struct_with_setter_class
;
118 static SCM class_number
, class_list
;
119 static SCM class_keyword
;
120 static SCM class_port
, class_input_output_port
;
121 static SCM class_input_port
, class_output_port
;
122 static SCM class_foreign_slot
;
123 static SCM class_self
, class_protected
;
124 static SCM class_hidden
, class_opaque
, class_read_only
;
125 static SCM class_protected_hidden
, class_protected_opaque
, class_protected_read_only
;
126 static SCM class_scm
;
127 static SCM class_int
, class_float
, class_double
;
129 static SCM class_foreign
;
130 static SCM class_hashtable
;
131 static SCM class_fluid
;
132 static SCM class_dynamic_state
;
133 static SCM class_frame
;
134 static SCM class_vm_cont
;
135 static SCM class_bytevector
;
136 static SCM class_uvec
;
137 static SCM class_array
;
138 static SCM class_bitvector
;
140 static SCM vtable_class_map
= SCM_BOOL_F
;
142 /* Port classes. Allocate 3 times the maximum number of port types so that
143 input ports, output ports, and in/out ports can be stored at different
144 offsets. See `SCM_IN_PCLASS_INDEX' et al. */
145 SCM scm_i_port_class
[3 * SCM_I_MAX_PORT_TYPE_COUNT
];
148 SCM scm_i_smob_class
[SCM_I_MAX_SMOB_TYPE_COUNT
];
150 SCM scm_module_goops
;
152 static SCM
scm_make_unbound (void);
153 static SCM
scm_unbound_p (SCM obj
);
154 static SCM
scm_sys_make_vtable_vtable (SCM layout
);
155 static SCM
scm_sys_init_layout_x (SCM
class, SCM layout
);
156 static SCM
scm_sys_clear_fields_x (SCM obj
);
157 static SCM
scm_sys_goops_early_init (void);
158 static SCM
scm_sys_goops_loaded (void);
163 SCM_DEFINE (scm_sys_make_vtable_vtable
, "%make-vtable-vtable", 1, 0, 0,
166 #define FUNC_NAME s_scm_sys_make_vtable_vtable
168 return scm_i_make_vtable_vtable (layout
);
173 scm_make_standard_class (SCM meta
, SCM name
, SCM dsupers
, SCM dslots
)
175 return scm_call_4 (scm_variable_ref (var_make_standard_class
),
176 meta
, name
, dsupers
, dslots
);
179 SCM_DEFINE (scm_sys_init_layout_x
, "%init-layout!", 2, 0, 0,
180 (SCM
class, SCM layout
),
182 #define FUNC_NAME s_scm_sys_init_layout_x
184 SCM_VALIDATE_INSTANCE (1, class);
185 SCM_ASSERT (!scm_is_symbol (SCM_VTABLE_LAYOUT (class)), class, 1, FUNC_NAME
);
186 SCM_VALIDATE_STRING (2, layout
);
188 SCM_SET_VTABLE_LAYOUT (class, scm_make_struct_layout (layout
));
189 scm_i_struct_inherit_vtable_magic (SCM_CLASS_OF (class), class);
190 SCM_SET_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_OR_VALID
);
192 return SCM_UNSPECIFIED
;
199 /* This function is used for efficient type dispatch. */
200 SCM_DEFINE (scm_class_of
, "class-of", 1, 0, 0,
202 "Return the class of @var{x}.")
203 #define FUNC_NAME s_scm_class_of
205 switch (SCM_ITAG3 (x
))
209 return class_integer
;
214 else if (scm_is_bool (x
))
215 return class_boolean
;
216 else if (scm_is_null (x
))
219 return class_unknown
;
222 switch (SCM_TYP7 (x
))
224 case scm_tcs_cons_nimcar
:
231 case scm_tc7_pointer
:
232 return class_foreign
;
233 case scm_tc7_hashtable
:
234 return class_hashtable
;
237 case scm_tc7_dynamic_state
:
238 return class_dynamic_state
;
241 case scm_tc7_keyword
:
242 return class_keyword
;
243 case scm_tc7_vm_cont
:
244 return class_vm_cont
;
245 case scm_tc7_bytevector
:
246 if (SCM_BYTEVECTOR_ELEMENT_TYPE (x
) == SCM_ARRAY_ELEMENT_TYPE_VU8
)
247 return class_bytevector
;
252 case scm_tc7_bitvector
:
253 return class_bitvector
;
257 switch SCM_TYP16 (x
) {
259 return class_integer
;
262 case scm_tc16_complex
:
263 return class_complex
;
264 case scm_tc16_fraction
:
265 return class_fraction
;
267 case scm_tc7_program
:
268 if (SCM_PROGRAM_IS_PRIMITIVE_GENERIC (x
)
269 && SCM_UNPACK (*SCM_SUBR_GENERIC (x
)))
270 return class_primitive_generic
;
272 return class_procedure
;
276 scm_t_bits type
= SCM_TYP16 (x
);
277 if (type
!= scm_tc16_port_with_ps
)
278 return scm_i_smob_class
[SCM_TC2SMOBNUM (type
)];
279 x
= SCM_PORT_WITH_PS_PORT (x
);
280 /* fall through to ports */
283 return scm_i_port_class
[(SCM_WRTNG
& SCM_CELL_WORD_0 (x
)
284 ? (SCM_RDNG
& SCM_CELL_WORD_0 (x
)
285 ? SCM_INOUT_PCLASS_INDEX
| SCM_PTOBNUM (x
)
286 : SCM_OUT_PCLASS_INDEX
| SCM_PTOBNUM (x
))
287 : SCM_IN_PCLASS_INDEX
| SCM_PTOBNUM (x
))];
289 if (SCM_OBJ_CLASS_FLAGS (x
) & SCM_CLASSF_GOOPS_VALID
)
290 /* A GOOPS object with a valid class. */
291 return SCM_CLASS_OF (x
);
292 else if (SCM_OBJ_CLASS_FLAGS (x
) & SCM_CLASSF_GOOPS
)
293 /* A GOOPS object whose class might have been redefined. */
295 SCM
class = SCM_CLASS_OF (x
);
296 SCM new_class
= scm_slot_ref (class, sym_redefined
);
297 if (!scm_is_false (new_class
))
298 scm_change_object_class (x
, class, new_class
);
299 /* Re-load class from instance. */
300 return SCM_CLASS_OF (x
);
303 return scm_i_define_class_for_vtable (SCM_CLASS_OF (x
));
308 return class_unknown
;
314 /* case scm_tc3_unused: */
318 return class_unknown
;
325 SCM_DEFINE (scm_instance_p
, "instance?", 1, 0, 0,
327 "Return @code{#t} if @var{obj} is an instance.")
328 #define FUNC_NAME s_scm_instance_p
330 return scm_from_bool (SCM_INSTANCEP (obj
));
335 scm_is_generic (SCM x
)
337 return SCM_INSTANCEP (x
) && SCM_SUBCLASSP (SCM_CLASS_OF (x
), class_generic
);
341 scm_is_method (SCM x
)
343 return SCM_INSTANCEP (x
) && SCM_SUBCLASSP (SCM_CLASS_OF (x
), class_method
);
350 scm_class_name (SCM obj
)
352 return scm_call_1 (scm_variable_ref (var_class_name
), obj
);
356 scm_class_direct_supers (SCM obj
)
358 return scm_call_1 (scm_variable_ref (var_class_direct_supers
), obj
);
362 scm_class_direct_slots (SCM obj
)
364 return scm_call_1 (scm_variable_ref (var_class_direct_slots
), obj
);
368 scm_class_direct_subclasses (SCM obj
)
370 return scm_call_1 (scm_variable_ref (var_class_direct_subclasses
), obj
);
374 scm_class_direct_methods (SCM obj
)
376 return scm_call_1 (scm_variable_ref (var_class_direct_methods
), obj
);
380 scm_class_precedence_list (SCM obj
)
382 return scm_call_1 (scm_variable_ref (var_class_precedence_list
), obj
);
386 scm_class_slots (SCM obj
)
388 return scm_call_1 (scm_variable_ref (var_class_slots
), obj
);
394 SCM_DEFINE (scm_generic_function_name
, "generic-function-name", 1, 0, 0,
396 "Return the name of the generic function @var{obj}.")
397 #define FUNC_NAME s_scm_generic_function_name
399 SCM_VALIDATE_GENERIC (1, obj
);
400 return scm_procedure_property (obj
, scm_sym_name
);
405 scm_generic_function_methods (SCM obj
)
407 return scm_call_1 (scm_variable_ref (var_generic_function_methods
), obj
);
411 scm_method_generic_function (SCM obj
)
413 return scm_call_1 (scm_variable_ref (var_method_generic_function
), obj
);
417 scm_method_specializers (SCM obj
)
419 return scm_call_1 (scm_variable_ref (var_method_specializers
), obj
);
423 scm_method_procedure (SCM obj
)
425 return scm_call_1 (scm_variable_ref (var_method_procedure
), obj
);
431 SCM_DEFINE (scm_make_unbound
, "make-unbound", 0, 0, 0,
433 "Return the unbound value.")
434 #define FUNC_NAME s_scm_make_unbound
436 return SCM_GOOPS_UNBOUND
;
440 SCM_DEFINE (scm_unbound_p
, "unbound?", 1, 0, 0,
442 "Return @code{#t} if @var{obj} is unbound.")
443 #define FUNC_NAME s_scm_unbound_p
445 return SCM_GOOPS_UNBOUNDP (obj
) ? SCM_BOOL_T
: SCM_BOOL_F
;
453 scm_slot_ref (SCM obj
, SCM slot_name
)
455 return scm_call_2 (scm_variable_ref (var_slot_ref
), obj
, slot_name
);
459 scm_slot_set_x (SCM obj
, SCM slot_name
, SCM value
)
461 return scm_call_3 (scm_variable_ref (var_slot_set_x
), obj
, slot_name
, value
);
465 scm_slot_bound_p (SCM obj
, SCM slot_name
)
467 return scm_call_2 (scm_variable_ref (var_slot_bound_p
), obj
, slot_name
);
471 scm_slot_exists_p (SCM obj
, SCM slot_name
)
473 return scm_call_2 (scm_variable_ref (var_slot_exists_p
), obj
, slot_name
);
479 SCM_DEFINE (scm_sys_clear_fields_x
, "%clear-fields!", 1, 0, 0,
482 #define FUNC_NAME s_scm_sys_clear_fields_x
484 scm_t_signed_bits n
, i
;
487 SCM_VALIDATE_STRUCT (1, obj
);
488 vtable
= SCM_STRUCT_VTABLE (obj
);
490 n
= SCM_STRUCT_DATA_REF (vtable
, scm_vtable_index_size
);
491 layout
= SCM_VTABLE_LAYOUT (vtable
);
493 /* Set all SCM-holding slots to the GOOPS unbound value. */
494 for (i
= 0; i
< n
; i
++)
495 if (scm_i_symbol_ref (layout
, i
*2) == 'p')
496 SCM_STRUCT_SLOT_SET (obj
, i
, SCM_GOOPS_UNBOUND
);
498 return SCM_UNSPECIFIED
;
505 SCM_DEFINE (scm_sys_modify_instance
, "%modify-instance", 2, 0, 0,
507 "Used by change-class to modify objects in place.")
508 #define FUNC_NAME s_scm_sys_modify_instance
510 SCM_VALIDATE_INSTANCE (1, old
);
511 SCM_VALIDATE_INSTANCE (2, new);
513 /* Exchange the data contained in old and new. We exchange rather than
514 * scratch the old value with new to be correct with GC.
515 * See "Class redefinition protocol above".
517 SCM_CRITICAL_SECTION_START
;
519 scm_t_bits word0
, word1
;
520 word0
= SCM_CELL_WORD_0 (old
);
521 word1
= SCM_CELL_WORD_1 (old
);
522 SCM_SET_CELL_WORD_0 (old
, SCM_CELL_WORD_0 (new));
523 SCM_SET_CELL_WORD_1 (old
, SCM_CELL_WORD_1 (new));
524 SCM_SET_CELL_WORD_0 (new, word0
);
525 SCM_SET_CELL_WORD_1 (new, word1
);
527 SCM_CRITICAL_SECTION_END
;
528 return SCM_UNSPECIFIED
;
532 SCM_DEFINE (scm_sys_modify_class
, "%modify-class", 2, 0, 0,
535 #define FUNC_NAME s_scm_sys_modify_class
537 SCM_VALIDATE_CLASS (1, old
);
538 SCM_VALIDATE_CLASS (2, new);
540 SCM_CRITICAL_SECTION_START
;
542 scm_t_bits word0
, word1
;
543 word0
= SCM_CELL_WORD_0 (old
);
544 word1
= SCM_CELL_WORD_1 (old
);
545 SCM_SET_CELL_WORD_0 (old
, SCM_CELL_WORD_0 (new));
546 SCM_SET_CELL_WORD_1 (old
, SCM_CELL_WORD_1 (new));
547 SCM_STRUCT_DATA (old
)[scm_vtable_index_self
] = SCM_UNPACK (old
);
548 SCM_SET_CELL_WORD_0 (new, word0
);
549 SCM_SET_CELL_WORD_1 (new, word1
);
550 SCM_STRUCT_DATA (new)[scm_vtable_index_self
] = SCM_UNPACK (new);
552 SCM_CRITICAL_SECTION_END
;
553 return SCM_UNSPECIFIED
;
557 /* When instances change class, they finally get a new body, but
558 * before that, they go through purgatory in hell. Odd as it may
559 * seem, this data structure saves us from eternal suffering in
560 * infinite recursions.
563 static scm_t_bits
**hell
;
564 static long n_hell
= 1; /* one place for the evil one himself */
565 static long hell_size
= 4;
566 static SCM hell_mutex
;
572 for (i
= 1; i
< n_hell
; ++i
)
573 if (SCM_STRUCT_DATA (o
) == hell
[i
])
582 scm_lock_mutex (hell_mutex
);
583 if (n_hell
>= hell_size
)
586 hell
= scm_realloc (hell
, hell_size
* sizeof(*hell
));
588 hell
[n_hell
++] = SCM_STRUCT_DATA (obj
);
589 scm_unlock_mutex (hell_mutex
);
593 go_to_heaven (void *o
)
596 scm_lock_mutex (hell_mutex
);
597 hell
[burnin (obj
)] = hell
[--n_hell
];
598 scm_unlock_mutex (hell_mutex
);
603 purgatory (SCM obj
, SCM new_class
)
605 return scm_call_2 (SCM_VARIABLE_REF (var_change_class
), obj
, new_class
);
608 /* This function calls the generic function change-class for all
609 * instances which aren't currently undergoing class change.
613 scm_change_object_class (SCM obj
, SCM old_class SCM_UNUSED
, SCM new_class
)
617 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE
);
618 scm_dynwind_rewind_handler (go_to_hell
, &obj
, SCM_F_WIND_EXPLICITLY
);
619 scm_dynwind_unwind_handler (go_to_heaven
, &obj
, SCM_F_WIND_EXPLICITLY
);
620 purgatory (obj
, new_class
);
628 /* Primitive generics: primitives that can dispatch to generics if their
629 arguments fail to apply. */
631 SCM_DEFINE (scm_generic_capability_p
, "generic-capability?", 1, 0, 0,
634 #define FUNC_NAME s_scm_generic_capability_p
636 SCM_ASSERT (scm_is_true (scm_procedure_p (proc
)),
637 proc
, SCM_ARG1
, FUNC_NAME
);
638 return (SCM_PRIMITIVE_GENERIC_P (proc
) ? SCM_BOOL_T
: SCM_BOOL_F
);
642 SCM_DEFINE (scm_enable_primitive_generic_x
, "enable-primitive-generic!", 0, 0, 1,
645 #define FUNC_NAME s_scm_enable_primitive_generic_x
647 SCM_VALIDATE_REST_ARGUMENT (subrs
);
648 while (!scm_is_null (subrs
))
650 SCM subr
= SCM_CAR (subrs
);
651 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr
), subr
, SCM_ARGn
, FUNC_NAME
);
652 SCM_SET_SUBR_GENERIC (subr
,
653 scm_make (scm_list_3 (class_generic
,
655 SCM_SUBR_NAME (subr
))));
656 subrs
= SCM_CDR (subrs
);
658 return SCM_UNSPECIFIED
;
662 SCM_DEFINE (scm_set_primitive_generic_x
, "set-primitive-generic!", 2, 0, 0,
663 (SCM subr
, SCM generic
),
665 #define FUNC_NAME s_scm_set_primitive_generic_x
667 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr
), subr
, SCM_ARG1
, FUNC_NAME
);
668 SCM_ASSERT (SCM_GENERICP (generic
), generic
, SCM_ARG2
, FUNC_NAME
);
669 SCM_SET_SUBR_GENERIC (subr
, generic
);
670 return SCM_UNSPECIFIED
;
674 SCM_DEFINE (scm_primitive_generic_generic
, "primitive-generic-generic", 1, 0, 0,
677 #define FUNC_NAME s_scm_primitive_generic_generic
679 if (SCM_PRIMITIVE_GENERIC_P (subr
))
681 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (subr
)))
682 scm_enable_primitive_generic_x (scm_list_1 (subr
));
683 return *SCM_SUBR_GENERIC (subr
);
685 SCM_WRONG_TYPE_ARG (SCM_ARG1
, subr
);
690 scm_wta_dispatch_0 (SCM gf
, const char *subr
)
692 if (!SCM_UNPACK (gf
))
693 scm_error_num_args_subr (subr
);
695 return scm_call_0 (gf
);
699 scm_wta_dispatch_1 (SCM gf
, SCM a1
, int pos
, const char *subr
)
701 if (!SCM_UNPACK (gf
))
702 scm_wrong_type_arg (subr
, pos
, a1
);
704 return scm_call_1 (gf
, a1
);
708 scm_wta_dispatch_2 (SCM gf
, SCM a1
, SCM a2
, int pos
, const char *subr
)
710 if (!SCM_UNPACK (gf
))
711 scm_wrong_type_arg (subr
, pos
, (pos
== SCM_ARG1
) ? a1
: a2
);
713 return scm_call_2 (gf
, a1
, a2
);
717 scm_wta_dispatch_n (SCM gf
, SCM args
, int pos
, const char *subr
)
719 if (!SCM_UNPACK (gf
))
720 scm_wrong_type_arg (subr
, pos
, scm_list_ref (args
, scm_from_int (pos
)));
722 return scm_apply_0 (gf
, args
);
731 return scm_apply_0 (scm_variable_ref (var_make
), args
);
737 /* SMOB, struct, and port classes. */
740 make_class_name (const char *prefix
, const char *type_name
, const char *suffix
)
744 return scm_string_to_symbol (scm_string_append
745 (scm_list_3 (scm_from_utf8_string (prefix
),
746 scm_from_utf8_string (type_name
),
747 scm_from_utf8_string (suffix
))));
751 scm_make_extended_class (char const *type_name
, int applicablep
)
753 SCM name
, meta
, supers
;
755 name
= make_class_name ("<", type_name
, ">");
759 supers
= scm_list_1 (class_applicable
);
761 supers
= scm_list_1 (class_top
);
763 return scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
767 scm_i_inherit_applicable (SCM c
)
769 scm_call_1 (scm_variable_ref (var_inherit_applicable
), c
);
773 create_smob_classes (void)
777 for (i
= 0; i
< SCM_I_MAX_SMOB_TYPE_COUNT
; ++i
)
778 scm_i_smob_class
[i
] = SCM_BOOL_F
;
780 for (i
= 0; i
< scm_numsmob
; ++i
)
781 if (scm_is_false (scm_i_smob_class
[i
]))
782 scm_i_smob_class
[i
] = scm_make_extended_class (SCM_SMOBNAME (i
),
783 scm_smobs
[i
].apply
!= 0);
787 scm_make_port_classes (long ptobnum
, char *type_name
)
789 SCM name
, meta
, super
, supers
;
793 name
= make_class_name ("<", type_name
, "-port>");
794 supers
= scm_list_1 (class_port
);
795 super
= scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
797 name
= make_class_name ("<", type_name
, "-input-port>");
798 supers
= scm_list_2 (super
, class_input_port
);
799 scm_i_port_class
[SCM_IN_PCLASS_INDEX
+ ptobnum
]
800 = scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
802 name
= make_class_name ("<", type_name
, "-output-port>");
803 supers
= scm_list_2 (super
, class_output_port
);
804 scm_i_port_class
[SCM_OUT_PCLASS_INDEX
+ ptobnum
]
805 = scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
807 name
= make_class_name ("<", type_name
, "-input-output-port>");
808 supers
= scm_list_2 (super
, class_input_output_port
);
809 scm_i_port_class
[SCM_INOUT_PCLASS_INDEX
+ ptobnum
]
810 = scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
814 create_port_classes (void)
818 for (i
= scm_c_num_port_types () - 1; i
>= 0; i
--)
819 scm_make_port_classes (i
, SCM_PTOBNAME (i
));
823 scm_i_define_class_for_vtable (SCM vtable
)
827 scm_i_pthread_mutex_lock (&scm_i_misc_mutex
);
828 if (scm_is_false (vtable_class_map
))
829 vtable_class_map
= scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY
);
830 scm_i_pthread_mutex_unlock (&scm_i_misc_mutex
);
832 if (scm_is_false (scm_struct_vtable_p (vtable
)))
835 class = scm_weak_table_refq (vtable_class_map
, vtable
, SCM_BOOL_F
);
837 if (scm_is_false (class))
839 if (SCM_UNPACK (class_class
))
841 SCM name
, meta
, supers
;
843 name
= SCM_VTABLE_NAME (vtable
);
844 if (scm_is_symbol (name
))
845 name
= scm_string_to_symbol
847 (scm_list_3 (scm_from_latin1_string ("<"),
848 scm_symbol_to_string (name
),
849 scm_from_latin1_string (">"))));
851 name
= scm_from_latin1_symbol ("<>");
853 if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable
, SCM_VTABLE_FLAG_SETTER
))
855 meta
= class_applicable_struct_with_setter_class
;
856 supers
= scm_list_1 (class_applicable_struct_with_setter
);
858 else if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable
,
859 SCM_VTABLE_FLAG_APPLICABLE
))
861 meta
= class_applicable_struct_class
;
862 supers
= scm_list_1 (class_applicable_struct
);
867 supers
= scm_list_1 (class_top
);
870 return scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
873 /* `create_struct_classes' will fill this in later. */
876 /* Don't worry about races. This only happens when creating a
877 vtable, which happens by definition in one thread. */
878 scm_weak_table_putq_x (vtable_class_map
, vtable
, class);
885 make_struct_class (void *closure SCM_UNUSED
,
886 SCM vtable
, SCM data
, SCM prev SCM_UNUSED
)
888 if (scm_is_false (data
))
889 scm_i_define_class_for_vtable (vtable
);
890 return SCM_UNSPECIFIED
;
894 create_struct_classes (void)
896 /* FIXME: take the vtable_class_map while initializing goops? */
897 scm_internal_hash_fold (make_struct_class
, 0, SCM_BOOL_F
,
908 scm_c_resolve_module ("oop goops");
912 scm_ensure_accessor (SCM name
)
916 var
= scm_module_variable (scm_current_module (), name
);
917 if (SCM_VARIABLEP (var
) && !SCM_UNBNDP (SCM_VARIABLE_REF (var
)))
918 gf
= SCM_VARIABLE_REF (var
);
922 if (!SCM_IS_A_P (gf
, class_accessor
))
924 gf
= scm_make (scm_list_3 (class_generic
, k_name
, name
));
925 gf
= scm_make (scm_list_5 (class_accessor
,
926 k_name
, name
, k_setter
, gf
));
935 SCM_DEFINE (scm_sys_goops_early_init
, "%goops-early-init", 0, 0, 0,
938 #define FUNC_NAME s_scm_sys_goops_early_init
940 var_make_standard_class
= scm_c_lookup ("make-standard-class");
941 var_make
= scm_c_lookup ("make");
942 var_inherit_applicable
= scm_c_lookup ("inherit-applicable!");
944 /* For SCM_SUBCLASSP. */
945 var_class_precedence_list
= scm_c_lookup ("class-precedence-list");
947 var_slot_ref
= scm_c_lookup ("slot-ref");
948 var_slot_set_x
= scm_c_lookup ("slot-set!");
949 var_slot_bound_p
= scm_c_lookup ("slot-bound?");
950 var_slot_exists_p
= scm_c_lookup ("slot-exists?");
952 class_class
= scm_variable_ref (scm_c_lookup ("<class>"));
953 class_top
= scm_variable_ref (scm_c_lookup ("<top>"));
954 class_object
= scm_variable_ref (scm_c_lookup ("<object>"));
956 class_foreign_slot
= scm_variable_ref (scm_c_lookup ("<foreign-slot>"));
957 class_protected
= scm_variable_ref (scm_c_lookup ("<protected-slot>"));
958 class_hidden
= scm_variable_ref (scm_c_lookup ("<hidden-slot>"));
959 class_opaque
= scm_variable_ref (scm_c_lookup ("<opaque-slot>"));
960 class_read_only
= scm_variable_ref (scm_c_lookup ("<read-only-slot>"));
961 class_self
= scm_variable_ref (scm_c_lookup ("<self-slot>"));
962 class_protected_opaque
= scm_variable_ref (scm_c_lookup ("<protected-opaque-slot>"));
963 class_protected_hidden
= scm_variable_ref (scm_c_lookup ("<protected-hidden-slot>"));
964 class_protected_read_only
= scm_variable_ref (scm_c_lookup ("<protected-read-only-slot>"));
965 class_scm
= scm_variable_ref (scm_c_lookup ("<scm-slot>"));
966 class_int
= scm_variable_ref (scm_c_lookup ("<int-slot>"));
967 class_float
= scm_variable_ref (scm_c_lookup ("<float-slot>"));
968 class_double
= scm_variable_ref (scm_c_lookup ("<double-slot>"));
971 class_procedure_class
= scm_variable_ref (scm_c_lookup ("<procedure-class>"));
972 class_applicable_struct_class
= scm_variable_ref (scm_c_lookup ("<applicable-struct-class>"));
973 class_applicable_struct_with_setter_class
=
974 scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter-class>"));
976 class_method
= scm_variable_ref (scm_c_lookup ("<method>"));
977 class_accessor_method
= scm_variable_ref (scm_c_lookup ("<accessor-method>"));
978 class_applicable
= scm_variable_ref (scm_c_lookup ("<applicable>"));
979 class_applicable_struct
= scm_variable_ref (scm_c_lookup ("<applicable-struct>"));
980 class_applicable_struct_with_setter
= scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter>"));
981 class_generic
= scm_variable_ref (scm_c_lookup ("<generic>"));
982 class_extended_generic
= scm_variable_ref (scm_c_lookup ("<extended-generic>"));
983 class_generic_with_setter
= scm_variable_ref (scm_c_lookup ("<generic-with-setter>"));
984 class_accessor
= scm_variable_ref (scm_c_lookup ("<accessor>"));
985 class_extended_generic_with_setter
= scm_variable_ref (scm_c_lookup ("<extended-generic-with-setter>"));
986 class_extended_accessor
= scm_variable_ref (scm_c_lookup ("<extended-accessor>"));
988 /* Primitive types classes */
989 class_boolean
= scm_variable_ref (scm_c_lookup ("<boolean>"));
990 class_char
= scm_variable_ref (scm_c_lookup ("<char>"));
991 class_list
= scm_variable_ref (scm_c_lookup ("<list>"));
992 class_pair
= scm_variable_ref (scm_c_lookup ("<pair>"));
993 class_null
= scm_variable_ref (scm_c_lookup ("<null>"));
994 class_string
= scm_variable_ref (scm_c_lookup ("<string>"));
995 class_symbol
= scm_variable_ref (scm_c_lookup ("<symbol>"));
996 class_vector
= scm_variable_ref (scm_c_lookup ("<vector>"));
997 class_foreign
= scm_variable_ref (scm_c_lookup ("<foreign>"));
998 class_hashtable
= scm_variable_ref (scm_c_lookup ("<hashtable>"));
999 class_fluid
= scm_variable_ref (scm_c_lookup ("<fluid>"));
1000 class_dynamic_state
= scm_variable_ref (scm_c_lookup ("<dynamic-state>"));
1001 class_frame
= scm_variable_ref (scm_c_lookup ("<frame>"));
1002 class_vm_cont
= scm_variable_ref (scm_c_lookup ("<vm-continuation>"));
1003 class_bytevector
= scm_variable_ref (scm_c_lookup ("<bytevector>"));
1004 class_uvec
= scm_variable_ref (scm_c_lookup ("<uvec>"));
1005 class_array
= scm_variable_ref (scm_c_lookup ("<array>"));
1006 class_bitvector
= scm_variable_ref (scm_c_lookup ("<bitvector>"));
1007 class_number
= scm_variable_ref (scm_c_lookup ("<number>"));
1008 class_complex
= scm_variable_ref (scm_c_lookup ("<complex>"));
1009 class_real
= scm_variable_ref (scm_c_lookup ("<real>"));
1010 class_integer
= scm_variable_ref (scm_c_lookup ("<integer>"));
1011 class_fraction
= scm_variable_ref (scm_c_lookup ("<fraction>"));
1012 class_keyword
= scm_variable_ref (scm_c_lookup ("<keyword>"));
1013 class_unknown
= scm_variable_ref (scm_c_lookup ("<unknown>"));
1014 class_procedure
= scm_variable_ref (scm_c_lookup ("<procedure>"));
1015 class_primitive_generic
= scm_variable_ref (scm_c_lookup ("<primitive-generic>"));
1016 class_port
= scm_variable_ref (scm_c_lookup ("<port>"));
1017 class_input_port
= scm_variable_ref (scm_c_lookup ("<input-port>"));
1018 class_output_port
= scm_variable_ref (scm_c_lookup ("<output-port>"));
1019 class_input_output_port
= scm_variable_ref (scm_c_lookup ("<input-output-port>"));
1021 create_smob_classes ();
1022 create_struct_classes ();
1023 create_port_classes ();
1025 return SCM_UNSPECIFIED
;
1029 SCM_DEFINE (scm_sys_goops_loaded
, "%goops-loaded", 0, 0, 0,
1031 "Announce that GOOPS is loaded and perform initialization\n"
1032 "on the C level which depends on the loaded GOOPS modules.")
1033 #define FUNC_NAME s_scm_sys_goops_loaded
1036 var_class_name
= scm_c_lookup ("class-name");
1037 var_class_direct_supers
= scm_c_lookup ("class-direct-supers");
1038 var_class_direct_slots
= scm_c_lookup ("class-direct-slots");
1039 var_class_direct_subclasses
= scm_c_lookup ("class-direct-subclasses");
1040 var_class_direct_methods
= scm_c_lookup ("class-direct-methods");
1041 var_class_slots
= scm_c_lookup ("class-slots");
1043 var_generic_function_methods
= scm_c_lookup ("generic-function-methods");
1044 var_method_generic_function
= scm_c_lookup ("method-generic-function");
1045 var_method_specializers
= scm_c_lookup ("method-specializers");
1046 var_method_procedure
= scm_c_lookup ("method-procedure");
1048 var_change_class
= scm_c_lookup ("change-class");
1050 #if (SCM_ENABLE_DEPRECATED == 1)
1051 scm_init_deprecated_goops ();
1054 return SCM_UNSPECIFIED
;
1059 scm_init_goops_builtins (void *unused
)
1061 scm_module_goops
= scm_current_module ();
1063 hell
= scm_calloc (hell_size
* sizeof (*hell
));
1064 hell_mutex
= scm_make_mutex ();
1066 #include "libguile/goops.x"
1068 scm_c_define ("vtable-flag-vtable",
1069 scm_from_int (SCM_VTABLE_FLAG_VTABLE
));
1070 scm_c_define ("vtable-flag-applicable-vtable",
1071 scm_from_int (SCM_VTABLE_FLAG_APPLICABLE_VTABLE
));
1072 scm_c_define ("vtable-flag-setter-vtable",
1073 scm_from_int (SCM_VTABLE_FLAG_SETTER_VTABLE
));
1074 scm_c_define ("vtable-flag-validated",
1075 scm_from_int (SCM_VTABLE_FLAG_VALIDATED
));
1076 scm_c_define ("vtable-flag-goops-class",
1077 scm_from_int (SCM_VTABLE_FLAG_GOOPS_CLASS
));
1078 scm_c_define ("vtable-flag-goops-valid",
1079 scm_from_int (SCM_VTABLE_FLAG_GOOPS_VALID
));
1085 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION
,
1086 "scm_init_goops_builtins", scm_init_goops_builtins
,