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 /* Objects have identity, so references to classes and instances are by
59 value, not by reference. Redefinition of a class or modification of
60 an instance causes in-place update; you can think of GOOPS as
61 building in its own indirection, and for that reason referring to
62 GOOPS values by variable reference is unnecessary.
64 References to ordinary procedures is by reference (by variable),
65 though, as in the rest of Guile. */
67 static SCM var_make_standard_class
= SCM_BOOL_F
;
68 static SCM var_slot_unbound
= SCM_BOOL_F
;
69 static SCM var_slot_missing
= SCM_BOOL_F
;
70 static SCM var_change_class
= SCM_BOOL_F
;
71 static SCM var_make
= SCM_BOOL_F
;
73 SCM_SYMBOL (sym_slot_unbound
, "slot-unbound");
74 SCM_SYMBOL (sym_slot_missing
, "slot-missing");
75 SCM_SYMBOL (sym_change_class
, "change-class");
77 SCM_VARIABLE (scm_var_make_extended_generic
, "make-extended-generic");
80 /* Class redefinition protocol:
82 A class is represented by a heap header h1 which points to a
83 malloc:ed memory block m1.
85 When a new version of a class is created, a new header h2 and
86 memory block m2 are allocated. The headers h1 and h2 then switch
87 pointers so that h1 refers to m2 and h2 to m1. In this way, names
88 bound to h1 will point to the new class at the same time as h2 will
89 be a handle which the GC will use to free m1.
91 The `redefined' slot of m1 will be set to point to h1. An old
92 instance will have its class pointer (the CAR of the heap header)
93 pointing to m1. The non-immediate `redefined'-slot in m1 indicates
94 the class modification and the new class pointer can be found via
98 #define TEST_CHANGE_CLASS(obj, class) \
100 class = SCM_CLASS_OF (obj); \
101 if (scm_is_true (SCM_OBJ_CLASS_REDEF (obj))) \
103 scm_change_object_class (obj, class, SCM_OBJ_CLASS_REDEF (obj));\
104 class = SCM_CLASS_OF (obj); \
108 #define SCM_GOOPS_UNBOUND SCM_UNBOUND
109 #define SCM_GOOPS_UNBOUNDP(x) (scm_is_eq (x, SCM_GOOPS_UNBOUND))
111 static int goops_loaded_p
= 0;
112 static scm_t_rstate
*goops_rstate
;
114 /* These variables are filled in by the object system when loaded. */
115 static SCM class_boolean
, class_char
, class_pair
;
116 static SCM class_procedure
, class_string
, class_symbol
;
117 static SCM class_primitive_generic
;
118 static SCM class_vector
, class_null
;
119 static SCM class_integer
, class_real
, class_complex
, class_fraction
;
120 static SCM class_unknown
;
121 static SCM class_top
, class_object
, class_class
;
122 static SCM class_applicable
;
123 static SCM class_applicable_struct
, class_applicable_struct_with_setter
;
124 static SCM class_generic
, class_generic_with_setter
;
125 static SCM class_accessor
;
126 static SCM class_extended_generic
, class_extended_generic_with_setter
;
127 static SCM class_extended_accessor
;
128 static SCM class_method
;
129 static SCM class_accessor_method
;
130 static SCM class_procedure_class
;
131 static SCM class_applicable_struct_class
;
132 static SCM class_applicable_struct_with_setter_class
;
133 static SCM class_number
, class_list
;
134 static SCM class_keyword
;
135 static SCM class_port
, class_input_output_port
;
136 static SCM class_input_port
, class_output_port
;
137 static SCM class_foreign_slot
;
138 static SCM class_self
, class_protected
;
139 static SCM class_hidden
, class_opaque
, class_read_only
;
140 static SCM class_protected_hidden
, class_protected_opaque
, class_protected_read_only
;
141 static SCM class_scm
;
142 static SCM class_int
, class_float
, class_double
;
144 static SCM class_foreign
;
145 static SCM class_hashtable
;
146 static SCM class_fluid
;
147 static SCM class_dynamic_state
;
148 static SCM class_frame
;
149 static SCM class_vm_cont
;
150 static SCM class_bytevector
;
151 static SCM class_uvec
;
152 static SCM class_array
;
153 static SCM class_bitvector
;
155 static SCM vtable_class_map
= SCM_BOOL_F
;
157 /* Port classes. Allocate 3 times the maximum number of port types so that
158 input ports, output ports, and in/out ports can be stored at different
159 offsets. See `SCM_IN_PCLASS_INDEX' et al. */
160 SCM scm_i_port_class
[3 * SCM_I_MAX_PORT_TYPE_COUNT
];
163 SCM scm_i_smob_class
[SCM_I_MAX_SMOB_TYPE_COUNT
];
165 static SCM
scm_make_unbound (void);
166 static SCM
scm_unbound_p (SCM obj
);
167 static SCM
scm_sys_bless_applicable_struct_vtables_x (SCM applicable
,
169 static SCM
scm_sys_bless_pure_generic_vtable_x (SCM vtable
);
170 static SCM
scm_sys_make_root_class (SCM name
, SCM dslots
,
171 SCM getters_n_setters
);
172 static SCM
scm_sys_init_layout_x (SCM
class, SCM layout
);
173 static SCM
scm_sys_goops_early_init (void);
174 static SCM
scm_sys_goops_loaded (void);
177 /* This function is used for efficient type dispatch. */
178 SCM_DEFINE (scm_class_of
, "class-of", 1, 0, 0,
180 "Return the class of @var{x}.")
181 #define FUNC_NAME s_scm_class_of
183 switch (SCM_ITAG3 (x
))
187 return class_integer
;
192 else if (scm_is_bool (x
))
193 return class_boolean
;
194 else if (scm_is_null (x
))
197 return class_unknown
;
200 switch (SCM_TYP7 (x
))
202 case scm_tcs_cons_nimcar
:
209 case scm_tc7_pointer
:
210 return class_foreign
;
211 case scm_tc7_hashtable
:
212 return class_hashtable
;
215 case scm_tc7_dynamic_state
:
216 return class_dynamic_state
;
219 case scm_tc7_keyword
:
220 return class_keyword
;
221 case scm_tc7_vm_cont
:
222 return class_vm_cont
;
223 case scm_tc7_bytevector
:
224 if (SCM_BYTEVECTOR_ELEMENT_TYPE (x
) == SCM_ARRAY_ELEMENT_TYPE_VU8
)
225 return class_bytevector
;
230 case scm_tc7_bitvector
:
231 return class_bitvector
;
235 switch SCM_TYP16 (x
) {
237 return class_integer
;
240 case scm_tc16_complex
:
241 return class_complex
;
242 case scm_tc16_fraction
:
243 return class_fraction
;
245 case scm_tc7_program
:
246 if (SCM_PROGRAM_IS_PRIMITIVE_GENERIC (x
)
247 && SCM_UNPACK (*SCM_SUBR_GENERIC (x
)))
248 return class_primitive_generic
;
250 return class_procedure
;
254 scm_t_bits type
= SCM_TYP16 (x
);
255 if (type
!= scm_tc16_port_with_ps
)
256 return scm_i_smob_class
[SCM_TC2SMOBNUM (type
)];
257 x
= SCM_PORT_WITH_PS_PORT (x
);
258 /* fall through to ports */
261 return scm_i_port_class
[(SCM_WRTNG
& SCM_CELL_WORD_0 (x
)
262 ? (SCM_RDNG
& SCM_CELL_WORD_0 (x
)
263 ? SCM_INOUT_PCLASS_INDEX
| SCM_PTOBNUM (x
)
264 : SCM_OUT_PCLASS_INDEX
| SCM_PTOBNUM (x
))
265 : SCM_IN_PCLASS_INDEX
| SCM_PTOBNUM (x
))];
267 if (SCM_OBJ_CLASS_FLAGS (x
) & SCM_CLASSF_GOOPS_VALID
)
268 return SCM_CLASS_OF (x
);
269 else if (SCM_OBJ_CLASS_FLAGS (x
) & SCM_CLASSF_GOOPS
)
272 if (! scm_is_false (SCM_OBJ_CLASS_REDEF (x
)))
273 scm_change_object_class (x
,
274 SCM_CLASS_OF (x
), /* old */
275 SCM_OBJ_CLASS_REDEF (x
)); /* new */
276 return SCM_CLASS_OF (x
);
279 return scm_i_define_class_for_vtable (SCM_CLASS_OF (x
));
284 return class_unknown
;
290 /* case scm_tc3_unused: */
294 return class_unknown
;
298 /******************************************************************************
302 ******************************************************************************/
304 /*fixme* Manufacture keywords in advance */
306 scm_i_get_keyword (SCM key
, SCM l
, long len
, SCM default_value
, const char *subr
)
310 for (i
= 0; i
!= len
; i
+= 2)
312 SCM obj
= SCM_CAR (l
);
314 if (!scm_is_keyword (obj
))
315 scm_misc_error (subr
, "bad keyword: ~S", scm_list_1 (obj
));
316 else if (scm_is_eq (obj
, key
))
322 return default_value
;
326 SCM_DEFINE (scm_get_keyword
, "get-keyword", 3, 0, 0,
327 (SCM key
, SCM l
, SCM default_value
),
328 "Determine an associated value for the keyword @var{key} from\n"
329 "the list @var{l}. The list @var{l} has to consist of an even\n"
330 "number of elements, where, starting with the first, every\n"
331 "second element is a keyword, followed by its associated value.\n"
332 "If @var{l} does not hold a value for @var{key}, the value\n"
333 "@var{default_value} is returned.")
334 #define FUNC_NAME s_scm_get_keyword
338 SCM_ASSERT (scm_is_keyword (key
), key
, SCM_ARG1
, FUNC_NAME
);
339 len
= scm_ilength (l
);
340 if (len
< 0 || len
% 2 == 1)
341 scm_misc_error (FUNC_NAME
, "Bad keyword-value list: ~S", scm_list_1 (l
));
343 return scm_i_get_keyword (key
, l
, len
, default_value
, FUNC_NAME
);
348 SCM_KEYWORD (k_init_keyword
, "init-keyword");
350 static SCM
get_slot_value (SCM
class, SCM obj
, SCM slotdef
);
351 static SCM
set_slot_value (SCM
class, SCM obj
, SCM slotdef
, SCM value
);
353 SCM_DEFINE (scm_sys_initialize_object
, "%initialize-object", 2, 0, 0,
354 (SCM obj
, SCM initargs
),
355 "Initialize the object @var{obj} with the given arguments\n"
357 #define FUNC_NAME s_scm_sys_initialize_object
359 SCM tmp
, get_n_set
, slots
;
360 SCM
class = SCM_CLASS_OF (obj
);
363 SCM_VALIDATE_INSTANCE (1, obj
);
364 n_initargs
= scm_ilength (initargs
);
365 SCM_ASSERT ((n_initargs
& 1) == 0, initargs
, SCM_ARG2
, FUNC_NAME
);
367 get_n_set
= SCM_SLOT (class, scm_si_getters_n_setters
);
368 slots
= SCM_SLOT (class, scm_si_slots
);
370 /* See for each slot how it must be initialized */
372 !scm_is_null (slots
);
373 get_n_set
= SCM_CDR (get_n_set
), slots
= SCM_CDR (slots
))
375 SCM slot_name
= SCM_CAR (slots
);
376 SCM slot_value
= SCM_GOOPS_UNBOUND
;
378 if (!scm_is_null (SCM_CDR (slot_name
)))
380 /* This slot admits (perhaps) to be initialized at creation time */
381 long n
= scm_ilength (SCM_CDR (slot_name
));
382 if (n
& 1) /* odd or -1 */
383 SCM_MISC_ERROR ("class contains bogus slot definition: ~S",
384 scm_list_1 (slot_name
));
385 tmp
= scm_i_get_keyword (k_init_keyword
,
390 slot_name
= SCM_CAR (slot_name
);
391 if (SCM_UNPACK (tmp
))
393 /* an initarg was provided for this slot */
394 if (!scm_is_keyword (tmp
))
395 SCM_MISC_ERROR ("initarg must be a keyword. It was ~S",
397 slot_value
= scm_i_get_keyword (tmp
,
405 if (!SCM_GOOPS_UNBOUNDP (slot_value
))
406 /* set slot to provided value */
407 set_slot_value (class, obj
, SCM_CAR (get_n_set
), slot_value
);
410 /* set slot to its :init-form if it exists */
411 tmp
= SCM_CADAR (get_n_set
);
412 if (scm_is_true (tmp
))
413 set_slot_value (class,
424 SCM_DEFINE (scm_sys_init_layout_x
, "%init-layout!", 2, 0, 0,
425 (SCM
class, SCM layout
),
427 #define FUNC_NAME s_scm_sys_init_layout_x
429 SCM_VALIDATE_INSTANCE (1, class);
430 SCM_ASSERT (!scm_is_symbol (SCM_VTABLE_LAYOUT (class)), class, 1, FUNC_NAME
);
431 SCM_VALIDATE_STRING (2, layout
);
433 SCM_SET_VTABLE_LAYOUT (class, scm_make_struct_layout (layout
));
434 return SCM_UNSPECIFIED
;
438 SCM_DEFINE (scm_sys_inherit_magic_x
, "%inherit-magic!", 2, 0, 0,
439 (SCM
class, SCM dsupers
),
441 #define FUNC_NAME s_scm_sys_inherit_magic_x
443 SCM_VALIDATE_INSTANCE (1, class);
444 scm_i_struct_inherit_vtable_magic (SCM_CLASS_OF (class), class);
445 SCM_SET_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_OR_VALID
);
447 return SCM_UNSPECIFIED
;
451 /******************************************************************************/
454 scm_make_standard_class (SCM meta
, SCM name
, SCM dsupers
, SCM dslots
)
456 return scm_call_4 (scm_variable_ref (var_make_standard_class
),
457 meta
, name
, dsupers
, dslots
);
460 /******************************************************************************/
462 SCM_DEFINE (scm_sys_make_root_class
, "%make-root-class", 3, 0, 0,
463 (SCM name
, SCM dslots
, SCM getters_n_setters
),
465 #define FUNC_NAME s_scm_sys_make_root_class
469 cs
= scm_from_locale_string (SCM_CLASS_CLASS_LAYOUT
);
470 z
= scm_i_make_vtable_vtable (cs
);
471 SCM_SET_CLASS_FLAGS (z
, (SCM_CLASSF_GOOPS_OR_VALID
472 | SCM_CLASSF_METACLASS
));
474 SCM_SET_SLOT (z
, scm_vtable_index_name
, name
);
475 SCM_SET_SLOT (z
, scm_si_direct_supers
, SCM_EOL
); /* will be changed */
476 SCM_SET_SLOT (z
, scm_si_direct_slots
, dslots
); /* will be changed */
477 SCM_SET_SLOT (z
, scm_si_direct_subclasses
, SCM_EOL
);
478 SCM_SET_SLOT (z
, scm_si_direct_methods
, SCM_EOL
);
479 SCM_SET_SLOT (z
, scm_si_cpl
, SCM_EOL
); /* will be changed */
480 SCM_SET_SLOT (z
, scm_si_slots
, dslots
); /* will be changed */
481 SCM_SET_SLOT (z
, scm_si_nfields
, scm_from_int (SCM_N_CLASS_SLOTS
));
482 SCM_SET_SLOT (z
, scm_si_getters_n_setters
, getters_n_setters
); /* will be changed */
483 SCM_SET_SLOT (z
, scm_si_redefined
, SCM_BOOL_F
);
489 /******************************************************************************/
491 SCM_DEFINE (scm_instance_p
, "instance?", 1, 0, 0,
493 "Return @code{#t} if @var{obj} is an instance.")
494 #define FUNC_NAME s_scm_instance_p
496 return scm_from_bool (SCM_INSTANCEP (obj
));
501 scm_is_generic (SCM x
)
503 return SCM_INSTANCEP (x
) && SCM_SUBCLASSP (SCM_CLASS_OF (x
), class_generic
);
507 scm_is_method (SCM x
)
509 return SCM_INSTANCEP (x
) && SCM_SUBCLASSP (SCM_CLASS_OF (x
), class_method
);
512 /******************************************************************************
514 * Meta object accessors
516 ******************************************************************************/
518 SCM_SYMBOL (sym_procedure
, "procedure");
519 SCM_SYMBOL (sym_direct_supers
, "direct-supers");
520 SCM_SYMBOL (sym_direct_slots
, "direct-slots");
521 SCM_SYMBOL (sym_direct_subclasses
, "direct-subclasses");
522 SCM_SYMBOL (sym_direct_methods
, "direct-methods");
523 SCM_SYMBOL (sym_cpl
, "cpl");
524 SCM_SYMBOL (sym_slots
, "slots");
526 SCM_DEFINE (scm_class_name
, "class-name", 1, 0, 0,
528 "Return the class name of @var{obj}.")
529 #define FUNC_NAME s_scm_class_name
531 SCM_VALIDATE_CLASS (1, obj
);
532 return scm_slot_ref (obj
, scm_sym_name
);
536 SCM_DEFINE (scm_class_direct_supers
, "class-direct-supers", 1, 0, 0,
538 "Return the direct superclasses of the class @var{obj}.")
539 #define FUNC_NAME s_scm_class_direct_supers
541 SCM_VALIDATE_CLASS (1, obj
);
542 return scm_slot_ref (obj
, sym_direct_supers
);
546 SCM_DEFINE (scm_class_direct_slots
, "class-direct-slots", 1, 0, 0,
548 "Return the direct slots of the class @var{obj}.")
549 #define FUNC_NAME s_scm_class_direct_slots
551 SCM_VALIDATE_CLASS (1, obj
);
552 return scm_slot_ref (obj
, sym_direct_slots
);
556 SCM_DEFINE (scm_class_direct_subclasses
, "class-direct-subclasses", 1, 0, 0,
558 "Return the direct subclasses of the class @var{obj}.")
559 #define FUNC_NAME s_scm_class_direct_subclasses
561 SCM_VALIDATE_CLASS (1, obj
);
562 return scm_slot_ref(obj
, sym_direct_subclasses
);
566 SCM_DEFINE (scm_class_direct_methods
, "class-direct-methods", 1, 0, 0,
568 "Return the direct methods of the class @var{obj}")
569 #define FUNC_NAME s_scm_class_direct_methods
571 SCM_VALIDATE_CLASS (1, obj
);
572 return scm_slot_ref (obj
, sym_direct_methods
);
576 SCM_DEFINE (scm_class_precedence_list
, "class-precedence-list", 1, 0, 0,
578 "Return the class precedence list of the class @var{obj}.")
579 #define FUNC_NAME s_scm_class_precedence_list
581 SCM_VALIDATE_CLASS (1, obj
);
582 return scm_slot_ref (obj
, sym_cpl
);
586 SCM_DEFINE (scm_class_slots
, "class-slots", 1, 0, 0,
588 "Return the slot list of the class @var{obj}.")
589 #define FUNC_NAME s_scm_class_slots
591 SCM_VALIDATE_CLASS (1, obj
);
592 return scm_slot_ref (obj
, sym_slots
);
596 SCM_DEFINE (scm_generic_function_name
, "generic-function-name", 1, 0, 0,
598 "Return the name of the generic function @var{obj}.")
599 #define FUNC_NAME s_scm_generic_function_name
601 SCM_VALIDATE_GENERIC (1, obj
);
602 return scm_procedure_property (obj
, scm_sym_name
);
606 SCM_SYMBOL (sym_methods
, "methods");
607 SCM_SYMBOL (sym_extended_by
, "extended-by");
608 SCM_SYMBOL (sym_extends
, "extends");
611 SCM
fold_downward_gf_methods (SCM method_lists
, SCM gf
)
613 SCM gfs
= scm_slot_ref (gf
, sym_extended_by
);
614 method_lists
= scm_cons (scm_slot_ref (gf
, sym_methods
), method_lists
);
615 while (!scm_is_null (gfs
))
617 method_lists
= fold_downward_gf_methods (method_lists
, SCM_CAR (gfs
));
624 SCM
fold_upward_gf_methods (SCM method_lists
, SCM gf
)
626 if (SCM_IS_A_P (gf
, class_extended_generic
))
628 SCM gfs
= scm_slot_ref (gf
, sym_extends
);
629 while (!scm_is_null (gfs
))
631 SCM methods
= scm_slot_ref (SCM_CAR (gfs
), sym_methods
);
632 method_lists
= fold_upward_gf_methods (scm_cons (methods
,
641 SCM_DEFINE (scm_generic_function_methods
, "generic-function-methods", 1, 0, 0,
643 "Return the methods of the generic function @var{obj}.")
644 #define FUNC_NAME s_scm_generic_function_methods
647 SCM_VALIDATE_GENERIC (1, obj
);
648 methods
= fold_upward_gf_methods (SCM_EOL
, obj
);
649 methods
= fold_downward_gf_methods (methods
, obj
);
650 return scm_append (methods
);
654 SCM_DEFINE (scm_method_generic_function
, "method-generic-function", 1, 0, 0,
656 "Return the generic function for the method @var{obj}.")
657 #define FUNC_NAME s_scm_method_generic_function
659 SCM_VALIDATE_METHOD (1, obj
);
660 return scm_slot_ref (obj
, scm_from_latin1_symbol ("generic-function"));
664 SCM_DEFINE (scm_method_specializers
, "method-specializers", 1, 0, 0,
666 "Return specializers of the method @var{obj}.")
667 #define FUNC_NAME s_scm_method_specializers
669 SCM_VALIDATE_METHOD (1, obj
);
670 return scm_slot_ref (obj
, scm_from_latin1_symbol ("specializers"));
674 SCM_DEFINE (scm_method_procedure
, "method-procedure", 1, 0, 0,
676 "Return the procedure of the method @var{obj}.")
677 #define FUNC_NAME s_scm_method_procedure
679 SCM_VALIDATE_METHOD (1, obj
);
680 return scm_slot_ref (obj
, sym_procedure
);
684 /******************************************************************************
686 * S l o t a c c e s s
688 ******************************************************************************/
690 SCM_DEFINE (scm_make_unbound
, "make-unbound", 0, 0, 0,
692 "Return the unbound value.")
693 #define FUNC_NAME s_scm_make_unbound
695 return SCM_GOOPS_UNBOUND
;
699 SCM_DEFINE (scm_unbound_p
, "unbound?", 1, 0, 0,
701 "Return @code{#t} if @var{obj} is unbound.")
702 #define FUNC_NAME s_scm_unbound_p
704 return SCM_GOOPS_UNBOUNDP (obj
) ? SCM_BOOL_T
: SCM_BOOL_F
;
712 /* In the future, this function will return the effective slot
713 * definition associated with SLOT_NAME. Now it just returns some of
714 * the information which will be stored in the effective slot
719 slot_definition_using_name (SCM
class, SCM slot_name
)
721 register SCM slots
= SCM_SLOT (class, scm_si_getters_n_setters
);
722 for (; !scm_is_null (slots
); slots
= SCM_CDR (slots
))
723 if (scm_is_eq (SCM_CAAR (slots
), slot_name
))
724 return SCM_CAR (slots
);
729 get_slot_value (SCM
class SCM_UNUSED
, SCM obj
, SCM slotdef
)
730 #define FUNC_NAME "%get-slot-value"
732 SCM access
= SCM_CDDR (slotdef
);
734 * - access is an integer (the offset of this slot in the slots vector)
735 * - otherwise (car access) is the getter function to apply
737 * Instances have never more than SCM_MOST_POSITIVE_FIXNUM slots, so
738 * we can just assume fixnums here.
740 if (SCM_I_INUMP (access
))
741 /* Don't poke at the slots directly, because scm_struct_ref handles the
742 access bits for us. */
743 return scm_struct_ref (obj
, access
);
745 return scm_call_1 (SCM_CAR (access
), obj
);
750 get_slot_value_using_name (SCM
class, SCM obj
, SCM slot_name
)
752 SCM slotdef
= slot_definition_using_name (class, slot_name
);
753 if (scm_is_true (slotdef
))
754 return get_slot_value (class, obj
, slotdef
);
756 return scm_call_3 (SCM_VARIABLE_REF (var_slot_missing
), class, obj
, slot_name
);
760 set_slot_value (SCM
class SCM_UNUSED
, SCM obj
, SCM slotdef
, SCM value
)
761 #define FUNC_NAME "%set-slot-value"
763 SCM access
= SCM_CDDR (slotdef
);
765 * - access is an integer (the offset of this slot in the slots vector)
766 * - otherwise (cadr access) is the setter function to apply
768 * Instances have never more than SCM_MOST_POSITIVE_FIXNUM slots, so
769 * we can just assume fixnums here.
771 if (SCM_I_INUMP (access
))
772 /* obey permissions bits via going through struct-set! */
773 scm_struct_set_x (obj
, access
, value
);
775 /* ((cadr l) obj value) */
776 scm_call_2 (SCM_CADR (access
), obj
, value
);
777 return SCM_UNSPECIFIED
;
782 set_slot_value_using_name (SCM
class, SCM obj
, SCM slot_name
, SCM value
)
784 SCM slotdef
= slot_definition_using_name (class, slot_name
);
785 if (scm_is_true (slotdef
))
786 return set_slot_value (class, obj
, slotdef
, value
);
788 return scm_call_4 (SCM_VARIABLE_REF (var_slot_missing
), class, obj
, slot_name
, value
);
792 test_slot_existence (SCM
class SCM_UNUSED
, SCM obj
, SCM slot_name
)
796 for (l
= SCM_ACCESSORS_OF (obj
); !scm_is_null (l
); l
= SCM_CDR (l
))
797 if (scm_is_eq (SCM_CAAR (l
), slot_name
))
803 /* ======================================== */
805 SCM_DEFINE (scm_slot_ref_using_class
, "slot-ref-using-class", 3, 0, 0,
806 (SCM
class, SCM obj
, SCM slot_name
),
808 #define FUNC_NAME s_scm_slot_ref_using_class
812 SCM_VALIDATE_CLASS (1, class);
813 SCM_VALIDATE_INSTANCE (2, obj
);
814 SCM_VALIDATE_SYMBOL (3, slot_name
);
816 res
= get_slot_value_using_name (class, obj
, slot_name
);
817 if (SCM_GOOPS_UNBOUNDP (res
))
818 return scm_call_3 (SCM_VARIABLE_REF (var_slot_unbound
), class, obj
, slot_name
);
824 SCM_DEFINE (scm_slot_set_using_class_x
, "slot-set-using-class!", 4, 0, 0,
825 (SCM
class, SCM obj
, SCM slot_name
, SCM value
),
827 #define FUNC_NAME s_scm_slot_set_using_class_x
829 SCM_VALIDATE_CLASS (1, class);
830 SCM_VALIDATE_INSTANCE (2, obj
);
831 SCM_VALIDATE_SYMBOL (3, slot_name
);
833 return set_slot_value_using_name (class, obj
, slot_name
, value
);
838 SCM_DEFINE (scm_slot_bound_using_class_p
, "slot-bound-using-class?", 3, 0, 0,
839 (SCM
class, SCM obj
, SCM slot_name
),
841 #define FUNC_NAME s_scm_slot_bound_using_class_p
843 SCM_VALIDATE_CLASS (1, class);
844 SCM_VALIDATE_INSTANCE (2, obj
);
845 SCM_VALIDATE_SYMBOL (3, slot_name
);
847 return (SCM_GOOPS_UNBOUNDP (get_slot_value_using_name (class, obj
, slot_name
))
853 SCM_DEFINE (scm_slot_exists_using_class_p
, "slot-exists-using-class?", 3, 0, 0,
854 (SCM
class, SCM obj
, SCM slot_name
),
856 #define FUNC_NAME s_scm_slot_exists_using_class_p
858 SCM_VALIDATE_CLASS (1, class);
859 SCM_VALIDATE_INSTANCE (2, obj
);
860 SCM_VALIDATE_SYMBOL (3, slot_name
);
861 return test_slot_existence (class, obj
, slot_name
);
866 /* ======================================== */
868 SCM_DEFINE (scm_slot_ref
, "slot-ref", 2, 0, 0,
869 (SCM obj
, SCM slot_name
),
870 "Return the value from @var{obj}'s slot with the name\n"
872 #define FUNC_NAME s_scm_slot_ref
876 SCM_VALIDATE_INSTANCE (1, obj
);
877 TEST_CHANGE_CLASS (obj
, class);
879 res
= get_slot_value_using_name (class, obj
, slot_name
);
880 if (SCM_GOOPS_UNBOUNDP (res
))
881 return scm_call_3 (SCM_VARIABLE_REF (var_slot_unbound
), class, obj
, slot_name
);
886 SCM_DEFINE (scm_slot_set_x
, "slot-set!", 3, 0, 0,
887 (SCM obj
, SCM slot_name
, SCM value
),
888 "Set the slot named @var{slot_name} of @var{obj} to @var{value}.")
889 #define FUNC_NAME s_scm_slot_set_x
893 SCM_VALIDATE_INSTANCE (1, obj
);
894 TEST_CHANGE_CLASS(obj
, class);
896 return set_slot_value_using_name (class, obj
, slot_name
, value
);
900 SCM_DEFINE (scm_slot_bound_p
, "slot-bound?", 2, 0, 0,
901 (SCM obj
, SCM slot_name
),
902 "Return @code{#t} if the slot named @var{slot_name} of @var{obj}\n"
904 #define FUNC_NAME s_scm_slot_bound_p
908 SCM_VALIDATE_INSTANCE (1, obj
);
909 TEST_CHANGE_CLASS(obj
, class);
911 return (SCM_GOOPS_UNBOUNDP (get_slot_value_using_name (class,
919 SCM_DEFINE (scm_slot_exists_p
, "slot-exists?", 2, 0, 0,
920 (SCM obj
, SCM slot_name
),
921 "Return @code{#t} if @var{obj} has a slot named @var{slot_name}.")
922 #define FUNC_NAME s_scm_slot_exists_p
926 SCM_VALIDATE_INSTANCE (1, obj
);
927 SCM_VALIDATE_SYMBOL (2, slot_name
);
928 TEST_CHANGE_CLASS (obj
, class);
930 return test_slot_existence (class, obj
, slot_name
);
935 /******************************************************************************
937 * %allocate-instance (the low level instance allocation primitive)
939 ******************************************************************************/
941 SCM_DEFINE (scm_sys_allocate_instance
, "%allocate-instance", 2, 0, 0,
942 (SCM
class, SCM initargs
),
943 "Create a new instance of class @var{class} and initialize it\n"
944 "from the arguments @var{initargs}.")
945 #define FUNC_NAME s_scm_sys_allocate_instance
948 scm_t_signed_bits n
, i
;
951 SCM_VALIDATE_CLASS (1, class);
953 /* FIXME: duplicates some of scm_make_struct. */
955 n
= SCM_I_INUM (SCM_SLOT (class, scm_si_nfields
));
956 obj
= scm_i_alloc_struct (SCM_STRUCT_DATA (class), n
);
958 layout
= SCM_VTABLE_LAYOUT (class);
960 /* Set all SCM-holding slots to unbound */
961 for (i
= 0; i
< n
; i
++)
963 scm_t_wchar c
= scm_i_symbol_ref (layout
, i
*2);
965 SCM_STRUCT_DATA (obj
)[i
] = SCM_UNPACK (SCM_GOOPS_UNBOUND
);
967 SCM_STRUCT_DATA (obj
)[i
] = SCM_UNPACK (obj
);
969 SCM_STRUCT_DATA (obj
)[i
] = 0;
976 /******************************************************************************
978 * %modify-instance (used by change-class to modify in place)
980 ******************************************************************************/
982 SCM_DEFINE (scm_sys_modify_instance
, "%modify-instance", 2, 0, 0,
985 #define FUNC_NAME s_scm_sys_modify_instance
987 SCM_VALIDATE_INSTANCE (1, old
);
988 SCM_VALIDATE_INSTANCE (2, new);
990 /* Exchange the data contained in old and new. We exchange rather than
991 * scratch the old value with new to be correct with GC.
992 * See "Class redefinition protocol above".
994 SCM_CRITICAL_SECTION_START
;
996 scm_t_bits word0
, word1
;
997 word0
= SCM_CELL_WORD_0 (old
);
998 word1
= SCM_CELL_WORD_1 (old
);
999 SCM_SET_CELL_WORD_0 (old
, SCM_CELL_WORD_0 (new));
1000 SCM_SET_CELL_WORD_1 (old
, SCM_CELL_WORD_1 (new));
1001 SCM_SET_CELL_WORD_0 (new, word0
);
1002 SCM_SET_CELL_WORD_1 (new, word1
);
1004 SCM_CRITICAL_SECTION_END
;
1005 return SCM_UNSPECIFIED
;
1009 SCM_DEFINE (scm_sys_modify_class
, "%modify-class", 2, 0, 0,
1012 #define FUNC_NAME s_scm_sys_modify_class
1014 SCM_VALIDATE_CLASS (1, old
);
1015 SCM_VALIDATE_CLASS (2, new);
1017 SCM_CRITICAL_SECTION_START
;
1019 scm_t_bits word0
, word1
;
1020 word0
= SCM_CELL_WORD_0 (old
);
1021 word1
= SCM_CELL_WORD_1 (old
);
1022 SCM_SET_CELL_WORD_0 (old
, SCM_CELL_WORD_0 (new));
1023 SCM_SET_CELL_WORD_1 (old
, SCM_CELL_WORD_1 (new));
1024 SCM_STRUCT_DATA (old
)[scm_vtable_index_self
] = SCM_UNPACK (old
);
1025 SCM_SET_CELL_WORD_0 (new, word0
);
1026 SCM_SET_CELL_WORD_1 (new, word1
);
1027 SCM_STRUCT_DATA (new)[scm_vtable_index_self
] = SCM_UNPACK (new);
1029 SCM_CRITICAL_SECTION_END
;
1030 return SCM_UNSPECIFIED
;
1034 SCM_DEFINE (scm_sys_invalidate_class
, "%invalidate-class", 1, 0, 0,
1037 #define FUNC_NAME s_scm_sys_invalidate_class
1039 SCM_VALIDATE_CLASS (1, class);
1040 SCM_CLEAR_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_VALID
);
1041 return SCM_UNSPECIFIED
;
1045 /* When instances change class, they finally get a new body, but
1046 * before that, they go through purgatory in hell. Odd as it may
1047 * seem, this data structure saves us from eternal suffering in
1048 * infinite recursions.
1051 static scm_t_bits
**hell
;
1052 static long n_hell
= 1; /* one place for the evil one himself */
1053 static long hell_size
= 4;
1054 static SCM hell_mutex
;
1060 for (i
= 1; i
< n_hell
; ++i
)
1061 if (SCM_STRUCT_DATA (o
) == hell
[i
])
1067 go_to_hell (void *o
)
1070 scm_lock_mutex (hell_mutex
);
1071 if (n_hell
>= hell_size
)
1074 hell
= scm_realloc (hell
, hell_size
* sizeof(*hell
));
1076 hell
[n_hell
++] = SCM_STRUCT_DATA (obj
);
1077 scm_unlock_mutex (hell_mutex
);
1081 go_to_heaven (void *o
)
1084 scm_lock_mutex (hell_mutex
);
1085 hell
[burnin (obj
)] = hell
[--n_hell
];
1086 scm_unlock_mutex (hell_mutex
);
1090 SCM_SYMBOL (scm_sym_change_class
, "change-class");
1093 purgatory (SCM obj
, SCM new_class
)
1095 return scm_call_2 (SCM_VARIABLE_REF (var_change_class
), obj
, new_class
);
1098 /* This function calls the generic function change-class for all
1099 * instances which aren't currently undergoing class change.
1103 scm_change_object_class (SCM obj
, SCM old_class SCM_UNUSED
, SCM new_class
)
1107 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE
);
1108 scm_dynwind_rewind_handler (go_to_hell
, &obj
, SCM_F_WIND_EXPLICITLY
);
1109 scm_dynwind_unwind_handler (go_to_heaven
, &obj
, SCM_F_WIND_EXPLICITLY
);
1110 purgatory (obj
, new_class
);
1115 /******************************************************************************
1121 * GGG E N E R I C F U N C T I O N S
1123 * This implementation provides
1124 * - generic functions (with class specializers)
1127 * - a hard-coded MOP for standard gf, which can be overloaded for non-std gf
1129 ******************************************************************************/
1131 SCM_KEYWORD (k_name
, "name");
1132 SCM_GLOBAL_SYMBOL (scm_sym_args
, "args");
1134 SCM_DEFINE (scm_generic_capability_p
, "generic-capability?", 1, 0, 0,
1137 #define FUNC_NAME s_scm_generic_capability_p
1139 SCM_ASSERT (scm_is_true (scm_procedure_p (proc
)),
1140 proc
, SCM_ARG1
, FUNC_NAME
);
1141 return (SCM_PRIMITIVE_GENERIC_P (proc
) ? SCM_BOOL_T
: SCM_BOOL_F
);
1145 SCM_DEFINE (scm_enable_primitive_generic_x
, "enable-primitive-generic!", 0, 0, 1,
1148 #define FUNC_NAME s_scm_enable_primitive_generic_x
1150 SCM_VALIDATE_REST_ARGUMENT (subrs
);
1151 while (!scm_is_null (subrs
))
1153 SCM subr
= SCM_CAR (subrs
);
1154 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr
), subr
, SCM_ARGn
, FUNC_NAME
);
1155 SCM_SET_SUBR_GENERIC (subr
,
1156 scm_make (scm_list_3 (class_generic
,
1158 SCM_SUBR_NAME (subr
))));
1159 subrs
= SCM_CDR (subrs
);
1161 return SCM_UNSPECIFIED
;
1165 SCM_DEFINE (scm_set_primitive_generic_x
, "set-primitive-generic!", 2, 0, 0,
1166 (SCM subr
, SCM generic
),
1168 #define FUNC_NAME s_scm_set_primitive_generic_x
1170 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr
), subr
, SCM_ARG1
, FUNC_NAME
);
1171 SCM_ASSERT (SCM_PUREGENERICP (generic
), generic
, SCM_ARG2
, FUNC_NAME
);
1172 SCM_SET_SUBR_GENERIC (subr
, generic
);
1173 return SCM_UNSPECIFIED
;
1177 SCM_DEFINE (scm_primitive_generic_generic
, "primitive-generic-generic", 1, 0, 0,
1180 #define FUNC_NAME s_scm_primitive_generic_generic
1182 if (SCM_PRIMITIVE_GENERIC_P (subr
))
1184 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (subr
)))
1185 scm_enable_primitive_generic_x (scm_list_1 (subr
));
1186 return *SCM_SUBR_GENERIC (subr
);
1188 SCM_WRONG_TYPE_ARG (SCM_ARG1
, subr
);
1192 typedef struct t_extension
{
1193 struct t_extension
*next
;
1199 /* Hint for `scm_gc_malloc ()' et al. when allocating `t_extension'
1201 static const char extension_gc_hint
[] = "GOOPS extension";
1203 static t_extension
*extensions
= 0;
1206 scm_c_extend_primitive_generic (SCM extended
, SCM extension
)
1211 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (extended
)))
1212 scm_enable_primitive_generic_x (scm_list_1 (extended
));
1213 gf
= *SCM_SUBR_GENERIC (extended
);
1214 gext
= scm_call_2 (SCM_VARIABLE_REF (scm_var_make_extended_generic
),
1216 SCM_SUBR_NAME (extension
));
1217 SCM_SET_SUBR_GENERIC (extension
, gext
);
1221 t_extension
*e
= scm_gc_malloc (sizeof (t_extension
),
1223 t_extension
**loc
= &extensions
;
1224 /* Make sure that extensions are placed before their own
1225 * extensions in the extensions list. O(N^2) algorithm, but
1226 * extensions of primitive generics are rare.
1228 while (*loc
&& !scm_is_eq (extension
, (*loc
)->extended
))
1229 loc
= &(*loc
)->next
;
1231 e
->extended
= extended
;
1232 e
->extension
= extension
;
1238 setup_extended_primitive_generics ()
1242 t_extension
*e
= extensions
;
1243 scm_c_extend_primitive_generic (e
->extended
, e
->extension
);
1244 extensions
= e
->next
;
1248 /* Dirk:FIXME:: In all of these scm_wta_dispatch_* routines it is
1249 * assumed that 'gf' is zero if uninitialized. It would be cleaner if
1250 * some valid SCM value like SCM_BOOL_F or SCM_UNDEFINED were chosen.
1254 scm_wta_dispatch_0 (SCM gf
, const char *subr
)
1256 if (!SCM_UNPACK (gf
))
1257 scm_error_num_args_subr (subr
);
1259 return scm_call_0 (gf
);
1263 scm_wta_dispatch_1 (SCM gf
, SCM a1
, int pos
, const char *subr
)
1265 if (!SCM_UNPACK (gf
))
1266 scm_wrong_type_arg (subr
, pos
, a1
);
1268 return scm_call_1 (gf
, a1
);
1272 scm_wta_dispatch_2 (SCM gf
, SCM a1
, SCM a2
, int pos
, const char *subr
)
1274 if (!SCM_UNPACK (gf
))
1275 scm_wrong_type_arg (subr
, pos
, (pos
== SCM_ARG1
) ? a1
: a2
);
1277 return scm_call_2 (gf
, a1
, a2
);
1281 scm_wta_dispatch_n (SCM gf
, SCM args
, int pos
, const char *subr
)
1283 if (!SCM_UNPACK (gf
))
1284 scm_wrong_type_arg (subr
, pos
, scm_list_ref (args
, scm_from_int (pos
)));
1286 return scm_apply_0 (gf
, args
);
1289 /******************************************************************************
1291 * Protocol for calling a generic fumction
1292 * This protocol is roughly equivalent to (parameter are a little bit different
1293 * for efficiency reasons):
1295 * + apply-generic (gf args)
1296 * + compute-applicable-methods (gf args ...)
1297 * + sort-applicable-methods (methods args)
1298 * + apply-methods (gf methods args)
1300 * apply-methods calls make-next-method to build the "continuation" of a a
1301 * method. Applying a next-method will call apply-next-method which in
1302 * turn will call apply again to call effectively the following method.
1304 ******************************************************************************/
1306 SCM_DEFINE (scm_make
, "make", 0, 0, 1,
1308 "Make a new object. @var{args} must contain the class and\n"
1309 "all necessary initialization information.")
1310 #define FUNC_NAME s_scm_make
1312 return scm_apply_0 (scm_variable_ref (var_make
), args
);
1317 /**********************************************************************
1321 **********************************************************************/
1324 make_class_name (const char *prefix
, const char *type_name
, const char *suffix
)
1328 return scm_string_to_symbol (scm_string_append
1329 (scm_list_3 (scm_from_utf8_string (prefix
),
1330 scm_from_utf8_string (type_name
),
1331 scm_from_utf8_string (suffix
))));
1335 scm_make_extended_class (char const *type_name
, int applicablep
)
1337 SCM name
, meta
, supers
;
1339 name
= make_class_name ("<", type_name
, ">");
1343 supers
= scm_list_1 (class_applicable
);
1345 supers
= scm_list_1 (class_top
);
1347 return scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
1351 scm_i_inherit_applicable (SCM c
)
1353 if (!SCM_SUBCLASSP (c
, class_applicable
))
1355 SCM dsupers
= SCM_SLOT (c
, scm_si_direct_supers
);
1356 SCM cpl
= SCM_SLOT (c
, scm_si_cpl
);
1357 /* patch class_applicable into direct-supers */
1358 SCM top
= scm_c_memq (class_top
, dsupers
);
1359 if (scm_is_false (top
))
1360 dsupers
= scm_append (scm_list_2 (dsupers
,
1361 scm_list_1 (class_applicable
)));
1364 SCM_SETCAR (top
, class_applicable
);
1365 SCM_SETCDR (top
, scm_cons (class_top
, SCM_CDR (top
)));
1367 SCM_SET_SLOT (c
, scm_si_direct_supers
, dsupers
);
1368 /* patch class_applicable into cpl */
1369 top
= scm_c_memq (class_top
, cpl
);
1370 if (scm_is_false (top
))
1374 SCM_SETCAR (top
, class_applicable
);
1375 SCM_SETCDR (top
, scm_cons (class_top
, SCM_CDR (top
)));
1377 /* add class to direct-subclasses of class_applicable */
1378 SCM_SET_SLOT (class_applicable
,
1379 scm_si_direct_subclasses
,
1380 scm_cons (c
, SCM_SLOT (class_applicable
,
1381 scm_si_direct_subclasses
)));
1386 create_smob_classes (void)
1390 for (i
= 0; i
< SCM_I_MAX_SMOB_TYPE_COUNT
; ++i
)
1391 scm_i_smob_class
[i
] = SCM_BOOL_F
;
1393 for (i
= 0; i
< scm_numsmob
; ++i
)
1394 if (scm_is_false (scm_i_smob_class
[i
]))
1395 scm_i_smob_class
[i
] = scm_make_extended_class (SCM_SMOBNAME (i
),
1396 scm_smobs
[i
].apply
!= 0);
1400 scm_make_port_classes (long ptobnum
, char *type_name
)
1402 SCM name
, meta
, super
, supers
;
1406 name
= make_class_name ("<", type_name
, "-port>");
1407 supers
= scm_list_1 (class_port
);
1408 super
= scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
1410 name
= make_class_name ("<", type_name
, "-input-port>");
1411 supers
= scm_list_2 (super
, class_input_port
);
1412 scm_i_port_class
[SCM_IN_PCLASS_INDEX
+ ptobnum
]
1413 = scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
1415 name
= make_class_name ("<", type_name
, "-output-port>");
1416 supers
= scm_list_2 (super
, class_output_port
);
1417 scm_i_port_class
[SCM_OUT_PCLASS_INDEX
+ ptobnum
]
1418 = scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
1420 name
= make_class_name ("<", type_name
, "-input-output-port>");
1421 supers
= scm_list_2 (super
, class_input_output_port
);
1422 scm_i_port_class
[SCM_INOUT_PCLASS_INDEX
+ ptobnum
]
1423 = scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
1427 create_port_classes (void)
1431 for (i
= scm_c_num_port_types () - 1; i
>= 0; i
--)
1432 scm_make_port_classes (i
, SCM_PTOBNAME (i
));
1436 scm_i_define_class_for_vtable (SCM vtable
)
1440 scm_i_pthread_mutex_lock (&scm_i_misc_mutex
);
1441 if (scm_is_false (vtable_class_map
))
1442 vtable_class_map
= scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY
);
1443 scm_i_pthread_mutex_unlock (&scm_i_misc_mutex
);
1445 if (scm_is_false (scm_struct_vtable_p (vtable
)))
1448 class = scm_weak_table_refq (vtable_class_map
, vtable
, SCM_BOOL_F
);
1450 if (scm_is_false (class))
1452 if (SCM_UNPACK (class_class
))
1454 SCM name
, meta
, supers
;
1456 name
= SCM_VTABLE_NAME (vtable
);
1457 if (scm_is_symbol (name
))
1458 name
= scm_string_to_symbol
1460 (scm_list_3 (scm_from_latin1_string ("<"),
1461 scm_symbol_to_string (name
),
1462 scm_from_latin1_string (">"))));
1464 name
= scm_from_latin1_symbol ("<>");
1466 if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable
, SCM_VTABLE_FLAG_SETTER
))
1468 meta
= class_applicable_struct_with_setter_class
;
1469 supers
= scm_list_1 (class_applicable_struct_with_setter
);
1471 else if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable
,
1472 SCM_VTABLE_FLAG_APPLICABLE
))
1474 meta
= class_applicable_struct_class
;
1475 supers
= scm_list_1 (class_applicable_struct
);
1480 supers
= scm_list_1 (class_top
);
1483 return scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
1486 /* `create_struct_classes' will fill this in later. */
1489 /* Don't worry about races. This only happens when creating a
1490 vtable, which happens by definition in one thread. */
1491 scm_weak_table_putq_x (vtable_class_map
, vtable
, class);
1498 make_struct_class (void *closure SCM_UNUSED
,
1499 SCM vtable
, SCM data
, SCM prev SCM_UNUSED
)
1501 if (scm_is_false (data
))
1502 scm_i_define_class_for_vtable (vtable
);
1503 return SCM_UNSPECIFIED
;
1507 create_struct_classes (void)
1509 /* FIXME: take the vtable_class_map while initializing goops? */
1510 scm_internal_hash_fold (make_struct_class
, 0, SCM_BOOL_F
,
1514 /**********************************************************************
1518 **********************************************************************/
1523 if (!goops_loaded_p
)
1524 scm_c_resolve_module ("oop goops");
1528 SCM_KEYWORD (k_setter
, "setter");
1531 scm_ensure_accessor (SCM name
)
1535 var
= scm_module_variable (scm_current_module (), name
);
1536 if (SCM_VARIABLEP (var
) && !SCM_UNBNDP (SCM_VARIABLE_REF (var
)))
1537 gf
= SCM_VARIABLE_REF (var
);
1541 if (!SCM_IS_A_P (gf
, class_accessor
))
1543 gf
= scm_make (scm_list_3 (class_generic
, k_name
, name
));
1544 gf
= scm_make (scm_list_5 (class_accessor
,
1545 k_name
, name
, k_setter
, gf
));
1553 * Debugging utilities
1556 SCM_DEFINE (scm_pure_generic_p
, "pure-generic?", 1, 0, 0,
1558 "Return @code{#t} if @var{obj} is a pure generic.")
1559 #define FUNC_NAME s_scm_pure_generic_p
1561 return scm_from_bool (SCM_PUREGENERICP (obj
));
1565 #endif /* GUILE_DEBUG */
1571 SCM_DEFINE (scm_sys_bless_applicable_struct_vtables_x
, "%bless-applicable-struct-vtables!", 2, 0, 0,
1572 (SCM applicable
, SCM setter
),
1574 #define FUNC_NAME s_scm_sys_bless_applicable_struct_vtables_x
1576 SCM_VALIDATE_CLASS (1, applicable
);
1577 SCM_VALIDATE_CLASS (2, setter
);
1578 SCM_SET_VTABLE_FLAGS (applicable
, SCM_VTABLE_FLAG_APPLICABLE_VTABLE
);
1579 SCM_SET_VTABLE_FLAGS (setter
, SCM_VTABLE_FLAG_SETTER_VTABLE
);
1580 return SCM_UNSPECIFIED
;
1584 SCM_DEFINE (scm_sys_bless_pure_generic_vtable_x
, "%bless-pure-generic-vtable!", 1, 0, 0,
1587 #define FUNC_NAME s_scm_sys_bless_pure_generic_vtable_x
1589 SCM_VALIDATE_CLASS (1, vtable
);
1590 SCM_SET_CLASS_FLAGS (vtable
, SCM_CLASSF_PURE_GENERIC
);
1591 return SCM_UNSPECIFIED
;
1595 SCM_DEFINE (scm_sys_goops_early_init
, "%goops-early-init", 0, 0, 0,
1598 #define FUNC_NAME s_scm_sys_goops_early_init
1600 var_make_standard_class
= scm_c_lookup ("make-standard-class");
1601 var_make
= scm_c_lookup ("make");
1603 class_class
= scm_variable_ref (scm_c_lookup ("<class>"));
1604 class_top
= scm_variable_ref (scm_c_lookup ("<top>"));
1605 class_object
= scm_variable_ref (scm_c_lookup ("<object>"));
1607 class_foreign_slot
= scm_variable_ref (scm_c_lookup ("<foreign-slot>"));
1608 class_protected
= scm_variable_ref (scm_c_lookup ("<protected-slot>"));
1609 class_hidden
= scm_variable_ref (scm_c_lookup ("<hidden-slot>"));
1610 class_opaque
= scm_variable_ref (scm_c_lookup ("<opaque-slot>"));
1611 class_read_only
= scm_variable_ref (scm_c_lookup ("<read-only-slot>"));
1612 class_self
= scm_variable_ref (scm_c_lookup ("<self-slot>"));
1613 class_protected_opaque
= scm_variable_ref (scm_c_lookup ("<protected-opaque-slot>"));
1614 class_protected_hidden
= scm_variable_ref (scm_c_lookup ("<protected-hidden-slot>"));
1615 class_protected_read_only
= scm_variable_ref (scm_c_lookup ("<protected-read-only-slot>"));
1616 class_scm
= scm_variable_ref (scm_c_lookup ("<scm-slot>"));
1617 class_int
= scm_variable_ref (scm_c_lookup ("<int-slot>"));
1618 class_float
= scm_variable_ref (scm_c_lookup ("<float-slot>"));
1619 class_double
= scm_variable_ref (scm_c_lookup ("<double-slot>"));
1622 class_procedure_class
= scm_variable_ref (scm_c_lookup ("<procedure-class>"));
1623 class_applicable_struct_class
= scm_variable_ref (scm_c_lookup ("<applicable-struct-class>"));
1624 class_applicable_struct_with_setter_class
=
1625 scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter-class>"));
1627 class_method
= scm_variable_ref (scm_c_lookup ("<method>"));
1628 class_accessor_method
= scm_variable_ref (scm_c_lookup ("<accessor-method>"));
1629 class_applicable
= scm_variable_ref (scm_c_lookup ("<applicable>"));
1630 class_applicable_struct
= scm_variable_ref (scm_c_lookup ("<applicable-struct>"));
1631 class_applicable_struct_with_setter
= scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter>"));
1632 class_generic
= scm_variable_ref (scm_c_lookup ("<generic>"));
1633 class_extended_generic
= scm_variable_ref (scm_c_lookup ("<extended-generic>"));
1634 class_generic_with_setter
= scm_variable_ref (scm_c_lookup ("<generic-with-setter>"));
1635 class_accessor
= scm_variable_ref (scm_c_lookup ("<accessor>"));
1636 class_extended_generic_with_setter
= scm_variable_ref (scm_c_lookup ("<extended-generic-with-setter>"));
1637 class_extended_accessor
= scm_variable_ref (scm_c_lookup ("<extended-accessor>"));
1639 /* Primitive types classes */
1640 class_boolean
= scm_variable_ref (scm_c_lookup ("<boolean>"));
1641 class_char
= scm_variable_ref (scm_c_lookup ("<char>"));
1642 class_list
= scm_variable_ref (scm_c_lookup ("<list>"));
1643 class_pair
= scm_variable_ref (scm_c_lookup ("<pair>"));
1644 class_null
= scm_variable_ref (scm_c_lookup ("<null>"));
1645 class_string
= scm_variable_ref (scm_c_lookup ("<string>"));
1646 class_symbol
= scm_variable_ref (scm_c_lookup ("<symbol>"));
1647 class_vector
= scm_variable_ref (scm_c_lookup ("<vector>"));
1648 class_foreign
= scm_variable_ref (scm_c_lookup ("<foreign>"));
1649 class_hashtable
= scm_variable_ref (scm_c_lookup ("<hashtable>"));
1650 class_fluid
= scm_variable_ref (scm_c_lookup ("<fluid>"));
1651 class_dynamic_state
= scm_variable_ref (scm_c_lookup ("<dynamic-state>"));
1652 class_frame
= scm_variable_ref (scm_c_lookup ("<frame>"));
1653 class_vm_cont
= scm_variable_ref (scm_c_lookup ("<vm-continuation>"));
1654 class_bytevector
= scm_variable_ref (scm_c_lookup ("<bytevector>"));
1655 class_uvec
= scm_variable_ref (scm_c_lookup ("<uvec>"));
1656 class_array
= scm_variable_ref (scm_c_lookup ("<array>"));
1657 class_bitvector
= scm_variable_ref (scm_c_lookup ("<bitvector>"));
1658 class_number
= scm_variable_ref (scm_c_lookup ("<number>"));
1659 class_complex
= scm_variable_ref (scm_c_lookup ("<complex>"));
1660 class_real
= scm_variable_ref (scm_c_lookup ("<real>"));
1661 class_integer
= scm_variable_ref (scm_c_lookup ("<integer>"));
1662 class_fraction
= scm_variable_ref (scm_c_lookup ("<fraction>"));
1663 class_keyword
= scm_variable_ref (scm_c_lookup ("<keyword>"));
1664 class_unknown
= scm_variable_ref (scm_c_lookup ("<unknown>"));
1665 class_procedure
= scm_variable_ref (scm_c_lookup ("<procedure>"));
1666 class_primitive_generic
= scm_variable_ref (scm_c_lookup ("<primitive-generic>"));
1667 class_port
= scm_variable_ref (scm_c_lookup ("<port>"));
1668 class_input_port
= scm_variable_ref (scm_c_lookup ("<input-port>"));
1669 class_output_port
= scm_variable_ref (scm_c_lookup ("<output-port>"));
1670 class_input_output_port
= scm_variable_ref (scm_c_lookup ("<input-output-port>"));
1672 create_smob_classes ();
1673 create_struct_classes ();
1674 create_port_classes ();
1676 return SCM_UNSPECIFIED
;
1680 SCM_DEFINE (scm_sys_goops_loaded
, "%goops-loaded", 0, 0, 0,
1682 "Announce that GOOPS is loaded and perform initialization\n"
1683 "on the C level which depends on the loaded GOOPS modules.")
1684 #define FUNC_NAME s_scm_sys_goops_loaded
1688 scm_module_variable (scm_module_goops
, sym_slot_unbound
);
1690 scm_module_variable (scm_module_goops
, sym_slot_missing
);
1692 scm_module_variable (scm_module_goops
, sym_change_class
);
1693 setup_extended_primitive_generics ();
1695 #if (SCM_ENABLE_DEPRECATED == 1)
1696 scm_init_deprecated_goops ();
1699 return SCM_UNSPECIFIED
;
1703 SCM scm_module_goops
;
1706 scm_init_goops_builtins (void *unused
)
1708 scm_module_goops
= scm_current_module ();
1710 goops_rstate
= scm_c_make_rstate ("GOOPS", 5);
1712 hell
= scm_calloc (hell_size
* sizeof (*hell
));
1713 hell_mutex
= scm_make_mutex ();
1715 #include "libguile/goops.x"
1721 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION
,
1722 "scm_init_goops_builtins", scm_init_goops_builtins
,