Add br-if-logtest opcode
[bpt/guile.git] / libguile / goops.c
CommitLineData
dc7a33fa 1/* Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2008,2009,2010,2011,2012,2013,2014
366ecaec 2 * Free Software Foundation, Inc.
6d77c894 3 *
73be1d9e 4 * This library is free software; you can redistribute it and/or
53befeb7
NJ
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.
6d77c894 8 *
53befeb7
NJ
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
6d77c894 13 *
73be1d9e
MV
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
53befeb7
NJ
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA
73be1d9e 18 */
80662eda
MD
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
dbb605f5
LC
28#ifdef HAVE_CONFIG_H
29# include <config.h>
30#endif
31
80662eda
MD
32#include <stdio.h>
33
34#include "libguile/_scm.h"
35#include "libguile/alist.h"
4e047c3e 36#include "libguile/async.h"
539d5410 37#include "libguile/chars.h"
80662eda
MD
38#include "libguile/debug.h"
39#include "libguile/dynl.h"
40#include "libguile/dynwind.h"
41#include "libguile/eval.h"
9fdf9fd3 42#include "libguile/gsubr.h"
80662eda
MD
43#include "libguile/hashtab.h"
44#include "libguile/keywords.h"
45#include "libguile/macros.h"
46#include "libguile/modules.h"
80662eda
MD
47#include "libguile/ports.h"
48#include "libguile/procprop.h"
efcebb5b 49#include "libguile/programs.h"
80662eda 50#include "libguile/random.h"
fdc28395 51#include "libguile/root.h"
80662eda
MD
52#include "libguile/smob.h"
53#include "libguile/strings.h"
54#include "libguile/strports.h"
55#include "libguile/vectors.h"
efcebb5b 56#include "libguile/vm.h"
80662eda 57
ca83b028 58#include "libguile/validate.h"
80662eda
MD
59#include "libguile/goops.h"
60
80662eda
MD
61#define SPEC_OF(x) SCM_SLOT (x, scm_si_specializers)
62
efcebb5b
AW
63/* Port classes */
64#define SCM_IN_PCLASS_INDEX 0
65#define SCM_OUT_PCLASS_INDEX SCM_I_MAX_PORT_TYPE_COUNT
66#define SCM_INOUT_PCLASS_INDEX (2 * SCM_I_MAX_PORT_TYPE_COUNT)
67
bef95911
AW
68/* this file is a mess. in theory, though, we shouldn't have many SCM references
69 -- most of the references should be to vars. */
70
71static SCM var_slot_unbound = SCM_BOOL_F;
72static SCM var_slot_missing = SCM_BOOL_F;
73static SCM var_compute_cpl = SCM_BOOL_F;
74static SCM var_no_applicable_method = SCM_BOOL_F;
bef95911
AW
75static SCM var_change_class = SCM_BOOL_F;
76
77SCM_SYMBOL (sym_slot_unbound, "slot-unbound");
78SCM_SYMBOL (sym_slot_missing, "slot-missing");
79SCM_SYMBOL (sym_compute_cpl, "compute-cpl");
80SCM_SYMBOL (sym_no_applicable_method, "no-applicable-method");
81SCM_SYMBOL (sym_memoize_method_x, "memoize-method!");
82SCM_SYMBOL (sym_change_class, "change-class");
83
84SCM_VARIABLE (scm_var_make_extended_generic, "make-extended-generic");
85
86
80662eda
MD
87/* Class redefinition protocol:
88
89 A class is represented by a heap header h1 which points to a
90 malloc:ed memory block m1.
91
92 When a new version of a class is created, a new header h2 and
93 memory block m2 are allocated. The headers h1 and h2 then switch
94 pointers so that h1 refers to m2 and h2 to m1. In this way, names
95 bound to h1 will point to the new class at the same time as h2 will
7346de61 96 be a handle which the GC will use to free m1.
80662eda
MD
97
98 The `redefined' slot of m1 will be set to point to h1. An old
7346de61 99 instance will have its class pointer (the CAR of the heap header)
80662eda
MD
100 pointing to m1. The non-immediate `redefined'-slot in m1 indicates
101 the class modification and the new class pointer can be found via
102 h1.
103*/
104
0fd7dcd3
MD
105#define TEST_CHANGE_CLASS(obj, class) \
106 { \
107 class = SCM_CLASS_OF (obj); \
7888309b 108 if (scm_is_true (SCM_OBJ_CLASS_REDEF (obj))) \
0fd7dcd3
MD
109 { \
110 scm_change_object_class (obj, class, SCM_OBJ_CLASS_REDEF (obj));\
111 class = SCM_CLASS_OF (obj); \
112 } \
80662eda
MD
113 }
114
115#define NXT_MTHD_METHODS(m) (SCM_VELTS (m)[1])
116#define NXT_MTHD_ARGS(m) (SCM_VELTS (m)[2])
117
118#define SCM_GOOPS_UNBOUND SCM_UNBOUND
d223c3fc 119#define SCM_GOOPS_UNBOUNDP(x) (scm_is_eq (x, SCM_GOOPS_UNBOUND))
80662eda
MD
120
121static int goops_loaded_p = 0;
92c2555f 122static scm_t_rstate *goops_rstate;
80662eda 123
539d5410
MV
124/* These variables are filled in by the object system when loaded. */
125SCM scm_class_boolean, scm_class_char, scm_class_pair;
126SCM scm_class_procedure, scm_class_string, scm_class_symbol;
ea68d342 127SCM scm_class_primitive_generic;
9ea31741 128SCM scm_class_vector, scm_class_null;
539d5410
MV
129SCM scm_class_integer, scm_class_real, scm_class_complex, scm_class_fraction;
130SCM scm_class_unknown;
80662eda 131SCM scm_class_top, scm_class_object, scm_class_class;
74b6d6e4 132SCM scm_class_applicable;
51f66c91 133SCM scm_class_applicable_struct, scm_class_applicable_struct_with_setter;
bbf8d523 134SCM scm_class_generic, scm_class_generic_with_setter;
f8af5c6d 135SCM scm_class_accessor;
bbf8d523 136SCM scm_class_extended_generic, scm_class_extended_generic_with_setter;
74b6d6e4 137SCM scm_class_extended_accessor;
bbf8d523 138SCM scm_class_method;
51f66c91 139SCM scm_class_accessor_method;
80662eda 140SCM scm_class_procedure_class;
51f66c91 141SCM scm_class_applicable_struct_class;
80662eda
MD
142SCM scm_class_number, scm_class_list;
143SCM scm_class_keyword;
144SCM scm_class_port, scm_class_input_output_port;
145SCM scm_class_input_port, scm_class_output_port;
80662eda
MD
146SCM scm_class_foreign_slot;
147SCM scm_class_self, scm_class_protected;
b6cf4d02
AW
148SCM scm_class_hidden, scm_class_opaque, scm_class_read_only;
149SCM scm_class_protected_hidden, scm_class_protected_opaque, scm_class_protected_read_only;
80662eda
MD
150SCM scm_class_scm;
151SCM scm_class_int, scm_class_float, scm_class_double;
152
e2c2a699 153static SCM class_foreign;
9ea31741
AW
154static SCM class_hashtable;
155static SCM class_fluid;
156static SCM class_dynamic_state;
6f3b0cc2 157static SCM class_frame;
6f3b0cc2 158static SCM class_vm_cont;
f826a886
AW
159static SCM class_bytevector;
160static SCM class_uvec;
b2637c98 161static SCM class_array;
ff1feca9 162static SCM class_bitvector;
9ea31741 163
f3c6a02c
AW
164static SCM vtable_class_map = SCM_BOOL_F;
165
63385df2
LC
166/* Port classes. Allocate 3 times the maximum number of port types so that
167 input ports, output ports, and in/out ports can be stored at different
168 offsets. See `SCM_IN_PCLASS_INDEX' et al. */
169SCM scm_port_class[3 * SCM_I_MAX_PORT_TYPE_COUNT];
170
171/* SMOB classes. */
47455469 172SCM scm_smob_class[SCM_I_MAX_SMOB_TYPE_COUNT];
539d5410
MV
173
174SCM scm_no_applicable_method;
175
80662eda
MD
176SCM_SYMBOL (scm_sym_define_public, "define-public");
177
178static SCM scm_make_unbound (void);
179static SCM scm_unbound_p (SCM obj);
398d8ee1
KN
180static SCM scm_assert_bound (SCM value, SCM obj);
181static SCM scm_at_assert_bound_ref (SCM obj, SCM index);
182static SCM scm_sys_goops_loaded (void);
9db8cf16
MG
183static SCM scm_make_extended_class_from_symbol (SCM type_name_sym,
184 int applicablep);
80662eda 185
f3c6a02c
AW
186
187SCM
188scm_i_define_class_for_vtable (SCM vtable)
189{
190 SCM class;
191
203a92b6 192 scm_i_pthread_mutex_lock (&scm_i_misc_mutex);
f3c6a02c 193 if (scm_is_false (vtable_class_map))
203a92b6
AW
194 vtable_class_map = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
195 scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
f3c6a02c
AW
196
197 if (scm_is_false (scm_struct_vtable_p (vtable)))
198 abort ();
199
203a92b6 200 class = scm_weak_table_refq (vtable_class_map, vtable, SCM_BOOL_F);
ea742d29 201
f3c6a02c
AW
202 if (scm_is_false (class))
203 {
204 if (SCM_UNPACK (scm_class_class))
205 {
206 SCM name = SCM_VTABLE_NAME (vtable);
207 if (!scm_is_symbol (name))
208 name = scm_string_to_symbol (scm_nullstr);
209
210 class = scm_make_extended_class_from_symbol
211 (name, SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_APPLICABLE));
212 }
213 else
214 /* `create_struct_classes' will fill this in later. */
215 class = SCM_BOOL_F;
ea742d29
AW
216
217 /* Don't worry about races. This only happens when creating a
218 vtable, which happens by definition in one thread. */
203a92b6 219 scm_weak_table_putq_x (vtable_class_map, vtable, class);
f3c6a02c
AW
220 }
221
222 return class;
223}
224
539d5410
MV
225/* This function is used for efficient type dispatch. */
226SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0,
227 (SCM x),
228 "Return the class of @var{x}.")
229#define FUNC_NAME s_scm_class_of
230{
231 switch (SCM_ITAG3 (x))
232 {
233 case scm_tc3_int_1:
234 case scm_tc3_int_2:
235 return scm_class_integer;
236
237 case scm_tc3_imm24:
238 if (SCM_CHARP (x))
239 return scm_class_char;
240 else if (scm_is_bool (x))
241 return scm_class_boolean;
242 else if (scm_is_null (x))
243 return scm_class_null;
244 else
245 return scm_class_unknown;
246
247 case scm_tc3_cons:
248 switch (SCM_TYP7 (x))
249 {
250 case scm_tcs_cons_nimcar:
251 return scm_class_pair;
539d5410
MV
252 case scm_tc7_symbol:
253 return scm_class_symbol;
254 case scm_tc7_vector:
255 case scm_tc7_wvect:
256 return scm_class_vector;
5b46a8c2 257 case scm_tc7_pointer:
e2c2a699 258 return class_foreign;
c99de5aa 259 case scm_tc7_hashtable:
9ea31741
AW
260 return class_hashtable;
261 case scm_tc7_fluid:
262 return class_fluid;
263 case scm_tc7_dynamic_state:
264 return class_dynamic_state;
6f3b0cc2
AW
265 case scm_tc7_frame:
266 return class_frame;
6f3b0cc2
AW
267 case scm_tc7_vm_cont:
268 return class_vm_cont;
f826a886
AW
269 case scm_tc7_bytevector:
270 if (SCM_BYTEVECTOR_ELEMENT_TYPE (x) == SCM_ARRAY_ELEMENT_TYPE_VU8)
271 return class_bytevector;
272 else
273 return class_uvec;
b2637c98
AW
274 case scm_tc7_array:
275 return class_array;
ff1feca9
AW
276 case scm_tc7_bitvector:
277 return class_bitvector;
539d5410
MV
278 case scm_tc7_string:
279 return scm_class_string;
280 case scm_tc7_number:
281 switch SCM_TYP16 (x) {
282 case scm_tc16_big:
283 return scm_class_integer;
284 case scm_tc16_real:
285 return scm_class_real;
286 case scm_tc16_complex:
287 return scm_class_complex;
288 case scm_tc16_fraction:
289 return scm_class_fraction;
290 }
e0755cd1 291 case scm_tc7_program:
b2b33168
AW
292 if (SCM_PROGRAM_IS_PRIMITIVE_GENERIC (x)
293 && SCM_UNPACK (*SCM_SUBR_GENERIC (x)))
fd12a19a
AW
294 return scm_class_primitive_generic;
295 else
296 return scm_class_procedure;
539d5410
MV
297
298 case scm_tc7_smob:
299 {
300 scm_t_bits type = SCM_TYP16 (x);
301 if (type != scm_tc16_port_with_ps)
302 return scm_smob_class[SCM_TC2SMOBNUM (type)];
303 x = SCM_PORT_WITH_PS_PORT (x);
304 /* fall through to ports */
305 }
306 case scm_tc7_port:
307 return scm_port_class[(SCM_WRTNG & SCM_CELL_WORD_0 (x)
308 ? (SCM_RDNG & SCM_CELL_WORD_0 (x)
309 ? SCM_INOUT_PCLASS_INDEX | SCM_PTOBNUM (x)
310 : SCM_OUT_PCLASS_INDEX | SCM_PTOBNUM (x))
311 : SCM_IN_PCLASS_INDEX | SCM_PTOBNUM (x))];
312 case scm_tcs_struct:
313 if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS_VALID)
314 return SCM_CLASS_OF (x);
315 else if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS)
316 {
317 /* Goops object */
318 if (! scm_is_false (SCM_OBJ_CLASS_REDEF (x)))
319 scm_change_object_class (x,
320 SCM_CLASS_OF (x), /* old */
321 SCM_OBJ_CLASS_REDEF (x)); /* new */
322 return SCM_CLASS_OF (x);
323 }
324 else
f3c6a02c 325 return scm_i_define_class_for_vtable (SCM_CLASS_OF (x));
539d5410
MV
326 default:
327 if (scm_is_pair (x))
328 return scm_class_pair;
329 else
330 return scm_class_unknown;
331 }
332
333 case scm_tc3_struct:
334 case scm_tc3_tc7_1:
335 case scm_tc3_tc7_2:
314b8716 336 /* case scm_tc3_unused: */
539d5410
MV
337 /* Never reached */
338 break;
339 }
340 return scm_class_unknown;
341}
342#undef FUNC_NAME
343
80662eda
MD
344/******************************************************************************
345 *
346 * Compute-cpl
347 *
bbf8d523
MD
348 * This version doesn't fully handle multiple-inheritance. It serves
349 * only for booting classes and will be overloaded in Scheme
80662eda
MD
350 *
351 ******************************************************************************/
352
80662eda
MD
353static SCM
354map (SCM (*proc) (SCM), SCM ls)
355{
d2e53ed6 356 if (scm_is_null (ls))
80662eda 357 return ls;
6b80d352
DH
358 else
359 {
360 SCM res = scm_cons (proc (SCM_CAR (ls)), SCM_EOL);
361 SCM h = res;
362 ls = SCM_CDR (ls);
13d807b7 363 while (scm_is_pair (ls))
6b80d352
DH
364 {
365 SCM_SETCDR (h, scm_cons (proc (SCM_CAR (ls)), SCM_EOL));
366 h = SCM_CDR (h);
367 ls = SCM_CDR (ls);
368 }
369 return res;
370 }
80662eda
MD
371}
372
373static SCM
374filter_cpl (SCM ls)
375{
376 SCM res = SCM_EOL;
13d807b7 377 while (scm_is_pair (ls))
80662eda
MD
378 {
379 SCM el = SCM_CAR (ls);
7888309b 380 if (scm_is_false (scm_c_memq (el, res)))
80662eda
MD
381 res = scm_cons (el, res);
382 ls = SCM_CDR (ls);
383 }
384 return res;
385}
386
387static SCM
388compute_cpl (SCM class)
389{
390 if (goops_loaded_p)
bef95911 391 return scm_call_1 (SCM_VARIABLE_REF (var_compute_cpl), class);
80662eda
MD
392 else
393 {
394 SCM supers = SCM_SLOT (class, scm_si_direct_supers);
395 SCM ls = scm_append (scm_acons (class, supers,
396 map (compute_cpl, supers)));
397 return scm_reverse_x (filter_cpl (ls), SCM_EOL);
398 }
399}
400
401/******************************************************************************
402 *
403 * compute-slots
404 *
405 ******************************************************************************/
406
407static SCM
408remove_duplicate_slots (SCM l, SCM res, SCM slots_already_seen)
409{
410 SCM tmp;
411
13d807b7 412 if (!scm_is_pair (l))
80662eda
MD
413 return res;
414
415 tmp = SCM_CAAR (l);
cc95e00a 416 if (!scm_is_symbol (tmp))
1afff620 417 scm_misc_error ("%compute-slots", "bad slot name ~S", scm_list_1 (tmp));
6d77c894 418
7888309b 419 if (scm_is_false (scm_c_memq (tmp, slots_already_seen))) {
80662eda
MD
420 res = scm_cons (SCM_CAR (l), res);
421 slots_already_seen = scm_cons (tmp, slots_already_seen);
422 }
6d77c894 423
80662eda
MD
424 return remove_duplicate_slots (SCM_CDR (l), res, slots_already_seen);
425}
426
13d807b7
AW
427static void
428check_cpl (SCM slots, SCM bslots)
429{
430 for (; scm_is_pair (bslots); bslots = SCM_CDR (bslots))
431 if (scm_is_true (scm_assq (SCM_CAAR (bslots), slots)))
432 scm_misc_error ("init-object", "a predefined <class> inherited "
433 "field cannot be redefined", SCM_EOL);
434}
435
436static SCM
437build_class_class_slots (void);
438
80662eda
MD
439static SCM
440build_slots_list (SCM dslots, SCM cpl)
441{
13d807b7
AW
442 SCM bslots, class_slots;
443 int classp;
444 SCM res = dslots;
445
446 class_slots = SCM_EOL;
447 classp = scm_is_true (scm_memq (scm_class_class, cpl));
448
449 if (classp)
450 {
451 bslots = build_class_class_slots ();
452 check_cpl (res, bslots);
453 }
454 else
455 bslots = SCM_EOL;
456
457 if (scm_is_pair (cpl))
458 {
459 for (cpl = SCM_CDR (cpl); scm_is_pair (cpl); cpl = SCM_CDR (cpl))
460 {
461 SCM new_slots = SCM_SLOT (SCM_CAR (cpl),
462 scm_si_direct_slots);
463 if (classp)
464 {
465 if (!scm_is_eq (SCM_CAR (cpl), scm_class_class))
466 check_cpl (new_slots, bslots);
467 else
468 {
469 /* Move class slots to the head of the list. */
470 class_slots = new_slots;
471 continue;
472 }
473 }
474 res = scm_append (scm_list_2 (new_slots, res));
475 }
476 }
477 else
478 scm_misc_error ("%compute-slots", "malformed cpl argument in "
479 "build_slots_list", SCM_EOL);
80662eda 480
13d807b7
AW
481 /* make sure to add the <class> slots to the head of the list */
482 if (classp)
483 res = scm_append (scm_list_2 (class_slots, res));
80662eda
MD
484
485 /* res contains a list of slots. Remove slots which appears more than once */
486 return remove_duplicate_slots (scm_reverse (res), SCM_EOL, SCM_EOL);
487}
488
489static SCM
490maplist (SCM ls)
491{
492 SCM orig = ls;
d2e53ed6 493 while (!scm_is_null (ls))
80662eda 494 {
13d807b7
AW
495 if (!scm_is_pair (ls))
496 scm_misc_error ("%compute-slots", "malformed ls argument in "
497 "maplist", SCM_EOL);
d2e53ed6 498 if (!scm_is_pair (SCM_CAR (ls)))
13d807b7 499 SCM_SETCAR (ls, scm_cons (SCM_CAR (ls), SCM_EOL));
80662eda
MD
500 ls = SCM_CDR (ls);
501 }
502 return orig;
503}
504
80662eda 505
23437298
DH
506SCM_DEFINE (scm_sys_compute_slots, "%compute-slots", 1, 0, 0,
507 (SCM class),
5352393c
MG
508 "Return a list consisting of the names of all slots belonging to\n"
509 "class @var{class}, i. e. the slots of @var{class} and of all of\n"
6d77c894 510 "its superclasses.")
23437298 511#define FUNC_NAME s_scm_sys_compute_slots
80662eda 512{
398d8ee1 513 SCM_VALIDATE_CLASS (1, class);
80662eda
MD
514 return build_slots_list (SCM_SLOT (class, scm_si_direct_slots),
515 SCM_SLOT (class, scm_si_cpl));
516}
23437298
DH
517#undef FUNC_NAME
518
80662eda
MD
519
520/******************************************************************************
521 *
522 * compute-getters-n-setters
6d77c894
TTN
523 *
524 * This version doesn't handle slot options. It serves only for booting
dcb410ec 525 * classes and will be overloaded in Scheme.
80662eda
MD
526 *
527 ******************************************************************************/
528
529SCM_KEYWORD (k_init_value, "init-value");
530SCM_KEYWORD (k_init_thunk, "init-thunk");
531
532static SCM
533compute_getters_n_setters (SCM slots)
534{
535 SCM res = SCM_EOL;
536 SCM *cdrloc = &res;
c014a02e 537 long i = 0;
80662eda 538
d2e53ed6 539 for ( ; !scm_is_null (slots); slots = SCM_CDR (slots))
80662eda
MD
540 {
541 SCM init = SCM_BOOL_F;
542 SCM options = SCM_CDAR (slots);
d2e53ed6 543 if (!scm_is_null (options))
80662eda 544 {
b2b33168
AW
545 init = scm_get_keyword (k_init_value, options, SCM_PACK (0));
546 if (SCM_UNPACK (init))
366ecaec 547 {
9d019f9b
AW
548 init = scm_primitive_eval (scm_list_3 (scm_sym_lambda,
549 SCM_EOL,
550 scm_list_2 (scm_sym_quote,
551 init)));
366ecaec 552 }
80662eda
MD
553 else
554 init = scm_get_keyword (k_init_thunk, options, SCM_BOOL_F);
555 }
556 *cdrloc = scm_cons (scm_cons (SCM_CAAR (slots),
557 scm_cons (init,
e11e83f3 558 scm_from_int (i++))),
80662eda
MD
559 SCM_EOL);
560 cdrloc = SCM_CDRLOC (*cdrloc);
561 }
562 return res;
563}
564
565/******************************************************************************
566 *
567 * initialize-object
568 *
569 ******************************************************************************/
570
571/*fixme* Manufacture keywords in advance */
572SCM
c014a02e 573scm_i_get_keyword (SCM key, SCM l, long len, SCM default_value, const char *subr)
80662eda 574{
c014a02e 575 long i;
23437298
DH
576
577 for (i = 0; i != len; i += 2)
80662eda 578 {
23437298
DH
579 SCM obj = SCM_CAR (l);
580
c598539a 581 if (!scm_is_keyword (obj))
1afff620 582 scm_misc_error (subr, "bad keyword: ~S", scm_list_1 (obj));
bc36d050 583 else if (scm_is_eq (obj, key))
80662eda 584 return SCM_CADR (l);
23437298
DH
585 else
586 l = SCM_CDDR (l);
80662eda 587 }
23437298 588
80662eda
MD
589 return default_value;
590}
591
80662eda 592
23437298
DH
593SCM_DEFINE (scm_get_keyword, "get-keyword", 3, 0, 0,
594 (SCM key, SCM l, SCM default_value),
5352393c
MG
595 "Determine an associated value for the keyword @var{key} from\n"
596 "the list @var{l}. The list @var{l} has to consist of an even\n"
597 "number of elements, where, starting with the first, every\n"
598 "second element is a keyword, followed by its associated value.\n"
599 "If @var{l} does not hold a value for @var{key}, the value\n"
600 "@var{default_value} is returned.")
23437298 601#define FUNC_NAME s_scm_get_keyword
80662eda 602{
c014a02e 603 long len;
23437298 604
c598539a 605 SCM_ASSERT (scm_is_keyword (key), key, SCM_ARG1, FUNC_NAME);
80662eda 606 len = scm_ilength (l);
b6311c08 607 if (len < 0 || len % 2 == 1)
1afff620 608 scm_misc_error (FUNC_NAME, "Bad keyword-value list: ~S", scm_list_1 (l));
23437298
DH
609
610 return scm_i_get_keyword (key, l, len, default_value, FUNC_NAME);
80662eda 611}
23437298
DH
612#undef FUNC_NAME
613
80662eda 614
80662eda
MD
615SCM_KEYWORD (k_init_keyword, "init-keyword");
616
617static SCM get_slot_value (SCM class, SCM obj, SCM slotdef);
618static SCM set_slot_value (SCM class, SCM obj, SCM slotdef, SCM value);
619
398d8ee1
KN
620SCM_DEFINE (scm_sys_initialize_object, "%initialize-object", 2, 0, 0,
621 (SCM obj, SCM initargs),
6bcefd15
MG
622 "Initialize the object @var{obj} with the given arguments\n"
623 "@var{initargs}.")
398d8ee1 624#define FUNC_NAME s_scm_sys_initialize_object
80662eda
MD
625{
626 SCM tmp, get_n_set, slots;
627 SCM class = SCM_CLASS_OF (obj);
c014a02e 628 long n_initargs;
80662eda 629
398d8ee1 630 SCM_VALIDATE_INSTANCE (1, obj);
80662eda 631 n_initargs = scm_ilength (initargs);
398d8ee1 632 SCM_ASSERT ((n_initargs & 1) == 0, initargs, SCM_ARG2, FUNC_NAME);
6d77c894 633
80662eda
MD
634 get_n_set = SCM_SLOT (class, scm_si_getters_n_setters);
635 slots = SCM_SLOT (class, scm_si_slots);
6d77c894 636
80662eda
MD
637 /* See for each slot how it must be initialized */
638 for (;
d2e53ed6 639 !scm_is_null (slots);
80662eda
MD
640 get_n_set = SCM_CDR (get_n_set), slots = SCM_CDR (slots))
641 {
642 SCM slot_name = SCM_CAR (slots);
48ad85fb 643 SCM slot_value = SCM_GOOPS_UNBOUND;
6d77c894 644
d2e53ed6 645 if (!scm_is_null (SCM_CDR (slot_name)))
80662eda
MD
646 {
647 /* This slot admits (perhaps) to be initialized at creation time */
c014a02e 648 long n = scm_ilength (SCM_CDR (slot_name));
80662eda 649 if (n & 1) /* odd or -1 */
398d8ee1 650 SCM_MISC_ERROR ("class contains bogus slot definition: ~S",
1afff620 651 scm_list_1 (slot_name));
80662eda
MD
652 tmp = scm_i_get_keyword (k_init_keyword,
653 SCM_CDR (slot_name),
654 n,
b2b33168 655 SCM_PACK (0),
398d8ee1 656 FUNC_NAME);
80662eda 657 slot_name = SCM_CAR (slot_name);
b2b33168 658 if (SCM_UNPACK (tmp))
80662eda
MD
659 {
660 /* an initarg was provided for this slot */
c598539a 661 if (!scm_is_keyword (tmp))
398d8ee1 662 SCM_MISC_ERROR ("initarg must be a keyword. It was ~S",
1afff620 663 scm_list_1 (tmp));
80662eda
MD
664 slot_value = scm_i_get_keyword (tmp,
665 initargs,
666 n_initargs,
48ad85fb 667 SCM_GOOPS_UNBOUND,
398d8ee1 668 FUNC_NAME);
80662eda
MD
669 }
670 }
671
48ad85fb 672 if (!SCM_GOOPS_UNBOUNDP (slot_value))
80662eda
MD
673 /* set slot to provided value */
674 set_slot_value (class, obj, SCM_CAR (get_n_set), slot_value);
675 else
676 {
677 /* set slot to its :init-form if it exists */
678 tmp = SCM_CADAR (get_n_set);
7888309b 679 if (scm_is_true (tmp))
48ad85fb
AW
680 set_slot_value (class,
681 obj,
682 SCM_CAR (get_n_set),
683 scm_call_0 (tmp));
80662eda
MD
684 }
685 }
6d77c894 686
80662eda
MD
687 return obj;
688}
398d8ee1 689#undef FUNC_NAME
80662eda 690
21ab2aeb
MD
691/* NOTE: The following macros are interdependent with code
692 * in goops.scm:compute-getters-n-setters
693 */
694#define SCM_GNS_INSTANCE_ALLOCATED_P(gns) \
e11e83f3 695 (SCM_I_INUMP (SCM_CDDR (gns)) \
d2e53ed6
MV
696 || (scm_is_pair (SCM_CDDR (gns)) \
697 && scm_is_pair (SCM_CDDDR (gns)) \
698 && scm_is_pair (SCM_CDDDDR (gns))))
21ab2aeb 699#define SCM_GNS_INDEX(gns) \
e11e83f3
MV
700 (SCM_I_INUMP (SCM_CDDR (gns)) \
701 ? SCM_I_INUM (SCM_CDDR (gns)) \
702 : scm_to_long (SCM_CAR (SCM_CDDDDR (gns))))
21ab2aeb 703#define SCM_GNS_SIZE(gns) \
e11e83f3 704 (SCM_I_INUMP (SCM_CDDR (gns)) \
21ab2aeb 705 ? 1 \
e11e83f3 706 : scm_to_long (SCM_CADR (SCM_CDDDDR (gns))))
80662eda
MD
707
708SCM_KEYWORD (k_class, "class");
b46fae00
MD
709SCM_KEYWORD (k_allocation, "allocation");
710SCM_KEYWORD (k_instance, "instance");
80662eda 711
398d8ee1
KN
712SCM_DEFINE (scm_sys_prep_layout_x, "%prep-layout!", 1, 0, 0,
713 (SCM class),
714 "")
715#define FUNC_NAME s_scm_sys_prep_layout_x
80662eda 716{
21ab2aeb 717 SCM slots, getters_n_setters, nfields;
6b80d352
DH
718 unsigned long int n, i;
719 char *s;
cc95e00a 720 SCM layout;
80662eda 721
398d8ee1 722 SCM_VALIDATE_INSTANCE (1, class);
80662eda 723 slots = SCM_SLOT (class, scm_si_slots);
21ab2aeb 724 getters_n_setters = SCM_SLOT (class, scm_si_getters_n_setters);
80662eda 725 nfields = SCM_SLOT (class, scm_si_nfields);
e11e83f3 726 if (!SCM_I_INUMP (nfields) || SCM_I_INUM (nfields) < 0)
398d8ee1 727 SCM_MISC_ERROR ("bad value in nfields slot: ~S",
1afff620 728 scm_list_1 (nfields));
e11e83f3 729 n = 2 * SCM_I_INUM (nfields);
80662eda
MD
730 if (n < sizeof (SCM_CLASS_CLASS_LAYOUT) - 1
731 && SCM_SUBCLASSP (class, scm_class_class))
398d8ee1 732 SCM_MISC_ERROR ("class object doesn't have enough fields: ~S",
1afff620 733 scm_list_1 (nfields));
6d77c894 734
190d4b0d 735 layout = scm_i_make_string (n, &s, 0);
21ab2aeb 736 i = 0;
d2e53ed6 737 while (scm_is_pair (getters_n_setters))
80662eda 738 {
21ab2aeb 739 if (SCM_GNS_INSTANCE_ALLOCATED_P (SCM_CAR (getters_n_setters)))
b46fae00 740 {
21ab2aeb
MD
741 SCM type;
742 int len, index, size;
743 char p, a;
744
d2e53ed6 745 if (i >= n || !scm_is_pair (slots))
21ab2aeb
MD
746 goto inconsistent;
747
748 /* extract slot type */
b46fae00 749 len = scm_ilength (SCM_CDAR (slots));
21ab2aeb
MD
750 type = scm_i_get_keyword (k_class, SCM_CDAR (slots),
751 len, SCM_BOOL_F, FUNC_NAME);
752 /* determine slot GC protection and access mode */
7888309b 753 if (scm_is_false (type))
6b80d352 754 {
21ab2aeb
MD
755 p = 'p';
756 a = 'w';
6b80d352
DH
757 }
758 else
759 {
21ab2aeb 760 if (!SCM_CLASSP (type))
cc95e00a 761 SCM_MISC_ERROR ("bad slot class", SCM_EOL);
21ab2aeb
MD
762 else if (SCM_SUBCLASSP (type, scm_class_foreign_slot))
763 {
764 if (SCM_SUBCLASSP (type, scm_class_self))
765 p = 's';
766 else if (SCM_SUBCLASSP (type, scm_class_protected))
767 p = 'p';
768 else
769 p = 'u';
770
771 if (SCM_SUBCLASSP (type, scm_class_opaque))
772 a = 'o';
773 else if (SCM_SUBCLASSP (type, scm_class_read_only))
774 a = 'r';
b6cf4d02
AW
775 else if (SCM_SUBCLASSP (type, scm_class_hidden))
776 a = 'h';
21ab2aeb
MD
777 else
778 a = 'w';
779 }
780 else
781 {
782 p = 'p';
783 a = 'w';
784 }
785 }
786
787 index = SCM_GNS_INDEX (SCM_CAR (getters_n_setters));
788 if (index != (i >> 1))
789 goto inconsistent;
790 size = SCM_GNS_SIZE (SCM_CAR (getters_n_setters));
791 while (size)
792 {
793 s[i++] = p;
794 s[i++] = a;
795 --size;
6b80d352 796 }
80662eda 797 }
80662eda 798 slots = SCM_CDR (slots);
21ab2aeb
MD
799 getters_n_setters = SCM_CDR (getters_n_setters);
800 }
d2e53ed6 801 if (!scm_is_null (slots))
21ab2aeb
MD
802 {
803 inconsistent:
21ab2aeb 804 SCM_MISC_ERROR ("inconsistent getters-n-setters", SCM_EOL);
80662eda 805 }
b6cf4d02 806 SCM_SET_VTABLE_LAYOUT (class, scm_string_to_symbol (layout));
80662eda
MD
807 return SCM_UNSPECIFIED;
808}
398d8ee1 809#undef FUNC_NAME
80662eda
MD
810
811static void prep_hashsets (SCM);
812
398d8ee1
KN
813SCM_DEFINE (scm_sys_inherit_magic_x, "%inherit-magic!", 2, 0, 0,
814 (SCM class, SCM dsupers),
815 "")
816#define FUNC_NAME s_scm_sys_inherit_magic_x
80662eda 817{
398d8ee1 818 SCM_VALIDATE_INSTANCE (1, class);
51f66c91
AW
819 scm_i_struct_inherit_vtable_magic (SCM_CLASS_OF (class), class);
820 SCM_SET_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_OR_VALID);
80662eda
MD
821
822 prep_hashsets (class);
6d77c894 823
80662eda
MD
824 return SCM_UNSPECIFIED;
825}
398d8ee1 826#undef FUNC_NAME
80662eda 827
63c1872f 828static void
80662eda
MD
829prep_hashsets (SCM class)
830{
dcb410ec 831 unsigned int i;
80662eda 832
e161c9f8 833 for (i = 0; i < 8; ++i)
dcb410ec 834 SCM_SET_HASHSET (class, i, scm_c_uniform32 (goops_rstate));
80662eda
MD
835}
836
837/******************************************************************************/
838
839SCM
840scm_basic_basic_make_class (SCM class, SCM name, SCM dsupers, SCM dslots)
841{
842 SCM z, cpl, slots, nfields, g_n_s;
843
844 /* Allocate one instance */
845 z = scm_make_struct (class, SCM_INUM0, SCM_EOL);
846
847 /* Initialize its slots */
dcb410ec 848 SCM_SET_SLOT (z, scm_si_direct_supers, dsupers);
80662eda
MD
849 cpl = compute_cpl (z);
850 slots = build_slots_list (maplist (dslots), cpl);
e11e83f3 851 nfields = scm_from_int (scm_ilength (slots));
80662eda
MD
852 g_n_s = compute_getters_n_setters (slots);
853
b6cf4d02 854 SCM_SET_SLOT (z, scm_vtable_index_name, name);
dcb410ec
DH
855 SCM_SET_SLOT (z, scm_si_direct_slots, dslots);
856 SCM_SET_SLOT (z, scm_si_direct_subclasses, SCM_EOL);
857 SCM_SET_SLOT (z, scm_si_direct_methods, SCM_EOL);
858 SCM_SET_SLOT (z, scm_si_cpl, cpl);
859 SCM_SET_SLOT (z, scm_si_slots, slots);
860 SCM_SET_SLOT (z, scm_si_nfields, nfields);
861 SCM_SET_SLOT (z, scm_si_getters_n_setters, g_n_s);
862 SCM_SET_SLOT (z, scm_si_redefined, SCM_BOOL_F);
80662eda
MD
863
864 /* Add this class in the direct-subclasses slot of dsupers */
865 {
866 SCM tmp;
d2e53ed6 867 for (tmp = dsupers; !scm_is_null (tmp); tmp = SCM_CDR (tmp))
dcb410ec
DH
868 SCM_SET_SLOT (SCM_CAR (tmp), scm_si_direct_subclasses,
869 scm_cons (z, SCM_SLOT (SCM_CAR (tmp),
870 scm_si_direct_subclasses)));
80662eda
MD
871 }
872
80662eda
MD
873 return z;
874}
875
876SCM
877scm_basic_make_class (SCM class, SCM name, SCM dsupers, SCM dslots)
878{
879 SCM z = scm_basic_basic_make_class (class, name, dsupers, dslots);
80662eda 880 scm_sys_prep_layout_x (z);
51f66c91 881 scm_sys_inherit_magic_x (z, dsupers);
80662eda
MD
882 return z;
883}
884
885/******************************************************************************/
886
6b80d352 887SCM_SYMBOL (sym_layout, "layout");
b6cf4d02
AW
888SCM_SYMBOL (sym_flags, "flags");
889SCM_SYMBOL (sym_self, "%self");
890SCM_SYMBOL (sym_instance_finalizer, "instance-finalizer");
891SCM_SYMBOL (sym_reserved_0, "%reserved-0");
892SCM_SYMBOL (sym_reserved_1, "%reserved-1");
6b80d352
DH
893SCM_SYMBOL (sym_print, "print");
894SCM_SYMBOL (sym_procedure, "procedure");
895SCM_SYMBOL (sym_setter, "setter");
896SCM_SYMBOL (sym_redefined, "redefined");
897SCM_SYMBOL (sym_h0, "h0");
898SCM_SYMBOL (sym_h1, "h1");
899SCM_SYMBOL (sym_h2, "h2");
900SCM_SYMBOL (sym_h3, "h3");
901SCM_SYMBOL (sym_h4, "h4");
902SCM_SYMBOL (sym_h5, "h5");
903SCM_SYMBOL (sym_h6, "h6");
904SCM_SYMBOL (sym_h7, "h7");
905SCM_SYMBOL (sym_name, "name");
906SCM_SYMBOL (sym_direct_supers, "direct-supers");
907SCM_SYMBOL (sym_direct_slots, "direct-slots");
908SCM_SYMBOL (sym_direct_subclasses, "direct-subclasses");
909SCM_SYMBOL (sym_direct_methods, "direct-methods");
910SCM_SYMBOL (sym_cpl, "cpl");
911SCM_SYMBOL (sym_default_slot_definition_class, "default-slot-definition-class");
912SCM_SYMBOL (sym_slots, "slots");
913SCM_SYMBOL (sym_getters_n_setters, "getters-n-setters");
6b80d352 914SCM_SYMBOL (sym_nfields, "nfields");
6b80d352
DH
915
916
80662eda 917static SCM
13d807b7 918build_class_class_slots (void)
80662eda 919{
b6cf4d02
AW
920 /* has to be kept in sync with SCM_VTABLE_BASE_LAYOUT and
921 SCM_CLASS_CLASS_LAYOUT */
6b80d352
DH
922 return scm_list_n (
923 scm_list_3 (sym_layout, k_class, scm_class_protected_read_only),
b6cf4d02
AW
924 scm_list_3 (sym_flags, k_class, scm_class_hidden),
925 scm_list_3 (sym_self, k_class, scm_class_self),
926 scm_list_3 (sym_instance_finalizer, k_class, scm_class_hidden),
6b80d352 927 scm_list_1 (sym_print),
b6cf4d02
AW
928 scm_list_3 (sym_name, k_class, scm_class_protected_hidden),
929 scm_list_3 (sym_reserved_0, k_class, scm_class_hidden),
930 scm_list_3 (sym_reserved_1, k_class, scm_class_hidden),
6b80d352
DH
931 scm_list_1 (sym_redefined),
932 scm_list_3 (sym_h0, k_class, scm_class_int),
933 scm_list_3 (sym_h1, k_class, scm_class_int),
934 scm_list_3 (sym_h2, k_class, scm_class_int),
935 scm_list_3 (sym_h3, k_class, scm_class_int),
936 scm_list_3 (sym_h4, k_class, scm_class_int),
937 scm_list_3 (sym_h5, k_class, scm_class_int),
938 scm_list_3 (sym_h6, k_class, scm_class_int),
939 scm_list_3 (sym_h7, k_class, scm_class_int),
6b80d352
DH
940 scm_list_1 (sym_direct_supers),
941 scm_list_1 (sym_direct_slots),
942 scm_list_1 (sym_direct_subclasses),
943 scm_list_1 (sym_direct_methods),
944 scm_list_1 (sym_cpl),
945 scm_list_1 (sym_default_slot_definition_class),
946 scm_list_1 (sym_slots),
947 scm_list_1 (sym_getters_n_setters),
6b80d352 948 scm_list_1 (sym_nfields),
6b80d352 949 SCM_UNDEFINED);
80662eda
MD
950}
951
952static void
953create_basic_classes (void)
954{
955 /* SCM slots_of_class = build_class_class_slots (); */
956
b6cf4d02
AW
957 /**** <class> ****/
958 SCM cs = scm_from_locale_string (SCM_CLASS_CLASS_LAYOUT);
4a655e50 959 SCM name = scm_from_latin1_symbol ("<class>");
0818837f 960 scm_class_class = scm_i_make_vtable_vtable (cs);
80662eda
MD
961 SCM_SET_CLASS_FLAGS (scm_class_class, (SCM_CLASSF_GOOPS_OR_VALID
962 | SCM_CLASSF_METACLASS));
963
b6cf4d02 964 SCM_SET_SLOT (scm_class_class, scm_vtable_index_name, name);
dcb410ec
DH
965 SCM_SET_SLOT (scm_class_class, scm_si_direct_supers, SCM_EOL); /* will be changed */
966 /* SCM_SET_SLOT (scm_class_class, scm_si_direct_slots, slots_of_class); */
967 SCM_SET_SLOT (scm_class_class, scm_si_direct_subclasses, SCM_EOL);
6d77c894 968 SCM_SET_SLOT (scm_class_class, scm_si_direct_methods, SCM_EOL);
dcb410ec
DH
969 SCM_SET_SLOT (scm_class_class, scm_si_cpl, SCM_EOL); /* will be changed */
970 /* SCM_SET_SLOT (scm_class_class, scm_si_slots, slots_of_class); */
e11e83f3 971 SCM_SET_SLOT (scm_class_class, scm_si_nfields, scm_from_int (SCM_N_CLASS_SLOTS));
dcb410ec
DH
972 /* SCM_SET_SLOT (scm_class_class, scm_si_getters_n_setters,
973 compute_getters_n_setters (slots_of_class)); */
974 SCM_SET_SLOT (scm_class_class, scm_si_redefined, SCM_BOOL_F);
80662eda
MD
975
976 prep_hashsets (scm_class_class);
977
28d0871b 978 scm_module_define (scm_module_goops, name, scm_class_class);
80662eda 979
51f66c91 980 /**** <top> ****/
4a655e50 981 name = scm_from_latin1_symbol ("<top>");
f39448c5
AW
982 scm_class_top = scm_basic_make_class (scm_class_class, name,
983 SCM_EOL, SCM_EOL);
80662eda 984
28d0871b 985 scm_module_define (scm_module_goops, name, scm_class_top);
6d77c894 986
51f66c91 987 /**** <object> ****/
4a655e50 988 name = scm_from_latin1_symbol ("<object>");
f39448c5
AW
989 scm_class_object = scm_basic_make_class (scm_class_class, name,
990 scm_list_1 (scm_class_top), SCM_EOL);
80662eda 991
28d0871b 992 scm_module_define (scm_module_goops, name, scm_class_object);
80662eda
MD
993
994 /* <top> <object> and <class> were partially initialized. Correct them here */
1afff620 995 SCM_SET_SLOT (scm_class_object, scm_si_direct_subclasses, scm_list_1 (scm_class_class));
80662eda 996
1afff620
KN
997 SCM_SET_SLOT (scm_class_class, scm_si_direct_supers, scm_list_1 (scm_class_object));
998 SCM_SET_SLOT (scm_class_class, scm_si_cpl, scm_list_3 (scm_class_class, scm_class_object, scm_class_top));
80662eda
MD
999}
1000
1001/******************************************************************************/
1002
398d8ee1
KN
1003SCM_DEFINE (scm_instance_p, "instance?", 1, 0, 0,
1004 (SCM obj),
6bcefd15 1005 "Return @code{#t} if @var{obj} is an instance.")
398d8ee1 1006#define FUNC_NAME s_scm_instance_p
80662eda 1007{
7888309b 1008 return scm_from_bool (SCM_INSTANCEP (obj));
80662eda 1009}
398d8ee1 1010#undef FUNC_NAME
80662eda 1011
80662eda
MD
1012
1013/******************************************************************************
6d77c894 1014 *
80662eda
MD
1015 * Meta object accessors
1016 *
1017 ******************************************************************************/
398d8ee1
KN
1018SCM_DEFINE (scm_class_name, "class-name", 1, 0, 0,
1019 (SCM obj),
6bcefd15 1020 "Return the class name of @var{obj}.")
398d8ee1 1021#define FUNC_NAME s_scm_class_name
80662eda 1022{
398d8ee1 1023 SCM_VALIDATE_CLASS (1, obj);
6b80d352 1024 return scm_slot_ref (obj, sym_name);
80662eda 1025}
398d8ee1 1026#undef FUNC_NAME
80662eda 1027
398d8ee1
KN
1028SCM_DEFINE (scm_class_direct_supers, "class-direct-supers", 1, 0, 0,
1029 (SCM obj),
6bcefd15 1030 "Return the direct superclasses of the class @var{obj}.")
398d8ee1 1031#define FUNC_NAME s_scm_class_direct_supers
80662eda 1032{
398d8ee1 1033 SCM_VALIDATE_CLASS (1, obj);
6b80d352 1034 return scm_slot_ref (obj, sym_direct_supers);
80662eda 1035}
398d8ee1 1036#undef FUNC_NAME
80662eda 1037
398d8ee1
KN
1038SCM_DEFINE (scm_class_direct_slots, "class-direct-slots", 1, 0, 0,
1039 (SCM obj),
6bcefd15 1040 "Return the direct slots of the class @var{obj}.")
398d8ee1 1041#define FUNC_NAME s_scm_class_direct_slots
80662eda 1042{
398d8ee1 1043 SCM_VALIDATE_CLASS (1, obj);
6b80d352 1044 return scm_slot_ref (obj, sym_direct_slots);
80662eda 1045}
398d8ee1 1046#undef FUNC_NAME
80662eda 1047
398d8ee1
KN
1048SCM_DEFINE (scm_class_direct_subclasses, "class-direct-subclasses", 1, 0, 0,
1049 (SCM obj),
6bcefd15 1050 "Return the direct subclasses of the class @var{obj}.")
398d8ee1 1051#define FUNC_NAME s_scm_class_direct_subclasses
80662eda 1052{
398d8ee1 1053 SCM_VALIDATE_CLASS (1, obj);
6b80d352 1054 return scm_slot_ref(obj, sym_direct_subclasses);
80662eda 1055}
398d8ee1 1056#undef FUNC_NAME
80662eda 1057
398d8ee1
KN
1058SCM_DEFINE (scm_class_direct_methods, "class-direct-methods", 1, 0, 0,
1059 (SCM obj),
6bcefd15 1060 "Return the direct methods of the class @var{obj}")
398d8ee1 1061#define FUNC_NAME s_scm_class_direct_methods
80662eda 1062{
398d8ee1 1063 SCM_VALIDATE_CLASS (1, obj);
6b80d352 1064 return scm_slot_ref (obj, sym_direct_methods);
80662eda 1065}
398d8ee1 1066#undef FUNC_NAME
80662eda 1067
398d8ee1
KN
1068SCM_DEFINE (scm_class_precedence_list, "class-precedence-list", 1, 0, 0,
1069 (SCM obj),
6bcefd15 1070 "Return the class precedence list of the class @var{obj}.")
398d8ee1 1071#define FUNC_NAME s_scm_class_precedence_list
80662eda 1072{
398d8ee1 1073 SCM_VALIDATE_CLASS (1, obj);
6b80d352 1074 return scm_slot_ref (obj, sym_cpl);
80662eda 1075}
398d8ee1 1076#undef FUNC_NAME
80662eda 1077
398d8ee1
KN
1078SCM_DEFINE (scm_class_slots, "class-slots", 1, 0, 0,
1079 (SCM obj),
6bcefd15 1080 "Return the slot list of the class @var{obj}.")
398d8ee1 1081#define FUNC_NAME s_scm_class_slots
80662eda 1082{
398d8ee1 1083 SCM_VALIDATE_CLASS (1, obj);
6b80d352 1084 return scm_slot_ref (obj, sym_slots);
80662eda 1085}
398d8ee1 1086#undef FUNC_NAME
80662eda 1087
398d8ee1
KN
1088SCM_DEFINE (scm_generic_function_name, "generic-function-name", 1, 0, 0,
1089 (SCM obj),
6bcefd15 1090 "Return the name of the generic function @var{obj}.")
398d8ee1 1091#define FUNC_NAME s_scm_generic_function_name
80662eda 1092{
398d8ee1 1093 SCM_VALIDATE_GENERIC (1, obj);
80662eda
MD
1094 return scm_procedure_property (obj, scm_sym_name);
1095}
398d8ee1 1096#undef FUNC_NAME
80662eda 1097
bbf8d523
MD
1098SCM_SYMBOL (sym_methods, "methods");
1099SCM_SYMBOL (sym_extended_by, "extended-by");
1100SCM_SYMBOL (sym_extends, "extends");
1101
1102static
1103SCM fold_downward_gf_methods (SCM method_lists, SCM gf)
1104{
1105 SCM gfs = scm_slot_ref (gf, sym_extended_by);
1106 method_lists = scm_cons (scm_slot_ref (gf, sym_methods), method_lists);
d2e53ed6 1107 while (!scm_is_null (gfs))
bbf8d523
MD
1108 {
1109 method_lists = fold_downward_gf_methods (method_lists, SCM_CAR (gfs));
1110 gfs = SCM_CDR (gfs);
1111 }
1112 return method_lists;
1113}
1114
1115static
1116SCM fold_upward_gf_methods (SCM method_lists, SCM gf)
1117{
1118 if (SCM_IS_A_P (gf, scm_class_extended_generic))
1119 {
1120 SCM gfs = scm_slot_ref (gf, sym_extends);
d2e53ed6 1121 while (!scm_is_null (gfs))
bbf8d523
MD
1122 {
1123 SCM methods = scm_slot_ref (SCM_CAR (gfs), sym_methods);
1124 method_lists = fold_upward_gf_methods (scm_cons (methods,
1125 method_lists),
1126 SCM_CAR (gfs));
1127 gfs = SCM_CDR (gfs);
1128 }
1129 }
1130 return method_lists;
1131}
1132
398d8ee1
KN
1133SCM_DEFINE (scm_generic_function_methods, "generic-function-methods", 1, 0, 0,
1134 (SCM obj),
6bcefd15 1135 "Return the methods of the generic function @var{obj}.")
398d8ee1 1136#define FUNC_NAME s_scm_generic_function_methods
80662eda 1137{
bbf8d523 1138 SCM methods;
398d8ee1 1139 SCM_VALIDATE_GENERIC (1, obj);
bbf8d523
MD
1140 methods = fold_upward_gf_methods (SCM_EOL, obj);
1141 methods = fold_downward_gf_methods (methods, obj);
1142 return scm_append (methods);
80662eda 1143}
398d8ee1 1144#undef FUNC_NAME
80662eda 1145
398d8ee1
KN
1146SCM_DEFINE (scm_method_generic_function, "method-generic-function", 1, 0, 0,
1147 (SCM obj),
bb2c02f2 1148 "Return the generic function for the method @var{obj}.")
398d8ee1 1149#define FUNC_NAME s_scm_method_generic_function
80662eda 1150{
398d8ee1 1151 SCM_VALIDATE_METHOD (1, obj);
4a655e50 1152 return scm_slot_ref (obj, scm_from_latin1_symbol ("generic-function"));
80662eda 1153}
398d8ee1 1154#undef FUNC_NAME
80662eda 1155
398d8ee1
KN
1156SCM_DEFINE (scm_method_specializers, "method-specializers", 1, 0, 0,
1157 (SCM obj),
6bcefd15 1158 "Return specializers of the method @var{obj}.")
398d8ee1 1159#define FUNC_NAME s_scm_method_specializers
80662eda 1160{
398d8ee1 1161 SCM_VALIDATE_METHOD (1, obj);
4a655e50 1162 return scm_slot_ref (obj, scm_from_latin1_symbol ("specializers"));
80662eda 1163}
398d8ee1 1164#undef FUNC_NAME
80662eda 1165
398d8ee1
KN
1166SCM_DEFINE (scm_method_procedure, "method-procedure", 1, 0, 0,
1167 (SCM obj),
6bcefd15 1168 "Return the procedure of the method @var{obj}.")
398d8ee1 1169#define FUNC_NAME s_scm_method_procedure
80662eda 1170{
398d8ee1 1171 SCM_VALIDATE_METHOD (1, obj);
6b80d352 1172 return scm_slot_ref (obj, sym_procedure);
80662eda 1173}
398d8ee1 1174#undef FUNC_NAME
80662eda 1175
80662eda
MD
1176/******************************************************************************
1177 *
1178 * S l o t a c c e s s
1179 *
1180 ******************************************************************************/
1181
398d8ee1
KN
1182SCM_DEFINE (scm_make_unbound, "make-unbound", 0, 0, 0,
1183 (),
6bcefd15 1184 "Return the unbound value.")
398d8ee1 1185#define FUNC_NAME s_scm_make_unbound
80662eda
MD
1186{
1187 return SCM_GOOPS_UNBOUND;
1188}
398d8ee1 1189#undef FUNC_NAME
80662eda 1190
398d8ee1
KN
1191SCM_DEFINE (scm_unbound_p, "unbound?", 1, 0, 0,
1192 (SCM obj),
6bcefd15 1193 "Return @code{#t} if @var{obj} is unbound.")
398d8ee1 1194#define FUNC_NAME s_scm_unbound_p
80662eda
MD
1195{
1196 return SCM_GOOPS_UNBOUNDP (obj) ? SCM_BOOL_T : SCM_BOOL_F;
1197}
398d8ee1 1198#undef FUNC_NAME
80662eda 1199
398d8ee1
KN
1200SCM_DEFINE (scm_assert_bound, "assert-bound", 2, 0, 0,
1201 (SCM value, SCM obj),
6bcefd15
MG
1202 "Return @var{value} if it is bound, and invoke the\n"
1203 "@var{slot-unbound} method of @var{obj} if it is not.")
398d8ee1 1204#define FUNC_NAME s_scm_assert_bound
80662eda
MD
1205{
1206 if (SCM_GOOPS_UNBOUNDP (value))
bef95911 1207 return scm_call_1 (SCM_VARIABLE_REF (var_slot_unbound), obj);
80662eda
MD
1208 return value;
1209}
398d8ee1 1210#undef FUNC_NAME
80662eda 1211
398d8ee1
KN
1212SCM_DEFINE (scm_at_assert_bound_ref, "@assert-bound-ref", 2, 0, 0,
1213 (SCM obj, SCM index),
6bcefd15
MG
1214 "Like @code{assert-bound}, but use @var{index} for accessing\n"
1215 "the value from @var{obj}.")
398d8ee1 1216#define FUNC_NAME s_scm_at_assert_bound_ref
80662eda 1217{
e11e83f3 1218 SCM value = SCM_SLOT (obj, scm_to_int (index));
80662eda 1219 if (SCM_GOOPS_UNBOUNDP (value))
bef95911 1220 return scm_call_1 (SCM_VARIABLE_REF (var_slot_unbound), obj);
80662eda
MD
1221 return value;
1222}
398d8ee1 1223#undef FUNC_NAME
80662eda 1224
398d8ee1
KN
1225SCM_DEFINE (scm_sys_fast_slot_ref, "%fast-slot-ref", 2, 0, 0,
1226 (SCM obj, SCM index),
6bcefd15 1227 "Return the slot value with index @var{index} from @var{obj}.")
398d8ee1 1228#define FUNC_NAME s_scm_sys_fast_slot_ref
80662eda 1229{
e25f3727 1230 scm_t_bits i;
80662eda 1231
398d8ee1 1232 SCM_VALIDATE_INSTANCE (1, obj);
a9931e4e
NJ
1233 i = scm_to_unsigned_integer (index, 0,
1234 SCM_I_INUM (SCM_SLOT (SCM_CLASS_OF (obj),
1235 scm_si_nfields))
1236 - 1);
58241edc 1237 return SCM_SLOT (obj, i);
80662eda 1238}
ca83b028
DH
1239#undef FUNC_NAME
1240
398d8ee1
KN
1241SCM_DEFINE (scm_sys_fast_slot_set_x, "%fast-slot-set!", 3, 0, 0,
1242 (SCM obj, SCM index, SCM value),
6bcefd15
MG
1243 "Set the slot with index @var{index} in @var{obj} to\n"
1244 "@var{value}.")
398d8ee1 1245#define FUNC_NAME s_scm_sys_fast_slot_set_x
80662eda 1246{
e25f3727 1247 scm_t_bits i;
80662eda 1248
398d8ee1 1249 SCM_VALIDATE_INSTANCE (1, obj);
a9931e4e
NJ
1250 i = scm_to_unsigned_integer (index, 0,
1251 SCM_I_INUM (SCM_SLOT (SCM_CLASS_OF (obj),
1252 scm_si_nfields))
1253 - 1);
6b80d352 1254
dcb410ec 1255 SCM_SET_SLOT (obj, i, value);
ca83b028 1256
80662eda
MD
1257 return SCM_UNSPECIFIED;
1258}
ca83b028
DH
1259#undef FUNC_NAME
1260
80662eda 1261
4d0949ea 1262\f
80662eda
MD
1263/** Utilities **/
1264
1265/* In the future, this function will return the effective slot
1266 * definition associated with SLOT_NAME. Now it just returns some of
1267 * the information which will be stored in the effective slot
1268 * definition.
1269 */
1270
1271static SCM
1272slot_definition_using_name (SCM class, SCM slot_name)
1273{
1274 register SCM slots = SCM_SLOT (class, scm_si_getters_n_setters);
d2e53ed6 1275 for (; !scm_is_null (slots); slots = SCM_CDR (slots))
d223c3fc 1276 if (scm_is_eq (SCM_CAAR (slots), slot_name))
80662eda
MD
1277 return SCM_CAR (slots);
1278 return SCM_BOOL_F;
1279}
1280
1281static SCM
e81d98ec 1282get_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef)
54ee7cdf 1283#define FUNC_NAME "%get-slot-value"
80662eda
MD
1284{
1285 SCM access = SCM_CDDR (slotdef);
1286 /* Two cases here:
1287 * - access is an integer (the offset of this slot in the slots vector)
1288 * - otherwise (car access) is the getter function to apply
e11e83f3
MV
1289 *
1290 * Instances have never more than SCM_MOST_POSITIVE_FIXNUM slots, so
1291 * we can just assume fixnums here.
23437298 1292 */
e11e83f3 1293 if (SCM_I_INUMP (access))
54ee7cdf
AW
1294 /* Don't poke at the slots directly, because scm_struct_ref handles the
1295 access bits for us. */
1296 return scm_struct_ref (obj, access);
80662eda 1297 else
9d019f9b 1298 return scm_call_1 (SCM_CAR (access), obj);
80662eda 1299}
54ee7cdf 1300#undef FUNC_NAME
80662eda
MD
1301
1302static SCM
1303get_slot_value_using_name (SCM class, SCM obj, SCM slot_name)
1304{
1305 SCM slotdef = slot_definition_using_name (class, slot_name);
7888309b 1306 if (scm_is_true (slotdef))
80662eda
MD
1307 return get_slot_value (class, obj, slotdef);
1308 else
bef95911 1309 return scm_call_3 (SCM_VARIABLE_REF (var_slot_missing), class, obj, slot_name);
80662eda
MD
1310}
1311
1312static SCM
e81d98ec 1313set_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef, SCM value)
54ee7cdf 1314#define FUNC_NAME "%set-slot-value"
80662eda
MD
1315{
1316 SCM access = SCM_CDDR (slotdef);
1317 /* Two cases here:
1318 * - access is an integer (the offset of this slot in the slots vector)
1319 * - otherwise (cadr access) is the setter function to apply
e11e83f3
MV
1320 *
1321 * Instances have never more than SCM_MOST_POSITIVE_FIXNUM slots, so
1322 * we can just assume fixnums here.
80662eda 1323 */
e11e83f3 1324 if (SCM_I_INUMP (access))
54ee7cdf
AW
1325 /* obey permissions bits via going through struct-set! */
1326 scm_struct_set_x (obj, access, value);
80662eda 1327 else
9d019f9b
AW
1328 /* ((cadr l) obj value) */
1329 scm_call_2 (SCM_CADR (access), obj, value);
80662eda
MD
1330 return SCM_UNSPECIFIED;
1331}
54ee7cdf 1332#undef FUNC_NAME
80662eda
MD
1333
1334static SCM
1335set_slot_value_using_name (SCM class, SCM obj, SCM slot_name, SCM value)
1336{
1337 SCM slotdef = slot_definition_using_name (class, slot_name);
7888309b 1338 if (scm_is_true (slotdef))
80662eda
MD
1339 return set_slot_value (class, obj, slotdef, value);
1340 else
bef95911 1341 return scm_call_4 (SCM_VARIABLE_REF (var_slot_missing), class, obj, slot_name, value);
80662eda
MD
1342}
1343
1344static SCM
e81d98ec 1345test_slot_existence (SCM class SCM_UNUSED, SCM obj, SCM slot_name)
80662eda
MD
1346{
1347 register SCM l;
1348
d2e53ed6 1349 for (l = SCM_ACCESSORS_OF (obj); !scm_is_null (l); l = SCM_CDR (l))
bc36d050 1350 if (scm_is_eq (SCM_CAAR (l), slot_name))
80662eda
MD
1351 return SCM_BOOL_T;
1352
1353 return SCM_BOOL_F;
1354}
1355
80662eda
MD
1356 /* ======================================== */
1357
23437298
DH
1358SCM_DEFINE (scm_slot_ref_using_class, "slot-ref-using-class", 3, 0, 0,
1359 (SCM class, SCM obj, SCM slot_name),
1360 "")
1361#define FUNC_NAME s_scm_slot_ref_using_class
80662eda
MD
1362{
1363 SCM res;
1364
398d8ee1
KN
1365 SCM_VALIDATE_CLASS (1, class);
1366 SCM_VALIDATE_INSTANCE (2, obj);
1367 SCM_VALIDATE_SYMBOL (3, slot_name);
80662eda
MD
1368
1369 res = get_slot_value_using_name (class, obj, slot_name);
1370 if (SCM_GOOPS_UNBOUNDP (res))
bef95911 1371 return scm_call_3 (SCM_VARIABLE_REF (var_slot_unbound), class, obj, slot_name);
80662eda
MD
1372 return res;
1373}
23437298 1374#undef FUNC_NAME
80662eda 1375
23437298
DH
1376
1377SCM_DEFINE (scm_slot_set_using_class_x, "slot-set-using-class!", 4, 0, 0,
1378 (SCM class, SCM obj, SCM slot_name, SCM value),
1379 "")
1380#define FUNC_NAME s_scm_slot_set_using_class_x
80662eda 1381{
398d8ee1
KN
1382 SCM_VALIDATE_CLASS (1, class);
1383 SCM_VALIDATE_INSTANCE (2, obj);
1384 SCM_VALIDATE_SYMBOL (3, slot_name);
23437298 1385
80662eda
MD
1386 return set_slot_value_using_name (class, obj, slot_name, value);
1387}
23437298
DH
1388#undef FUNC_NAME
1389
80662eda 1390
398d8ee1
KN
1391SCM_DEFINE (scm_slot_bound_using_class_p, "slot-bound-using-class?", 3, 0, 0,
1392 (SCM class, SCM obj, SCM slot_name),
1393 "")
1394#define FUNC_NAME s_scm_slot_bound_using_class_p
80662eda 1395{
398d8ee1
KN
1396 SCM_VALIDATE_CLASS (1, class);
1397 SCM_VALIDATE_INSTANCE (2, obj);
1398 SCM_VALIDATE_SYMBOL (3, slot_name);
80662eda
MD
1399
1400 return (SCM_GOOPS_UNBOUNDP (get_slot_value_using_name (class, obj, slot_name))
1401 ? SCM_BOOL_F
1402 : SCM_BOOL_T);
1403}
398d8ee1 1404#undef FUNC_NAME
80662eda 1405
398d8ee1
KN
1406SCM_DEFINE (scm_slot_exists_using_class_p, "slot-exists-using-class?", 3, 0, 0,
1407 (SCM class, SCM obj, SCM slot_name),
1408 "")
1409#define FUNC_NAME s_scm_slot_exists_using_class_p
1410{
1411 SCM_VALIDATE_CLASS (1, class);
1412 SCM_VALIDATE_INSTANCE (2, obj);
1413 SCM_VALIDATE_SYMBOL (3, slot_name);
80662eda
MD
1414 return test_slot_existence (class, obj, slot_name);
1415}
398d8ee1 1416#undef FUNC_NAME
80662eda
MD
1417
1418
1419 /* ======================================== */
1420
398d8ee1
KN
1421SCM_DEFINE (scm_slot_ref, "slot-ref", 2, 0, 0,
1422 (SCM obj, SCM slot_name),
6bcefd15
MG
1423 "Return the value from @var{obj}'s slot with the name\n"
1424 "@var{slot_name}.")
398d8ee1 1425#define FUNC_NAME s_scm_slot_ref
80662eda
MD
1426{
1427 SCM res, class;
1428
398d8ee1 1429 SCM_VALIDATE_INSTANCE (1, obj);
80662eda
MD
1430 TEST_CHANGE_CLASS (obj, class);
1431
1432 res = get_slot_value_using_name (class, obj, slot_name);
1433 if (SCM_GOOPS_UNBOUNDP (res))
bef95911 1434 return scm_call_3 (SCM_VARIABLE_REF (var_slot_unbound), class, obj, slot_name);
80662eda
MD
1435 return res;
1436}
398d8ee1 1437#undef FUNC_NAME
80662eda 1438
398d8ee1
KN
1439SCM_DEFINE (scm_slot_set_x, "slot-set!", 3, 0, 0,
1440 (SCM obj, SCM slot_name, SCM value),
6bcefd15 1441 "Set the slot named @var{slot_name} of @var{obj} to @var{value}.")
398d8ee1 1442#define FUNC_NAME s_scm_slot_set_x
80662eda
MD
1443{
1444 SCM class;
1445
398d8ee1 1446 SCM_VALIDATE_INSTANCE (1, obj);
80662eda
MD
1447 TEST_CHANGE_CLASS(obj, class);
1448
1449 return set_slot_value_using_name (class, obj, slot_name, value);
1450}
398d8ee1 1451#undef FUNC_NAME
80662eda 1452
398d8ee1 1453const char *scm_s_slot_set_x = s_scm_slot_set_x;
80662eda 1454
398d8ee1
KN
1455SCM_DEFINE (scm_slot_bound_p, "slot-bound?", 2, 0, 0,
1456 (SCM obj, SCM slot_name),
6bcefd15
MG
1457 "Return @code{#t} if the slot named @var{slot_name} of @var{obj}\n"
1458 "is bound.")
398d8ee1 1459#define FUNC_NAME s_scm_slot_bound_p
80662eda
MD
1460{
1461 SCM class;
1462
398d8ee1 1463 SCM_VALIDATE_INSTANCE (1, obj);
80662eda
MD
1464 TEST_CHANGE_CLASS(obj, class);
1465
1466 return (SCM_GOOPS_UNBOUNDP (get_slot_value_using_name (class,
1467 obj,
1468 slot_name))
1469 ? SCM_BOOL_F
1470 : SCM_BOOL_T);
1471}
398d8ee1 1472#undef FUNC_NAME
80662eda 1473
6d77c894 1474SCM_DEFINE (scm_slot_exists_p, "slot-exists?", 2, 0, 0,
398d8ee1 1475 (SCM obj, SCM slot_name),
6bcefd15 1476 "Return @code{#t} if @var{obj} has a slot named @var{slot_name}.")
6d77c894 1477#define FUNC_NAME s_scm_slot_exists_p
80662eda
MD
1478{
1479 SCM class;
1480
398d8ee1
KN
1481 SCM_VALIDATE_INSTANCE (1, obj);
1482 SCM_VALIDATE_SYMBOL (2, slot_name);
80662eda
MD
1483 TEST_CHANGE_CLASS (obj, class);
1484
1485 return test_slot_existence (class, obj, slot_name);
1486}
398d8ee1 1487#undef FUNC_NAME
80662eda
MD
1488
1489
1490/******************************************************************************
1491 *
1492 * %allocate-instance (the low level instance allocation primitive)
1493 *
1494 ******************************************************************************/
1495
1496static void clear_method_cache (SCM);
1497
398d8ee1
KN
1498SCM_DEFINE (scm_sys_allocate_instance, "%allocate-instance", 2, 0, 0,
1499 (SCM class, SCM initargs),
6bcefd15
MG
1500 "Create a new instance of class @var{class} and initialize it\n"
1501 "from the arguments @var{initargs}.")
398d8ee1 1502#define FUNC_NAME s_scm_sys_allocate_instance
80662eda 1503{
b6cf4d02 1504 SCM obj;
e25f3727 1505 scm_t_signed_bits n, i;
b6cf4d02 1506 SCM layout;
80662eda 1507
398d8ee1 1508 SCM_VALIDATE_CLASS (1, class);
80662eda 1509
b6cf4d02 1510 /* FIXME: duplicates some of scm_make_struct. */
80662eda 1511
e11e83f3 1512 n = SCM_I_INUM (SCM_SLOT (class, scm_si_nfields));
96a44c1c 1513 obj = scm_i_alloc_struct (SCM_STRUCT_DATA (class), n);
6d77c894 1514
b6cf4d02
AW
1515 layout = SCM_VTABLE_LAYOUT (class);
1516
1517 /* Set all SCM-holding slots to unbound */
1518 for (i = 0; i < n; i++)
71fc6438
AW
1519 {
1520 scm_t_wchar c = scm_i_symbol_ref (layout, i*2);
b6cf4d02
AW
1521 if (c == 'p')
1522 SCM_STRUCT_DATA (obj)[i] = SCM_UNPACK (SCM_GOOPS_UNBOUND);
1523 else if (c == 's')
1524 SCM_STRUCT_DATA (obj)[i] = SCM_UNPACK (obj);
1525 else
1526 SCM_STRUCT_DATA (obj)[i] = 0;
80662eda 1527 }
6d77c894 1528
b6cf4d02
AW
1529 if (SCM_CLASS_FLAGS (class) & SCM_CLASSF_PURE_GENERIC)
1530 clear_method_cache (obj);
80662eda 1531
b6cf4d02 1532 return obj;
80662eda 1533}
398d8ee1 1534#undef FUNC_NAME
80662eda 1535
398d8ee1
KN
1536SCM_DEFINE (scm_sys_set_object_setter_x, "%set-object-setter!", 2, 0, 0,
1537 (SCM obj, SCM setter),
1538 "")
1539#define FUNC_NAME s_scm_sys_set_object_setter_x
80662eda 1540{
11561496
AW
1541 SCM_ASSERT (SCM_STRUCTP (obj)
1542 && (SCM_OBJ_CLASS_FLAGS (obj) & SCM_CLASSF_PURE_GENERIC),
80662eda
MD
1543 obj,
1544 SCM_ARG1,
398d8ee1 1545 FUNC_NAME);
11561496 1546 SCM_SET_GENERIC_SETTER (obj, setter);
80662eda
MD
1547 return SCM_UNSPECIFIED;
1548}
398d8ee1 1549#undef FUNC_NAME
80662eda
MD
1550
1551/******************************************************************************
1552 *
1553 * %modify-instance (used by change-class to modify in place)
6d77c894 1554 *
80662eda
MD
1555 ******************************************************************************/
1556
398d8ee1
KN
1557SCM_DEFINE (scm_sys_modify_instance, "%modify-instance", 2, 0, 0,
1558 (SCM old, SCM new),
1559 "")
1560#define FUNC_NAME s_scm_sys_modify_instance
80662eda 1561{
398d8ee1
KN
1562 SCM_VALIDATE_INSTANCE (1, old);
1563 SCM_VALIDATE_INSTANCE (2, new);
80662eda 1564
6d77c894 1565 /* Exchange the data contained in old and new. We exchange rather than
80662eda
MD
1566 * scratch the old value with new to be correct with GC.
1567 * See "Class redefinition protocol above".
1568 */
9de87eea 1569 SCM_CRITICAL_SECTION_START;
80662eda 1570 {
32b12f40
KR
1571 scm_t_bits word0, word1;
1572 word0 = SCM_CELL_WORD_0 (old);
1573 word1 = SCM_CELL_WORD_1 (old);
1574 SCM_SET_CELL_WORD_0 (old, SCM_CELL_WORD_0 (new));
1575 SCM_SET_CELL_WORD_1 (old, SCM_CELL_WORD_1 (new));
1576 SCM_SET_CELL_WORD_0 (new, word0);
1577 SCM_SET_CELL_WORD_1 (new, word1);
80662eda 1578 }
9de87eea 1579 SCM_CRITICAL_SECTION_END;
80662eda
MD
1580 return SCM_UNSPECIFIED;
1581}
398d8ee1 1582#undef FUNC_NAME
80662eda 1583
398d8ee1
KN
1584SCM_DEFINE (scm_sys_modify_class, "%modify-class", 2, 0, 0,
1585 (SCM old, SCM new),
1586 "")
1587#define FUNC_NAME s_scm_sys_modify_class
80662eda 1588{
398d8ee1
KN
1589 SCM_VALIDATE_CLASS (1, old);
1590 SCM_VALIDATE_CLASS (2, new);
80662eda 1591
9de87eea 1592 SCM_CRITICAL_SECTION_START;
80662eda 1593 {
32b12f40
KR
1594 scm_t_bits word0, word1;
1595 word0 = SCM_CELL_WORD_0 (old);
1596 word1 = SCM_CELL_WORD_1 (old);
1597 SCM_SET_CELL_WORD_0 (old, SCM_CELL_WORD_0 (new));
1598 SCM_SET_CELL_WORD_1 (old, SCM_CELL_WORD_1 (new));
b6cf4d02 1599 SCM_STRUCT_DATA (old)[scm_vtable_index_self] = SCM_UNPACK (old);
32b12f40
KR
1600 SCM_SET_CELL_WORD_0 (new, word0);
1601 SCM_SET_CELL_WORD_1 (new, word1);
b6cf4d02 1602 SCM_STRUCT_DATA (new)[scm_vtable_index_self] = SCM_UNPACK (new);
80662eda 1603 }
9de87eea 1604 SCM_CRITICAL_SECTION_END;
80662eda
MD
1605 return SCM_UNSPECIFIED;
1606}
398d8ee1 1607#undef FUNC_NAME
80662eda 1608
398d8ee1
KN
1609SCM_DEFINE (scm_sys_invalidate_class, "%invalidate-class", 1, 0, 0,
1610 (SCM class),
1611 "")
1612#define FUNC_NAME s_scm_sys_invalidate_class
80662eda 1613{
398d8ee1 1614 SCM_VALIDATE_CLASS (1, class);
80662eda
MD
1615 SCM_CLEAR_CLASS_FLAGS (class, SCM_CLASSF_GOOPS_VALID);
1616 return SCM_UNSPECIFIED;
1617}
398d8ee1 1618#undef FUNC_NAME
80662eda
MD
1619
1620/* When instances change class, they finally get a new body, but
1621 * before that, they go through purgatory in hell. Odd as it may
1622 * seem, this data structure saves us from eternal suffering in
1623 * infinite recursions.
1624 */
1625
92c2555f 1626static scm_t_bits **hell;
c014a02e
ML
1627static long n_hell = 1; /* one place for the evil one himself */
1628static long hell_size = 4;
2132f0d2 1629static SCM hell_mutex;
80662eda 1630
c014a02e 1631static long
80662eda
MD
1632burnin (SCM o)
1633{
c014a02e 1634 long i;
80662eda 1635 for (i = 1; i < n_hell; ++i)
6b80d352 1636 if (SCM_STRUCT_DATA (o) == hell[i])
80662eda
MD
1637 return i;
1638 return 0;
1639}
1640
1641static void
1642go_to_hell (void *o)
1643{
b5df9cda 1644 SCM obj = *(SCM*)o;
2132f0d2 1645 scm_lock_mutex (hell_mutex);
51ef99f7 1646 if (n_hell >= hell_size)
80662eda 1647 {
51ef99f7 1648 hell_size *= 2;
408bcd99 1649 hell = scm_realloc (hell, hell_size * sizeof(*hell));
80662eda 1650 }
6b80d352 1651 hell[n_hell++] = SCM_STRUCT_DATA (obj);
2132f0d2 1652 scm_unlock_mutex (hell_mutex);
80662eda
MD
1653}
1654
1655static void
1656go_to_heaven (void *o)
1657{
b5df9cda 1658 SCM obj = *(SCM*)o;
2132f0d2 1659 scm_lock_mutex (hell_mutex);
b5df9cda 1660 hell[burnin (obj)] = hell[--n_hell];
2132f0d2 1661 scm_unlock_mutex (hell_mutex);
80662eda
MD
1662}
1663
6b80d352
DH
1664
1665SCM_SYMBOL (scm_sym_change_class, "change-class");
1666
80662eda 1667static SCM
b5df9cda 1668purgatory (SCM obj, SCM new_class)
80662eda 1669{
b5df9cda 1670 return scm_call_2 (SCM_VARIABLE_REF (var_change_class), obj, new_class);
80662eda
MD
1671}
1672
38d8927c
MD
1673/* This function calls the generic function change-class for all
1674 * instances which aren't currently undergoing class change.
1675 */
1676
80662eda 1677void
e81d98ec 1678scm_change_object_class (SCM obj, SCM old_class SCM_UNUSED, SCM new_class)
80662eda
MD
1679{
1680 if (!burnin (obj))
b5df9cda
AW
1681 {
1682 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
1683 scm_dynwind_rewind_handler (go_to_hell, &obj, SCM_F_WIND_EXPLICITLY);
1684 scm_dynwind_unwind_handler (go_to_heaven, &obj, SCM_F_WIND_EXPLICITLY);
1685 purgatory (obj, new_class);
1686 scm_dynwind_end ();
1687 }
80662eda
MD
1688}
1689
1690/******************************************************************************
1691 *
6d77c894
TTN
1692 * GGGG FFFFF
1693 * G F
1694 * G GG FFF
1695 * G G F
80662eda
MD
1696 * GGG E N E R I C F U N C T I O N S
1697 *
1698 * This implementation provides
1699 * - generic functions (with class specializers)
1700 * - multi-methods
6d77c894 1701 * - next-method
80662eda
MD
1702 * - a hard-coded MOP for standard gf, which can be overloaded for non-std gf
1703 *
1704 ******************************************************************************/
1705
1706SCM_KEYWORD (k_name, "name");
1707
63c1872f 1708SCM_GLOBAL_SYMBOL (scm_sym_args, "args");
80662eda 1709
e29db33c 1710SCM_SYMBOL (sym_delayed_compile, "delayed-compile");
efcebb5b 1711
60617d81
MW
1712static SCM delayed_compile_var;
1713
1714static void
1715init_delayed_compile_var (void)
1716{
1717 delayed_compile_var
1718 = scm_c_private_lookup ("oop goops dispatch", "delayed-compile");
1719}
1720
e29db33c
AW
1721static SCM
1722make_dispatch_procedure (SCM gf)
1723{
60617d81
MW
1724 static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
1725 scm_i_pthread_once (&once, init_delayed_compile_var);
1726
1727 return scm_call_1 (scm_variable_ref (delayed_compile_var), gf);
e29db33c
AW
1728}
1729
80662eda
MD
1730static void
1731clear_method_cache (SCM gf)
1732{
e29db33c 1733 SCM_SET_GENERIC_DISPATCH_PROCEDURE (gf, make_dispatch_procedure (gf));
a9a90a88 1734 SCM_CLEAR_GENERIC_EFFECTIVE_METHODS (gf);
80662eda
MD
1735}
1736
398d8ee1
KN
1737SCM_DEFINE (scm_sys_invalidate_method_cache_x, "%invalidate-method-cache!", 1, 0, 0,
1738 (SCM gf),
1739 "")
1740#define FUNC_NAME s_scm_sys_invalidate_method_cache_x
80662eda 1741{
25ba37df 1742 SCM_ASSERT (SCM_PUREGENERICP (gf), gf, SCM_ARG1, FUNC_NAME);
6d33e90f 1743 clear_method_cache (gf);
80662eda
MD
1744 return SCM_UNSPECIFIED;
1745}
398d8ee1 1746#undef FUNC_NAME
80662eda 1747
398d8ee1
KN
1748SCM_DEFINE (scm_generic_capability_p, "generic-capability?", 1, 0, 0,
1749 (SCM proc),
1750 "")
1751#define FUNC_NAME s_scm_generic_capability_p
80662eda 1752{
7888309b 1753 SCM_ASSERT (scm_is_true (scm_procedure_p (proc)),
398d8ee1 1754 proc, SCM_ARG1, FUNC_NAME);
9fdf9fd3 1755 return (SCM_PRIMITIVE_GENERIC_P (proc) ? SCM_BOOL_T : SCM_BOOL_F);
80662eda 1756}
398d8ee1 1757#undef FUNC_NAME
80662eda 1758
398d8ee1
KN
1759SCM_DEFINE (scm_enable_primitive_generic_x, "enable-primitive-generic!", 0, 0, 1,
1760 (SCM subrs),
1761 "")
1762#define FUNC_NAME s_scm_enable_primitive_generic_x
80662eda 1763{
6b80d352 1764 SCM_VALIDATE_REST_ARGUMENT (subrs);
d2e53ed6 1765 while (!scm_is_null (subrs))
80662eda
MD
1766 {
1767 SCM subr = SCM_CAR (subrs);
9fdf9fd3 1768 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARGn, FUNC_NAME);
52fd9639
AW
1769 SCM_SET_SUBR_GENERIC (subr,
1770 scm_make (scm_list_3 (scm_class_generic,
1771 k_name,
1772 SCM_SUBR_NAME (subr))));
80662eda
MD
1773 subrs = SCM_CDR (subrs);
1774 }
1775 return SCM_UNSPECIFIED;
1776}
398d8ee1 1777#undef FUNC_NAME
80662eda 1778
9f63ce02
AW
1779SCM_DEFINE (scm_set_primitive_generic_x, "set-primitive-generic!", 2, 0, 0,
1780 (SCM subr, SCM generic),
1781 "")
1782#define FUNC_NAME s_scm_set_primitive_generic_x
1783{
9fdf9fd3 1784 SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARG1, FUNC_NAME);
9f63ce02 1785 SCM_ASSERT (SCM_PUREGENERICP (generic), generic, SCM_ARG2, FUNC_NAME);
52fd9639 1786 SCM_SET_SUBR_GENERIC (subr, generic);
9f63ce02
AW
1787 return SCM_UNSPECIFIED;
1788}
1789#undef FUNC_NAME
1790
398d8ee1
KN
1791SCM_DEFINE (scm_primitive_generic_generic, "primitive-generic-generic", 1, 0, 0,
1792 (SCM subr),
1793 "")
1794#define FUNC_NAME s_scm_primitive_generic_generic
80662eda 1795{
9fdf9fd3 1796 if (SCM_PRIMITIVE_GENERIC_P (subr))
80662eda 1797 {
b2b33168 1798 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (subr)))
a48d60b1
MD
1799 scm_enable_primitive_generic_x (scm_list_1 (subr));
1800 return *SCM_SUBR_GENERIC (subr);
80662eda 1801 }
db4b4ca6 1802 SCM_WRONG_TYPE_ARG (SCM_ARG1, subr);
80662eda 1803}
398d8ee1 1804#undef FUNC_NAME
80662eda 1805
a48d60b1
MD
1806typedef struct t_extension {
1807 struct t_extension *next;
1808 SCM extended;
1809 SCM extension;
1810} t_extension;
1811
d0cad249
LC
1812
1813/* Hint for `scm_gc_malloc ()' et al. when allocating `t_extension'
1814 objects. */
1815static const char extension_gc_hint[] = "GOOPS extension";
1816
a48d60b1
MD
1817static t_extension *extensions = 0;
1818
a48d60b1
MD
1819void
1820scm_c_extend_primitive_generic (SCM extended, SCM extension)
1821{
1822 if (goops_loaded_p)
1823 {
1824 SCM gf, gext;
b2b33168 1825 if (!SCM_UNPACK (*SCM_SUBR_GENERIC (extended)))
a48d60b1
MD
1826 scm_enable_primitive_generic_x (scm_list_1 (extended));
1827 gf = *SCM_SUBR_GENERIC (extended);
1828 gext = scm_call_2 (SCM_VARIABLE_REF (scm_var_make_extended_generic),
1829 gf,
ce471ab8 1830 SCM_SUBR_NAME (extension));
feccd2d3 1831 SCM_SET_SUBR_GENERIC (extension, gext);
a48d60b1
MD
1832 }
1833 else
1834 {
d0cad249
LC
1835 t_extension *e = scm_gc_malloc (sizeof (t_extension),
1836 extension_gc_hint);
a48d60b1
MD
1837 t_extension **loc = &extensions;
1838 /* Make sure that extensions are placed before their own
1839 * extensions in the extensions list. O(N^2) algorithm, but
1840 * extensions of primitive generics are rare.
1841 */
d223c3fc 1842 while (*loc && !scm_is_eq (extension, (*loc)->extended))
a48d60b1
MD
1843 loc = &(*loc)->next;
1844 e->next = *loc;
1845 e->extended = extended;
1846 e->extension = extension;
1847 *loc = e;
1848 }
1849}
1850
1851static void
1852setup_extended_primitive_generics ()
1853{
1854 while (extensions)
1855 {
1856 t_extension *e = extensions;
1857 scm_c_extend_primitive_generic (e->extended, e->extension);
1858 extensions = e->next;
a48d60b1
MD
1859 }
1860}
1861
fa075d40
AW
1862/* Dirk:FIXME:: In all of these scm_wta_dispatch_* routines it is
1863 * assumed that 'gf' is zero if uninitialized. It would be cleaner if
1864 * some valid SCM value like SCM_BOOL_F or SCM_UNDEFINED were chosen.
1865 */
1866
1867SCM
1868scm_wta_dispatch_0 (SCM gf, const char *subr)
1869{
1870 if (!SCM_UNPACK (gf))
1871 scm_error_num_args_subr (subr);
1872
1873 return scm_call_0 (gf);
1874}
1875
1876SCM
1877scm_wta_dispatch_1 (SCM gf, SCM a1, int pos, const char *subr)
1878{
1879 if (!SCM_UNPACK (gf))
1880 scm_wrong_type_arg (subr, pos, a1);
1881
1882 return scm_call_1 (gf, a1);
1883}
1884
1885SCM
1886scm_wta_dispatch_2 (SCM gf, SCM a1, SCM a2, int pos, const char *subr)
1887{
1888 if (!SCM_UNPACK (gf))
1889 scm_wrong_type_arg (subr, pos, (pos == SCM_ARG1) ? a1 : a2);
1890
1891 return scm_call_2 (gf, a1, a2);
1892}
1893
1894SCM
1895scm_wta_dispatch_n (SCM gf, SCM args, int pos, const char *subr)
1896{
1897 if (!SCM_UNPACK (gf))
1898 scm_wrong_type_arg (subr, pos, scm_list_ref (args, scm_from_int (pos)));
1899
1900 return scm_apply_0 (gf, args);
1901}
1902
80662eda 1903/******************************************************************************
6d77c894 1904 *
80662eda 1905 * Protocol for calling a generic fumction
6d77c894 1906 * This protocol is roughly equivalent to (parameter are a little bit different
80662eda
MD
1907 * for efficiency reasons):
1908 *
1909 * + apply-generic (gf args)
1910 * + compute-applicable-methods (gf args ...)
1911 * + sort-applicable-methods (methods args)
1912 * + apply-methods (gf methods args)
6d77c894
TTN
1913 *
1914 * apply-methods calls make-next-method to build the "continuation" of a a
80662eda
MD
1915 * method. Applying a next-method will call apply-next-method which in
1916 * turn will call apply again to call effectively the following method.
1917 *
1918 ******************************************************************************/
1919
1920static int
1921applicablep (SCM actual, SCM formal)
1922{
79a3dafe 1923 /* We already know that the cpl is well formed. */
7888309b 1924 return scm_is_true (scm_c_memq (formal, SCM_SLOT (actual, scm_si_cpl)));
80662eda
MD
1925}
1926
1927static int
34d19ef6 1928more_specificp (SCM m1, SCM m2, SCM const *targs)
80662eda
MD
1929{
1930 register SCM s1, s2;
c014a02e 1931 register long i;
6d77c894
TTN
1932 /*
1933 * Note:
1934 * m1 and m2 can have != length (i.e. one can be one element longer than the
80662eda
MD
1935 * other when we have a dotted parameter list). For instance, with the call
1936 * (M 1)
1937 * with
1938 * (define-method M (a . l) ....)
6d77c894 1939 * (define-method M (a) ....)
80662eda
MD
1940 *
1941 * we consider that the second method is more specific.
1942 *
1943 * BTW, targs is an array of types. We don't need it's size since
1944 * we already know that m1 and m2 are applicable (no risk to go past
1945 * the end of this array).
1946 *
1947 */
34d19ef6 1948 for (i=0, s1=SPEC_OF(m1), s2=SPEC_OF(m2); ; i++, s1=SCM_CDR(s1), s2=SCM_CDR(s2)) {
d2e53ed6
MV
1949 if (scm_is_null(s1)) return 1;
1950 if (scm_is_null(s2)) return 0;
d223c3fc 1951 if (!scm_is_eq (SCM_CAR(s1), SCM_CAR(s2))) {
80662eda 1952 register SCM l, cs1 = SCM_CAR(s1), cs2 = SCM_CAR(s2);
6d77c894 1953
dcb410ec 1954 for (l = SCM_SLOT (targs[i], scm_si_cpl); ; l = SCM_CDR(l)) {
d223c3fc 1955 if (scm_is_eq (cs1, SCM_CAR (l)))
80662eda 1956 return 1;
d223c3fc 1957 if (scm_is_eq (cs2, SCM_CAR (l)))
80662eda
MD
1958 return 0;
1959 }
1960 return 0;/* should not occur! */
1961 }
1962 }
1963 return 0; /* should not occur! */
1964}
1965
1966#define BUFFSIZE 32 /* big enough for most uses */
1967
1968static SCM
c014a02e 1969scm_i_vector2list (SCM l, long len)
80662eda 1970{
c014a02e 1971 long j;
00ffa0e7 1972 SCM z = scm_c_make_vector (len, SCM_UNDEFINED);
6d77c894 1973
80662eda 1974 for (j = 0; j < len; j++, l = SCM_CDR (l)) {
4057a3e0 1975 SCM_SIMPLE_VECTOR_SET (z, j, SCM_CAR (l));
80662eda
MD
1976 }
1977 return z;
1978}
1979
1980static SCM
34d19ef6 1981sort_applicable_methods (SCM method_list, long size, SCM const *targs)
80662eda 1982{
c014a02e 1983 long i, j, incr;
80662eda
MD
1984 SCM *v, vector = SCM_EOL;
1985 SCM buffer[BUFFSIZE];
1986 SCM save = method_list;
4057a3e0 1987 scm_t_array_handle handle;
80662eda
MD
1988
1989 /* For reasonably sized method_lists we can try to avoid all the
1990 * consing and reorder the list in place...
1991 * This idea is due to David McClain <Dave_McClain@msn.com>
1992 */
1993 if (size <= BUFFSIZE)
1994 {
1995 for (i = 0; i < size; i++)
1996 {
1997 buffer[i] = SCM_CAR (method_list);
1998 method_list = SCM_CDR (method_list);
1999 }
2000 v = buffer;
6d77c894 2001 }
80662eda
MD
2002 else
2003 {
2004 /* Too many elements in method_list to keep everything locally */
2005 vector = scm_i_vector2list (save, size);
4057a3e0 2006 v = scm_vector_writable_elements (vector, &handle, NULL, NULL);
80662eda
MD
2007 }
2008
6d77c894 2009 /* Use a simple shell sort since it is generally faster than qsort on
80662eda
MD
2010 * small vectors (which is probably mostly the case when we have to
2011 * sort a list of applicable methods).
2012 */
2013 for (incr = size / 2; incr; incr /= 2)
2014 {
2015 for (i = incr; i < size; i++)
2016 {
2017 for (j = i - incr; j >= 0; j -= incr)
2018 {
2019 if (more_specificp (v[j], v[j+incr], targs))
2020 break;
2021 else
2022 {
2023 SCM tmp = v[j + incr];
2024 v[j + incr] = v[j];
2025 v[j] = tmp;
2026 }
2027 }
2028 }
2029 }
2030
2031 if (size <= BUFFSIZE)
2032 {
2033 /* We did it in locally, so restore the original list (reordered) in-place */
2034 for (i = 0, method_list = save; i < size; i++, v++)
2035 {
2036 SCM_SETCAR (method_list, *v);
2037 method_list = SCM_CDR (method_list);
2038 }
2039 return save;
2040 }
4057a3e0 2041
6d77c894 2042 /* If we are here, that's that we did it the hard way... */
c8857a4d 2043 scm_array_handle_release (&handle);
80662eda
MD
2044 return scm_vector_to_list (vector);
2045}
2046
2047SCM
c014a02e 2048scm_compute_applicable_methods (SCM gf, SCM args, long len, int find_method_p)
80662eda 2049{
c014a02e
ML
2050 register long i;
2051 long count = 0;
80662eda
MD
2052 SCM l, fl, applicable = SCM_EOL;
2053 SCM save = args;
34d19ef6
HWN
2054 SCM buffer[BUFFSIZE];
2055 SCM const *types;
2056 SCM *p;
2057 SCM tmp = SCM_EOL;
4057a3e0 2058 scm_t_array_handle handle;
6d77c894 2059
80662eda 2060 /* Build the list of arguments types */
4057a3e0
MV
2061 if (len >= BUFFSIZE)
2062 {
2063 tmp = scm_c_make_vector (len, SCM_UNDEFINED);
2064 types = p = scm_vector_writable_elements (tmp, &handle, NULL, NULL);
34d19ef6
HWN
2065
2066 /*
2067 note that we don't have to work to reset the generation
2068 count. TMP is a new vector anyway, and it is found
2069 conservatively.
2070 */
4057a3e0 2071 }
80662eda
MD
2072 else
2073 types = p = buffer;
6d77c894 2074
d2e53ed6 2075 for ( ; !scm_is_null (args); args = SCM_CDR (args))
80662eda 2076 *p++ = scm_class_of (SCM_CAR (args));
34d19ef6 2077
80662eda 2078 /* Build a list of all applicable methods */
d2e53ed6 2079 for (l = scm_generic_function_methods (gf); !scm_is_null (l); l = SCM_CDR (l))
80662eda
MD
2080 {
2081 fl = SPEC_OF (SCM_CAR (l));
80662eda
MD
2082 for (i = 0; ; i++, fl = SCM_CDR (fl))
2083 {
c312aca7 2084 if (SCM_INSTANCEP (fl)
80662eda 2085 /* We have a dotted argument list */
d2e53ed6 2086 || (i >= len && scm_is_null (fl)))
80662eda
MD
2087 { /* both list exhausted */
2088 applicable = scm_cons (SCM_CAR (l), applicable);
2089 count += 1;
2090 break;
2091 }
2092 if (i >= len
d2e53ed6 2093 || scm_is_null (fl)
80662eda
MD
2094 || !applicablep (types[i], SCM_CAR (fl)))
2095 break;
2096 }
2097 }
2098
c8857a4d
MV
2099 if (len >= BUFFSIZE)
2100 scm_array_handle_release (&handle);
2101
80662eda
MD
2102 if (count == 0)
2103 {
2104 if (find_method_p)
2105 return SCM_BOOL_F;
bef95911 2106 scm_call_2 (SCM_VARIABLE_REF (var_no_applicable_method), gf, save);
80662eda
MD
2107 /* if we are here, it's because no-applicable-method hasn't signaled an error */
2108 return SCM_BOOL_F;
2109 }
34d19ef6 2110
80662eda
MD
2111 return (count == 1
2112 ? applicable
2113 : sort_applicable_methods (applicable, count, types));
2114}
2115
2116#if 0
2117SCM_PROC (s_sys_compute_applicable_methods, "%compute-applicable-methods", 2, 0, 0, scm_sys_compute_applicable_methods);
2118#endif
2119
2120static const char s_sys_compute_applicable_methods[] = "%compute-applicable-methods";
2121
2122SCM
2123scm_sys_compute_applicable_methods (SCM gf, SCM args)
398d8ee1 2124#define FUNC_NAME s_sys_compute_applicable_methods
80662eda 2125{
c014a02e 2126 long n;
398d8ee1 2127 SCM_VALIDATE_GENERIC (1, gf);
80662eda 2128 n = scm_ilength (args);
398d8ee1 2129 SCM_ASSERT (n >= 0, args, SCM_ARG2, FUNC_NAME);
80662eda
MD
2130 return scm_compute_applicable_methods (gf, args, n, 1);
2131}
398d8ee1 2132#undef FUNC_NAME
80662eda 2133
86d31dfe 2134SCM_SYMBOL (sym_compute_applicable_methods, "compute-applicable-methods");
cc7005bc
AW
2135SCM_VARIABLE_INIT (var_compute_applicable_methods, "compute-applicable-methods",
2136 scm_c_define_gsubr (s_sys_compute_applicable_methods, 2, 0, 0,
2137 scm_sys_compute_applicable_methods));
80662eda 2138
80662eda
MD
2139/******************************************************************************
2140 *
2141 * A simple make (which will be redefined later in Scheme)
2142 * This version handles only creation of gf, methods and classes (no instances)
2143 *
6d77c894 2144 * Since this code will disappear when Goops will be fully booted,
80662eda
MD
2145 * no precaution is taken to be efficient.
2146 *
2147 ******************************************************************************/
2148
2149SCM_KEYWORD (k_setter, "setter");
2150SCM_KEYWORD (k_specializers, "specializers");
2151SCM_KEYWORD (k_procedure, "procedure");
5487977b
AW
2152SCM_KEYWORD (k_formals, "formals");
2153SCM_KEYWORD (k_body, "body");
e177058b 2154SCM_KEYWORD (k_make_procedure, "make-procedure");
80662eda
MD
2155SCM_KEYWORD (k_dsupers, "dsupers");
2156SCM_KEYWORD (k_slots, "slots");
2157SCM_KEYWORD (k_gf, "generic-function");
2158
398d8ee1
KN
2159SCM_DEFINE (scm_make, "make", 0, 0, 1,
2160 (SCM args),
27c37006 2161 "Make a new object. @var{args} must contain the class and\n"
6bcefd15 2162 "all necessary initialization information.")
398d8ee1 2163#define FUNC_NAME s_scm_make
80662eda
MD
2164{
2165 SCM class, z;
c014a02e 2166 long len = scm_ilength (args);
80662eda
MD
2167
2168 if (len <= 0 || (len & 1) == 0)
398d8ee1 2169 SCM_WRONG_NUM_ARGS ();
80662eda
MD
2170
2171 class = SCM_CAR(args);
2172 args = SCM_CDR(args);
2173
d223c3fc
AW
2174 if (scm_is_eq (class, scm_class_generic)
2175 || scm_is_eq (class, scm_class_accessor))
80662eda 2176 {
80662eda 2177 z = scm_make_struct (class, SCM_INUM0,
72d2e7e6 2178 scm_list_4 (SCM_BOOL_F,
51f66c91 2179 SCM_EOL,
1afff620 2180 SCM_INUM0,
bbf8d523 2181 SCM_EOL));
80662eda
MD
2182 scm_set_procedure_property_x (z, scm_sym_name,
2183 scm_get_keyword (k_name,
2184 args,
2185 SCM_BOOL_F));
2186 clear_method_cache (z);
d223c3fc 2187 if (scm_is_eq (class, scm_class_accessor))
80662eda
MD
2188 {
2189 SCM setter = scm_get_keyword (k_setter, args, SCM_BOOL_F);
7888309b 2190 if (scm_is_true (setter))
80662eda
MD
2191 scm_sys_set_object_setter_x (z, setter);
2192 }
2193 }
2194 else
2195 {
2196 z = scm_sys_allocate_instance (class, args);
2197
d223c3fc
AW
2198 if (scm_is_eq (class, scm_class_method)
2199 || scm_is_eq (class, scm_class_accessor_method))
80662eda 2200 {
6d77c894 2201 SCM_SET_SLOT (z, scm_si_generic_function,
80662eda
MD
2202 scm_i_get_keyword (k_gf,
2203 args,
2204 len - 1,
2205 SCM_BOOL_F,
dcb410ec 2206 FUNC_NAME));
6d77c894 2207 SCM_SET_SLOT (z, scm_si_specializers,
80662eda
MD
2208 scm_i_get_keyword (k_specializers,
2209 args,
2210 len - 1,
2211 SCM_EOL,
dcb410ec 2212 FUNC_NAME));
6d77c894 2213 SCM_SET_SLOT (z, scm_si_procedure,
80662eda
MD
2214 scm_i_get_keyword (k_procedure,
2215 args,
2216 len - 1,
e177058b 2217 SCM_BOOL_F,
dcb410ec 2218 FUNC_NAME));
5487977b
AW
2219 SCM_SET_SLOT (z, scm_si_formals,
2220 scm_i_get_keyword (k_formals,
2221 args,
2222 len - 1,
2223 SCM_EOL,
2224 FUNC_NAME));
2225 SCM_SET_SLOT (z, scm_si_body,
2226 scm_i_get_keyword (k_body,
2227 args,
2228 len - 1,
2229 SCM_EOL,
2230 FUNC_NAME));
e177058b
AW
2231 SCM_SET_SLOT (z, scm_si_make_procedure,
2232 scm_i_get_keyword (k_make_procedure,
5487977b
AW
2233 args,
2234 len - 1,
2235 SCM_BOOL_F,
2236 FUNC_NAME));
80662eda
MD
2237 }
2238 else
2239 {
2240 /* In all the others case, make a new class .... No instance here */
b6cf4d02 2241 SCM_SET_SLOT (z, scm_vtable_index_name,
80662eda
MD
2242 scm_i_get_keyword (k_name,
2243 args,
2244 len - 1,
4a655e50 2245 scm_from_latin1_symbol ("???"),
dcb410ec 2246 FUNC_NAME));
6d77c894 2247 SCM_SET_SLOT (z, scm_si_direct_supers,
80662eda
MD
2248 scm_i_get_keyword (k_dsupers,
2249 args,
2250 len - 1,
2251 SCM_EOL,
dcb410ec 2252 FUNC_NAME));
6d77c894 2253 SCM_SET_SLOT (z, scm_si_direct_slots,
80662eda
MD
2254 scm_i_get_keyword (k_slots,
2255 args,
2256 len - 1,
2257 SCM_EOL,
dcb410ec 2258 FUNC_NAME));
80662eda
MD
2259 }
2260 }
2261 return z;
2262}
398d8ee1 2263#undef FUNC_NAME
80662eda 2264
398d8ee1
KN
2265SCM_DEFINE (scm_find_method, "find-method", 0, 0, 1,
2266 (SCM l),
2267 "")
2268#define FUNC_NAME s_scm_find_method
80662eda
MD
2269{
2270 SCM gf;
c014a02e 2271 long len = scm_ilength (l);
80662eda
MD
2272
2273 if (len == 0)
398d8ee1 2274 SCM_WRONG_NUM_ARGS ();
80662eda
MD
2275
2276 gf = SCM_CAR(l); l = SCM_CDR(l);
398d8ee1 2277 SCM_VALIDATE_GENERIC (1, gf);
d2e53ed6 2278 if (scm_is_null (SCM_SLOT (gf, scm_si_methods)))
1afff620 2279 SCM_MISC_ERROR ("no methods for generic ~S", scm_list_1 (gf));
80662eda
MD
2280
2281 return scm_compute_applicable_methods (gf, l, len - 1, 1);
2282}
398d8ee1 2283#undef FUNC_NAME
80662eda 2284
398d8ee1
KN
2285SCM_DEFINE (scm_sys_method_more_specific_p, "%method-more-specific?", 3, 0, 0,
2286 (SCM m1, SCM m2, SCM targs),
b1f57ea4
LC
2287 "Return true if method @var{m1} is more specific than @var{m2} "
2288 "given the argument types (classes) listed in @var{targs}.")
398d8ee1 2289#define FUNC_NAME s_scm_sys_method_more_specific_p
80662eda 2290{
4057a3e0
MV
2291 SCM l, v, result;
2292 SCM *v_elts;
b1f57ea4 2293 long i, len, m1_specs, m2_specs;
4057a3e0 2294 scm_t_array_handle handle;
80662eda 2295
398d8ee1
KN
2296 SCM_VALIDATE_METHOD (1, m1);
2297 SCM_VALIDATE_METHOD (2, m2);
80662eda 2298
b1f57ea4
LC
2299 len = scm_ilength (targs);
2300 m1_specs = scm_ilength (SPEC_OF (m1));
2301 m2_specs = scm_ilength (SPEC_OF (m2));
2302 SCM_ASSERT ((len >= m1_specs) || (len >= m2_specs),
2303 targs, SCM_ARG3, FUNC_NAME);
2304
2305 /* Verify that all the arguments of TARGS are classes and place them
2306 in a vector. */
4057a3e0 2307
00ffa0e7 2308 v = scm_c_make_vector (len, SCM_EOL);
4057a3e0 2309 v_elts = scm_vector_writable_elements (v, &handle, NULL, NULL);
80662eda 2310
b1f57ea4
LC
2311 for (i = 0, l = targs;
2312 i < len && scm_is_pair (l);
2313 i++, l = SCM_CDR (l))
4057a3e0
MV
2314 {
2315 SCM_ASSERT (SCM_CLASSP (SCM_CAR (l)), targs, SCM_ARG3, FUNC_NAME);
b1f57ea4 2316 v_elts[i] = SCM_CAR (l);
4057a3e0 2317 }
4057a3e0 2318 result = more_specificp (m1, m2, v_elts) ? SCM_BOOL_T: SCM_BOOL_F;
c8857a4d
MV
2319
2320 scm_array_handle_release (&handle);
2321
4057a3e0 2322 return result;
80662eda 2323}
398d8ee1 2324#undef FUNC_NAME
6d77c894
TTN
2325
2326
80662eda
MD
2327
2328/******************************************************************************
2329 *
6d77c894 2330 * Initializations
80662eda
MD
2331 *
2332 ******************************************************************************/
2333
ae88d9bc
AW
2334/* Munge the CPL of C in place such that BEFORE appears before AFTER,
2335 assuming that currently the reverse is true. Recalculate slots and
2336 associated getters-n-setters. */
74b6d6e4
MD
2337static void
2338fix_cpl (SCM c, SCM before, SCM after)
2339{
2340 SCM cpl = SCM_SLOT (c, scm_si_cpl);
2341 SCM ls = scm_c_memq (after, cpl);
ae88d9bc
AW
2342 SCM tail;
2343
7888309b 2344 if (scm_is_false (ls))
74b6d6e4
MD
2345 /* if this condition occurs, fix_cpl should not be applied this way */
2346 abort ();
ae88d9bc
AW
2347
2348 tail = scm_delq1_x (before, SCM_CDR (ls));
74b6d6e4
MD
2349 SCM_SETCAR (ls, before);
2350 SCM_SETCDR (ls, scm_cons (after, tail));
2351 {
2352 SCM dslots = SCM_SLOT (c, scm_si_direct_slots);
2353 SCM slots = build_slots_list (maplist (dslots), cpl);
2354 SCM g_n_s = compute_getters_n_setters (slots);
2355 SCM_SET_SLOT (c, scm_si_slots, slots);
2356 SCM_SET_SLOT (c, scm_si_getters_n_setters, g_n_s);
2357 }
2358}
2359
80662eda
MD
2360
2361static void
2362make_stdcls (SCM *var, char *name, SCM meta, SCM super, SCM slots)
2363{
25d50a05 2364 SCM tmp = scm_from_utf8_symbol (name);
6d77c894 2365
f39448c5
AW
2366 *var = scm_basic_make_class (meta, tmp,
2367 scm_is_pair (super) ? super : scm_list_1 (super),
2368 slots);
28d0871b 2369 scm_module_define (scm_module_goops, tmp, *var);
80662eda
MD
2370}
2371
2372
2373SCM_KEYWORD (k_slot_definition, "slot-definition");
2374
2375static void
2376create_standard_classes (void)
2377{
2378 SCM slots;
4a655e50
AW
2379 SCM method_slots = scm_list_n (scm_from_latin1_symbol ("generic-function"),
2380 scm_from_latin1_symbol ("specializers"),
6b80d352 2381 sym_procedure,
4a655e50
AW
2382 scm_from_latin1_symbol ("formals"),
2383 scm_from_latin1_symbol ("body"),
2384 scm_from_latin1_symbol ("make-procedure"),
21497600 2385 SCM_UNDEFINED);
4a655e50 2386 SCM amethod_slots = scm_list_1 (scm_list_3 (scm_from_latin1_symbol ("slot-definition"),
1afff620
KN
2387 k_init_keyword,
2388 k_slot_definition));
4a655e50
AW
2389 SCM gf_slots = scm_list_4 (scm_from_latin1_symbol ("methods"),
2390 scm_list_3 (scm_from_latin1_symbol ("n-specialized"),
1afff620
KN
2391 k_init_value,
2392 SCM_INUM0),
4a655e50 2393 scm_list_3 (scm_from_latin1_symbol ("extended-by"),
bbf8d523 2394 k_init_value,
b6cf4d02 2395 SCM_EOL),
4a655e50 2396 scm_from_latin1_symbol ("effective-methods"));
a9a90a88 2397 SCM setter_slots = scm_list_1 (sym_setter);
4a655e50 2398 SCM egf_slots = scm_list_1 (scm_list_3 (scm_from_latin1_symbol ("extends"),
bbf8d523
MD
2399 k_init_value,
2400 SCM_EOL));
80662eda
MD
2401 /* Foreign class slot classes */
2402 make_stdcls (&scm_class_foreign_slot, "<foreign-slot>",
2403 scm_class_class, scm_class_top, SCM_EOL);
2404 make_stdcls (&scm_class_protected, "<protected-slot>",
2405 scm_class_class, scm_class_foreign_slot, SCM_EOL);
b6cf4d02
AW
2406 make_stdcls (&scm_class_hidden, "<hidden-slot>",
2407 scm_class_class, scm_class_foreign_slot, SCM_EOL);
80662eda
MD
2408 make_stdcls (&scm_class_opaque, "<opaque-slot>",
2409 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2410 make_stdcls (&scm_class_read_only, "<read-only-slot>",
2411 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2412 make_stdcls (&scm_class_self, "<self-slot>",
b6cf4d02 2413 scm_class_class, scm_class_read_only, SCM_EOL);
80662eda
MD
2414 make_stdcls (&scm_class_protected_opaque, "<protected-opaque-slot>",
2415 scm_class_class,
1afff620 2416 scm_list_2 (scm_class_protected, scm_class_opaque),
80662eda 2417 SCM_EOL);
b6cf4d02
AW
2418 make_stdcls (&scm_class_protected_hidden, "<protected-hidden-slot>",
2419 scm_class_class,
2420 scm_list_2 (scm_class_protected, scm_class_hidden),
2421 SCM_EOL);
80662eda
MD
2422 make_stdcls (&scm_class_protected_read_only, "<protected-read-only-slot>",
2423 scm_class_class,
1afff620 2424 scm_list_2 (scm_class_protected, scm_class_read_only),
80662eda
MD
2425 SCM_EOL);
2426 make_stdcls (&scm_class_scm, "<scm-slot>",
2427 scm_class_class, scm_class_protected, SCM_EOL);
2428 make_stdcls (&scm_class_int, "<int-slot>",
2429 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2430 make_stdcls (&scm_class_float, "<float-slot>",
2431 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2432 make_stdcls (&scm_class_double, "<double-slot>",
2433 scm_class_class, scm_class_foreign_slot, SCM_EOL);
2434
2435 /* Continue initialization of class <class> */
6d77c894 2436
80662eda 2437 slots = build_class_class_slots ();
dcb410ec
DH
2438 SCM_SET_SLOT (scm_class_class, scm_si_direct_slots, slots);
2439 SCM_SET_SLOT (scm_class_class, scm_si_slots, slots);
2440 SCM_SET_SLOT (scm_class_class, scm_si_getters_n_setters,
2441 compute_getters_n_setters (slots));
6d77c894 2442
80662eda
MD
2443 /* scm_class_generic functions classes */
2444 make_stdcls (&scm_class_procedure_class, "<procedure-class>",
2445 scm_class_class, scm_class_class, SCM_EOL);
51f66c91 2446 make_stdcls (&scm_class_applicable_struct_class, "<applicable-struct-class>",
80662eda 2447 scm_class_class, scm_class_procedure_class, SCM_EOL);
2f652c68 2448 SCM_SET_VTABLE_FLAGS (scm_class_applicable_struct_class, SCM_VTABLE_FLAG_APPLICABLE_VTABLE);
80662eda
MD
2449 make_stdcls (&scm_class_method, "<method>",
2450 scm_class_class, scm_class_object, method_slots);
f8af5c6d 2451 make_stdcls (&scm_class_accessor_method, "<accessor-method>",
51f66c91 2452 scm_class_class, scm_class_method, amethod_slots);
74b6d6e4
MD
2453 make_stdcls (&scm_class_applicable, "<applicable>",
2454 scm_class_class, scm_class_top, SCM_EOL);
51f66c91
AW
2455 make_stdcls (&scm_class_applicable_struct, "<applicable-struct>",
2456 scm_class_applicable_struct_class,
74b6d6e4 2457 scm_list_2 (scm_class_object, scm_class_applicable),
51f66c91 2458 scm_list_1 (sym_procedure));
80662eda 2459 make_stdcls (&scm_class_generic, "<generic>",
51f66c91 2460 scm_class_applicable_struct_class, scm_class_applicable_struct, gf_slots);
80662eda 2461 SCM_SET_CLASS_FLAGS (scm_class_generic, SCM_CLASSF_PURE_GENERIC);
bbf8d523 2462 make_stdcls (&scm_class_extended_generic, "<extended-generic>",
51f66c91 2463 scm_class_applicable_struct_class, scm_class_generic, egf_slots);
bbf8d523 2464 SCM_SET_CLASS_FLAGS (scm_class_extended_generic, SCM_CLASSF_PURE_GENERIC);
80662eda 2465 make_stdcls (&scm_class_generic_with_setter, "<generic-with-setter>",
51f66c91 2466 scm_class_applicable_struct_class, scm_class_generic, setter_slots);
80662eda 2467 SCM_SET_CLASS_FLAGS (scm_class_generic_with_setter, SCM_CLASSF_PURE_GENERIC);
f8af5c6d 2468 make_stdcls (&scm_class_accessor, "<accessor>",
51f66c91 2469 scm_class_applicable_struct_class, scm_class_generic_with_setter, SCM_EOL);
f8af5c6d 2470 SCM_SET_CLASS_FLAGS (scm_class_accessor, SCM_CLASSF_PURE_GENERIC);
bbf8d523
MD
2471 make_stdcls (&scm_class_extended_generic_with_setter,
2472 "<extended-generic-with-setter>",
51f66c91 2473 scm_class_applicable_struct_class,
ae88d9bc
AW
2474 scm_list_2 (scm_class_extended_generic,
2475 scm_class_generic_with_setter),
bbf8d523
MD
2476 SCM_EOL);
2477 SCM_SET_CLASS_FLAGS (scm_class_extended_generic_with_setter,
2478 SCM_CLASSF_PURE_GENERIC);
74b6d6e4 2479 make_stdcls (&scm_class_extended_accessor, "<extended-accessor>",
51f66c91 2480 scm_class_applicable_struct_class,
74b6d6e4
MD
2481 scm_list_2 (scm_class_accessor,
2482 scm_class_extended_generic_with_setter),
2483 SCM_EOL);
ae88d9bc 2484 /* <extended-generic> is misplaced. */
74b6d6e4 2485 fix_cpl (scm_class_extended_accessor,
ae88d9bc 2486 scm_class_extended_generic, scm_class_generic_with_setter);
74b6d6e4 2487 SCM_SET_CLASS_FLAGS (scm_class_extended_accessor, SCM_CLASSF_PURE_GENERIC);
80662eda
MD
2488
2489 /* Primitive types classes */
2490 make_stdcls (&scm_class_boolean, "<boolean>",
2491 scm_class_class, scm_class_top, SCM_EOL);
2492 make_stdcls (&scm_class_char, "<char>",
2493 scm_class_class, scm_class_top, SCM_EOL);
2494 make_stdcls (&scm_class_list, "<list>",
2495 scm_class_class, scm_class_top, SCM_EOL);
2496 make_stdcls (&scm_class_pair, "<pair>",
2497 scm_class_class, scm_class_list, SCM_EOL);
2498 make_stdcls (&scm_class_null, "<null>",
2499 scm_class_class, scm_class_list, SCM_EOL);
2500 make_stdcls (&scm_class_string, "<string>",
2501 scm_class_class, scm_class_top, SCM_EOL);
2502 make_stdcls (&scm_class_symbol, "<symbol>",
2503 scm_class_class, scm_class_top, SCM_EOL);
2504 make_stdcls (&scm_class_vector, "<vector>",
2505 scm_class_class, scm_class_top, SCM_EOL);
e2c2a699
AW
2506 make_stdcls (&class_foreign, "<foreign>",
2507 scm_class_class, scm_class_top, SCM_EOL);
9ea31741
AW
2508 make_stdcls (&class_hashtable, "<hashtable>",
2509 scm_class_class, scm_class_top, SCM_EOL);
2510 make_stdcls (&class_fluid, "<fluid>",
2511 scm_class_class, scm_class_top, SCM_EOL);
2512 make_stdcls (&class_dynamic_state, "<dynamic-state>",
c99de5aa 2513 scm_class_class, scm_class_top, SCM_EOL);
6f3b0cc2
AW
2514 make_stdcls (&class_frame, "<frame>",
2515 scm_class_class, scm_class_top, SCM_EOL);
6f3b0cc2
AW
2516 make_stdcls (&class_vm_cont, "<vm-continuation>",
2517 scm_class_class, scm_class_top, SCM_EOL);
f826a886
AW
2518 make_stdcls (&class_bytevector, "<bytevector>",
2519 scm_class_class, scm_class_top, SCM_EOL);
2520 make_stdcls (&class_uvec, "<uvec>",
2521 scm_class_class, class_bytevector, SCM_EOL);
b2637c98
AW
2522 make_stdcls (&class_array, "<array>",
2523 scm_class_class, scm_class_top, SCM_EOL);
ff1feca9
AW
2524 make_stdcls (&class_bitvector, "<bitvector>",
2525 scm_class_class, scm_class_top, SCM_EOL);
80662eda
MD
2526 make_stdcls (&scm_class_number, "<number>",
2527 scm_class_class, scm_class_top, SCM_EOL);
2528 make_stdcls (&scm_class_complex, "<complex>",
2529 scm_class_class, scm_class_number, SCM_EOL);
2530 make_stdcls (&scm_class_real, "<real>",
2531 scm_class_class, scm_class_complex, SCM_EOL);
2532 make_stdcls (&scm_class_integer, "<integer>",
2533 scm_class_class, scm_class_real, SCM_EOL);
f92e85f7
MV
2534 make_stdcls (&scm_class_fraction, "<fraction>",
2535 scm_class_class, scm_class_real, SCM_EOL);
80662eda
MD
2536 make_stdcls (&scm_class_keyword, "<keyword>",
2537 scm_class_class, scm_class_top, SCM_EOL);
2538 make_stdcls (&scm_class_unknown, "<unknown>",
2539 scm_class_class, scm_class_top, SCM_EOL);
2540 make_stdcls (&scm_class_procedure, "<procedure>",
74b6d6e4 2541 scm_class_procedure_class, scm_class_applicable, SCM_EOL);
80662eda
MD
2542 make_stdcls (&scm_class_primitive_generic, "<primitive-generic>",
2543 scm_class_procedure_class, scm_class_procedure, SCM_EOL);
2544 make_stdcls (&scm_class_port, "<port>",
2545 scm_class_class, scm_class_top, SCM_EOL);
2546 make_stdcls (&scm_class_input_port, "<input-port>",
2547 scm_class_class, scm_class_port, SCM_EOL);
2548 make_stdcls (&scm_class_output_port, "<output-port>",
2549 scm_class_class, scm_class_port, SCM_EOL);
2550 make_stdcls (&scm_class_input_output_port, "<input-output-port>",
2551 scm_class_class,
1afff620 2552 scm_list_2 (scm_class_input_port, scm_class_output_port),
80662eda
MD
2553 SCM_EOL);
2554}
2555
2556/**********************************************************************
2557 *
2558 * Smob classes
2559 *
2560 **********************************************************************/
2561
2562static SCM
da0e6c2b 2563make_class_from_template (char const *template, char const *type_name, SCM supers, int applicablep)
80662eda 2564{
28d0871b 2565 SCM name;
80662eda
MD
2566 if (type_name)
2567 {
2568 char buffer[100];
2569 sprintf (buffer, template, type_name);
25d50a05 2570 name = scm_from_utf8_symbol (buffer);
80662eda
MD
2571 }
2572 else
2573 name = SCM_GOOPS_UNBOUND;
2574
28d0871b
AW
2575 return scm_basic_make_class (applicablep ? scm_class_procedure_class : scm_class_class,
2576 name, supers, SCM_EOL);
80662eda
MD
2577}
2578
9db8cf16
MG
2579static SCM
2580make_class_from_symbol (SCM type_name_sym, SCM supers, int applicablep)
2581{
28d0871b
AW
2582 SCM name;
2583
393baa8a 2584 if (scm_is_true (type_name_sym))
9db8cf16
MG
2585 {
2586 name = scm_string_append (scm_list_3 (scm_from_locale_string ("<"),
2587 scm_symbol_to_string (type_name_sym),
2588 scm_from_locale_string (">")));
2589 name = scm_string_to_symbol (name);
2590 }
2591 else
2592 name = SCM_GOOPS_UNBOUND;
2593
28d0871b
AW
2594 return scm_basic_make_class (applicablep ? scm_class_procedure_class : scm_class_class,
2595 name, supers, SCM_EOL);
9db8cf16
MG
2596}
2597
80662eda 2598SCM
da0e6c2b 2599scm_make_extended_class (char const *type_name, int applicablep)
80662eda
MD
2600{
2601 return make_class_from_template ("<%s>",
2602 type_name,
74b6d6e4
MD
2603 scm_list_1 (applicablep
2604 ? scm_class_applicable
2605 : scm_class_top),
2606 applicablep);
2607}
2608
9db8cf16
MG
2609static SCM
2610scm_make_extended_class_from_symbol (SCM type_name_sym, int applicablep)
2611{
2612 return make_class_from_symbol (type_name_sym,
2613 scm_list_1 (applicablep
2614 ? scm_class_applicable
2615 : scm_class_top),
2616 applicablep);
2617}
2618
74b6d6e4
MD
2619void
2620scm_i_inherit_applicable (SCM c)
2621{
2622 if (!SCM_SUBCLASSP (c, scm_class_applicable))
2623 {
2624 SCM dsupers = SCM_SLOT (c, scm_si_direct_supers);
2625 SCM cpl = SCM_SLOT (c, scm_si_cpl);
2626 /* patch scm_class_applicable into direct-supers */
2627 SCM top = scm_c_memq (scm_class_top, dsupers);
7888309b 2628 if (scm_is_false (top))
74b6d6e4
MD
2629 dsupers = scm_append (scm_list_2 (dsupers,
2630 scm_list_1 (scm_class_applicable)));
2631 else
2632 {
2633 SCM_SETCAR (top, scm_class_applicable);
2634 SCM_SETCDR (top, scm_cons (scm_class_top, SCM_CDR (top)));
2635 }
2636 SCM_SET_SLOT (c, scm_si_direct_supers, dsupers);
2637 /* patch scm_class_applicable into cpl */
2638 top = scm_c_memq (scm_class_top, cpl);
7888309b 2639 if (scm_is_false (top))
74b6d6e4
MD
2640 abort ();
2641 else
2642 {
2643 SCM_SETCAR (top, scm_class_applicable);
2644 SCM_SETCDR (top, scm_cons (scm_class_top, SCM_CDR (top)));
2645 }
2646 /* add class to direct-subclasses of scm_class_applicable */
2647 SCM_SET_SLOT (scm_class_applicable,
2648 scm_si_direct_subclasses,
2649 scm_cons (c, SCM_SLOT (scm_class_applicable,
2650 scm_si_direct_subclasses)));
2651 }
80662eda
MD
2652}
2653
2654static void
2655create_smob_classes (void)
2656{
c014a02e 2657 long i;
80662eda 2658
c891a40e 2659 for (i = 0; i < SCM_I_MAX_SMOB_TYPE_COUNT; ++i)
393baa8a 2660 scm_smob_class[i] = SCM_BOOL_F;
80662eda 2661
80662eda 2662 scm_smob_class[SCM_TC2SMOBNUM (scm_tc16_keyword)] = scm_class_keyword;
6d77c894 2663
80662eda 2664 for (i = 0; i < scm_numsmob; ++i)
393baa8a 2665 if (scm_is_false (scm_smob_class[i]))
74b6d6e4
MD
2666 scm_smob_class[i] = scm_make_extended_class (SCM_SMOBNAME (i),
2667 scm_smobs[i].apply != 0);
80662eda
MD
2668}
2669
2670void
c014a02e 2671scm_make_port_classes (long ptobnum, char *type_name)
80662eda
MD
2672{
2673 SCM c, class = make_class_from_template ("<%s-port>",
2674 type_name,
74b6d6e4
MD
2675 scm_list_1 (scm_class_port),
2676 0);
80662eda
MD
2677 scm_port_class[SCM_IN_PCLASS_INDEX + ptobnum]
2678 = make_class_from_template ("<%s-input-port>",
2679 type_name,
74b6d6e4
MD
2680 scm_list_2 (class, scm_class_input_port),
2681 0);
80662eda
MD
2682 scm_port_class[SCM_OUT_PCLASS_INDEX + ptobnum]
2683 = make_class_from_template ("<%s-output-port>",
2684 type_name,
74b6d6e4
MD
2685 scm_list_2 (class, scm_class_output_port),
2686 0);
80662eda
MD
2687 scm_port_class[SCM_INOUT_PCLASS_INDEX + ptobnum]
2688 = c
2689 = make_class_from_template ("<%s-input-output-port>",
2690 type_name,
74b6d6e4
MD
2691 scm_list_2 (class, scm_class_input_output_port),
2692 0);
80662eda 2693 /* Patch cpl (since this tree is too complex for the C level compute-cpl) */
dcb410ec
DH
2694 SCM_SET_SLOT (c, scm_si_cpl,
2695 scm_cons2 (c, class, SCM_SLOT (scm_class_input_output_port, scm_si_cpl)));
80662eda
MD
2696}
2697
2698static void
2699create_port_classes (void)
2700{
c014a02e 2701 long i;
80662eda 2702
62bd5d66 2703 for (i = scm_c_num_port_types () - 1; i >= 0; i--)
80662eda
MD
2704 scm_make_port_classes (i, SCM_PTOBNAME (i));
2705}
2706
2707static SCM
74b6d6e4
MD
2708make_struct_class (void *closure SCM_UNUSED,
2709 SCM vtable, SCM data, SCM prev SCM_UNUSED)
80662eda 2710{
f3c6a02c
AW
2711 if (scm_is_false (data))
2712 scm_i_define_class_for_vtable (vtable);
80662eda
MD
2713 return SCM_UNSPECIFIED;
2714}
2715
2716static void
2717create_struct_classes (void)
2718{
ea742d29 2719 /* FIXME: take the vtable_class_map while initializing goops? */
f3c6a02c
AW
2720 scm_internal_hash_fold (make_struct_class, 0, SCM_BOOL_F,
2721 vtable_class_map);
80662eda
MD
2722}
2723
2724/**********************************************************************
2725 *
2726 * C interface
2727 *
2728 **********************************************************************/
2729
2730void
2731scm_load_goops ()
2732{
2733 if (!goops_loaded_p)
abd28220 2734 scm_c_resolve_module ("oop goops");
80662eda
MD
2735}
2736
e11208ca 2737
80662eda
MD
2738SCM_SYMBOL (sym_o, "o");
2739SCM_SYMBOL (sym_x, "x");
2740
2741SCM_KEYWORD (k_accessor, "accessor");
2742SCM_KEYWORD (k_getter, "getter");
2743
80662eda
MD
2744SCM
2745scm_ensure_accessor (SCM name)
2746{
3f48638c
AW
2747 SCM var, gf;
2748
2749 var = scm_module_variable (scm_current_module (), name);
2750 if (SCM_VARIABLEP (var) && !SCM_UNBNDP (SCM_VARIABLE_REF (var)))
2751 gf = SCM_VARIABLE_REF (var);
2752 else
2753 gf = SCM_BOOL_F;
2754
f8af5c6d 2755 if (!SCM_IS_A_P (gf, scm_class_accessor))
80662eda 2756 {
1afff620 2757 gf = scm_make (scm_list_3 (scm_class_generic, k_name, name));
f8af5c6d 2758 gf = scm_make (scm_list_5 (scm_class_accessor,
1afff620 2759 k_name, name, k_setter, gf));
80662eda 2760 }
3f48638c 2761
80662eda
MD
2762 return gf;
2763}
2764
80662eda
MD
2765#ifdef GUILE_DEBUG
2766/*
2767 * Debugging utilities
2768 */
2769
398d8ee1
KN
2770SCM_DEFINE (scm_pure_generic_p, "pure-generic?", 1, 0, 0,
2771 (SCM obj),
6bcefd15 2772 "Return @code{#t} if @var{obj} is a pure generic.")
398d8ee1 2773#define FUNC_NAME s_scm_pure_generic_p
80662eda 2774{
7888309b 2775 return scm_from_bool (SCM_PUREGENERICP (obj));
80662eda 2776}
398d8ee1 2777#undef FUNC_NAME
80662eda
MD
2778
2779#endif /* GUILE_DEBUG */
2780
2781/*
2782 * Initialization
2783 */
2784
398d8ee1
KN
2785SCM_DEFINE (scm_sys_goops_loaded, "%goops-loaded", 0, 0, 0,
2786 (),
6bcefd15
MG
2787 "Announce that GOOPS is loaded and perform initialization\n"
2788 "on the C level which depends on the loaded GOOPS modules.")
398d8ee1 2789#define FUNC_NAME s_scm_sys_goops_loaded
80662eda
MD
2790{
2791 goops_loaded_p = 1;
86d31dfe 2792 var_compute_applicable_methods =
f39448c5 2793 scm_module_variable (scm_module_goops, sym_compute_applicable_methods);
bef95911 2794 var_slot_unbound =
f39448c5 2795 scm_module_variable (scm_module_goops, sym_slot_unbound);
bef95911 2796 var_slot_missing =
f39448c5 2797 scm_module_variable (scm_module_goops, sym_slot_missing);
bef95911 2798 var_compute_cpl =
f39448c5 2799 scm_module_variable (scm_module_goops, sym_compute_cpl);
bef95911 2800 var_no_applicable_method =
f39448c5 2801 scm_module_variable (scm_module_goops, sym_no_applicable_method);
bef95911 2802 var_change_class =
f39448c5 2803 scm_module_variable (scm_module_goops, sym_change_class);
a48d60b1 2804 setup_extended_primitive_generics ();
80662eda
MD
2805 return SCM_UNSPECIFIED;
2806}
398d8ee1 2807#undef FUNC_NAME
80662eda
MD
2808
2809SCM scm_module_goops;
2810
abd28220
MV
2811SCM
2812scm_init_goops_builtins (void)
80662eda 2813{
abd28220 2814 scm_module_goops = scm_current_module ();
80662eda 2815
80662eda
MD
2816 goops_rstate = scm_c_make_rstate ("GOOPS", 5);
2817
2818#include "libguile/goops.x"
2819
bb764c0e 2820 hell = scm_calloc (hell_size * sizeof (*hell));
f39448c5 2821 hell_mutex = scm_make_mutex ();
80662eda
MD
2822
2823 create_basic_classes ();
2824 create_standard_classes ();
2825 create_smob_classes ();
2826 create_struct_classes ();
2827 create_port_classes ();
2828
2829 {
4a655e50 2830 SCM name = scm_from_latin1_symbol ("no-applicable-method");
f39448c5
AW
2831 scm_no_applicable_method =
2832 scm_make (scm_list_3 (scm_class_generic, k_name, name));
28d0871b 2833 scm_module_define (scm_module_goops, name, scm_no_applicable_method);
80662eda 2834 }
abd28220
MV
2835
2836 return SCM_UNSPECIFIED;
80662eda
MD
2837}
2838
2839void
abd28220 2840scm_init_goops ()
80662eda 2841{
9a441ddb
MV
2842 scm_c_define_gsubr ("%init-goops-builtins", 0, 0, 0,
2843 scm_init_goops_builtins);
80662eda 2844}
23437298
DH
2845
2846/*
2847 Local Variables:
2848 c-file-style: "gnu"
2849 End:
2850*/