summaryrefslogtreecommitdiff
path: root/libguile/goops.c
diff options
context:
space:
mode:
Diffstat (limited to 'libguile/goops.c')
-rw-r--r--libguile/goops.c230
1 files changed, 160 insertions, 70 deletions
diff --git a/libguile/goops.c b/libguile/goops.c
index bbeb58433..4616fa240 100644
--- a/libguile/goops.c
+++ b/libguile/goops.c
@@ -2,18 +2,19 @@
* Free Software Foundation, Inc.
*
* This library 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 2.1 of the License, or (at your option) any later version.
+ * 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.
*
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * This library 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 this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*/
@@ -59,24 +60,32 @@
#define SPEC_OF(x) SCM_SLOT (x, scm_si_specializers)
-#define DEFVAR(v, val) \
-{ scm_eval (scm_list_3 (scm_sym_define_public, (v), (val)), \
- scm_module_goops); }
-/* Temporary hack until we get the new module system */
-/*fixme* Should optimize by keeping track of the variable object itself */
-#define GETVAR(v) (SCM_VARIABLE_REF (scm_call_2 (scm_goops_lookup_closure, \
- (v), SCM_BOOL_F)))
-
-/* Fixme: Should use already interned symbols */
-
-#define CALL_GF1(name, a) (scm_call_1 (GETVAR (scm_from_locale_symbol (name)), \
- a))
-#define CALL_GF2(name, a, b) (scm_call_2 (GETVAR (scm_from_locale_symbol (name)), \
- a, b))
-#define CALL_GF3(name, a, b, c) (scm_call_3 (GETVAR (scm_from_locale_symbol (name)), \
- a, b, c))
-#define CALL_GF4(name, a, b, c, d) (scm_call_4 (GETVAR (scm_from_locale_symbol (name)), \
- a, b, c, d))
+/* this file is a mess. in theory, though, we shouldn't have many SCM references
+ -- most of the references should be to vars. */
+
+static SCM var_slot_unbound = SCM_BOOL_F;
+static SCM var_slot_missing = SCM_BOOL_F;
+static SCM var_compute_cpl = SCM_BOOL_F;
+static SCM var_no_applicable_method = SCM_BOOL_F;
+static SCM var_memoize_method_x = SCM_BOOL_F;
+static SCM var_change_class = SCM_BOOL_F;
+
+SCM_SYMBOL (sym_slot_unbound, "slot-unbound");
+SCM_SYMBOL (sym_slot_missing, "slot-missing");
+SCM_SYMBOL (sym_compute_cpl, "compute-cpl");
+SCM_SYMBOL (sym_no_applicable_method, "no-applicable-method");
+SCM_SYMBOL (sym_memoize_method_x, "memoize-method!");
+SCM_SYMBOL (sym_change_class, "change-class");
+
+SCM_VARIABLE (scm_var_make_extended_generic, "make-extended-generic");
+
+
+/* FIXME, exports should come from the scm file only */
+#define DEFVAR(v, val) \
+ { scm_module_define (scm_module_goops, (v), (val)); \
+ scm_module_export (scm_module_goops, scm_list_1 ((v))); \
+ }
+
/* Class redefinition protocol:
@@ -119,8 +128,6 @@
static int goops_loaded_p = 0;
static scm_t_rstate *goops_rstate;
-static SCM scm_goops_lookup_closure;
-
/* These variables are filled in by the object system when loaded. */
SCM scm_class_boolean, scm_class_char, scm_class_pair;
SCM scm_class_procedure, scm_class_string, scm_class_symbol;
@@ -169,6 +176,8 @@ static SCM scm_unbound_p (SCM obj);
static SCM scm_assert_bound (SCM value, SCM obj);
static SCM scm_at_assert_bound_ref (SCM obj, SCM index);
static SCM scm_sys_goops_loaded (void);
+static SCM scm_make_extended_class_from_symbol (SCM type_name_sym,
+ int applicablep);
/* This function is used for efficient type dispatch. */
SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0,
@@ -234,6 +243,7 @@ SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0,
else
return scm_class_procedure;
case scm_tc7_gsubr:
+ case scm_tc7_program:
return scm_class_procedure;
case scm_tc7_pws:
return scm_class_procedure_with_setter;
@@ -273,9 +283,9 @@ SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0,
else
{
SCM name = SCM_STRUCT_TABLE_NAME (SCM_CDR (handle));
- SCM class = scm_make_extended_class (scm_is_true (name)
- ? scm_i_symbol_chars (name)
- : 0,
+ SCM class = scm_make_extended_class_from_symbol (scm_is_true (name)
+ ? name
+ : scm_nullstr,
SCM_I_OPERATORP (x));
SCM_SET_STRUCT_TABLE_CLASS (SCM_CDR (handle), class);
return class;
@@ -346,7 +356,7 @@ static SCM
compute_cpl (SCM class)
{
if (goops_loaded_p)
- return CALL_GF1 ("compute-cpl", class);
+ return scm_call_1 (SCM_VARIABLE_REF (var_compute_cpl), class);
else
{
SCM supers = SCM_SLOT (class, scm_si_direct_supers);
@@ -588,13 +598,10 @@ SCM_DEFINE (scm_sys_initialize_object, "%initialize-object", 2, 0, 0,
{
slot_value = get_slot_value (class, obj, SCM_CAR (get_n_set));
if (SCM_GOOPS_UNBOUNDP (slot_value))
- {
- SCM env = SCM_EXTEND_ENV (SCM_EOL, SCM_EOL, SCM_ENV (tmp));
- set_slot_value (class,
- obj,
- SCM_CAR (get_n_set),
- scm_eval_body (SCM_CLOSURE_BODY (tmp), env));
- }
+ set_slot_value (class,
+ obj,
+ SCM_CAR (get_n_set),
+ scm_call_0 (tmp));
}
}
}
@@ -1195,7 +1202,7 @@ SCM_DEFINE (scm_assert_bound, "assert-bound", 2, 0, 0,
#define FUNC_NAME s_scm_assert_bound
{
if (SCM_GOOPS_UNBOUNDP (value))
- return CALL_GF1 ("slot-unbound", obj);
+ return scm_call_1 (SCM_VARIABLE_REF (var_slot_unbound), obj);
return value;
}
#undef FUNC_NAME
@@ -1208,7 +1215,7 @@ SCM_DEFINE (scm_at_assert_bound_ref, "@assert-bound-ref", 2, 0, 0,
{
SCM value = SCM_SLOT (obj, scm_to_int (index));
if (SCM_GOOPS_UNBOUNDP (value))
- return CALL_GF1 ("slot-unbound", obj);
+ return scm_call_1 (SCM_VARIABLE_REF (var_slot_unbound), obj);
return value;
}
#undef FUNC_NAME
@@ -1250,10 +1257,7 @@ SCM_DEFINE (scm_sys_fast_slot_set_x, "%fast-slot-set!", 3, 0, 0,
#undef FUNC_NAME
-SCM_SYNTAX (s_atslot_ref, "@slot-ref", scm_i_makbimacro, scm_m_atslot_ref);
-SCM_SYNTAX (s_atslot_set_x, "@slot-set!", scm_i_makbimacro, scm_m_atslot_set_x);
-
-
+
/** Utilities **/
/* In the future, this function will return the effective slot
@@ -1296,7 +1300,7 @@ get_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef)
code = SCM_CAR (access);
if (!SCM_CLOSUREP (code))
- return SCM_SUBRF (code) (obj);
+ return scm_call_1 (code, obj);
env = SCM_EXTEND_ENV (SCM_CLOSURE_FORMALS (code),
scm_list_1 (obj),
SCM_ENV (code));
@@ -1313,7 +1317,7 @@ get_slot_value_using_name (SCM class, SCM obj, SCM slot_name)
if (scm_is_true (slotdef))
return get_slot_value (class, obj, slotdef);
else
- return CALL_GF3 ("slot-missing", class, obj, slot_name);
+ return scm_call_3 (SCM_VARIABLE_REF (var_slot_missing), class, obj, slot_name);
}
static SCM
@@ -1339,7 +1343,7 @@ set_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef, SCM value)
code = SCM_CADR (access);
if (!SCM_CLOSUREP (code))
- SCM_SUBRF (code) (obj, value);
+ scm_call_2 (code, obj, value);
else
{
env = SCM_EXTEND_ENV (SCM_CLOSURE_FORMALS (code),
@@ -1360,7 +1364,7 @@ set_slot_value_using_name (SCM class, SCM obj, SCM slot_name, SCM value)
if (scm_is_true (slotdef))
return set_slot_value (class, obj, slotdef, value);
else
- return CALL_GF4 ("slot-missing", class, obj, slot_name, value);
+ return scm_call_4 (SCM_VARIABLE_REF (var_slot_missing), class, obj, slot_name, value);
}
static SCM
@@ -1390,7 +1394,7 @@ SCM_DEFINE (scm_slot_ref_using_class, "slot-ref-using-class", 3, 0, 0,
res = get_slot_value_using_name (class, obj, slot_name);
if (SCM_GOOPS_UNBOUNDP (res))
- return CALL_GF3 ("slot-unbound", class, obj, slot_name);
+ return scm_call_3 (SCM_VARIABLE_REF (var_slot_unbound), class, obj, slot_name);
return res;
}
#undef FUNC_NAME
@@ -1453,7 +1457,7 @@ SCM_DEFINE (scm_slot_ref, "slot-ref", 2, 0, 0,
res = get_slot_value_using_name (class, obj, slot_name);
if (SCM_GOOPS_UNBOUNDP (res))
- return CALL_GF3 ("slot-unbound", class, obj, slot_name);
+ return scm_call_3 (SCM_VARIABLE_REF (var_slot_unbound), class, obj, slot_name);
return res;
}
#undef FUNC_NAME
@@ -1522,11 +1526,11 @@ wrap_init (SCM class, SCM *m, long n)
{
long i;
scm_t_bits slayout = SCM_STRUCT_DATA (class)[scm_vtable_index_layout];
- const char *layout = scm_i_symbol_chars (SCM_PACK (slayout));
+ SCM layout = SCM_PACK (slayout);
/* Set all SCM-holding slots to unbound */
for (i = 0; i < n; i++)
- if (layout[i*2] == 'p')
+ if (scm_i_symbol_ref (layout, i*2) == 'p')
m[i] = SCM_GOOPS_UNBOUND;
else
m[i] = 0;
@@ -1742,7 +1746,7 @@ SCM_SYMBOL (scm_sym_change_class, "change-class");
static SCM
purgatory (void *args)
{
- return scm_apply_0 (GETVAR (scm_sym_change_class),
+ return scm_apply_0 (SCM_VARIABLE_REF (var_change_class),
SCM_PACK ((scm_t_bits) args));
}
@@ -1856,7 +1860,7 @@ SCM_DEFINE (scm_enable_primitive_generic_x, "enable-primitive-generic!", 0, 0, 1
*SCM_SUBR_GENERIC (subr)
= scm_make (scm_list_3 (scm_class_generic,
k_name,
- SCM_SNAME (subr)));
+ SCM_SUBR_NAME (subr)));
subrs = SCM_CDR (subrs);
}
return SCM_UNSPECIFIED;
@@ -1904,7 +1908,7 @@ scm_c_extend_primitive_generic (SCM extended, SCM extension)
gf = *SCM_SUBR_GENERIC (extended);
gext = scm_call_2 (SCM_VARIABLE_REF (scm_var_make_extended_generic),
gf,
- SCM_SNAME (extension));
+ SCM_SUBR_NAME (extension));
SCM_SET_SUBR_GENERIC (extension, gext);
}
else
@@ -2143,7 +2147,7 @@ scm_compute_applicable_methods (SCM gf, SCM args, long len, int find_method_p)
{
if (find_method_p)
return SCM_BOOL_F;
- CALL_GF2 ("no-applicable-method", gf, save);
+ scm_call_2 (SCM_VARIABLE_REF (var_no_applicable_method), gf, save);
/* if we are here, it's because no-applicable-method hasn't signaled an error */
return SCM_BOOL_F;
}
@@ -2200,8 +2204,13 @@ call_memoize_method (void *a)
SCM cmethod = scm_mcache_lookup_cmethod (x, SCM_CDDR (args));
if (scm_is_true (cmethod))
return cmethod;
- /*fixme* Use scm_apply */
- return CALL_GF3 ("memoize-method!", gf, SCM_CDDR (args), x);
+
+ if (SCM_UNLIKELY (scm_is_false (var_memoize_method_x)))
+ var_memoize_method_x =
+ scm_permanent_object
+ (scm_module_variable (scm_module_goops, sym_memoize_method_x));
+
+ return scm_call_3 (SCM_VARIABLE_REF (var_memoize_method_x), gf, SCM_CDDR (args), x);
}
SCM
@@ -2229,6 +2238,9 @@ scm_memoize_method (SCM x, SCM args)
SCM_KEYWORD (k_setter, "setter");
SCM_KEYWORD (k_specializers, "specializers");
SCM_KEYWORD (k_procedure, "procedure");
+SCM_KEYWORD (k_formals, "formals");
+SCM_KEYWORD (k_body, "body");
+SCM_KEYWORD (k_make_procedure, "make-procedure");
SCM_KEYWORD (k_dsupers, "dsupers");
SCM_KEYWORD (k_slots, "slots");
SCM_KEYWORD (k_gf, "generic-function");
@@ -2292,9 +2304,27 @@ SCM_DEFINE (scm_make, "make", 0, 0, 1,
scm_i_get_keyword (k_procedure,
args,
len - 1,
- SCM_EOL,
+ SCM_BOOL_F,
FUNC_NAME));
SCM_SET_SLOT (z, scm_si_code_table, SCM_EOL);
+ SCM_SET_SLOT (z, scm_si_formals,
+ scm_i_get_keyword (k_formals,
+ args,
+ len - 1,
+ SCM_EOL,
+ FUNC_NAME));
+ SCM_SET_SLOT (z, scm_si_body,
+ scm_i_get_keyword (k_body,
+ args,
+ len - 1,
+ SCM_EOL,
+ FUNC_NAME));
+ SCM_SET_SLOT (z, scm_si_make_procedure,
+ scm_i_get_keyword (k_make_procedure,
+ args,
+ len - 1,
+ SCM_BOOL_F,
+ FUNC_NAME));
}
else
{
@@ -2434,10 +2464,14 @@ static void
create_standard_classes (void)
{
SCM slots;
- SCM method_slots = scm_list_4 (scm_from_locale_symbol ("generic-function"),
+ SCM method_slots = scm_list_n (scm_from_locale_symbol ("generic-function"),
scm_from_locale_symbol ("specializers"),
sym_procedure,
- scm_from_locale_symbol ("code-table"));
+ scm_from_locale_symbol ("code-table"),
+ scm_from_locale_symbol ("formals"),
+ scm_from_locale_symbol ("body"),
+ scm_from_locale_symbol ("make-procedure"),
+ SCM_UNDEFINED);
SCM amethod_slots = scm_list_1 (scm_list_3 (scm_from_locale_symbol ("slot-definition"),
k_init_keyword,
k_slot_definition));
@@ -2646,7 +2680,35 @@ make_class_from_template (char const *template, char const *type_name, SCM super
/* Only define name if doesn't already exist. */
if (!SCM_GOOPS_UNBOUNDP (name)
- && scm_is_false (scm_call_2 (scm_goops_lookup_closure, name, SCM_BOOL_F)))
+ && scm_is_false (scm_module_variable (scm_module_goops, name)))
+ DEFVAR (name, class);
+ return class;
+}
+
+static SCM
+make_class_from_symbol (SCM type_name_sym, SCM supers, int applicablep)
+{
+ SCM class, name;
+ if (type_name_sym != SCM_BOOL_F)
+ {
+ name = scm_string_append (scm_list_3 (scm_from_locale_string ("<"),
+ scm_symbol_to_string (type_name_sym),
+ scm_from_locale_string (">")));
+ name = scm_string_to_symbol (name);
+ }
+ else
+ name = SCM_GOOPS_UNBOUND;
+
+ class = scm_permanent_object (scm_basic_make_class (applicablep
+ ? scm_class_procedure_class
+ : scm_class_class,
+ name,
+ supers,
+ SCM_EOL));
+
+ /* Only define name if doesn't already exist. */
+ if (!SCM_GOOPS_UNBOUNDP (name)
+ && scm_is_false (scm_module_variable (scm_module_goops, name)))
DEFVAR (name, class);
return class;
}
@@ -2662,6 +2724,16 @@ scm_make_extended_class (char const *type_name, int applicablep)
applicablep);
}
+static SCM
+scm_make_extended_class_from_symbol (SCM type_name_sym, int applicablep)
+{
+ return make_class_from_symbol (type_name_sym,
+ scm_list_1 (applicablep
+ ? scm_class_applicable
+ : scm_class_top),
+ applicablep);
+}
+
void
scm_i_inherit_applicable (SCM c)
{
@@ -2754,11 +2826,16 @@ static SCM
make_struct_class (void *closure SCM_UNUSED,
SCM vtable, SCM data, SCM prev SCM_UNUSED)
{
- if (scm_is_true (SCM_STRUCT_TABLE_NAME (data)))
- SCM_SET_STRUCT_TABLE_CLASS (data,
- scm_make_extended_class
- (scm_i_symbol_chars (SCM_STRUCT_TABLE_NAME (data)),
- SCM_CLASS_FLAGS (vtable) & SCM_CLASSF_OPERATOR));
+ SCM sym = SCM_STRUCT_TABLE_NAME (data);
+ if (scm_is_true (sym))
+ {
+ int applicablep = SCM_CLASS_FLAGS (vtable) & SCM_CLASSF_OPERATOR;
+
+ SCM_SET_STRUCT_TABLE_CLASS (data,
+ scm_make_extended_class_from_symbol (sym, applicablep));
+ }
+
+ scm_remember_upto_here_2 (data, vtable);
return SCM_UNSPECIFIED;
}
@@ -2978,8 +3055,23 @@ SCM_DEFINE (scm_sys_goops_loaded, "%goops-loaded", 0, 0, 0,
{
goops_loaded_p = 1;
var_compute_applicable_methods =
- scm_sym2var (sym_compute_applicable_methods, scm_goops_lookup_closure,
- SCM_BOOL_F);
+ scm_permanent_object
+ (scm_module_variable (scm_module_goops, sym_compute_applicable_methods));
+ var_slot_unbound =
+ scm_permanent_object
+ (scm_module_variable (scm_module_goops, sym_slot_unbound));
+ var_slot_missing =
+ scm_permanent_object
+ (scm_module_variable (scm_module_goops, sym_slot_missing));
+ var_compute_cpl =
+ scm_permanent_object
+ (scm_module_variable (scm_module_goops, sym_compute_cpl));
+ var_no_applicable_method =
+ scm_permanent_object
+ (scm_module_variable (scm_module_goops, sym_no_applicable_method));
+ var_change_class =
+ scm_permanent_object
+ (scm_module_variable (scm_module_goops, sym_change_class));
setup_extended_primitive_generics ();
return SCM_UNSPECIFIED;
}
@@ -2991,12 +3083,10 @@ SCM
scm_init_goops_builtins (void)
{
scm_module_goops = scm_current_module ();
- scm_goops_lookup_closure = scm_module_lookup_closure (scm_module_goops);
/* Not really necessary right now, but who knows...
*/
scm_permanent_object (scm_module_goops);
- scm_permanent_object (scm_goops_lookup_closure);
scm_components = scm_permanent_object (scm_make_weak_key_hash_table
(scm_from_int (37)));