123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020 |
- /* Copyright 1998-2004,2008-2015,2017-2018
- Free Software Foundation, Inc.
- This file is part of Guile.
- Guile is free software: you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Guile is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with Guile. If not, see
- <https://www.gnu.org/licenses/>. */
- /* This software is a derivative work of other copyrighted softwares; the
- * copyright notices of these softwares are placed in the file COPYRIGHTS
- *
- * This file is based upon stklos.c from the STk distribution by
- * Erick Gallesio <eg@unice.fr>.
- */
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- #include "async.h"
- #include "boolean.h"
- #include "chars.h"
- #include "dynwind.h"
- #include "eval.h"
- #include "extensions.h"
- #include "foreign.h"
- #include "gsubr.h"
- #include "hashtab.h"
- #include "keywords.h"
- #include "macros.h"
- #include "modules.h"
- #include "numbers.h"
- #include "pairs.h"
- #include "ports-internal.h"
- #include "ports.h"
- #include "procprop.h"
- #include "programs.h"
- #include "smob.h"
- #include "strings.h"
- #include "strports.h"
- #include "symbols.h"
- #include "variable.h"
- #include "vectors.h"
- #include "version.h"
- #include "weak-table.h"
- #include "goops.h"
- /* Objects have identity, so references to classes and instances are by
- value, not by reference. Redefinition of a class or modification of
- an instance causes in-place update; you can think of GOOPS as
- building in its own indirection, and for that reason referring to
- GOOPS values by variable reference is unnecessary.
- References to ordinary procedures is by reference (by variable),
- though, as in the rest of Guile. */
- SCM_KEYWORD (k_name, "name");
- SCM_KEYWORD (k_setter, "setter");
- SCM_SYMBOL (sym_redefined, "redefined");
- SCM_GLOBAL_SYMBOL (scm_sym_args, "args");
- static int goops_loaded_p = 0;
- static SCM var_make_standard_class = SCM_BOOL_F;
- static SCM var_class_of_obsolete_indirect_instance = SCM_BOOL_F;
- static SCM var_make = SCM_BOOL_F;
- static SCM var_inherit_applicable = SCM_BOOL_F;
- static SCM var_class_name = SCM_BOOL_F;
- static SCM var_class_direct_supers = SCM_BOOL_F;
- static SCM var_class_direct_slots = SCM_BOOL_F;
- static SCM var_class_direct_subclasses = SCM_BOOL_F;
- static SCM var_class_direct_methods = SCM_BOOL_F;
- static SCM var_class_precedence_list = SCM_BOOL_F;
- static SCM var_class_slots = SCM_BOOL_F;
- static SCM var_generic_function_methods = SCM_BOOL_F;
- static SCM var_method_generic_function = SCM_BOOL_F;
- static SCM var_method_specializers = SCM_BOOL_F;
- static SCM var_method_procedure = SCM_BOOL_F;
- static SCM var_slot_ref = SCM_BOOL_F;
- static SCM var_slot_set_x = SCM_BOOL_F;
- static SCM var_slot_bound_p = SCM_BOOL_F;
- static SCM var_slot_exists_p = SCM_BOOL_F;
- /* These variables are filled in by the object system when loaded. */
- static SCM class_boolean, class_char, class_pair;
- static SCM class_procedure, class_string, class_symbol;
- static SCM class_primitive_generic;
- static SCM class_vector, class_null;
- static SCM class_integer, class_real, class_complex, class_fraction;
- static SCM class_unknown;
- static SCM class_top, class_class;
- static SCM class_applicable;
- static SCM class_applicable_struct, class_applicable_struct_with_setter;
- static SCM class_generic, class_generic_with_setter;
- static SCM class_accessor;
- static SCM class_extended_generic, class_extended_generic_with_setter;
- static SCM class_extended_accessor;
- static SCM class_method;
- static SCM class_accessor_method;
- static SCM class_procedure_class;
- static SCM class_applicable_struct_class;
- static SCM class_applicable_struct_with_setter_class;
- static SCM class_number, class_list;
- static SCM class_keyword;
- static SCM class_syntax;
- static SCM class_atomic_box;
- static SCM class_port, class_input_output_port;
- static SCM class_input_port, class_output_port;
- static SCM class_foreign;
- static SCM class_hashtable;
- static SCM class_fluid;
- static SCM class_dynamic_state;
- static SCM class_frame;
- static SCM class_vm_cont;
- static SCM class_bytevector;
- static SCM class_uvec;
- static SCM class_array;
- static SCM class_bitvector;
- static SCM vtable_class_map = SCM_BOOL_F;
- /* SMOB classes. */
- SCM scm_i_smob_class[SCM_I_MAX_SMOB_TYPE_COUNT];
- SCM scm_module_goops;
- static SCM scm_sys_make_vtable_vtable (SCM layout);
- static SCM scm_sys_init_layout_x (SCM class, SCM layout);
- static SCM scm_sys_clear_fields_x (SCM obj, SCM unbound);
- static SCM scm_sys_goops_early_init (void);
- static SCM scm_sys_goops_loaded (void);
- SCM_DEFINE (scm_sys_make_vtable_vtable, "%make-vtable-vtable", 1, 0, 0,
- (SCM layout),
- "")
- #define FUNC_NAME s_scm_sys_make_vtable_vtable
- {
- return scm_i_make_vtable_vtable (layout);
- }
- #undef FUNC_NAME
- SCM
- scm_make_standard_class (SCM meta, SCM name, SCM dsupers, SCM dslots)
- {
- return scm_call_4 (scm_variable_ref (var_make_standard_class),
- meta, name, dsupers, dslots);
- }
- SCM_DEFINE (scm_sys_init_layout_x, "%init-layout!", 2, 0, 0,
- (SCM class, SCM layout),
- "")
- #define FUNC_NAME s_scm_sys_init_layout_x
- {
- SCM_VALIDATE_INSTANCE (1, class);
- SCM_ASSERT (!scm_is_symbol (SCM_VTABLE_LAYOUT (class)), class, 1, FUNC_NAME);
- SCM_VALIDATE_STRING (2, layout);
- SCM_SET_VTABLE_LAYOUT (class, scm_make_struct_layout (layout));
- scm_i_struct_inherit_vtable_magic (scm_class_of (class), class);
- SCM_SET_CLASS_FLAGS (class, SCM_VTABLE_FLAG_GOOPS_CLASS);
- return SCM_UNSPECIFIED;
- }
- #undef FUNC_NAME
- static SCM
- get_indirect_slots (SCM x)
- {
- /* Precondition: X is an indirect instance. The indirect slots are in
- the last field. */
- scm_t_bits nfields =
- SCM_STRUCT_DATA_REF (SCM_STRUCT_VTABLE (x), scm_vtable_index_size);
- return SCM_STRUCT_SLOT_REF (x, nfields - 1);
- }
- /* This function is used for efficient type dispatch. */
- SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0,
- (SCM x),
- "Return the class of @var{x}.")
- #define FUNC_NAME s_scm_class_of
- {
- switch (SCM_ITAG3 (x))
- {
- case scm_tc3_int_1:
- case scm_tc3_int_2:
- return class_integer;
- case scm_tc3_imm24:
- if (SCM_CHARP (x))
- return class_char;
- else if (scm_is_bool (x))
- return class_boolean;
- else if (scm_is_null (x))
- return class_null;
- else
- return class_unknown;
- case scm_tc3_cons:
- switch (SCM_TYP7 (x))
- {
- case scm_tcs_cons_nimcar:
- return class_pair;
- case scm_tc7_symbol:
- return class_symbol;
- case scm_tc7_vector:
- case scm_tc7_wvect:
- return class_vector;
- case scm_tc7_pointer:
- return class_foreign;
- case scm_tc7_hashtable:
- return class_hashtable;
- case scm_tc7_fluid:
- return class_fluid;
- case scm_tc7_dynamic_state:
- return class_dynamic_state;
- case scm_tc7_frame:
- return class_frame;
- case scm_tc7_keyword:
- return class_keyword;
- case scm_tc7_syntax:
- return class_syntax;
- case scm_tc7_atomic_box:
- return class_atomic_box;
- case scm_tc7_vm_cont:
- return class_vm_cont;
- case scm_tc7_bytevector:
- if (SCM_BYTEVECTOR_ELEMENT_TYPE (x) == SCM_ARRAY_ELEMENT_TYPE_VU8)
- return class_bytevector;
- else
- return class_uvec;
- case scm_tc7_array:
- return class_array;
- case scm_tc7_bitvector:
- return class_bitvector;
- case scm_tc7_string:
- return class_string;
- case scm_tc7_number:
- switch SCM_TYP16 (x) {
- case scm_tc16_big:
- return class_integer;
- case scm_tc16_real:
- return class_real;
- case scm_tc16_complex:
- return class_complex;
- case scm_tc16_fraction:
- return class_fraction;
- }
- case scm_tc7_program:
- if (SCM_PROGRAM_IS_PRIMITIVE_GENERIC (x)
- && SCM_UNPACK (*SCM_SUBR_GENERIC (x)))
- return class_primitive_generic;
- else
- return class_procedure;
- case scm_tc7_smob:
- {
- scm_t_bits type = SCM_TYP16 (x);
- if (type != scm_tc16_port_with_ps)
- return scm_i_smob_class[SCM_TC2SMOBNUM (type)];
- x = SCM_PORT_WITH_PS_PORT (x);
- /* fall through to ports */
- }
- case scm_tc7_port:
- {
- scm_t_port_type *ptob = SCM_PORT_TYPE (x);
- if (SCM_INPUT_PORT_P (x))
- {
- if (SCM_OUTPUT_PORT_P (x))
- return ptob->input_output_class;
- return ptob->input_class;
- }
- return ptob->output_class;
- }
- case scm_tcs_struct:
- {
- SCM vtable = SCM_STRUCT_VTABLE (x);
- scm_t_bits flags = SCM_VTABLE_FLAGS (vtable);
- scm_t_bits direct = SCM_VTABLE_FLAG_GOOPS_CLASS;
- scm_t_bits indirect = direct | SCM_VTABLE_FLAG_GOOPS_INDIRECT;
- scm_t_bits mask = indirect;
- if ((flags & mask) == direct)
- /* A direct GOOPS object. */
- return vtable;
- else if ((flags & mask) == indirect)
- /* An indirect GOOPS object. If the vtable of the slots
- object is flagged to indicate that there's a new class
- definition available, migrate the instance before
- returning the class. */
- {
- SCM slots = get_indirect_slots (x);
- scm_t_bits slot_flags = SCM_OBJ_CLASS_FLAGS (slots);
- if (slot_flags & SCM_VTABLE_FLAG_GOOPS_NEEDS_MIGRATION)
- return scm_call_1
- (scm_variable_ref (var_class_of_obsolete_indirect_instance),
- x);
- else
- return vtable;
- }
- else
- /* A non-GOOPS struct. */
- return scm_i_define_class_for_vtable (vtable);
- }
- default:
- if (scm_is_pair (x))
- return class_pair;
- else
- return class_unknown;
- }
- case scm_tc3_struct:
- case scm_tc3_tc7_1:
- case scm_tc3_tc7_2:
- /* case scm_tc3_unused: */
- /* Never reached */
- break;
- }
- return class_unknown;
- }
- #undef FUNC_NAME
- SCM_DEFINE (scm_instance_p, "instance?", 1, 0, 0,
- (SCM obj),
- "Return @code{#t} if @var{obj} is an instance.")
- #define FUNC_NAME s_scm_instance_p
- {
- return scm_from_bool (SCM_INSTANCEP (obj));
- }
- #undef FUNC_NAME
- int
- scm_is_generic (SCM x)
- {
- return SCM_INSTANCEP (x) && SCM_SUBCLASSP (scm_class_of (x), class_generic);
- }
- int
- scm_is_method (SCM x)
- {
- return SCM_INSTANCEP (x) && SCM_SUBCLASSP (scm_class_of (x), class_method);
- }
- SCM
- scm_class_name (SCM obj)
- {
- return scm_call_1 (scm_variable_ref (var_class_name), obj);
- }
- SCM
- scm_class_direct_supers (SCM obj)
- {
- return scm_call_1 (scm_variable_ref (var_class_direct_supers), obj);
- }
- SCM
- scm_class_direct_slots (SCM obj)
- {
- return scm_call_1 (scm_variable_ref (var_class_direct_slots), obj);
- }
- SCM
- scm_class_direct_subclasses (SCM obj)
- {
- return scm_call_1 (scm_variable_ref (var_class_direct_subclasses), obj);
- }
- SCM
- scm_class_direct_methods (SCM obj)
- {
- return scm_call_1 (scm_variable_ref (var_class_direct_methods), obj);
- }
- SCM
- scm_class_precedence_list (SCM obj)
- {
- return scm_call_1 (scm_variable_ref (var_class_precedence_list), obj);
- }
- SCM
- scm_class_slots (SCM obj)
- {
- return scm_call_1 (scm_variable_ref (var_class_slots), obj);
- }
- SCM_DEFINE (scm_generic_function_name, "generic-function-name", 1, 0, 0,
- (SCM obj),
- "Return the name of the generic function @var{obj}.")
- #define FUNC_NAME s_scm_generic_function_name
- {
- SCM_VALIDATE_GENERIC (1, obj);
- return scm_procedure_property (obj, scm_sym_name);
- }
- #undef FUNC_NAME
- SCM
- scm_generic_function_methods (SCM obj)
- {
- return scm_call_1 (scm_variable_ref (var_generic_function_methods), obj);
- }
- SCM
- scm_method_generic_function (SCM obj)
- {
- return scm_call_1 (scm_variable_ref (var_method_generic_function), obj);
- }
- SCM
- scm_method_specializers (SCM obj)
- {
- return scm_call_1 (scm_variable_ref (var_method_specializers), obj);
- }
- SCM
- scm_method_procedure (SCM obj)
- {
- return scm_call_1 (scm_variable_ref (var_method_procedure), obj);
- }
- SCM
- scm_slot_ref (SCM obj, SCM slot_name)
- {
- return scm_call_2 (scm_variable_ref (var_slot_ref), obj, slot_name);
- }
- SCM
- scm_slot_set_x (SCM obj, SCM slot_name, SCM value)
- {
- return scm_call_3 (scm_variable_ref (var_slot_set_x), obj, slot_name, value);
- }
- SCM
- scm_slot_bound_p (SCM obj, SCM slot_name)
- {
- return scm_call_2 (scm_variable_ref (var_slot_bound_p), obj, slot_name);
- }
- SCM
- scm_slot_exists_p (SCM obj, SCM slot_name)
- {
- return scm_call_2 (scm_variable_ref (var_slot_exists_p), obj, slot_name);
- }
- SCM_DEFINE (scm_sys_clear_fields_x, "%clear-fields!", 2, 0, 0,
- (SCM obj, SCM unbound),
- "")
- #define FUNC_NAME s_scm_sys_clear_fields_x
- {
- scm_t_signed_bits n, i;
- SCM_VALIDATE_STRUCT (1, obj);
- n = SCM_STRUCT_SIZE (obj);
- /* Set all SCM-holding slots to the GOOPS unbound value. */
- for (i = 0; i < n; i++)
- if (!SCM_STRUCT_FIELD_IS_UNBOXED (obj, i))
- SCM_STRUCT_SLOT_SET (obj, i, unbound);
- return SCM_UNSPECIFIED;
- }
- #undef FUNC_NAME
- static scm_i_pthread_mutex_t goops_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
- SCM_DEFINE (scm_sys_modify_instance, "%modify-instance", 2, 0, 0,
- (SCM old, SCM new),
- "Used by change-class to modify objects in place.")
- #define FUNC_NAME s_scm_sys_modify_instance
- {
- scm_t_bits i, old_nfields, new_nfields;
- SCM_VALIDATE_INSTANCE (1, old);
- SCM_VALIDATE_INSTANCE (2, new);
- old_nfields = SCM_STRUCT_DATA_REF (SCM_STRUCT_VTABLE (old),
- scm_vtable_index_size);
- new_nfields = SCM_STRUCT_DATA_REF (SCM_STRUCT_VTABLE (new),
- scm_vtable_index_size);
- SCM_ASSERT (old_nfields == new_nfields, new, SCM_ARG2, FUNC_NAME);
- /* Exchange the data contained in old and new. We exchange rather than
- scratch the old value with new to be correct with GC. See "Class
- redefinition protocol" in goops.scm. */
- scm_i_pthread_mutex_lock (&goops_lock);
- /* Swap vtables. */
- {
- scm_t_bits tmp = SCM_CELL_WORD_0 (old);
- SCM_SET_CELL_WORD_0 (old, SCM_CELL_WORD_0 (new));
- SCM_SET_CELL_WORD_0 (new, tmp);
- }
- /* Swap data. */
- for (i = 0; i < old_nfields; i++)
- {
- scm_t_bits tmp = SCM_STRUCT_DATA_REF (old, i);
- SCM_STRUCT_DATA_SET (old, i, SCM_STRUCT_DATA_REF (new, i));
- SCM_STRUCT_DATA_SET (new, i, tmp);
- }
- scm_i_pthread_mutex_unlock (&goops_lock);
- return SCM_UNSPECIFIED;
- }
- #undef FUNC_NAME
- /* Primitive generics: primitives that can dispatch to generics if their
- arguments fail to apply. */
- SCM_DEFINE (scm_generic_capability_p, "generic-capability?", 1, 0, 0,
- (SCM proc),
- "")
- #define FUNC_NAME s_scm_generic_capability_p
- {
- SCM_ASSERT (scm_is_true (scm_procedure_p (proc)),
- proc, SCM_ARG1, FUNC_NAME);
- return (SCM_PRIMITIVE_GENERIC_P (proc) ? SCM_BOOL_T : SCM_BOOL_F);
- }
- #undef FUNC_NAME
- SCM_DEFINE (scm_enable_primitive_generic_x, "enable-primitive-generic!", 0, 0, 1,
- (SCM subrs),
- "")
- #define FUNC_NAME s_scm_enable_primitive_generic_x
- {
- SCM_VALIDATE_REST_ARGUMENT (subrs);
- while (!scm_is_null (subrs))
- {
- SCM subr = SCM_CAR (subrs);
- SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARGn, FUNC_NAME);
- SCM_SET_SUBR_GENERIC (subr,
- scm_make (scm_list_3 (class_generic,
- k_name,
- SCM_SUBR_NAME (subr))));
- subrs = SCM_CDR (subrs);
- }
- return SCM_UNSPECIFIED;
- }
- #undef FUNC_NAME
- SCM_DEFINE (scm_set_primitive_generic_x, "set-primitive-generic!", 2, 0, 0,
- (SCM subr, SCM generic),
- "")
- #define FUNC_NAME s_scm_set_primitive_generic_x
- {
- SCM_ASSERT (SCM_PRIMITIVE_GENERIC_P (subr), subr, SCM_ARG1, FUNC_NAME);
- SCM_ASSERT (SCM_GENERICP (generic), generic, SCM_ARG2, FUNC_NAME);
- SCM_SET_SUBR_GENERIC (subr, generic);
- return SCM_UNSPECIFIED;
- }
- #undef FUNC_NAME
- SCM_DEFINE (scm_primitive_generic_generic, "primitive-generic-generic", 1, 0, 0,
- (SCM subr),
- "")
- #define FUNC_NAME s_scm_primitive_generic_generic
- {
- if (SCM_PRIMITIVE_GENERIC_P (subr))
- {
- if (!SCM_UNPACK (*SCM_SUBR_GENERIC (subr)))
- scm_enable_primitive_generic_x (scm_list_1 (subr));
- return *SCM_SUBR_GENERIC (subr);
- }
- SCM_WRONG_TYPE_ARG (SCM_ARG1, subr);
- }
- #undef FUNC_NAME
- SCM
- scm_wta_dispatch_0 (SCM gf, const char *subr)
- {
- if (!SCM_UNPACK (gf))
- scm_error_num_args_subr (subr);
- return scm_call_0 (gf);
- }
- SCM
- scm_wta_dispatch_1 (SCM gf, SCM a1, int pos, const char *subr)
- {
- if (!SCM_UNPACK (gf))
- scm_wrong_type_arg (subr, pos, a1);
- return scm_call_1 (gf, a1);
- }
- SCM
- scm_wta_dispatch_2 (SCM gf, SCM a1, SCM a2, int pos, const char *subr)
- {
- if (!SCM_UNPACK (gf))
- scm_wrong_type_arg (subr, pos, (pos == SCM_ARG1) ? a1 : a2);
- return scm_call_2 (gf, a1, a2);
- }
- SCM
- scm_wta_dispatch_n (SCM gf, SCM args, int pos, const char *subr)
- {
- if (!SCM_UNPACK (gf))
- scm_wrong_type_arg (subr, pos, scm_list_ref (args, scm_from_int (pos)));
- return scm_apply_0 (gf, args);
- }
- SCM
- scm_make (SCM args)
- {
- return scm_apply_0 (scm_variable_ref (var_make), args);
- }
- /* SMOB, struct, and port classes. */
- static SCM
- make_class_name (const char *prefix, const char *type_name, const char *suffix)
- {
- if (!type_name)
- type_name = "";
- return scm_string_to_symbol (scm_string_append
- (scm_list_3 (scm_from_utf8_string (prefix),
- scm_from_utf8_string (type_name),
- scm_from_utf8_string (suffix))));
- }
- SCM
- scm_make_extended_class (char const *type_name, int applicablep)
- {
- SCM name, meta, supers;
- name = make_class_name ("<", type_name, ">");
- meta = class_class;
- if (applicablep)
- supers = scm_list_1 (class_applicable);
- else
- supers = scm_list_1 (class_top);
- return scm_make_standard_class (meta, name, supers, SCM_EOL);
- }
- void
- scm_i_inherit_applicable (SCM c)
- {
- scm_call_1 (scm_variable_ref (var_inherit_applicable), c);
- }
- static void
- create_smob_classes (void)
- {
- long i;
- for (i = 0; i < SCM_I_MAX_SMOB_TYPE_COUNT; ++i)
- scm_i_smob_class[i] = SCM_BOOL_F;
- for (i = 0; i < scm_numsmob; ++i)
- if (scm_is_false (scm_i_smob_class[i]))
- scm_i_smob_class[i] = scm_make_extended_class (SCM_SMOBNAME (i),
- scm_smobs[i].apply != 0);
- }
- struct pre_goops_port_type
- {
- scm_t_port_type *ptob;
- struct pre_goops_port_type *prev;
- };
- struct pre_goops_port_type *pre_goops_port_types;
- static void
- make_port_classes (scm_t_port_type *ptob)
- {
- SCM name, meta, super, supers;
- meta = class_class;
- name = make_class_name ("<", ptob->name, "-port>");
- supers = scm_list_1 (class_port);
- super = scm_make_standard_class (meta, name, supers, SCM_EOL);
- name = make_class_name ("<", ptob->name, "-input-port>");
- supers = scm_list_2 (super, class_input_port);
- ptob->input_class = scm_make_standard_class (meta, name, supers, SCM_EOL);
- name = make_class_name ("<", ptob->name, "-output-port>");
- supers = scm_list_2 (super, class_output_port);
- ptob->output_class = scm_make_standard_class (meta, name, supers, SCM_EOL);
- name = make_class_name ("<", ptob->name, "-input-output-port>");
- supers = scm_list_2 (super, class_input_output_port);
- ptob->input_output_class =
- scm_make_standard_class (meta, name, supers, SCM_EOL);
- }
- void
- scm_make_port_classes (scm_t_port_type *ptob)
- {
- ptob->input_class = SCM_BOOL_F;
- ptob->output_class = SCM_BOOL_F;
- ptob->input_output_class = SCM_BOOL_F;
- if (!goops_loaded_p)
- {
- /* Not really a pair. */
- struct pre_goops_port_type *link;
- link = scm_gc_typed_calloc (struct pre_goops_port_type);
- link->ptob = ptob;
- link->prev = pre_goops_port_types;
- pre_goops_port_types = link;
- return;
- }
- make_port_classes (ptob);
- }
- static void
- create_port_classes (void)
- {
- while (pre_goops_port_types)
- {
- make_port_classes (pre_goops_port_types->ptob);
- pre_goops_port_types = pre_goops_port_types->prev;
- }
- }
- SCM
- scm_i_define_class_for_vtable (SCM vtable)
- {
- SCM class;
- scm_i_pthread_mutex_lock (&scm_i_misc_mutex);
- if (scm_is_false (vtable_class_map))
- vtable_class_map = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
- scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
- if (scm_is_false (scm_struct_vtable_p (vtable)))
- abort ();
- class = scm_weak_table_refq (vtable_class_map, vtable, SCM_BOOL_F);
- if (scm_is_false (class))
- {
- if (SCM_UNPACK (class_class))
- {
- SCM name, meta, supers;
- name = SCM_VTABLE_NAME (vtable);
- if (scm_is_symbol (name))
- name = scm_string_to_symbol
- (scm_string_append
- (scm_list_3 (scm_from_latin1_string ("<"),
- scm_symbol_to_string (name),
- scm_from_latin1_string (">"))));
- else
- name = scm_from_latin1_symbol ("<>");
- if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SETTER))
- {
- meta = class_applicable_struct_with_setter_class;
- supers = scm_list_1 (class_applicable_struct_with_setter);
- }
- else if (SCM_STRUCT_VTABLE_FLAG_IS_SET (vtable,
- SCM_VTABLE_FLAG_APPLICABLE))
- {
- meta = class_applicable_struct_class;
- supers = scm_list_1 (class_applicable_struct);
- }
- else
- {
- meta = class_class;
- supers = scm_list_1 (class_top);
- }
- class = scm_make_standard_class (meta, name, supers, SCM_EOL);
- }
- else
- /* `create_struct_classes' will fill this in later. */
- class = SCM_BOOL_F;
- /* Don't worry about races. This only happens when creating a
- vtable, which happens by definition in one thread. */
- scm_weak_table_putq_x (vtable_class_map, vtable, class);
- }
- return class;
- }
- static SCM
- make_struct_class (void *closure SCM_UNUSED,
- SCM vtable, SCM data, SCM prev SCM_UNUSED)
- {
- if (scm_is_false (data))
- scm_i_define_class_for_vtable (vtable);
- return SCM_UNSPECIFIED;
- }
- static void
- create_struct_classes (void)
- {
- /* FIXME: take the vtable_class_map while initializing goops? */
- scm_internal_hash_fold (make_struct_class, 0, SCM_BOOL_F,
- vtable_class_map);
- }
- void
- scm_load_goops ()
- {
- if (!goops_loaded_p)
- scm_c_resolve_module ("oop goops");
- }
- SCM
- scm_ensure_accessor (SCM name)
- {
- SCM var, gf;
- var = scm_module_variable (scm_current_module (), name);
- if (SCM_VARIABLEP (var) && !SCM_UNBNDP (SCM_VARIABLE_REF (var)))
- gf = SCM_VARIABLE_REF (var);
- else
- gf = SCM_BOOL_F;
- if (!SCM_IS_A_P (gf, class_accessor))
- {
- gf = scm_make (scm_list_3 (class_generic, k_name, name));
- gf = scm_make (scm_list_5 (class_accessor,
- k_name, name, k_setter, gf));
- }
- return gf;
- }
- SCM_DEFINE (scm_sys_goops_early_init, "%goops-early-init", 0, 0, 0,
- (),
- "")
- #define FUNC_NAME s_scm_sys_goops_early_init
- {
- var_make_standard_class = scm_c_lookup ("make-standard-class");
- var_make = scm_c_lookup ("make");
- var_inherit_applicable = scm_c_lookup ("inherit-applicable!");
- /* For SCM_SUBCLASSP. */
- var_class_precedence_list = scm_c_lookup ("class-precedence-list");
- var_slot_ref = scm_c_lookup ("slot-ref");
- var_slot_set_x = scm_c_lookup ("slot-set!");
- var_slot_bound_p = scm_c_lookup ("slot-bound?");
- var_slot_exists_p = scm_c_lookup ("slot-exists?");
- class_class = scm_variable_ref (scm_c_lookup ("<class>"));
- class_top = scm_variable_ref (scm_c_lookup ("<top>"));
- /* Applicables */
- class_procedure_class = scm_variable_ref (scm_c_lookup ("<procedure-class>"));
- class_applicable_struct_class = scm_variable_ref (scm_c_lookup ("<applicable-struct-class>"));
- class_applicable_struct_with_setter_class =
- scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter-class>"));
- class_method = scm_variable_ref (scm_c_lookup ("<method>"));
- class_accessor_method = scm_variable_ref (scm_c_lookup ("<accessor-method>"));
- class_applicable = scm_variable_ref (scm_c_lookup ("<applicable>"));
- class_applicable_struct = scm_variable_ref (scm_c_lookup ("<applicable-struct>"));
- class_applicable_struct_with_setter = scm_variable_ref (scm_c_lookup ("<applicable-struct-with-setter>"));
- class_generic = scm_variable_ref (scm_c_lookup ("<generic>"));
- class_extended_generic = scm_variable_ref (scm_c_lookup ("<extended-generic>"));
- class_generic_with_setter = scm_variable_ref (scm_c_lookup ("<generic-with-setter>"));
- class_accessor = scm_variable_ref (scm_c_lookup ("<accessor>"));
- class_extended_generic_with_setter = scm_variable_ref (scm_c_lookup ("<extended-generic-with-setter>"));
- class_extended_accessor = scm_variable_ref (scm_c_lookup ("<extended-accessor>"));
- /* Primitive types classes */
- class_boolean = scm_variable_ref (scm_c_lookup ("<boolean>"));
- class_char = scm_variable_ref (scm_c_lookup ("<char>"));
- class_list = scm_variable_ref (scm_c_lookup ("<list>"));
- class_pair = scm_variable_ref (scm_c_lookup ("<pair>"));
- class_null = scm_variable_ref (scm_c_lookup ("<null>"));
- class_string = scm_variable_ref (scm_c_lookup ("<string>"));
- class_symbol = scm_variable_ref (scm_c_lookup ("<symbol>"));
- class_vector = scm_variable_ref (scm_c_lookup ("<vector>"));
- class_foreign = scm_variable_ref (scm_c_lookup ("<foreign>"));
- class_hashtable = scm_variable_ref (scm_c_lookup ("<hashtable>"));
- class_fluid = scm_variable_ref (scm_c_lookup ("<fluid>"));
- class_dynamic_state = scm_variable_ref (scm_c_lookup ("<dynamic-state>"));
- class_frame = scm_variable_ref (scm_c_lookup ("<frame>"));
- class_keyword = scm_variable_ref (scm_c_lookup ("<keyword>"));
- class_syntax = scm_variable_ref (scm_c_lookup ("<syntax>"));
- class_atomic_box = scm_variable_ref (scm_c_lookup ("<atomic-box>"));
- class_vm_cont = scm_variable_ref (scm_c_lookup ("<vm-continuation>"));
- class_bytevector = scm_variable_ref (scm_c_lookup ("<bytevector>"));
- class_uvec = scm_variable_ref (scm_c_lookup ("<uvec>"));
- class_array = scm_variable_ref (scm_c_lookup ("<array>"));
- class_bitvector = scm_variable_ref (scm_c_lookup ("<bitvector>"));
- class_number = scm_variable_ref (scm_c_lookup ("<number>"));
- class_complex = scm_variable_ref (scm_c_lookup ("<complex>"));
- class_real = scm_variable_ref (scm_c_lookup ("<real>"));
- class_integer = scm_variable_ref (scm_c_lookup ("<integer>"));
- class_fraction = scm_variable_ref (scm_c_lookup ("<fraction>"));
- class_unknown = scm_variable_ref (scm_c_lookup ("<unknown>"));
- class_procedure = scm_variable_ref (scm_c_lookup ("<procedure>"));
- class_primitive_generic = scm_variable_ref (scm_c_lookup ("<primitive-generic>"));
- class_port = scm_variable_ref (scm_c_lookup ("<port>"));
- class_input_port = scm_variable_ref (scm_c_lookup ("<input-port>"));
- class_output_port = scm_variable_ref (scm_c_lookup ("<output-port>"));
- class_input_output_port = scm_variable_ref (scm_c_lookup ("<input-output-port>"));
- create_smob_classes ();
- create_struct_classes ();
- create_port_classes ();
- return SCM_UNSPECIFIED;
- }
- #undef FUNC_NAME
- SCM_DEFINE (scm_sys_goops_loaded, "%goops-loaded", 0, 0, 0,
- (),
- "Announce that GOOPS is loaded and perform initialization\n"
- "on the C level which depends on the loaded GOOPS modules.")
- #define FUNC_NAME s_scm_sys_goops_loaded
- {
- goops_loaded_p = 1;
- var_class_name = scm_c_lookup ("class-name");
- var_class_direct_supers = scm_c_lookup ("class-direct-supers");
- var_class_direct_slots = scm_c_lookup ("class-direct-slots");
- var_class_direct_subclasses = scm_c_lookup ("class-direct-subclasses");
- var_class_direct_methods = scm_c_lookup ("class-direct-methods");
- var_class_slots = scm_c_lookup ("class-slots");
- var_generic_function_methods = scm_c_lookup ("generic-function-methods");
- var_method_generic_function = scm_c_lookup ("method-generic-function");
- var_method_specializers = scm_c_lookup ("method-specializers");
- var_method_procedure = scm_c_lookup ("method-procedure");
- var_class_of_obsolete_indirect_instance =
- scm_c_lookup ("class-of-obsolete-indirect-instance");
- return SCM_UNSPECIFIED;
- }
- #undef FUNC_NAME
- static void
- scm_init_goops_builtins (void *unused)
- {
- scm_module_goops = scm_current_module ();
- #include "goops.x"
- scm_c_define ("vtable-flag-vtable",
- scm_from_int (SCM_VTABLE_FLAG_VTABLE));
- scm_c_define ("vtable-flag-applicable-vtable",
- scm_from_int (SCM_VTABLE_FLAG_APPLICABLE_VTABLE));
- scm_c_define ("vtable-flag-setter-vtable",
- scm_from_int (SCM_VTABLE_FLAG_SETTER_VTABLE));
- scm_c_define ("vtable-flag-validated",
- scm_from_int (SCM_VTABLE_FLAG_VALIDATED));
- scm_c_define ("vtable-flag-goops-class",
- scm_from_int (SCM_VTABLE_FLAG_GOOPS_CLASS));
- scm_c_define ("vtable-flag-goops-slot",
- scm_from_int (SCM_VTABLE_FLAG_GOOPS_SLOT));
- scm_c_define ("vtable-flag-goops-static-slot-allocation",
- scm_from_int (SCM_VTABLE_FLAG_GOOPS_STATIC_SLOT_ALLOCATION));
- scm_c_define ("vtable-flag-goops-indirect",
- scm_from_int (SCM_VTABLE_FLAG_GOOPS_INDIRECT));
- scm_c_define ("vtable-flag-goops-needs-migration",
- scm_from_int (SCM_VTABLE_FLAG_GOOPS_NEEDS_MIGRATION));
- }
- void
- scm_init_goops ()
- {
- scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
- "scm_init_goops_builtins", scm_init_goops_builtins,
- NULL);
- }
|