Merge commit 'feccd2d3100fd2964d4c2df58ab3da7ce4949a66' into vm-check
[bpt/guile.git] / libguile / goops.c
index 9cebeb2..2fc6c31 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998,1999,2000,2001,2002,2003,2004
+/* Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2008
  * Free Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * Erick Gallesio <eg@unice.fr>.
  */
 
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
 #include <stdio.h>
+#include <assert.h>
 
 #include "libguile/_scm.h"
 #include "libguile/alist.h"
 
 #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:
 
 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;
@@ -147,8 +158,13 @@ SCM scm_class_protected_opaque, scm_class_protected_read_only;
 SCM scm_class_scm;
 SCM scm_class_int, scm_class_float, scm_class_double;
 
-SCM *scm_port_class = 0;
-SCM *scm_smob_class = 0;
+/* Port classes.  Allocate 3 times the maximum number of port types so that
+   input ports, output ports, and in/out ports can be stored at different
+   offsets.  See `SCM_IN_PCLASS_INDEX' et al.  */
+SCM scm_port_class[3 * SCM_I_MAX_PORT_TYPE_COUNT];
+
+/* SMOB classes.  */
+SCM scm_smob_class[SCM_I_MAX_SMOB_TYPE_COUNT];
 
 SCM scm_no_applicable_method;
 
@@ -336,7 +352,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);
@@ -578,13 +594,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));
            }
        }
     }
@@ -1187,7 +1200,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
@@ -1200,7 +1213,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
@@ -1213,7 +1226,10 @@ SCM_DEFINE (scm_sys_fast_slot_ref, "%fast-slot-ref", 2, 0, 0,
   unsigned long int i;
 
   SCM_VALIDATE_INSTANCE (1, obj);
-  i = scm_to_unsigned_integer (index, 0, SCM_NUMBER_OF_SLOTS(obj)-1);
+  i = scm_to_unsigned_integer (index, 0,
+                              SCM_I_INUM (SCM_SLOT (SCM_CLASS_OF (obj),
+                                                    scm_si_nfields))
+                              - 1);
   return SCM_SLOT (obj, i);
 }
 #undef FUNC_NAME
@@ -1227,7 +1243,10 @@ SCM_DEFINE (scm_sys_fast_slot_set_x, "%fast-slot-set!", 3, 0, 0,
   unsigned long int i;
 
   SCM_VALIDATE_INSTANCE (1, obj);
-  i = scm_to_unsigned_integer (index, 0, SCM_NUMBER_OF_SLOTS(obj)-1);
+  i = scm_to_unsigned_integer (index, 0,
+                              SCM_I_INUM (SCM_SLOT (SCM_CLASS_OF (obj),
+                                                    scm_si_nfields))
+                              - 1);
 
   SCM_SET_SLOT (obj, i, value);
 
@@ -1260,6 +1279,7 @@ slot_definition_using_name (SCM class, SCM slot_name)
 
 static SCM
 get_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef)
