* arbiters.c, async.c, regex-posix.c: Use new smob interface.
[bpt/guile.git] / libguile / objects.c
index cbf4467..235aaab 100644 (file)
@@ -49,6 +49,9 @@
 
 #include "struct.h"
 #include "procprop.h"
+#include "chars.h"
+#include "keywords.h"
+#include "smob.h"
 
 #include "objects.h"
 \f
 SCM scm_metaclass_standard;
 SCM scm_metaclass_operator;
 
+/* 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;
+SCM scm_class_procedure_with_setter;
+SCM scm_class_vector, scm_class_null;
+SCM scm_class_integer, scm_class_real, scm_class_complex;
+SCM scm_class_unknown;
+
+SCM *scm_smob_class = 0;
+
+SCM (*scm_make_extended_class) (char *type_name);
+void (*scm_change_object_class) (SCM, SCM, SCM);
+
+/* This function is used for efficient type dispatch.  */
+SCM
+scm_class_of (SCM x)
+{
+  switch (SCM_ITAG3 (x))
+    {
+    case scm_tc3_int_1:
+    case scm_tc3_int_2:
+      return scm_class_integer;
+
+    case scm_tc3_imm24:
+      if (SCM_ICHRP (x))
+       return scm_class_char;
+      else
+       {
+         switch (SCM_ISYMNUM (x))
+           {
+           case SCM_ISYMNUM (SCM_BOOL_F):
+           case SCM_ISYMNUM (SCM_BOOL_T):
+             return scm_class_boolean;
+           case SCM_ISYMNUM (SCM_EOL):
+             return scm_class_null;
+           default:
+             return scm_class_unknown;
+           }
+       }
+
+    case scm_tc3_cons:
+      switch (SCM_TYP7 (x))
+       {
+       case scm_tcs_cons_nimcar:
+         return scm_class_pair;
+       case scm_tcs_closures:
+         return scm_class_procedure;
+       case scm_tcs_symbols:
+         return scm_class_symbol;
+       case scm_tc7_vector:
+       case scm_tc7_wvect:
+       case scm_tc7_bvect:
+       case scm_tc7_byvect:
+       case scm_tc7_svect:
+       case scm_tc7_ivect:
+       case scm_tc7_uvect:
+       case scm_tc7_fvect:
+       case scm_tc7_dvect:
+       case scm_tc7_cvect:
+         return scm_class_vector;
+       case scm_tc7_string:
+       case scm_tc7_substring:
+         return scm_class_string;
+       case scm_tc7_asubr:
+       case scm_tc7_subr_0:
+       case scm_tc7_subr_1:
+       case scm_tc7_cxr:
+       case scm_tc7_subr_3:
+       case scm_tc7_subr_2:
+       case scm_tc7_rpsubr:
+       case scm_tc7_subr_1o:
+       case scm_tc7_subr_2o:
+       case scm_tc7_lsubr_2:
+       case scm_tc7_lsubr:
+       case scm_tc7_cclo:
+         return scm_class_procedure;
+       case scm_tc7_pws:
+         return scm_class_procedure_with_setter;
+
+       case scm_tc7_port:
+         return scm_class_unknown;
+       case scm_tc7_smob:
+         {
+           SCM type = SCM_TYP16 (x);
+           if (type == scm_tc16_flo)
+             {
+               if (SCM_CAR (x) & SCM_IMAG_PART)
+                 return scm_class_complex;
+               else
+                 return scm_class_real;
+             }
+           else
+             return scm_smob_class[SCM_TC2SMOBNUM (type)];
+         }
+       case scm_tcs_cons_gloc:
+         /* must be a struct */
+         if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS)
+           {
+             /* Goops object */
+             if (SCM_OBJ_CLASS_REDEF (x) != SCM_BOOL_F)
+               scm_change_object_class (x,
+                                        SCM_CLASS_OF (x),         /* old */
+                                        SCM_OBJ_CLASS_REDEF (x)); /* new */
+             return SCM_CLASS_OF (x);
+           }
+         else
+           {
+             /* ordinary struct */
+             SCM handle = scm_struct_create_handle (SCM_STRUCT_VTABLE (x));
+             if (SCM_NFALSEP (SCM_STRUCT_TABLE_CLASS (SCM_CDR (handle))))
+               return SCM_STRUCT_TABLE_CLASS (SCM_CDR (handle));
+             else
+               {
+                 SCM name = SCM_STRUCT_TABLE_NAME (SCM_CDR (handle));
+                 SCM class = scm_make_extended_class (SCM_NFALSEP (name)
+                                                      ? SCM_ROCHARS (name)
+                                                      : 0);
+                 SCM_SET_STRUCT_TABLE_CLASS (handle, class);
+                 return class;
+               }
+           }
+       default:
+         if (SCM_CONSP (x))
+           return scm_class_pair;
+         else
+           return scm_class_unknown;
+       }
+
+    case scm_tc3_cons_gloc:
+    case scm_tc3_tc7_1:
+    case scm_tc3_tc7_2:
+    case scm_tc3_closure:
+      /* Never reached */
+      break;
+    }
+  return scm_class_unknown;
+}
+
+SCM_PROC (s_entity_p, "entity?", 1, 0, 0, scm_entity_p);
+
+SCM
+scm_entity_p (SCM obj)
+{
+  return (SCM_NIMP (obj) && SCM_STRUCTP (obj) && SCM_I_ENTITYP (obj)
+         ? SCM_BOOL_T
+         : SCM_BOOL_F);
+}
+
 SCM_PROC (s_set_object_procedure_x, "set-object-procedure!", 1, 0, 1, scm_set_object_procedure_x);
 
 SCM
