Remove TEST_CHANGE_CLASS
[bpt/guile.git] / libguile / goops.c
... / ...
CommitLineData
1/* Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2008,2009,2010,2011,2012,2013,2014,2015
2 * Free Software Foundation, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation; either version 3 of
7 * the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA
18 */
19\f
20
21/* This software is a derivative work of other copyrighted softwares; the
22 * copyright notices of these softwares are placed in the file COPYRIGHTS
23 *
24 * This file is based upon stklos.c from the STk distribution by
25 * Erick Gallesio <eg@unice.fr>.
26 */
27
28#ifdef HAVE_CONFIG_H
29# include <config.h>
30#endif
31
32#include "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"
49
50#include "libguile/validate.h"
51#include "libguile/goops.h"
52
53/* Port classes */
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)
57
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.
63
64 References to ordinary procedures is by reference (by variable),
65 though, as in the rest of Guile. */
66
67static SCM var_make_standard_class = SCM_BOOL_F;
68static SCM var_change_class = SCM_BOOL_F;
69static SCM var_make = SCM_BOOL_F;
70static SCM var_class_name = SCM_BOOL_F;
71static SCM var_class_direct_supers = SCM_BOOL_F;
72static SCM var_class_direct_slots = SCM_BOOL_F;
73static SCM var_class_direct_subclasses = SCM_BOOL_F;
74static SCM var_class_direct_methods = SCM_BOOL_F;
75static SCM var_class_precedence_list = SCM_BOOL_F;
76static SCM var_class_slots = SCM_BOOL_F;
77
78static SCM var_generic_function_methods = SCM_BOOL_F;
79static SCM var_method_generic_function = SCM_BOOL_F;
80static SCM var_method_specializers = SCM_BOOL_F;
81static SCM var_method_procedure = SCM_BOOL_F;
82
83static SCM var_slot_ref_using_class = SCM_BOOL_F;
84static SCM var_slot_set_using_class_x = SCM_BOOL_F;
85static SCM var_slot_bound_using_class_p = SCM_BOOL_F;
86static SCM var_slot_exists_using_class_p = SCM_BOOL_F;
87
88static SCM var_slot_ref = SCM_BOOL_F;
89static SCM var_slot_set_x = SCM_BOOL_F;
90static SCM var_slot_bound_p = SCM_BOOL_F;
91static SCM var_slot_exists_p = SCM_BOOL_F;
92
93
94SCM_SYMBOL (sym_change_class, "change-class");
95
96SCM_VARIABLE (scm_var_make_extended_generic, "make-extended-generic");
97
98
99#define SCM_GOOPS_UNBOUND SCM_UNBOUND
100#define SCM_GOOPS_UNBOUNDP(x) (scm_is_eq (x, SCM_GOOPS_UNBOUND))
101
102static int goops_loaded_p = 0;
103
104/* These variables are filled in by the object system when loaded. */
105static SCM class_boolean, class_char, class_pair;
106static SCM class_procedure, class_string, class_symbol;
107static SCM class_primitive_generic;
108static SCM class_vector, class_null;
109static SCM class_integer, class_real, class_complex, class_fraction;
110static SCM class_unknown;
111static SCM class_top, class_object, class_class;
112static SCM class_applicable;
113static SCM class_applicable_struct, class_applicable_struct_with_setter;
114static SCM class_generic, class_generic_with_setter;
115static SCM class_accessor;
116static SCM class_extended_generic, class_extended_generic_with_setter;
117static SCM class_extended_accessor;
118static SCM class_method;
119static SCM class_accessor_method;
120static SCM class_procedure_class;
121static SCM class_applicable_struct_class;
122static SCM class_applicable_struct_with_setter_class;
123static SCM class_number, class_list;
124static SCM class_keyword;
125static SCM class_port, class_input_output_port;
126static SCM class_input_port, class_output_port;
127static SCM class_foreign_slot;
128static SCM class_self, class_protected;
129static SCM class_hidden, class_opaque, class_read_only;
130static SCM class_protected_hidden, class_protected_opaque, class_protected_read_only;
131static SCM class_scm;
132static SCM class_int, class_float, class_double;
133
134static SCM class_foreign;
135static SCM class_hashtable;
136static SCM class_fluid;
137static SCM class_dynamic_state;
138static SCM class_frame;
139static SCM class_vm_cont;
140static SCM class_bytevector;
141static SCM class_uvec;
142static SCM class_array;
143static SCM class_bitvector;
144
145static SCM vtable_class_map = SCM_BOOL_F;
146
147/* Port classes. Allocate 3 times the maximum number of port types so that
148 input ports, output ports, and in/out ports can be stored at different
149 offsets. See `SCM_IN_PCLASS_INDEX' et al. */
150SCM scm_i_port_class[3 * SCM_I_MAX_PORT_TYPE_COUNT];
151
152/* SMOB classes. */
153SCM scm_i_smob_class[SCM_I_MAX_SMOB_TYPE_COUNT];
154
155static SCM scm_make_unbound (void);
156static SCM scm_unbound_p (SCM obj);
157static SCM scm_class_p (SCM obj);
158static SCM scm_sys_bless_applicable_struct_vtables_x (SCM applicable,
159 SCM setter);
160static SCM scm_sys_bless_pure_generic_vtable_x (SCM vtable);
161static SCM scm_sys_make_root_class (SCM name, SCM dslots,
162 SCM getters_n_setters);
163static SCM scm_sys_init_layout_x (SCM class, SCM layout);
164static SCM scm_sys_goops_early_init (void);
165static SCM scm_sys_goops_loaded (void);
166
167
168/* This function is used for efficient type dispatch. */
169SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0,
170 (SCM x),
171 "Return the class of @var{x}.")
172#define FUNC_NAME s_scm_class_of
173{
174 switch (SCM_ITAG3 (x))
175 {
176 case scm_tc3_int_1:
177 case scm_tc3_int_2:
178 return class_integer;
179
180 case scm_tc3_imm24:
181 if (SCM_CHARP (x))
182 return class_char;
183 else if (scm_is_bool (x))
184 return class_boolean;
185 else if (scm_is_null (x))
186 return class_null;
187 else
188 return class_unknown;
189
190 case scm_tc3_cons:
191 switch (SCM_TYP7 (x))
192 {
193 case scm_tcs_cons_nimcar:
194 return class_pair;
195 case scm_tc7_symbol:
196 return class_symbol;
197 case scm_tc7_vector:
198 case scm_tc7_wvect:
199 return class_vector;
200 case scm_tc7_pointer:
201 return class_foreign;
202 case scm_tc7_hashtable:
203 return class_hashtable;
204 case scm_tc7_fluid:
205 return class_fluid;
206 case scm_tc7_dynamic_state:
207 return class_dynamic_state;
208 case scm_tc7_frame:
209 return class_frame;
210 case scm_tc7_keyword:
211 return class_keyword;
212 case scm_tc7_vm_cont:
213 return class_vm_cont;
214 case scm_tc7_bytevector:
215 if (SCM_BYTEVECTOR_ELEMENT_TYPE (x) == SCM_ARRAY_ELEMENT_TYPE_VU8)
216 return class_bytevector;
217 else
218 return class_uvec;
219 case scm_tc7_array:
220 return class_array;
221 case scm_tc7_bitvector:
222 return class_bitvector;
223 case scm_tc7_string:
224 return class_string;
225 case scm_tc7_number:
226 switch SCM_TYP16 (x) {
227 case scm_tc16_big:
228 return class_integer;
229 case scm_tc16_real:
230 return class_real;
231 case scm_tc16_complex:
232 return class_complex;
233 case scm_tc16_fraction:
234 return class_fraction;
235 }
236 case scm_tc7_program:
237 if (SCM_PROGRAM_IS_PRIMITIVE_GENERIC (x)
238 && SCM_UNPACK (*SCM_SUBR_GENERIC (x)))
239 return class_primitive_generic;
240 else
241 return class_procedure;
242
243 case scm_tc7_smob:
244 {
245 scm_t_bits type = SCM_TYP16 (x);
246 if (type != scm_tc16_port_with_ps)
247 return scm_i_smob_class[SCM_TC2SMOBNUM (type)];
248 x = SCM_PORT_WITH_PS_PORT (x);
249 /* fall through to ports */
250 }
251 case scm_tc7_port:
252 return scm_i_port_class[(SCM_WRTNG & SCM_CELL_WORD_0 (x)
253 ? (SCM_RDNG & SCM_CELL_WORD_0 (x)
254 ? SCM_INOUT_PCLASS_INDEX | SCM_PTOBNUM (x)
255 : SCM_OUT_PCLASS_INDEX | SCM_PTOBNUM (x))
256 : SCM_IN_PCLASS_INDEX | SCM_PTOBNUM (x))];
257 case scm_tcs_struct:
258 if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS_VALID)
259 return SCM_CLASS_OF (x);
260 else if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS)
261 {
262 /* Goops object */
263 if (! scm_is_false (SCM_OBJ_CLASS_REDEF (x)))
264 scm_change_object_class (x,
265 SCM_CLASS_OF (x), /* old */
266 SCM_OBJ_CLASS_REDEF (x)); /* new */
267 return SCM_CLASS_OF (x);
268 }
269 else
270 return scm_i_define_class_for_vtable (SCM_CLASS_OF (x));
271 default:
272 if (scm_is_pair (x))
273 return class_pair;
274 else
275 return class_unknown;
276 }
277
278 case scm_tc3_struct:
279 case scm_tc3_tc7_1:
280 case scm_tc3_tc7_2:
281 /* case scm_tc3_unused: */
282 /* Never reached */
283 break;
284 }
285 return class_unknown;
286}
287#undef FUNC_NAME
288
289/******************************************************************************
290 *
291 * initialize-object
292 *
293 ******************************************************************************/
294
295/*fixme* Manufacture keywords in advance */
296SCM
297scm_i_get_keyword (SCM key, SCM l, long len, SCM default_value, const char *subr)
298{
299 long i;
300
301 for (i = 0; i != len; i += 2)
302 {
303 SCM obj = SCM_CAR (l);
304
305 if (!scm_is_keyword (obj))
306 scm_misc_error (subr, "bad keyword: ~S", scm_list_1 (obj));
307 else if (scm_is_eq (obj, key))
308 return SCM_CADR (l);
309 else
310 l = SCM_CDDR (l);
311 }
312
313 return default_value;
314}
315
316
317SCM_DEFINE (scm_get_keyword, "get-keyword", 3, 0, 0,
318 (SCM key, SCM l, SCM default_value),
319 "Determine an associated value for the keyword @var{key} from\n"
320 "the list @var{l}. The list @var{l} has to consist of an even\n"
321 "number of elements, where, starting with the first, every\n"
322 "second element is a keyword, followed by its associated value.\n"
323 "If @var{l} does not hold a value for @var{key}, the value\n"
324 "@var{default_value} is returned.")
325#define FUNC_NAME s_scm_get_keyword
326{
327 long len;
328
329 SCM_ASSERT (scm_is_keyword (key), key, SCM_ARG1, FUNC_NAME);
330 len = scm_ilength (l);
331 if (len < 0 || len % 2 == 1)
332 scm_misc_error (FUNC_NAME, "Bad keyword-value list: ~S", scm_list_1 (l));
333
334 return scm_i_get_keyword (key, l, len, default_value, FUNC_NAME);
335}
336#undef FUNC_NAME
337
338
339SCM_KEYWORD (k_init_keyword, "init-keyword");
340
341
342SCM_DEFINE (scm_sys_initialize_object, "%initialize-object", 2, 0, 0,
343 (SCM obj, SCM initargs),
344 "Initialize the object @var{obj} with the given arguments\n"
345 "@var{initargs}.")
346#define FUNC_NAME s_scm_sys_initialize_object
347{
348 SCM tmp, get_n_set, slots;
349 SCM class = SCM_CLASS_OF (obj);
350 long n_initargs;
351
352 SCM_VALIDATE_INSTANCE (1, obj);
353 n_initargs = scm_ilength (initargs);
354 SCM_ASSERT ((n_initargs & 1) == 0, initargs, SCM_ARG2, FUNC_NAME);
355
356 get_n_set = SCM_SLOT (class, scm_si_getters_n_setters);
357 slots = SCM_SLOT (class, scm_si_slots);
358
359 /* See for each slot how it must be initialized */
360 for (;
361 !scm_is_null (slots);
362 get_n_set = SCM_CDR (get_n_set), slots = SCM_CDR (slots))
363 {
364 SCM slot_name = SCM_CAR (slots);
365 SCM slot_value = SCM_GOOPS_UNBOUND;
366
367 if (!scm_is_null (SCM_CDR (slot_name)))
368 {
369 /* This slot admits (perhaps) to be initialized at creation time */
370 long n = scm_ilength (SCM_CDR (slot_name));
371 if (n & 1) /* odd or -1 */
372 SCM_MISC_ERROR ("class contains bogus slot definition: ~S",
373 scm_list_1 (slot_name));
374 tmp = scm_i_get_keyword (k_init_keyword,
375 SCM_CDR (slot_name),
376 n,
377 SCM_PACK (0),
378 FUNC_NAME);
379 slot_name = SCM_CAR (slot_name);
380 if (SCM_UNPACK (tmp))
381 {
382 /* an initarg was provided for this slot */
383 if (!scm_is_keyword (tmp))
384 SCM_MISC_ERROR ("initarg must be a keyword. It was ~S",
385 scm_list_1 (tmp));
386 slot_value = scm_i_get_keyword (tmp,
387 initargs,
388 n_initargs,
389 SCM_GOOPS_UNBOUND,
390 FUNC_NAME);
391 }
392 }
393
394 if (!SCM_GOOPS_UNBOUNDP (slot_value))
395 /* set slot to provided value */
396 scm_slot_set_x (obj, slot_name, slot_value);
397 else
398 {
399 /* set slot to its :init-form if it exists */
400 tmp = SCM_CADAR (get_n_set);
401 if (scm_is_true (tmp))
402 scm_slot_set_x (obj, slot_name, scm_call_0 (tmp));
403 }
404 }
405
406 return obj;
407}
408#undef FUNC_NAME
409
410SCM_DEFINE (scm_sys_init_layout_x, "%init-layout!", 2, 0, 0,
411 (SCM class, SCM layout),
412 "")
413#define FUNC_NAME s_scm_sys_init_layout_x
414{
415 SCM_VALIDATE_INSTANCE (1, class);
416 SCM_ASSERT (!scm_is_symbol (SCM_VTABLE_LAYOUT (class)), class, 1, FUNC_NAME);
417 SCM_VALIDATE_STRING (2, layout);
418
419 SCM_SET_VTABLE_LAYOUT (class, scm_make_struct_layout (layout));
420 return SCM_UNSPECIFIED;
421}
422#undef FUNC_NAME
423
424SCM_DEFINE (scm_sys_inherit_magic_x, "%inherit-magic!", 2, 0, 0,
425 (SCM class, SCM dsupers),
426 "")
427#define FUNC_NAME s_scm_sys_inherit_magic_x
428{
429 SCM_VALIDATE_INSTANCE (1, class);
430 scm_i_struct_inherit_vtable_magic (SCM_CLASS_OF (class), class);
431 SCM_SET_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_OR_VALID);
432
433 return SCM_UNSPECIFIED;
434}
435#undef FUNC_NAME
436
437/******************************************************************************/
438
439SCM
440scm_make_standard_class (SCM meta, SCM name, SCM dsupers, SCM dslots)
441{
442 return scm_call_4 (scm_variable_ref (var_make_standard_class),
443 meta, name, dsupers, dslots);
444}
445
446/******************************************************************************/
447
448SCM_DEFINE (scm_sys_make_root_class, "%make-root-class", 3, 0, 0,
449 (SCM name, SCM dslots, SCM getters_n_setters),
450 "")
451#define FUNC_NAME s_scm_sys_make_root_class
452{
453 SCM cs, z;
454
455 cs = scm_from_locale_string (SCM_CLASS_CLASS_LAYOUT);
456 z = scm_i_make_vtable_vtable (cs);
457 SCM_SET_CLASS_FLAGS (z, (SCM_CLASSF_GOOPS_OR_VALID
458 | SCM_CLASSF_METACLASS));
459
460 SCM_SET_SLOT (z, scm_vtable_index_name, name);
461 SCM_SET_SLOT (z, scm_si_direct_supers, SCM_EOL); /* will be changed */
462 SCM_SET_SLOT (z, scm_si_direct_slots, dslots); /* will be changed */
463 SCM_SET_SLOT (z, scm_si_direct_subclasses, SCM_EOL);
464 SCM_SET_SLOT (z, scm_si_direct_methods, SCM_EOL);
465 SCM_SET_SLOT (z, scm_si_cpl, SCM_EOL); /* will be changed */
466 SCM_SET_SLOT (z, scm_si_slots, dslots); /* will be changed */
467 SCM_SET_SLOT (z, scm_si_nfields, scm_from_int (SCM_N_CLASS_SLOTS));
468 SCM_SET_SLOT (z, scm_si_getters_n_setters, getters_n_setters); /* will be changed */
469 SCM_SET_SLOT (z, scm_si_redefined, SCM_BOOL_F);
470
471 return z;
472}
473#undef FUNC_NAME
474
475/******************************************************************************/
476
477SCM_DEFINE (scm_instance_p, "instance?", 1, 0, 0,
478 (SCM obj),
479 "Return @code{#t} if @var{obj} is an instance.")
480#define FUNC_NAME s_scm_instance_p
481{
482 return scm_from_bool (SCM_INSTANCEP (obj));
483}
484#undef FUNC_NAME
485
486SCM_DEFINE (scm_class_p, "class?", 1, 0, 0,
487 (SCM obj),
488 "Return @code{#t} if @var{obj} is a class.")
489#define FUNC_NAME s_scm_class_p
490{
491 return scm_from_bool (SCM_CLASSP (obj));
492}
493#undef FUNC_NAME
494
495int
496scm_is_generic (SCM x)
497{
498 return SCM_INSTANCEP (x) && SCM_SUBCLASSP (SCM_CLASS_OF (x), class_generic);
499}
500
501int
502scm_is_method (SCM x)
503{
504 return SCM_INSTANCEP (x) && SCM_SUBCLASSP (SCM_CLASS_OF (x), class_method);
505}
506
507/******************************************************************************
508 *
509 * Meta object accessors
510 *
511 ******************************************************************************/
512
513SCM_SYMBOL (sym_procedure, "procedure");
514
515SCM
516scm_class_name (SCM obj)
517{
518 return scm_call_1 (scm_variable_ref (var_class_name), obj);
519}
520
521SCM
522scm_class_direct_supers (SCM obj)
523{
524 return scm_call_1 (scm_variable_ref (var_class_direct_supers), obj);
525}
526
527SCM
528scm_class_direct_slots (SCM obj)
529{
530 return scm_call_1 (scm_variable_ref (var_class_direct_slots), obj);
531}
532
533SCM
534scm_class_direct_subclasses (SCM obj)
535{
536 return scm_call_1 (scm_variable_ref (var_class_direct_subclasses), obj);
537}
538
539SCM
540scm_class_direct_methods (SCM obj)
541{
542 return scm_call_1 (scm_variable_ref (var_class_direct_methods), obj);
543}
544
545SCM
546scm_class_precedence_list (SCM obj)
547{
548 return scm_call_1 (scm_variable_ref (var_class_precedence_list), obj);
549}
550
551SCM
552scm_class_slots (SCM obj)
553{
554 return scm_call_1 (scm_variable_ref (var_class_slots), obj);
555}
556
557SCM_DEFINE (scm_generic_function_name, "generic-function-name", 1, 0, 0,
558 (SCM obj),
559 "Return the name of the generic function @var{obj}.")
560#define FUNC_NAME s_scm_generic_function_name
561{
562 SCM_VALIDATE_GENERIC (1, obj);
563 return scm_procedure_property (obj, scm_sym_name);
564}
565#undef FUNC_NAME
566
567SCM
568scm_generic_function_methods (SCM obj)
569{
570 return scm_call_1 (scm_variable_ref (var_generic_function_methods), obj);
571}
572
573SCM
574scm_method_generic_function (SCM obj)
575{
576 return scm_call_1 (scm_variable_ref (var_method_generic_function), obj);
577}
578
579SCM
580scm_method_specializers (SCM obj)
581{
582 return scm_call_1 (scm_variable_ref (var_method_specializers), obj);
583}
584
585SCM
586scm_method_procedure (SCM obj)
587{
588 return scm_call_1 (scm_variable_ref (var_method_procedure), obj);
589}
590
591/******************************************************************************
592 *
593 * S l o t a c c e s s
594 *
595 ******************************************************************************/
596
597SCM_DEFINE (scm_make_unbound, "make-unbound", 0, 0, 0,
598 (),
599 "Return the unbound value.")
600#define FUNC_NAME s_scm_make_unbound
601{
602 return SCM_GOOPS_UNBOUND;
603}
604#undef FUNC_NAME
605
606SCM_DEFINE (scm_unbound_p, "unbound?", 1, 0, 0,
607 (SCM obj),
608 "Return @code{#t} if @var{obj} is unbound.")
609#define FUNC_NAME s_scm_unbound_p
610{
611 return SCM_GOOPS_UNBOUNDP (obj) ? SCM_BOOL_T : SCM_BOOL_F;
612}
613#undef FUNC_NAME
614
615
616\f
617
618SCM
619scm_slot_ref_using_class (SCM class, SCM obj, SCM slot_name)
620{
621 return scm_call_3 (scm_variable_ref (var_slot_ref_using_class),
622 class, obj, slot_name);
623}
624
625SCM
626scm_slot_set_using_class_x (SCM class, SCM obj, SCM slot_name, SCM value)
627{
628 return scm_call_4 (scm_variable_ref (var_slot_set_using_class_x),
629 class, obj, slot_name, value);
630}
631
632SCM
633scm_slot_bound_using_class_p (SCM class, SCM obj, SCM slot_name)
634{
635 return scm_call_3 (scm_variable_ref (var_slot_bound_using_class_p),
636 class, obj, slot_name);
637}
638
639SCM
640scm_slot_exists_using_class_p (SCM class, SCM obj, SCM slot_name)
641{
642 return scm_call_3 (scm_variable_ref (var_slot_exists_using_class_p),
643 class, obj, slot_name);
644}
645
646SCM
647scm_slot_ref (SCM obj, SCM slot_name)
648{
649 return scm_call_2 (scm_variable_ref (var_slot_ref), obj, slot_name);
650}
651
652SCM
653scm_slot_set_x (SCM obj, SCM slot_name, SCM value)
654{
655 return scm_call_3 (scm_variable_ref (var_slot_set_x), obj, slot_name, value);
656}
657
658SCM
659scm_slot_bound_p (SCM obj, SCM slot_name)
660{
661 return scm_call_2 (scm_variable_ref (var_slot_bound_p), obj, slot_name);
662}
663
664SCM
665scm_slot_exists_p (SCM obj, SCM slot_name)
666{
667 return scm_call_2 (scm_variable_ref (var_slot_exists_p), obj, slot_name);
668}
669
670
671/******************************************************************************
672 *
673 * %allocate-instance (the low level instance allocation primitive)
674 *
675 ******************************************************************************/
676
677SCM_DEFINE (scm_sys_allocate_instance, "%allocate-instance", 2, 0, 0,
678 (SCM class, SCM initargs),
679 "Create a new instance of class @var{class} and initialize it\n"
680 "from the arguments @var{initargs}.")
681#define FUNC_NAME s_scm_sys_allocate_instance
682{
683 SCM obj;
684 scm_t_signed_bits n, i;
685 SCM layout;
686
687 SCM_VALIDATE_CLASS (1, class);
688
689 /* FIXME: duplicates some of scm_make_struct. */
690
691 n = SCM_I_INUM (SCM_SLOT (class, scm_si_nfields));
692 obj = scm_i_alloc_struct (SCM_STRUCT_DATA (class), n);
693
694 layout = SCM_VTABLE_LAYOUT (class);
695
696 /* Set all SCM-holding slots to unbound */
697 for (i = 0; i < n; i++)
698 {
699 scm_t_wchar c = scm_i_symbol_ref (layout, i*2);
700 if (c == 'p')
701 SCM_STRUCT_DATA (obj)[i] = SCM_UNPACK (SCM_GOOPS_UNBOUND);
702 else if (c == 's')
703 SCM_STRUCT_DATA (obj)[i] = SCM_UNPACK (obj);
704 else
705 SCM_STRUCT_DATA (obj)[i] = 0;
706 }
707
708 return obj;
709}
710#undef FUNC_NAME
711
712/******************************************************************************
713 *
714 * %modify-instance (used by change-class to modify in place)
715 *
716 ******************************************************************************/
717
718SCM_DEFINE (scm_sys_modify_instance, "%modify-instance", 2, 0, 0,
719 (SCM old, SCM new),
720 "")
721#define FUNC_NAME s_scm_sys_modify_instance
722{
723 SCM_VALIDATE_INSTANCE (1, old);
724 SCM_VALIDATE_INSTANCE (2, new);
725
726 /* Exchange the data contained in old and new. We exchange rather than
727 * scratch the old value with new to be correct with GC.
728 * See "Class redefinition protocol above".
729 */
730 SCM_CRITICAL_SECTION_START;
731 {
732 scm_t_bits word0, word1;
733 word0 = SCM_CELL_WORD_0 (old);
734 word1 = SCM_CELL_WORD_1 (old);
735 SCM_SET_CELL_WORD_0 (old, SCM_CELL_WORD_0 (new));
736 SCM_SET_CELL_WORD_1 (old, SCM_CELL_WORD_1 (new));
737 SCM_SET_CELL_WORD_0 (new, word0);
738 SCM_SET_CELL_WORD_1 (new, word1);
739 }
740 SCM_CRITICAL_SECTION_END;
741 return SCM_UNSPECIFIED;
742}
743#undef FUNC_NAME
744
745SCM_DEFINE (scm_sys_modify_class, "%modify-class", 2, 0, 0,
746 (SCM old, SCM new),
747 "")
748#define FUNC_NAME s_scm_sys_modify_class
749{
750 SCM_VALIDATE_CLASS (1, old);
751 SCM_VALIDATE_CLASS (2, new);
752
753 SCM_CRITICAL_SECTION_START;
754 {
755 scm_t_bits word0, word1;
756 word0 = SCM_CELL_WORD_0 (old);
757 word1 = SCM_CELL_WORD_1 (old);
758 SCM_SET_CELL_WORD_0 (old, SCM_CELL_WORD_0 (new));
759 SCM_SET_CELL_WORD_1 (old, SCM_CELL_WORD_1 (new));
760 SCM_STRUCT_DATA (old)[scm_vtable_index_self] = SCM_UNPACK (old);
761 SCM_SET_CELL_WORD_0 (new, word0);
762 SCM_SET_CELL_WORD_1 (new, word1);
763 SCM_STRUCT_DATA (new)[scm_vtable_index_self] = SCM_UNPACK (new);
764 }
765 SCM_CRITICAL_SECTION_END;
766 return SCM_UNSPECIFIED;
767}
768#undef FUNC_NAME
769
770SCM_DEFINE (scm_sys_invalidate_class, "%invalidate-class", 1, 0, 0,
771 (SCM class),
772 "")
773#define FUNC_NAME s_scm_sys_invalidate_class
774{
775 SCM_VALIDATE_CLASS (1, class);
776 SCM_CLEAR_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_VALID);
777 return SCM_UNSPECIFIED;
778}
779#undef FUNC_NAME
780
781/* When instances change class, they finally get a new body, but
782 * before that, they go through purgatory in hell. Odd as it may
783 * seem, this data structure saves us from eternal suffering in
784 * infinite recursions.
785 */
786
787static scm_t_bits **hell;
788static long n_hell = 1; /* one place for the evil one himself */
789static long hell_size = 4;
790static SCM hell_mutex;
791
792static long
793burnin (SCM o)
794{
795 long i;
796 for (i = 1; i < n_hell; ++i)
797 if (SCM_STRUCT_DATA (o) == hell[i])
798 return i;
799 return 0;
800}
801
802static void
803go_to_hell (void *o)
804{
805 SCM obj = *(SCM*)o;
806 scm_lock_mutex (hell_mutex);
807 if (n_hell >= hell_size)
808 {
809 hell_size *= 2;
810 hell = scm_realloc (hell, hell_size * sizeof(*hell));
811 }
812 hell[n_hell++] = SCM_STRUCT_DATA (obj);
813 scm_unlock_mutex (hell_mutex);
814}
815
816static void
817go_to_heaven (void *o)
818{
819 SCM obj = *(SCM*)o;
820 scm_lock_mutex (hell_mutex);
821 hell[burnin (obj)] = hell[--n_hell];
822 scm_unlock_mutex (hell_mutex);
823}
824
825
826SCM_SYMBOL (scm_sym_change_class, "change-class");
827
828static SCM
829purgatory (SCM obj, SCM new_class)
830{
831 return scm_call_2 (SCM_VARIABLE_REF (var_change_class), obj, new_class);
832}
833
834/* This function calls the generic function change-class for all
835 * instances which aren't currently undergoing class change.
836 */
837
838void
839scm_change_object_class (SCM obj, SCM old_class SCM_UNUSED, SCM new_class)
840{
841 if (!burnin (obj))
842 {
843 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
844 scm_dynwind_rewind_handler (go_to_hell, &obj, SCM_F_WIND_EXPLICITLY);
845 scm_dynwind_unwind_handler (go_to_heaven, &obj, SCM_F_WIND_EXPLICITLY);
846 purgatory (obj, new_class);
847 scm_dynwind_end ();
848 }
849}
850
851/******************************************************************************
852 *
853 * GGGG FFFFF
854 * G F
855 * G GG FFF
856 * G G F
857 * GGG E N E R I C F U N C T I O N S
858 *
859 * This implementation provides
860 * - generic functions (with class specializers)
861 * - multi-methods
862 * - next-method
863 * - a hard-coded MOP for standard gf, which can be overloaded for non-std gf
864 *
865 ******************************************************************************/
866
867SCM_KEYWORD (k_name, "name");
868SCM_GLOBAL_SYMBOL (scm_sym_args, "args");
869
870SCM_DEFINE (scm_generic_capability_p, "generic-capability?", 1, 0, 0,
871 (SCM proc),
872 "")
873#define FUNC_NAME s_scm_generic_capability_p
874{
875 SCM_ASSERT (scm_is_true (scm_procedure_p (proc)),
876 proc, SCM_ARG1, FUNC_NAME);
877 return (SCM_PRIMITIVE_GENERIC_P (proc) ? SCM_BOOL_T : SCM_BOOL_F);
878}
879#undef FUNC_NAME
880
881SCM_DEFINE (scm_enable_primitive_generic_x, "enable-primitive-generic!", 0, 0, 1,
882 (SCM subrs),
883 "")
884#define FUNC_NAME s_scm_enable_primitive_generic_x
885{
886 SCM_VALIDATE_REST_ARGUMENT (subrs);
887 while (!scm_is_null (subrs))
888 {
889 SCM subr = SCM_CAR (subrs);
890 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARGn, FUNC_NAME);
891 SCM_SET_SUBR_GENERIC (subr,
892 scm_make (scm_list_3 (class_generic,
893 k_name,
894 SCM_SUBR_NAME (subr))));
895 subrs = SCM_CDR (subrs);
896 }
897 return SCM_UNSPECIFIED;
898}
899#undef FUNC_NAME
900
901SCM_DEFINE (scm_set_primitive_generic_x, "set-primitive-generic!", 2, 0, 0,
902 (SCM subr, SCM generic),
903 "")
904#define FUNC_NAME s_scm_set_primitive_generic_x
905{
906 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARG1, FUNC_NAME);
907 SCM_ASSERT (SCM_PUREGENERICP (generic), generic, SCM_ARG2, FUNC_NAME);
908 SCM_SET_SUBR_GENERIC (subr, generic);
909 return SCM_UNSPECIFIED;
910}
911#undef FUNC_NAME
912
913SCM_DEFINE (scm_primitive_generic_generic, "primitive-generic-generic", 1, 0, 0,
914 (SCM subr),
915 "")
916#define FUNC_NAME s_scm_primitive_generic_generic
917{
918 if (SCM_PRIMITIVE_GENERIC_P (subr))
919 {
920 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (subr)))
921 scm_enable_primitive_generic_x (scm_list_1 (subr));
922 return *SCM_SUBR_GENERIC (subr);
923 }
924 SCM_WRONG_TYPE_ARG (SCM_ARG1, subr);
925}
926#undef FUNC_NAME
927
928typedef struct t_extension {
929 struct t_extension *next;
930 SCM extended;
931 SCM extension;
932} t_extension;
933
934
935/* Hint for `scm_gc_malloc ()' et al. when allocating `t_extension'
936 objects. */
937static const char extension_gc_hint[] = "GOOPS extension";
938
939static t_extension *extensions = 0;
940
941void
942scm_c_extend_primitive_generic (SCM extended, SCM extension)
943{
944 if (goops_loaded_p)
945 {
946 SCM gf, gext;
947 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (extended)))
948 scm_enable_primitive_generic_x (scm_list_1 (extended));
949 gf = *SCM_SUBR_GENERIC (extended);
950 gext = scm_call_2 (SCM_VARIABLE_REF (scm_var_make_extended_generic),
951 gf,
952 SCM_SUBR_NAME (extension));
953 SCM_SET_SUBR_GENERIC (extension, gext);
954 }
955 else
956 {
957 t_extension *e = scm_gc_malloc (sizeof (t_extension),
958 extension_gc_hint);
959 t_extension **loc = &extensions;
960 /* Make sure that extensions are placed before their own
961 * extensions in the extensions list. O(N^2) algorithm, but
962 * extensions of primitive generics are rare.
963 */
964 while (*loc && !scm_is_eq (extension, (*loc)->extended))
965 loc = &(*loc)->next;
966 e->next = *loc;
967 e->extended = extended;
968 e->extension = extension;
969 *loc = e;
970 }
971}
972
973static void
974setup_extended_primitive_generics ()
975{
976 while (extensions)
977 {
978 t_extension *e = extensions;
979 scm_c_extend_primitive_generic (e->extended, e->extension);
980 extensions = e->next;
981 }
982}
983
984/* Dirk:FIXME:: In all of these scm_wta_dispatch_* routines it is
985 * assumed that 'gf' is zero if uninitialized. It would be cleaner if
986 * some valid SCM value like SCM_BOOL_F or SCM_UNDEFINED were chosen.
987 */
988
989SCM
990scm_wta_dispatch_0 (SCM gf, const char *subr)
991{
992 if (!SCM_UNPACK (gf))
993 scm_error_num_args_subr (subr);
994
995 return scm_call_0 (gf);
996}
997
998SCM
999scm_wta_dispatch_1 (SCM gf, SCM a1, int pos, const char *subr)
1000{
1001 if (!SCM_UNPACK (gf))
1002 scm_wrong_type_arg (subr, pos, a1);
1003
1004 return scm_call_1 (gf, a1);
1005}
1006
1007SCM
1008scm_wta_dispatch_2 (SCM gf, SCM a1, SCM a2, int pos, const char *subr)
1009{
1010 if (!SCM_UNPACK (gf))
1011 scm_wrong_type_arg (subr, pos, (pos == SCM_ARG1) ? a1 : a2);
1012
1013 return scm_call_2 (gf, a1, a2);
1014}
1015
1016SCM
1017scm_wta_dispatch_n (SCM gf, SCM args, int pos, const char *subr)
1018{
1019 if (!SCM_UNPACK (gf))
1020 scm_wrong_type_arg (subr, pos, scm_list_ref (args, scm_from_int (pos)));
1021
1022 return scm_apply_0 (gf, args);
1023}
1024
1025/******************************************************************************
1026 *
1027 * Protocol for calling a generic fumction
1028 * This protocol is roughly equivalent to (parameter are a little bit different
1029 * for efficiency reasons):
1030 *
1031 * + apply-generic (gf args)
1032 * + compute-applicable-methods (gf args ...)
1033 * + sort-applicable-methods (methods args)
1034 * + apply-methods (gf methods args)
1035 *
1036 * apply-methods calls make-next-method to build the "continuation" of a a
1037 * method. Applying a next-method will call apply-next-method which in
1038 * turn will call apply again to call effectively the following method.
1039 *
1040 ******************************************************************************/
1041
1042SCM_DEFINE (scm_make, "make", 0, 0, 1,
1043 (SCM args),
1044 "Make a new object. @var{args} must contain the class and\n"
1045 "all necessary initialization information.")
1046#define FUNC_NAME s_scm_make
1047{
1048 return scm_apply_0 (scm_variable_ref (var_make), args);
1049}
1050#undef FUNC_NAME
1051
1052
1053/**********************************************************************
1054 *
1055 * Smob classes
1056 *
1057 **********************************************************************/
1058
1059static SCM
1060make_class_name (const char *prefix, const char *type_name, const char *suffix)
1061{
1062 if (!type_name)
1063 type_name = "";
1064 return scm_string_to_symbol (scm_string_append
1065 (scm_list_3 (scm_from_utf8_string (prefix),
1066 scm_from_utf8_string (type_name),
1067 scm_from_utf8_string (suffix))));
1068}
1069
1070SCM
1071scm_make_extended_class (char const *type_name, int applicablep)
1072{
1073 SCM name, meta, supers;
1074
1075 name = make_class_name ("<", type_name, ">");
1076 meta = class_class;
1077
1078 if (applicablep)
1079 supers = scm_list_1 (class_applicable);
1080 else
1081 supers = scm_list_1 (class_top);
1082
1083 return scm_make_standard_class (meta, name, supers, SCM_EOL);
1084}
1085
1086void
1087scm_i_inherit_applicable (SCM c)
1088{
1089 if (!SCM_SUBCLASSP (c, class_applicable))
1090 {
1091 SCM dsupers = SCM_SLOT (c, scm_si_direct_supers);
1092 SCM cpl = SCM_SLOT (c, scm_si_cpl);
1093 /* patch class_applicable into direct-supers */
1094 SCM top = scm_c_memq (class_top, dsupers);
1095 if (scm_is_false (top))
1096 dsupers = scm_append (scm_list_2 (dsupers,
1097 scm_list_1 (class_applicable)));
1098 else
1099 {
1100 SCM_SETCAR (top, class_applicable);
1101 SCM_SETCDR (top, scm_cons (class_top, SCM_CDR (top)));
1102 }
1103 SCM_SET_SLOT (c, scm_si_direct_supers, dsupers);
1104 /* patch class_applicable into cpl */
1105 top = scm_c_memq (class_top, cpl);
1106 if (scm_is_false (top))
1107 abort ();
1108 else
1109 {
1110 SCM_SETCAR (top, class_applicable);
1111 SCM_SETCDR (top, scm_cons (class_top, SCM_CDR (top)));
1112 }
1113 /* add class to direct-subclasses of class_applicable */
1114 SCM_SET_SLOT (class_applicable,
1115 scm_si_direct_subclasses,
1116 scm_cons (c, SCM_SLOT (class_applicable,
1117 scm_si_direct_subclasses)));
1118 }
1119}
1120
1121static void
1122create_smob_classes (void)
1123{
1124 long i;
1125
1126 for (i = 0; i < SCM_I_MAX_SMOB_TYPE_COUNT; ++i)
1127 scm_i_smob_class[i] = SCM_BOOL_F;
1128
1129 for (i = 0; i < scm_numsmob; ++i)
1130 if (scm_is_false (scm_i_smob_class[i]))
1131 scm_i_smob_class[i] = scm_make_extended_class (SCM_SMOBNAME (i),
1132 scm_smobs[i].apply != 0);
1133}
1134
1135void
1136scm_make_port_classes (long ptobnum, char *type_name)
1137{
1138 SCM name, meta, super, supers;
1139
1140 meta = class_class;
1141
1142 name = make_class_name ("<", type_name, "-port>");
1143 supers = scm_list_1 (class_port);
1144 super = scm_make_standard_class (meta, name, supers, SCM_EOL);
1145
1146 name = make_class_name ("<", type_name, "-input-port>");
1147 supers = scm_list_2 (super, class_input_port);
1148 scm_i_port_class[SCM_IN_PCLASS_INDEX + ptobnum]
1149 = scm_make_standard_class (meta, name, supers, SCM_EOL);
1150
1151 name = make_class_name ("<", type_name, "-output-port>");
1152 supers = scm_list_2 (super, class_output_port);
1153 scm_i_port_class[SCM_OUT_PCLASS_INDEX + ptobnum]
1154 = scm_make_standard_class (meta, name, supers, SCM_EOL);
1155
1156 name = make_class_name ("<", type_name, "-input-output-port>");
1157 supers = scm_list_2 (super, class_input_output_port);
1158 scm_i_port_class[SCM_INOUT_PCLASS_INDEX + ptobnum]
1159 = scm_make_standard_class (meta, name, supers, SCM_EOL);
1160}
1161
1162static void
1163create_port_classes (void)
1164{
1165 long i;
1166
1167 for (i = scm_c_num_port_types () - 1; i >= 0; i--)
1168 scm_make_port_classes (i, SCM_PTOBNAME (i));
1169}
1170
1171SCM
1172scm_i_define_class_for_vtable (SCM vtable)
1173{
1174 SCM class;
1175
1176 scm_i_pthread_mutex_lock (&scm_i_misc_mutex);
1177 if (scm_is_false (vtable_class_map))
1178 vtable_class_map = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
1179 scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
1180
1181 if (scm_is_false (scm_struct_vtable_p (vtable)))
1182 abort ();
1183
1184 class = scm_weak_table_refq (vtable_class_map, vtable, SCM_BOOL_F);
1185
1186 if (scm_is_false (class))
1187 {
1188 if (SCM_UNPACK (class_class))
1189 {
1190 SCM name, meta, supers;
1191
1192 name = SCM_VTABLE_NAME (vtable);
1193 if (scm_is_symbol (name))
1194 name = scm_string_to_symbol
1195 (scm_string_append
1196 (scm_list_3 (scm_from_latin1_string ("<"),
1197 scm_symbol_to_string (name),
1198 scm_from_latin1_string (">"))));
1199 else
1200 name = scm_from_latin1_symbol ("<>");
1201
1202 if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SETTER))
1203 {
1204 meta = class_applicable_struct_with_setter_class;
1205 supers = scm_list_1 (class_applicable_struct_with_setter);
1206 }
1207 else if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable,
1208 SCM_VTABLE_FLAG_APPLICABLE))
1209 {
1210 meta = class_applicable_struct_class;
1211 supers = scm_list_1 (class_applicable_struct);
1212 }
1213 else
1214 {
1215 meta = class_class;
1216 supers = scm_list_1 (class_top);
1217 }
1218
1219 return scm_make_standard_class (meta, name, supers, SCM_EOL);
1220 }
1221 else
1222 /* `create_struct_classes' will fill this in later. */
1223 class = SCM_BOOL_F;
1224
1225 /* Don't worry about races. This only happens when creating a
1226 vtable, which happens by definition in one thread. */
1227 scm_weak_table_putq_x (vtable_class_map, vtable, class);
1228 }
1229
1230 return class;
1231}
1232
1233static SCM
1234make_struct_class (void *closure SCM_UNUSED,
1235 SCM vtable, SCM data, SCM prev SCM_UNUSED)
1236{
1237 if (scm_is_false (data))
1238 scm_i_define_class_for_vtable (vtable);
1239 return SCM_UNSPECIFIED;
1240}
1241
1242static void
1243create_struct_classes (void)
1244{
1245 /* FIXME: take the vtable_class_map while initializing goops? */
1246 scm_internal_hash_fold (make_struct_class, 0, SCM_BOOL_F,
1247 vtable_class_map);
1248}
1249
1250/**********************************************************************
1251 *
1252 * C interface
1253 *
1254 **********************************************************************/
1255
1256void
1257scm_load_goops ()
1258{
1259 if (!goops_loaded_p)
1260 scm_c_resolve_module ("oop goops");
1261}
1262
1263
1264SCM_KEYWORD (k_setter, "setter");
1265
1266SCM
1267scm_ensure_accessor (SCM name)
1268{
1269 SCM var, gf;
1270
1271 var = scm_module_variable (scm_current_module (), name);
1272 if (SCM_VARIABLEP (var) && !SCM_UNBNDP (SCM_VARIABLE_REF (var)))
1273 gf = SCM_VARIABLE_REF (var);
1274 else
1275 gf = SCM_BOOL_F;
1276
1277 if (!SCM_IS_A_P (gf, class_accessor))
1278 {
1279 gf = scm_make (scm_list_3 (class_generic, k_name, name));
1280 gf = scm_make (scm_list_5 (class_accessor,
1281 k_name, name, k_setter, gf));
1282 }
1283
1284 return gf;
1285}
1286
1287/*
1288 * Initialization
1289 */
1290
1291SCM_DEFINE (scm_sys_bless_applicable_struct_vtables_x, "%bless-applicable-struct-vtables!", 2, 0, 0,
1292 (SCM applicable, SCM setter),
1293 "")
1294#define FUNC_NAME s_scm_sys_bless_applicable_struct_vtables_x
1295{
1296 SCM_VALIDATE_CLASS (1, applicable);
1297 SCM_VALIDATE_CLASS (2, setter);
1298 SCM_SET_VTABLE_FLAGS (applicable, SCM_VTABLE_FLAG_APPLICABLE_VTABLE);
1299 SCM_SET_VTABLE_FLAGS (setter, SCM_VTABLE_FLAG_SETTER_VTABLE);
1300 return SCM_UNSPECIFIED;
1301}
1302#undef FUNC_NAME
1303
1304SCM_DEFINE (scm_sys_bless_pure_generic_vtable_x, "%bless-pure-generic-vtable!", 1, 0, 0,
1305 (SCM vtable),
1306 "")
1307#define FUNC_NAME s_scm_sys_bless_pure_generic_vtable_x
1308{
1309 SCM_VALIDATE_CLASS (1, vtable);
1310 SCM_SET_CLASS_FLAGS (vtable, SCM_CLASSF_PURE_GENERIC);
1311 return SCM_UNSPECIFIED;
1312}
1313#undef FUNC_NAME
1314
1315SCM_DEFINE (scm_sys_goops_early_init, "%goops-early-init", 0, 0, 0,
1316 (),
1317 "")
1318#define FUNC_NAME s_scm_sys_goops_early_init
1319{
1320 var_make_standard_class = scm_c_lookup ("make-standard-class");
1321 var_make = scm_c_lookup ("make");
1322
1323 var_slot_ref_using_class = scm_c_lookup ("slot-ref-using-class");
1324 var_slot_set_using_class_x = scm_c_lookup ("slot-set-using-class!");
1325 var_slot_bound_using_class_p = scm_c_lookup ("slot-bound-using-class?");
1326 var_slot_exists_using_class_p = scm_c_lookup ("slot-exists-using-class?");
1327
1328 var_slot_ref = scm_c_lookup ("slot-ref");
1329 var_slot_set_x = scm_c_lookup ("slot-set!");
1330 var_slot_bound_p = scm_c_lookup ("slot-bound?");
1331 var_slot_exists_p = scm_c_lookup ("slot-exists?");
1332
1333 class_class = scm_variable_ref (scm_c_lookup ("<class>"));
1334 class_top = scm_variable_ref (scm_c_lookup ("<top>"));
1335 class_object = scm_variable_ref (scm_c_lookup ("<object>"));
1336
1337 class_foreign_slot = scm_variable_ref (scm_c_lookup ("<foreign-slot>"));
1338 class_protected = scm_variable_ref (scm_c_lookup ("<protected-slot>"));
1339 class_hidden = scm_variable_ref (scm_c_lookup ("<hidden-slot>"));
1340 class_opaque = scm_variable_ref (scm_c_lookup ("<opaque-slot>"));
1341 class_read_only = scm_variable_ref (scm_c_lookup ("<read-only-slot>"));
1342 class_self = scm_variable_ref (scm_c_lookup ("<self-slot>"));
1343 class_protected_opaque = scm_variable_ref (scm_c_lookup ("<protected-opaque-slot>"));
1344 class_protected_hidden = scm_variable_ref (scm_c_lookup ("<protected-hidden-slot>"));
1345 class_protected_read_only = scm_variable_ref (scm_c_lookup ("<protected-read-only-slot>"));
1346 class_scm = scm_variable_ref (scm_c_lookup ("<scm-slot>"));
1347 class_int = scm_variable_ref (scm_c_lookup ("<int-slot>"));
1348 class_float = scm_variable_ref (scm_c_lookup ("<float-slot>"));
1349 class_double = scm_variable_ref (scm_c_lookup ("<double-slot>"));
1350
1351 /* Applicables */
1352 class_procedure_class = scm_variable_ref (scm_c_lookup ("<procedure-class>"));
1353 class_applicable_struct_class = scm_variable_ref (scm_c_lookup ("<applicable-struct-class>"));
1354 class_applicable_struct_with_setter_class =
1355 scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter-class>"));
1356
1357 class_method = scm_variable_ref (scm_c_lookup ("<method>"));
1358 class_accessor_method = scm_variable_ref (scm_c_lookup ("<accessor-method>"));
1359 class_applicable = scm_variable_ref (scm_c_lookup ("<applicable>"));
1360 class_applicable_struct = scm_variable_ref (scm_c_lookup ("<applicable-struct>"));
1361 class_applicable_struct_with_setter = scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter>"));
1362 class_generic = scm_variable_ref (scm_c_lookup ("<generic>"));
1363 class_extended_generic = scm_variable_ref (scm_c_lookup ("<extended-generic>"));
1364 class_generic_with_setter = scm_variable_ref (scm_c_lookup ("<generic-with-setter>"));
1365 class_accessor = scm_variable_ref (scm_c_lookup ("<accessor>"));
1366 class_extended_generic_with_setter = scm_variable_ref (scm_c_lookup ("<extended-generic-with-setter>"));
1367 class_extended_accessor = scm_variable_ref (scm_c_lookup ("<extended-accessor>"));
1368
1369 /* Primitive types classes */
1370 class_boolean = scm_variable_ref (scm_c_lookup ("<boolean>"));
1371 class_char = scm_variable_ref (scm_c_lookup ("<char>"));
1372 class_list = scm_variable_ref (scm_c_lookup ("<list>"));
1373 class_pair = scm_variable_ref (scm_c_lookup ("<pair>"));
1374 class_null = scm_variable_ref (scm_c_lookup ("<null>"));
1375 class_string = scm_variable_ref (scm_c_lookup ("<string>"));
1376 class_symbol = scm_variable_ref (scm_c_lookup ("<symbol>"));
1377 class_vector = scm_variable_ref (scm_c_lookup ("<vector>"));
1378 class_foreign = scm_variable_ref (scm_c_lookup ("<foreign>"));
1379 class_hashtable = scm_variable_ref (scm_c_lookup ("<hashtable>"));
1380 class_fluid = scm_variable_ref (scm_c_lookup ("<fluid>"));
1381 class_dynamic_state = scm_variable_ref (scm_c_lookup ("<dynamic-state>"));
1382 class_frame = scm_variable_ref (scm_c_lookup ("<frame>"));
1383 class_vm_cont = scm_variable_ref (scm_c_lookup ("<vm-continuation>"));
1384 class_bytevector = scm_variable_ref (scm_c_lookup ("<bytevector>"));
1385 class_uvec = scm_variable_ref (scm_c_lookup ("<uvec>"));
1386 class_array = scm_variable_ref (scm_c_lookup ("<array>"));
1387 class_bitvector = scm_variable_ref (scm_c_lookup ("<bitvector>"));
1388 class_number = scm_variable_ref (scm_c_lookup ("<number>"));
1389 class_complex = scm_variable_ref (scm_c_lookup ("<complex>"));
1390 class_real = scm_variable_ref (scm_c_lookup ("<real>"));
1391 class_integer = scm_variable_ref (scm_c_lookup ("<integer>"));
1392 class_fraction = scm_variable_ref (scm_c_lookup ("<fraction>"));
1393 class_keyword = scm_variable_ref (scm_c_lookup ("<keyword>"));
1394 class_unknown = scm_variable_ref (scm_c_lookup ("<unknown>"));
1395 class_procedure = scm_variable_ref (scm_c_lookup ("<procedure>"));
1396 class_primitive_generic = scm_variable_ref (scm_c_lookup ("<primitive-generic>"));
1397 class_port = scm_variable_ref (scm_c_lookup ("<port>"));
1398 class_input_port = scm_variable_ref (scm_c_lookup ("<input-port>"));
1399 class_output_port = scm_variable_ref (scm_c_lookup ("<output-port>"));
1400 class_input_output_port = scm_variable_ref (scm_c_lookup ("<input-output-port>"));
1401
1402 create_smob_classes ();
1403 create_struct_classes ();
1404 create_port_classes ();
1405
1406 return SCM_UNSPECIFIED;
1407}
1408#undef FUNC_NAME
1409
1410SCM_DEFINE (scm_sys_goops_loaded, "%goops-loaded", 0, 0, 0,
1411 (),
1412 "Announce that GOOPS is loaded and perform initialization\n"
1413 "on the C level which depends on the loaded GOOPS modules.")
1414#define FUNC_NAME s_scm_sys_goops_loaded
1415{
1416 goops_loaded_p = 1;
1417 var_class_name = scm_c_lookup ("class-name");
1418 var_class_direct_supers = scm_c_lookup ("class-direct-supers");
1419 var_class_direct_slots = scm_c_lookup ("class-direct-slots");
1420 var_class_direct_subclasses = scm_c_lookup ("class-direct-subclasses");
1421 var_class_direct_methods = scm_c_lookup ("class-direct-methods");
1422 var_class_precedence_list = scm_c_lookup ("class-precedence-list");
1423 var_class_slots = scm_c_lookup ("class-slots");
1424
1425 var_generic_function_methods = scm_c_lookup ("generic-function-methods");
1426 var_method_generic_function = scm_c_lookup ("method-generic-function");
1427 var_method_specializers = scm_c_lookup ("method-specializers");
1428 var_method_procedure = scm_c_lookup ("method-procedure");
1429
1430 var_change_class =
1431 scm_module_variable (scm_module_goops, sym_change_class);
1432 setup_extended_primitive_generics ();
1433
1434#if (SCM_ENABLE_DEPRECATED == 1)
1435 scm_init_deprecated_goops ();
1436#endif
1437
1438 return SCM_UNSPECIFIED;
1439}
1440#undef FUNC_NAME
1441
1442SCM scm_module_goops;
1443
1444static void
1445scm_init_goops_builtins (void *unused)
1446{
1447 scm_module_goops = scm_current_module ();
1448
1449 hell = scm_calloc (hell_size * sizeof (*hell));
1450 hell_mutex = scm_make_mutex ();
1451
1452#include "libguile/goops.x"
1453}
1454
1455void
1456scm_init_goops ()
1457{
1458 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
1459 "scm_init_goops_builtins", scm_init_goops_builtins,
1460 NULL);
1461}
1462
1463/*
1464 Local Variables:
1465 c-file-style: "gnu"
1466 End:
1467*/