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 SCM_DEFINE (scm_sys_init_layout_x
, "%init-layout!", 2, 0, 0,
283 (SCM
class, SCM layout
),
285 #define FUNC_NAME s_scm_sys_init_layout_x
287 SCM_VALIDATE_INSTANCE (1, class);
288 SCM_ASSERT (!scm_is_symbol (SCM_VTABLE_LAYOUT (class)), class, 1, FUNC_NAME
);
289 SCM_VALIDATE_STRING (2, layout
);
291 SCM_SET_VTABLE_LAYOUT (class, scm_make_struct_layout (layout
));
292 return SCM_UNSPECIFIED
;
296 SCM_DEFINE (scm_sys_inherit_magic_x
, "%inherit-magic!", 2, 0, 0,
297 (SCM
class, SCM dsupers
),
299 #define FUNC_NAME s_scm_sys_inherit_magic_x
301 SCM_VALIDATE_INSTANCE (1, class);
302 scm_i_struct_inherit_vtable_magic (SCM_CLASS_OF (class), class);
303 SCM_SET_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_OR_VALID
);
305 return SCM_UNSPECIFIED
;
309 /******************************************************************************/
312 scm_make_standard_class (SCM meta
, SCM name
, SCM dsupers
, SCM dslots
)
314 return scm_call_4 (scm_variable_ref (var_make_standard_class
),
315 meta
, name
, dsupers
, dslots
);
318 /******************************************************************************/
320 SCM_DEFINE (scm_sys_make_root_class
, "%make-root-class", 3, 0, 0,
321 (SCM name
, SCM dslots
, SCM getters_n_setters
),
323 #define FUNC_NAME s_scm_sys_make_root_class
327 cs
= scm_from_locale_string (SCM_CLASS_CLASS_LAYOUT
);
328 z
= scm_i_make_vtable_vtable (cs
);
329 SCM_SET_CLASS_FLAGS (z
, (SCM_CLASSF_GOOPS_OR_VALID
330 | SCM_CLASSF_METACLASS
));
332 SCM_SET_SLOT (z
, scm_vtable_index_name
, name
);
333 SCM_SET_SLOT (z
, scm_si_direct_supers
, SCM_EOL
); /* will be changed */
334 SCM_SET_SLOT (z
, scm_si_direct_slots
, dslots
); /* will be changed */
335 SCM_SET_SLOT (z
, scm_si_direct_subclasses
, SCM_EOL
);
336 SCM_SET_SLOT (z
, scm_si_direct_methods
, SCM_EOL
);
337 SCM_SET_SLOT (z
, scm_si_cpl
, SCM_EOL
); /* will be changed */
338 SCM_SET_SLOT (z
, scm_si_slots
, dslots
); /* will be changed */
339 SCM_SET_SLOT (z
, scm_si_nfields
, scm_from_int (SCM_N_CLASS_SLOTS
));
340 SCM_SET_SLOT (z
, scm_si_getters_n_setters
, getters_n_setters
); /* will be changed */
341 SCM_SET_SLOT (z
, scm_si_redefined
, SCM_BOOL_F
);
347 /******************************************************************************/
349 SCM_DEFINE (scm_instance_p
, "instance?", 1, 0, 0,
351 "Return @code{#t} if @var{obj} is an instance.")
352 #define FUNC_NAME s_scm_instance_p
354 return scm_from_bool (SCM_INSTANCEP (obj
));
358 SCM_DEFINE (scm_class_p
, "class?", 1, 0, 0,
360 "Return @code{#t} if @var{obj} is a class.")
361 #define FUNC_NAME s_scm_class_p
363 return scm_from_bool (SCM_CLASSP (obj
));
368 scm_is_generic (SCM x
)
370 return SCM_INSTANCEP (x
) && SCM_SUBCLASSP (SCM_CLASS_OF (x
), class_generic
);
374 scm_is_method (SCM x
)
376 return SCM_INSTANCEP (x
) && SCM_SUBCLASSP (SCM_CLASS_OF (x
), class_method
);
379 /******************************************************************************
381 * Meta object accessors
383 ******************************************************************************/
386 scm_class_name (SCM obj
)
388 return scm_call_1 (scm_variable_ref (var_class_name
), obj
);
392 scm_class_direct_supers (SCM obj
)
394 return scm_call_1 (scm_variable_ref (var_class_direct_supers
), obj
);
398 scm_class_direct_slots (SCM obj
)
400 return scm_call_1 (scm_variable_ref (var_class_direct_slots
), obj
);
404 scm_class_direct_subclasses (SCM obj
)
406 return scm_call_1 (scm_variable_ref (var_class_direct_subclasses
), obj
);
410 scm_class_direct_methods (SCM obj
)
412 return scm_call_1 (scm_variable_ref (var_class_direct_methods
), obj
);
416 scm_class_precedence_list (SCM obj
)
418 return scm_call_1 (scm_variable_ref (var_class_precedence_list
), obj
);
422 scm_class_slots (SCM obj
)
424 return scm_call_1 (scm_variable_ref (var_class_slots
), obj
);
427 SCM_DEFINE (scm_generic_function_name
, "generic-function-name", 1, 0, 0,
429 "Return the name of the generic function @var{obj}.")
430 #define FUNC_NAME s_scm_generic_function_name
432 SCM_VALIDATE_GENERIC (1, obj
);
433 return scm_procedure_property (obj
, scm_sym_name
);
438 scm_generic_function_methods (SCM obj
)
440 return scm_call_1 (scm_variable_ref (var_generic_function_methods
), obj
);
444 scm_method_generic_function (SCM obj
)
446 return scm_call_1 (scm_variable_ref (var_method_generic_function
), obj
);
450 scm_method_specializers (SCM obj
)
452 return scm_call_1 (scm_variable_ref (var_method_specializers
), obj
);
456 scm_method_procedure (SCM obj
)
458 return scm_call_1 (scm_variable_ref (var_method_procedure
), obj
);
461 /******************************************************************************
463 * S l o t a c c e s s
465 ******************************************************************************/
467 SCM_DEFINE (scm_make_unbound
, "make-unbound", 0, 0, 0,
469 "Return the unbound value.")
470 #define FUNC_NAME s_scm_make_unbound
472 return SCM_GOOPS_UNBOUND
;
476 SCM_DEFINE (scm_unbound_p
, "unbound?", 1, 0, 0,
478 "Return @code{#t} if @var{obj} is unbound.")
479 #define FUNC_NAME s_scm_unbound_p
481 return SCM_GOOPS_UNBOUNDP (obj
) ? SCM_BOOL_T
: SCM_BOOL_F
;
489 scm_slot_ref_using_class (SCM
class, SCM obj
, SCM slot_name
)
491 return scm_call_3 (scm_variable_ref (var_slot_ref_using_class
),
492 class, obj
, slot_name
);
496 scm_slot_set_using_class_x (SCM
class, SCM obj
, SCM slot_name
, SCM value
)
498 return scm_call_4 (scm_variable_ref (var_slot_set_using_class_x
),
499 class, obj
, slot_name
, value
);
503 scm_slot_bound_using_class_p (SCM
class, SCM obj
, SCM slot_name
)
505 return scm_call_3 (scm_variable_ref (var_slot_bound_using_class_p
),
506 class, obj
, slot_name
);
510 scm_slot_exists_using_class_p (SCM
class, SCM obj
, SCM slot_name
)
512 return scm_call_3 (scm_variable_ref (var_slot_exists_using_class_p
),
513 class, obj
, slot_name
);
517 scm_slot_ref (SCM obj
, SCM slot_name
)
519 return scm_call_2 (scm_variable_ref (var_slot_ref
), obj
, slot_name
);
523 scm_slot_set_x (SCM obj
, SCM slot_name
, SCM value
)
525 return scm_call_3 (scm_variable_ref (var_slot_set_x
), obj
, slot_name
, value
);
529 scm_slot_bound_p (SCM obj
, SCM slot_name
)
531 return scm_call_2 (scm_variable_ref (var_slot_bound_p
), obj
, slot_name
);
535 scm_slot_exists_p (SCM obj
, SCM slot_name
)
537 return scm_call_2 (scm_variable_ref (var_slot_exists_p
), obj
, slot_name
);
541 /******************************************************************************
543 * %allocate-instance (the low level instance allocation primitive)
545 ******************************************************************************/
547 SCM_DEFINE (scm_sys_allocate_instance
, "%allocate-instance", 2, 0, 0,
548 (SCM
class, SCM initargs
),
549 "Create a new instance of class @var{class} and initialize it\n"
550 "from the arguments @var{initargs}.")
551 #define FUNC_NAME s_scm_sys_allocate_instance
554 scm_t_signed_bits n
, i
;
557 SCM_VALIDATE_CLASS (1, class);
559 /* FIXME: duplicates some of scm_make_struct. */
561 n
= SCM_I_INUM (SCM_SLOT (class, scm_si_nfields
));
562 obj
= scm_i_alloc_struct (SCM_STRUCT_DATA (class), n
);
564 layout
= SCM_VTABLE_LAYOUT (class);
566 /* Set all SCM-holding slots to unbound */
567 for (i
= 0; i
< n
; i
++)
569 scm_t_wchar c
= scm_i_symbol_ref (layout
, i
*2);
571 SCM_STRUCT_DATA (obj
)[i
] = SCM_UNPACK (SCM_GOOPS_UNBOUND
);
573 SCM_STRUCT_DATA (obj
)[i
] = SCM_UNPACK (obj
);
575 SCM_STRUCT_DATA (obj
)[i
] = 0;
582 /******************************************************************************
584 * %modify-instance (used by change-class to modify in place)
586 ******************************************************************************/
588 SCM_DEFINE (scm_sys_modify_instance
, "%modify-instance", 2, 0, 0,
591 #define FUNC_NAME s_scm_sys_modify_instance
593 SCM_VALIDATE_INSTANCE (1, old
);
594 SCM_VALIDATE_INSTANCE (2, new);
596 /* Exchange the data contained in old and new. We exchange rather than
597 * scratch the old value with new to be correct with GC.
598 * See "Class redefinition protocol above".
600 SCM_CRITICAL_SECTION_START
;
602 scm_t_bits word0
, word1
;
603 word0
= SCM_CELL_WORD_0 (old
);
604 word1
= SCM_CELL_WORD_1 (old
);
605 SCM_SET_CELL_WORD_0 (old
, SCM_CELL_WORD_0 (new));
606 SCM_SET_CELL_WORD_1 (old
, SCM_CELL_WORD_1 (new));
607 SCM_SET_CELL_WORD_0 (new, word0
);
608 SCM_SET_CELL_WORD_1 (new, word1
);
610 SCM_CRITICAL_SECTION_END
;
611 return SCM_UNSPECIFIED
;
615 SCM_DEFINE (scm_sys_modify_class
, "%modify-class", 2, 0, 0,
618 #define FUNC_NAME s_scm_sys_modify_class
620 SCM_VALIDATE_CLASS (1, old
);
621 SCM_VALIDATE_CLASS (2, new);
623 SCM_CRITICAL_SECTION_START
;
625 scm_t_bits word0
, word1
;
626 word0
= SCM_CELL_WORD_0 (old
);
627 word1
= SCM_CELL_WORD_1 (old
);
628 SCM_SET_CELL_WORD_0 (old
, SCM_CELL_WORD_0 (new));
629 SCM_SET_CELL_WORD_1 (old
, SCM_CELL_WORD_1 (new));
630 SCM_STRUCT_DATA (old
)[scm_vtable_index_self
] = SCM_UNPACK (old
);
631 SCM_SET_CELL_WORD_0 (new, word0
);
632 SCM_SET_CELL_WORD_1 (new, word1
);
633 SCM_STRUCT_DATA (new)[scm_vtable_index_self
] = SCM_UNPACK (new);
635 SCM_CRITICAL_SECTION_END
;
636 return SCM_UNSPECIFIED
;
640 SCM_DEFINE (scm_sys_invalidate_class
, "%invalidate-class", 1, 0, 0,
643 #define FUNC_NAME s_scm_sys_invalidate_class
645 SCM_VALIDATE_CLASS (1, class);
646 SCM_CLEAR_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_VALID
);
647 return SCM_UNSPECIFIED
;
651 /* When instances change class, they finally get a new body, but
652 * before that, they go through purgatory in hell. Odd as it may
653 * seem, this data structure saves us from eternal suffering in
654 * infinite recursions.
657 static scm_t_bits
**hell
;
658 static long n_hell
= 1; /* one place for the evil one himself */
659 static long hell_size
= 4;
660 static SCM hell_mutex
;
666 for (i
= 1; i
< n_hell
; ++i
)
667 if (SCM_STRUCT_DATA (o
) == hell
[i
])
676 scm_lock_mutex (hell_mutex
);
677 if (n_hell
>= hell_size
)
680 hell
= scm_realloc (hell
, hell_size
* sizeof(*hell
));
682 hell
[n_hell
++] = SCM_STRUCT_DATA (obj
);
683 scm_unlock_mutex (hell_mutex
);
687 go_to_heaven (void *o
)
690 scm_lock_mutex (hell_mutex
);
691 hell
[burnin (obj
)] = hell
[--n_hell
];
692 scm_unlock_mutex (hell_mutex
);
697 purgatory (SCM obj
, SCM new_class
)
699 return scm_call_2 (SCM_VARIABLE_REF (var_change_class
), obj
, new_class
);
702 /* This function calls the generic function change-class for all
703 * instances which aren't currently undergoing class change.
707 scm_change_object_class (SCM obj
, SCM old_class SCM_UNUSED
, SCM new_class
)
711 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE
);
712 scm_dynwind_rewind_handler (go_to_hell
, &obj
, SCM_F_WIND_EXPLICITLY
);
713 scm_dynwind_unwind_handler (go_to_heaven
, &obj
, SCM_F_WIND_EXPLICITLY
);
714 purgatory (obj
, new_class
);
719 /******************************************************************************
725 * GGG E N E R I C F U N C T I O N S
727 * This implementation provides
728 * - generic functions (with class specializers)
731 * - a hard-coded MOP for standard gf, which can be overloaded for non-std gf
733 ******************************************************************************/
735 SCM_KEYWORD (k_name
, "name");
736 SCM_GLOBAL_SYMBOL (scm_sym_args
, "args");
738 SCM_DEFINE (scm_generic_capability_p
, "generic-capability?", 1, 0, 0,
741 #define FUNC_NAME s_scm_generic_capability_p
743 SCM_ASSERT (scm_is_true (scm_procedure_p (proc
)),
744 proc
, SCM_ARG1
, FUNC_NAME
);
745 return (SCM_PRIMITIVE_GENERIC_P (proc
) ? SCM_BOOL_T
: SCM_BOOL_F
);
749 SCM_DEFINE (scm_enable_primitive_generic_x
, "enable-primitive-generic!", 0, 0, 1,
752 #define FUNC_NAME s_scm_enable_primitive_generic_x
754 SCM_VALIDATE_REST_ARGUMENT (subrs
);
755 while (!scm_is_null (subrs
))
757 SCM subr
= SCM_CAR (subrs
);
758 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr
), subr
, SCM_ARGn
, FUNC_NAME
);
759 SCM_SET_SUBR_GENERIC (subr
,
760 scm_make (scm_list_3 (class_generic
,
762 SCM_SUBR_NAME (subr
))));
763 subrs
= SCM_CDR (subrs
);
765 return SCM_UNSPECIFIED
;
769 SCM_DEFINE (scm_set_primitive_generic_x
, "set-primitive-generic!", 2, 0, 0,
770 (SCM subr
, SCM generic
),
772 #define FUNC_NAME s_scm_set_primitive_generic_x
774 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr
), subr
, SCM_ARG1
, FUNC_NAME
);
775 SCM_ASSERT (SCM_GENERICP (generic
), generic
, SCM_ARG2
, FUNC_NAME
);
776 SCM_SET_SUBR_GENERIC (subr
, generic
);
777 return SCM_UNSPECIFIED
;
781 SCM_DEFINE (scm_primitive_generic_generic
, "primitive-generic-generic", 1, 0, 0,
784 #define FUNC_NAME s_scm_primitive_generic_generic
786 if (SCM_PRIMITIVE_GENERIC_P (subr
))
788 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (subr
)))
789 scm_enable_primitive_generic_x (scm_list_1 (subr
));
790 return *SCM_SUBR_GENERIC (subr
);
792 SCM_WRONG_TYPE_ARG (SCM_ARG1
, subr
);
796 /* Dirk:FIXME:: In all of these scm_wta_dispatch_* routines it is
797 * assumed that 'gf' is zero if uninitialized. It would be cleaner if
798 * some valid SCM value like SCM_BOOL_F or SCM_UNDEFINED were chosen.
802 scm_wta_dispatch_0 (SCM gf
, const char *subr
)
804 if (!SCM_UNPACK (gf
))
805 scm_error_num_args_subr (subr
);
807 return scm_call_0 (gf
);
811 scm_wta_dispatch_1 (SCM gf
, SCM a1
, int pos
, const char *subr
)
813 if (!SCM_UNPACK (gf
))
814 scm_wrong_type_arg (subr
, pos
, a1
);
816 return scm_call_1 (gf
, a1
);
820 scm_wta_dispatch_2 (SCM gf
, SCM a1
, SCM a2
, int pos
, const char *subr
)
822 if (!SCM_UNPACK (gf
))
823 scm_wrong_type_arg (subr
, pos
, (pos
== SCM_ARG1
) ? a1
: a2
);
825 return scm_call_2 (gf
, a1
, a2
);
829 scm_wta_dispatch_n (SCM gf
, SCM args
, int pos
, const char *subr
)
831 if (!SCM_UNPACK (gf
))
832 scm_wrong_type_arg (subr
, pos
, scm_list_ref (args
, scm_from_int (pos
)));
834 return scm_apply_0 (gf
, args
);
837 /******************************************************************************
839 * Protocol for calling a generic fumction
840 * This protocol is roughly equivalent to (parameter are a little bit different
841 * for efficiency reasons):
843 * + apply-generic (gf args)
844 * + compute-applicable-methods (gf args ...)
845 * + sort-applicable-methods (methods args)
846 * + apply-methods (gf methods args)
848 * apply-methods calls make-next-method to build the "continuation" of a a
849 * method. Applying a next-method will call apply-next-method which in
850 * turn will call apply again to call effectively the following method.
852 ******************************************************************************/
854 SCM_DEFINE (scm_make
, "make", 0, 0, 1,
856 "Make a new object. @var{args} must contain the class and\n"
857 "all necessary initialization information.")
858 #define FUNC_NAME s_scm_make
860 return scm_apply_0 (scm_variable_ref (var_make
), args
);
865 /**********************************************************************
869 **********************************************************************/
872 make_class_name (const char *prefix
, const char *type_name
, const char *suffix
)
876 return scm_string_to_symbol (scm_string_append
877 (scm_list_3 (scm_from_utf8_string (prefix
),
878 scm_from_utf8_string (type_name
),
879 scm_from_utf8_string (suffix
))));
883 scm_make_extended_class (char const *type_name
, int applicablep
)
885 SCM name
, meta
, supers
;
887 name
= make_class_name ("<", type_name
, ">");
891 supers
= scm_list_1 (class_applicable
);
893 supers
= scm_list_1 (class_top
);
895 return scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
899 scm_i_inherit_applicable (SCM c
)
901 if (!SCM_SUBCLASSP (c
, class_applicable
))
903 SCM dsupers
= SCM_SLOT (c
, scm_si_direct_supers
);
904 SCM cpl
= SCM_SLOT (c
, scm_si_cpl
);
905 /* patch class_applicable into direct-supers */
906 SCM top
= scm_c_memq (class_top
, dsupers
);
907 if (scm_is_false (top
))
908 dsupers
= scm_append (scm_list_2 (dsupers
,
909 scm_list_1 (class_applicable
)));
912 SCM_SETCAR (top
, class_applicable
);
913 SCM_SETCDR (top
, scm_cons (class_top
, SCM_CDR (top
)));
915 SCM_SET_SLOT (c
, scm_si_direct_supers
, dsupers
);
916 /* patch class_applicable into cpl */
917 top
= scm_c_memq (class_top
, cpl
);
918 if (scm_is_false (top
))
922 SCM_SETCAR (top
, class_applicable
);
923 SCM_SETCDR (top
, scm_cons (class_top
, SCM_CDR (top
)));
925 /* add class to direct-subclasses of class_applicable */
926 SCM_SET_SLOT (class_applicable
,
927 scm_si_direct_subclasses
,
928 scm_cons (c
, SCM_SLOT (class_applicable
,
929 scm_si_direct_subclasses
)));
934 create_smob_classes (void)
938 for (i
= 0; i
< SCM_I_MAX_SMOB_TYPE_COUNT
; ++i
)
939 scm_i_smob_class
[i
] = SCM_BOOL_F
;
941 for (i
= 0; i
< scm_numsmob
; ++i
)
942 if (scm_is_false (scm_i_smob_class
[i
]))
943 scm_i_smob_class
[i
] = scm_make_extended_class (SCM_SMOBNAME (i
),
944 scm_smobs
[i
].apply
!= 0);
948 scm_make_port_classes (long ptobnum
, char *type_name
)
950 SCM name
, meta
, super
, supers
;
954 name
= make_class_name ("<", type_name
, "-port>");
955 supers
= scm_list_1 (class_port
);
956 super
= scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
958 name
= make_class_name ("<", type_name
, "-input-port>");
959 supers
= scm_list_2 (super
, class_input_port
);
960 scm_i_port_class
[SCM_IN_PCLASS_INDEX
+ ptobnum
]
961 = scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
963 name
= make_class_name ("<", type_name
, "-output-port>");
964 supers
= scm_list_2 (super
, class_output_port
);
965 scm_i_port_class
[SCM_OUT_PCLASS_INDEX
+ ptobnum
]
966 = scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
968 name
= make_class_name ("<", type_name
, "-input-output-port>");
969 supers
= scm_list_2 (super
, class_input_output_port
);
970 scm_i_port_class
[SCM_INOUT_PCLASS_INDEX
+ ptobnum
]
971 = scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
975 create_port_classes (void)
979 for (i
= scm_c_num_port_types () - 1; i
>= 0; i
--)
980 scm_make_port_classes (i
, SCM_PTOBNAME (i
));
984 scm_i_define_class_for_vtable (SCM vtable
)
988 scm_i_pthread_mutex_lock (&scm_i_misc_mutex
);
989 if (scm_is_false (vtable_class_map
))
990 vtable_class_map
= scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY
);
991 scm_i_pthread_mutex_unlock (&scm_i_misc_mutex
);
993 if (scm_is_false (scm_struct_vtable_p (vtable
)))
996 class = scm_weak_table_refq (vtable_class_map
, vtable
, SCM_BOOL_F
);
998 if (scm_is_false (class))
1000 if (SCM_UNPACK (class_class
))
1002 SCM name
, meta
, supers
;
1004 name
= SCM_VTABLE_NAME (vtable
);
1005 if (scm_is_symbol (name
))
1006 name
= scm_string_to_symbol
1008 (scm_list_3 (scm_from_latin1_string ("<"),
1009 scm_symbol_to_string (name
),
1010 scm_from_latin1_string (">"))));
1012 name
= scm_from_latin1_symbol ("<>");
1014 if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable
, SCM_VTABLE_FLAG_SETTER
))
1016 meta
= class_applicable_struct_with_setter_class
;
1017 supers
= scm_list_1 (class_applicable_struct_with_setter
);
1019 else if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable
,
1020 SCM_VTABLE_FLAG_APPLICABLE
))
1022 meta
= class_applicable_struct_class
;
1023 supers
= scm_list_1 (class_applicable_struct
);
1028 supers
= scm_list_1 (class_top
);
1031 return scm_make_standard_class (meta
, name
, supers
, SCM_EOL
);
1034 /* `create_struct_classes' will fill this in later. */
1037 /* Don't worry about races. This only happens when creating a
1038 vtable, which happens by definition in one thread. */
1039 scm_weak_table_putq_x (vtable_class_map
, vtable
, class);
1046 make_struct_class (void *closure SCM_UNUSED
,
1047 SCM vtable
, SCM data
, SCM prev SCM_UNUSED
)
1049 if (scm_is_false (data
))
1050 scm_i_define_class_for_vtable (vtable
);
1051 return SCM_UNSPECIFIED
;
1055 create_struct_classes (void)
1057 /* FIXME: take the vtable_class_map while initializing goops? */
1058 scm_internal_hash_fold (make_struct_class
, 0, SCM_BOOL_F
,
1062 /**********************************************************************
1066 **********************************************************************/
1071 if (!goops_loaded_p
)
1072 scm_c_resolve_module ("oop goops");
1076 SCM_KEYWORD (k_setter
, "setter");
1079 scm_ensure_accessor (SCM name
)
1083 var
= scm_module_variable (scm_current_module (), name
);
1084 if (SCM_VARIABLEP (var
) && !SCM_UNBNDP (SCM_VARIABLE_REF (var
)))
1085 gf
= SCM_VARIABLE_REF (var
);
1089 if (!SCM_IS_A_P (gf
, class_accessor
))
1091 gf
= scm_make (scm_list_3 (class_generic
, k_name
, name
));
1092 gf
= scm_make (scm_list_5 (class_accessor
,
1093 k_name
, name
, k_setter
, gf
));
1103 SCM_DEFINE (scm_sys_bless_applicable_struct_vtables_x
, "%bless-applicable-struct-vtables!", 2, 0, 0,
1104 (SCM applicable
, SCM setter
),
1106 #define FUNC_NAME s_scm_sys_bless_applicable_struct_vtables_x
1108 SCM_VALIDATE_CLASS (1, applicable
);
1109 SCM_VALIDATE_CLASS (2, setter
);
1110 SCM_SET_VTABLE_FLAGS (applicable
, SCM_VTABLE_FLAG_APPLICABLE_VTABLE
);
1111 SCM_SET_VTABLE_FLAGS (setter
, SCM_VTABLE_FLAG_SETTER_VTABLE
);
1112 return SCM_UNSPECIFIED
;
1116 SCM_DEFINE (scm_sys_goops_early_init
, "%goops-early-init", 0, 0, 0,
1119 #define FUNC_NAME s_scm_sys_goops_early_init
1121 var_make_standard_class
= scm_c_lookup ("make-standard-class");
1122 var_make
= scm_c_lookup ("make");
1124 var_slot_ref_using_class
= scm_c_lookup ("slot-ref-using-class");
1125 var_slot_set_using_class_x
= scm_c_lookup ("slot-set-using-class!");
1126 var_slot_bound_using_class_p
= scm_c_lookup ("slot-bound-using-class?");
1127 var_slot_exists_using_class_p
= scm_c_lookup ("slot-exists-using-class?");
1129 var_slot_ref
= scm_c_lookup ("slot-ref");
1130 var_slot_set_x
= scm_c_lookup ("slot-set!");
1131 var_slot_bound_p
= scm_c_lookup ("slot-bound?");
1132 var_slot_exists_p
= scm_c_lookup ("slot-exists?");
1134 class_class
= scm_variable_ref (scm_c_lookup ("<class>"));
1135 class_top
= scm_variable_ref (scm_c_lookup ("<top>"));
1136 class_object
= scm_variable_ref (scm_c_lookup ("<object>"));
1138 class_foreign_slot
= scm_variable_ref (scm_c_lookup ("<foreign-slot>"));
1139 class_protected
= scm_variable_ref (scm_c_lookup ("<protected-slot>"));
1140 class_hidden
= scm_variable_ref (scm_c_lookup ("<hidden-slot>"));
1141 class_opaque
= scm_variable_ref (scm_c_lookup ("<opaque-slot>"));
1142 class_read_only
= scm_variable_ref (scm_c_lookup ("<read-only-slot>"));
1143 class_self
= scm_variable_ref (scm_c_lookup ("<self-slot>"));
1144 class_protected_opaque
= scm_variable_ref (scm_c_lookup ("<protected-opaque-slot>"));
1145 class_protected_hidden
= scm_variable_ref (scm_c_lookup ("<protected-hidden-slot>"));
1146 class_protected_read_only
= scm_variable_ref (scm_c_lookup ("<protected-read-only-slot>"));
1147 class_scm
= scm_variable_ref (scm_c_lookup ("<scm-slot>"));
1148 class_int
= scm_variable_ref (scm_c_lookup ("<int-slot>"));
1149 class_float
= scm_variable_ref (scm_c_lookup ("<float-slot>"));
1150 class_double
= scm_variable_ref (scm_c_lookup ("<double-slot>"));
1153 class_procedure_class
= scm_variable_ref (scm_c_lookup ("<procedure-class>"));
1154 class_applicable_struct_class
= scm_variable_ref (scm_c_lookup ("<applicable-struct-class>"));
1155 class_applicable_struct_with_setter_class
=
1156 scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter-class>"));
1158 class_method
= scm_variable_ref (scm_c_lookup ("<method>"));
1159 class_accessor_method
= scm_variable_ref (scm_c_lookup ("<accessor-method>"));
1160 class_applicable
= scm_variable_ref (scm_c_lookup ("<applicable>"));
1161 class_applicable_struct
= scm_variable_ref (scm_c_lookup ("<applicable-struct>"));
1162 class_applicable_struct_with_setter
= scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter>"));
1163 class_generic
= scm_variable_ref (scm_c_lookup ("<generic>"));
1164 class_extended_generic
= scm_variable_ref (scm_c_lookup ("<extended-generic>"));
1165 class_generic_with_setter
= scm_variable_ref (scm_c_lookup ("<generic-with-setter>"));
1166 class_accessor
= scm_variable_ref (scm_c_lookup ("<accessor>"));
1167 class_extended_generic_with_setter
= scm_variable_ref (scm_c_lookup ("<extended-generic-with-setter>"));
1168 class_extended_accessor
= scm_variable_ref (scm_c_lookup ("<extended-accessor>"));
1170 /* Primitive types classes */
1171 class_boolean
= scm_variable_ref (scm_c_lookup ("<boolean>"));
1172 class_char
= scm_variable_ref (scm_c_lookup ("<char>"));
1173 class_list
= scm_variable_ref (scm_c_lookup ("<list>"));
1174 class_pair
= scm_variable_ref (scm_c_lookup ("<pair>"));
1175 class_null
= scm_variable_ref (scm_c_lookup ("<null>"));
1176 class_string
= scm_variable_ref (scm_c_lookup ("<string>"));
1177 class_symbol
= scm_variable_ref (scm_c_lookup ("<symbol>"));
1178 class_vector
= scm_variable_ref (scm_c_lookup ("<vector>"));
1179 class_foreign
= scm_variable_ref (scm_c_lookup ("<foreign>"));
1180 class_hashtable
= scm_variable_ref (scm_c_lookup ("<hashtable>"));
1181 class_fluid
= scm_variable_ref (scm_c_lookup ("<fluid>"));
1182 class_dynamic_state
= scm_variable_ref (scm_c_lookup ("<dynamic-state>"));
1183 class_frame
= scm_variable_ref (scm_c_lookup ("<frame>"));
1184 class_vm_cont
= scm_variable_ref (scm_c_lookup ("<vm-continuation>"));
1185 class_bytevector
= scm_variable_ref (scm_c_lookup ("<bytevector>"));
1186 class_uvec
= scm_variable_ref (scm_c_lookup ("<uvec>"));
1187 class_array
= scm_variable_ref (scm_c_lookup ("<array>"));
1188 class_bitvector
= scm_variable_ref (scm_c_lookup ("<bitvector>"));
1189 class_number
= scm_variable_ref (scm_c_lookup ("<number>"));
1190 class_complex
= scm_variable_ref (scm_c_lookup ("<complex>"));
1191 class_real
= scm_variable_ref (scm_c_lookup ("<real>"));
1192 class_integer
= scm_variable_ref (scm_c_lookup ("<integer>"));
1193 class_fraction
= scm_variable_ref (scm_c_lookup ("<fraction>"));
1194 class_keyword
= scm_variable_ref (scm_c_lookup ("<keyword>"));
1195 class_unknown
= scm_variable_ref (scm_c_lookup ("<unknown>"));
1196 class_procedure
= scm_variable_ref (scm_c_lookup ("<procedure>"));
1197 class_primitive_generic
= scm_variable_ref (scm_c_lookup ("<primitive-generic>"));
1198 class_port
= scm_variable_ref (scm_c_lookup ("<port>"));
1199 class_input_port
= scm_variable_ref (scm_c_lookup ("<input-port>"));
1200 class_output_port
= scm_variable_ref (scm_c_lookup ("<output-port>"));
1201 class_input_output_port
= scm_variable_ref (scm_c_lookup ("<input-output-port>"));
1203 create_smob_classes ();
1204 create_struct_classes ();
1205 create_port_classes ();
1207 return SCM_UNSPECIFIED
;
1211 SCM_DEFINE (scm_sys_goops_loaded
, "%goops-loaded", 0, 0, 0,
1213 "Announce that GOOPS is loaded and perform initialization\n"
1214 "on the C level which depends on the loaded GOOPS modules.")
1215 #define FUNC_NAME s_scm_sys_goops_loaded
1218 var_class_name
= scm_c_lookup ("class-name");
1219 var_class_direct_supers
= scm_c_lookup ("class-direct-supers");
1220 var_class_direct_slots
= scm_c_lookup ("class-direct-slots");
1221 var_class_direct_subclasses
= scm_c_lookup ("class-direct-subclasses");
1222 var_class_direct_methods
= scm_c_lookup ("class-direct-methods");
1223 var_class_precedence_list
= scm_c_lookup ("class-precedence-list");
1224 var_class_slots
= scm_c_lookup ("class-slots");
1226 var_generic_function_methods
= scm_c_lookup ("generic-function-methods");
1227 var_method_generic_function
= scm_c_lookup ("method-generic-function");
1228 var_method_specializers
= scm_c_lookup ("method-specializers");
1229 var_method_procedure
= scm_c_lookup ("method-procedure");
1231 var_change_class
= scm_c_lookup ("change-class");
1233 #if (SCM_ENABLE_DEPRECATED == 1)
1234 scm_init_deprecated_goops ();
1237 return SCM_UNSPECIFIED
;
1241 SCM scm_module_goops
;
1244 scm_init_goops_builtins (void *unused
)
1246 scm_module_goops
= scm_current_module ();
1248 hell
= scm_calloc (hell_size
* sizeof (*hell
));
1249 hell_mutex
= scm_make_mutex ();
1251 #include "libguile/goops.x"
1257 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION
,
1258 "scm_init_goops_builtins", scm_init_goops_builtins
,