@@ -150,20 +301,18 @@ scm_set_object_procedure_x (SCM obj, SCM procs)
   return SCM_UNSPECIFIED;
 }
 
-static SCM
-make_class_object (SCM meta,
-                  SCM pl,
-                  SCM layout,
-                  unsigned long flags,
-                  char* subr)
+/* The following procedures are not a part of Goops but a minimal
+ * object system built upon structs.  They are here for those who
+ * want to implement their own object system.
+ */
+
+SCM
+scm_i_make_class_object (SCM meta,
+                        SCM layout_string,
+                        unsigned long flags)
 {
   SCM c;
-  SCM_ASSERT (SCM_NIMP (meta) && SCM_STRUCTP (meta), meta, SCM_ARG1, subr);
-  SCM_ASSERT (SCM_NIMP (layout) && SCM_STRINGP (layout),
-             layout,
-             SCM_ARG2,
-             subr);
-  layout = scm_make_struct_layout (scm_string_append (SCM_LIST2 (pl, layout)));
+  SCM layout = scm_make_struct_layout (layout_string);
   c = scm_make_struct (meta,
                       SCM_INUM0,
                       SCM_LIST4 (layout, SCM_BOOL_F, SCM_EOL, SCM_EOL));
@@ -177,13 +326,13 @@ SCM
 scm_make_class_object (SCM metaclass, SCM layout)
 {
   unsigned long flags = 0;
+  SCM_ASSERT (SCM_NIMP (metaclass) && SCM_STRUCTP (metaclass),
+             metaclass, SCM_ARG1, s_make_class_object);
+  SCM_ASSERT (SCM_NIMP (layout) && SCM_STRINGP (layout),
+             layout, SCM_ARG2, s_make_class_object);
   if (metaclass == scm_metaclass_operator)
     flags = SCM_CLASSF_OPERATOR;
-  return make_class_object (metaclass,
-                           scm_nullstr,
-                           layout,
-                           flags,
-                           s_make_class_object);
+  return scm_i_make_class_object (metaclass, layout, flags);
 }
 
 SCM_PROC (s_make_subclass_object, "make-subclass-object", 2, 0, 0, scm_make_subclass_object);
@@ -196,13 +345,16 @@ scm_make_subclass_object (SCM class, SCM layout)
              class,
              SCM_ARG1,
              s_make_subclass_object);
+  SCM_ASSERT (SCM_NIMP (layout) && SCM_STRINGP (layout),
+             layout,
+             SCM_ARG2,
+             s_make_subclass_object);
   pl = SCM_STRUCT_DATA (class)[scm_vtable_index_layout];
+  /* Convert symbol->string */
   pl = scm_makfromstr (SCM_CHARS (pl), (scm_sizet) SCM_LENGTH (pl), 0);
-  return make_class_object (scm_metaclass_standard,
-                           pl,
-                           layout,
-                           SCM_CLASS_FLAGS (class),
-                           s_make_subclass_object);
+  return scm_i_make_class_object (SCM_STRUCT_VTABLE (class),
+                                 scm_string_append (SCM_LIST2 (pl, layout)),
+                                 SCM_CLASS_FLAGS (class));
 }
 
 void
@@ -223,12 +375,12 @@ scm_init_objects ()
   SCM et = scm_make_struct (mt, SCM_INUM0,
                            SCM_LIST4 (el, SCM_BOOL_F, SCM_EOL, SCM_EOL));
 
-  scm_sysintern ("<standard-metaclass>", mt);
+  scm_sysintern ("<class>", mt);
   scm_metaclass_standard = mt;
-  scm_sysintern ("<operator-metaclass>", ot);
+  scm_sysintern ("<operator-class>", ot);
   scm_metaclass_operator = ot;
   SCM_SET_CLASS_FLAGS (et, SCM_CLASSF_OPERATOR | SCM_CLASSF_ENTITY);
-  scm_sysintern ("<entity-class>", et);
+  scm_sysintern ("<entity>", et);
 
 #include "objects.x"
 }