+#define FUNC_NAME "%get-slot-value"
 {
   SCM access = SCM_CDDR (slotdef);
   /* Two cases here:
@@ -1270,7 +1290,9 @@ get_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef)
    * we can just assume fixnums here.
    */
   if (SCM_I_INUMP (access))
-    return SCM_SLOT (obj, SCM_I_INUM (access));
+    /* Don't poke at the slots directly, because scm_struct_ref handles the
+       access bits for us. */
+    return scm_struct_ref (obj, access);
   else
     {
       /* We must evaluate (apply (car access) (list obj))
@@ -1279,7 +1301,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));
@@ -1287,6 +1309,7 @@ get_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef)
       return scm_eval_body (SCM_CLOSURE_BODY (code), env);
     }
 }
+#undef FUNC_NAME
 
 static SCM
 get_slot_value_using_name (SCM class, SCM obj, SCM slot_name)
@@ -1295,11 +1318,12 @@ 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
 set_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef, SCM value)
+#define FUNC_NAME "%set-slot-value"
 {
   SCM access = SCM_CDDR (slotdef);
   /* Two cases here:
@@ -1310,7 +1334,8 @@ set_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef, SCM value)
    * we can just assume fixnums here.
    */
   if (SCM_I_INUMP (access))
-    SCM_SET_SLOT (obj, SCM_I_INUM (access), value);
+    /* obey permissions bits via going through struct-set! */
+    scm_struct_set_x (obj, access, value);
   else
     {
       /* We must evaluate (apply (cadr l) (list obj value))
@@ -1319,7 +1344,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),
@@ -1331,6 +1356,7 @@ set_slot_value (SCM class SCM_UNUSED, SCM obj, SCM slotdef, SCM value)
     }
   return SCM_UNSPECIFIED;
 }
+#undef FUNC_NAME
 
 static SCM
 set_slot_value_using_name (SCM class, SCM obj, SCM slot_name, SCM value)
@@ -1339,7 +1365,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
@@ -1369,7 +1395,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
@@ -1432,7 +1458,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
@@ -1500,10 +1526,15 @@ static SCM
 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));
 
-  /* Set all slots to unbound */
+  /* Set all SCM-holding slots to unbound */
   for (i = 0; i < n; i++)
-    m[i] = SCM_GOOPS_UNBOUND;
+    if (layout[i*2] == 'p')
+      m[i] = SCM_GOOPS_UNBOUND;
+    else
+      m[i] = 0;
 
   return scm_double_cell ((((scm_t_bits) SCM_STRUCT_DATA (class))
                           | scm_tc3_struct),
@@ -1693,11 +1724,10 @@ go_to_hell (void *o)
 {
   SCM obj = SCM_PACK ((scm_t_bits) o);
   scm_lock_mutex (hell_mutex);
-  if (n_hell == hell_size)
+  if (n_hell >= hell_size)
     {
-      long new_size = 2 * hell_size;
-      hell = scm_realloc (hell, new_size);
-      hell_size = new_size;
+      hell_size *= 2;
+      hell = scm_realloc (hell, hell_size * sizeof(*hell));
     }
   hell[n_hell++] = SCM_STRUCT_DATA (obj);
   scm_unlock_mutex (hell_mutex);
@@ -1717,7 +1747,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));
 }
 
@@ -1875,7 +1905,7 @@ scm_c_extend_primitive_generic (SCM extended, SCM extension)
       gext = scm_call_2 (SCM_VARIABLE_REF (scm_var_make_extended_generic),
                         gf,
                         SCM_SNAME (extension));
-      *SCM_SUBR_GENERIC (extension) = gext;
+      SCM_SET_SUBR_GENERIC (extension, gext);
     }
   else
     {
@@ -2113,7 +2143,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;
     }
@@ -2170,8 +2200,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
@@ -2199,6 +2234,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");
@@ -2262,9 +2300,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
        {
@@ -2404,10 +2460,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));
@@ -2616,7 +2676,7 @@ 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;
 }
@@ -2672,8 +2732,7 @@ create_smob_classes (void)
 {
   long i;
 
-  scm_smob_class = (SCM *) scm_malloc (255 * sizeof (SCM));
-  for (i = 0; i < 255; ++i)
+  for (i = 0; i < SCM_I_MAX_SMOB_TYPE_COUNT; ++i)
     scm_smob_class[i] = 0;
 
   scm_smob_class[SCM_TC2SMOBNUM (scm_tc16_keyword)] = scm_class_keyword;
@@ -2717,10 +2776,6 @@ create_port_classes (void)
 {
   long i;
 
-  scm_port_class = (SCM *) scm_malloc (3 * 256 * sizeof (SCM));
-  for (i = 0; i < 3 * 256; ++i)
-    scm_port_class[i] = 0;
-
   for (i = 0; i < scm_numptob; ++i)
     scm_make_port_classes (i, SCM_PTOBNAME (i));
 }
@@ -2870,7 +2925,8 @@ scm_add_slot (SCM class, char *slot_name, SCM slot_class,
                                              scm_list_1 (slot))));
       {
        SCM n = SCM_SLOT (class, scm_si_nfields);
-       SCM gns = scm_list_n (name, SCM_BOOL_F, get, set, n, scm_from_int (1));
+       SCM gns = scm_list_n (name, SCM_BOOL_F, get, set, n, scm_from_int (1),
+                             SCM_UNDEFINED);
        SCM_SET_SLOT (class, scm_si_getters_n_setters,
                      scm_append_x (scm_list_2 (SCM_SLOT (class, scm_si_getters_n_setters),
                                                scm_list_1 (gns))));
@@ -2953,8 +3009,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;
 }
@@ -2966,12 +3037,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)));
@@ -2982,7 +3051,7 @@ scm_init_goops_builtins (void)
 
   list_of_no_method = scm_permanent_object (scm_list_1 (sym_no_method));
 
-  hell = scm_malloc (hell_size);
+  hell = scm_calloc (hell_size * sizeof (*hell));
   hell_mutex = scm_permanent_object (scm_make_mutex ());
 
   create_basic_classes ();