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