[m-rev.] for review: debugging typeclass_infos

Zoltan Somogyi zs at cs.mu.OZ.AU
Wed Jan 21 13:47:45 AEDT 2004


On 21-Jan-2004, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> I'm not sure that this helps very much, because the names "typeclass_info"
> and "base_typeclass_info" are already quite misleading -- they really
> give information about a type class instance, not a type class.

Some of the information they give, e.g. the number of superclasses, comes from
the type class declaration, not the instance declaration.

> As a result, names like "MR_typeclass_info_param_type_info" are quite
> unclear -- is it the type_info for a parameter of the instance declaration,
> or a parameter of the type class?
> Likewise for "MR_typeclass_info_num_params".

I added documentation of what the macros do, and will soon do. The updated
diff for the relevant file is added below; the only changes are in the
comments.

Zoltan.

Index: mercury_type_info.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_type_info.h,v
retrieving revision 1.108
diff -u -b -r1.108 mercury_type_info.h
--- mercury_type_info.h	23 Oct 2003 02:02:31 -0000	1.108
+++ mercury_type_info.h	21 Jan 2004 02:26:33 -0000
@@ -408,44 +408,149 @@
 /*---------------------------------------------------------------------------*/
 
 /*
-** Definitions for accessing the representation of the
-** Mercury typeclass_info.
+** Definitions for accessing typeclass_infos and base_typeclass_infos.
+** Their structure is described type_class_transformation.html in
+** compiler/notes.
+*/
+
+/*
+** Extract the base_typeclass_info from a typeclass_info.
+*/
+
+#define MR_typeclass_info_base(tci)                                 \
+    (*(MR_Word **)(tci))
+
+/*
+** The following macros look up fields of the base_typeclass_info in the given
+** typeclass_info. These fields yield information about the instance
+** declaration from which the given typeclass_info is constructed, or about the
+** type class declaration itself.
+**
+** MR_typeclass_info_num_instance_type_vars gives the number of type variables
+** in the head of the instance declaration that aren't constrained by type
+** class constraints on the instance declaration. (Soon, this will change to
+** simply the number of type variables in the head of the instance
+** declaration.)
+**
+** MR_typeclass_info_num_instance_constraints gives the number of constraints
+** on the instance declaration.
+**
+** MR_typeclass_info_num_extra_instance_args gives the sum of
+** MR_typeclass_info_num_instance_type_vars and
+** MR_typeclass_info_num_instance_constraints.
+**
+** MR_typeclass_info_num_superclasses gives the number of typeclass constraints
+** on the typeclass declaration.
+**
+** MR_typeclass_info_num_params gives the number of parameters of the typeclass
+** declaration, which perforce is also the number of parameters of the instance
+** declaration; in other words, the arity of the type class.
 */
 
 #define MR_typeclass_info_num_extra_instance_args(tci)              \
-    ((MR_Integer)(*(MR_Word **)(tci))[0])
+    ((MR_Integer) MR_typeclass_info_base(tci)[0])
 #define MR_typeclass_info_num_instance_constraints(tci)             \
-    ((MR_Integer)(*(MR_Word **)(tci))[1])
+    ((MR_Integer) MR_typeclass_info_base(tci)[1])
 #define MR_typeclass_info_num_superclasses(tci)                     \
-    ((MR_Integer)(*(MR_Word **)(tci))[2])
-#define MR_typeclass_info_num_type_infos(tci)                       \
-    ((MR_Integer)(*(MR_Word **)(tci))[3])
+    ((MR_Integer) MR_typeclass_info_base(tci)[2])
+#define MR_typeclass_info_num_params(tci)                           \
+    ((MR_Integer) MR_typeclass_info_base(tci)[3])
 #define MR_typeclass_info_num_methods(tci)                          \
-    ((MR_Integer)(*(MR_Word **)(tci))[4])
+    ((MR_Integer) MR_typeclass_info_base(tci)[4])
 #define MR_typeclass_info_class_method(tci, n)                      \
-    ((MR_Code *)(*(MR_Word **)tci)[(n+4)])
+    ((MR_Code *) MR_typeclass_info_base(tci)[(n+4)])
+
+#define MR_typeclass_info_num_instance_type_vars(tci)               \
+    ( MR_typeclass_info_num_extra_instance_args(tci)                \
+    - MR_typeclass_info_num_instance_constraints(tci))
 
 /*
-** The following have the same definitions. This is because
-** the call to MR_typeclass_info_arg_typeclass_info must already
-** have the number of unconstrained type variables for the instance
-** added to it.
+** MR_typeclass_info_instance_tvar_type_info returns a typeinfo for
+** one of the type variables in the instance declaration that isn't constrained
+** by a type class constraints on the instance declaration. (Soon, this will
+** change, as above.)
+**
+** MR_typeclass_info_arg_typeclass_info returns a typeclass_info for one of the
+** constrains on the instance declaration.
+**
+** MR_typeclass_info_extra_instance_arg returns either what
+** MR_typeclass_info_instance_tvar_type_info or
+** MR_typeclass_info_arg_typeclass_info returns, depending on the value of n
+** supplied.
+**
+** Except for the sanity checks, the following macros have the same
+** definitions. This is because calls to MR_typeclass_info_arg_typeclass_info
+** must already have the number of (unconstrained) type variables in the head
+** of the instance declaration added to it.
 */
-#define MR_typeclass_info_arg_typeclass_info(tci, n)                \
+
+#ifdef  MR_CHECK_TYPECLASS_REFS
+  #define MR_typeclass_info_extra_instance_arg(tci, n)              \
+    ((0 < (n) && (n) <= MR_typeclass_info_num_extra_instance_args(tci)) \
+    ? (((MR_Word *)(tci))[(n)])                                     \
+    : MR_typeclass_ref_error((tci), (n),                            \
+        "MR_typeclass_info_extra_instance_arg"))
+  #define MR_typeclass_info_instance_tvar_type_info(tci, n)         \
+    ((0 < (n) && (n) <= MR_typeclass_info_num_instance_type_vars(tci)) \
+    ? (((MR_Word *)(tci))[(n)])                                     \
+    : MR_typeclass_ref_error((tci), (n),                            \
+        "MR_typeclass_info_instance_tvar_type_info"))
+  #define MR_typeclass_info_arg_typeclass_info(tci, n)              \
+    ((MR_typeclass_info_num_instance_type_vars(tci) < (n)           \
+      && (n) <= MR_typeclass_info_num_extra_instance_args(tci))     \
+    ? (((MR_Word *)(tci))[(n)])                                     \
+    : MR_typeclass_ref_error((tci), (n),                            \
+        "MR_typeclass_info_arg_typeclass_info"))
+#else
+  #define MR_typeclass_info_extra_instance_arg(tci, n)              \
     (((MR_Word *)(tci))[(n)])
-#define MR_typeclass_info_unconstrained_type_info(tci, n)           \
+  #define MR_typeclass_info_instance_tvar_type_info(tci, n)         \
     (((MR_Word *)(tci))[(n)])
+  #define MR_typeclass_info_arg_typeclass_info(tci, n)              \
+    (((MR_Word *)(tci))[(n)])
+#endif
 
 /*
-** The following have the same definitions. This is because
-** the call to MR_typeclass_info_type_info must already have the
-** number of superclass_infos for the class added to it.
+** MR_typeclass_info_superclass_info return a typeclass_info for one of the
+** constraints on the typeclass declaration, i.e. for one this class's
+** superclasses.
+**
+** MR_typeclass_info_param_type_info returns a typeinfo for one the types
+** to which the type class constraint applies, i.e. for one of the types bound
+** to the type variables in the head of the type class declaration.
+**
+** Except for the sanity checks, the following macros have the same
+** definitions. This is because calls to MR_typeclass_info_param_type_info
+** must already have the number of superclasses for the class added to it.
 */
 
-#define MR_typeclass_info_superclass_info(tci, n)                   \
+#ifdef  MR_CHECK_TYPECLASS_REFS
+  #define MR_typeclass_info_superclass_info(tci, n)                 \
+    ((0 < (n) && (n) <= MR_typeclass_info_num_superclasses(tci))    \
+    ? (((MR_Word *)(tci))[                                          \
+        MR_typeclass_info_num_extra_instance_args(tci) + (n)])      \
+    : MR_typeclass_ref_error((tci), (n), "MR_typeclass_info_superclass_info"))
+  #define MR_typeclass_info_param_type_info(tci, n)                 \
+    ((MR_typeclass_info_num_superclasses(tci) < (n)                 \
+      && ((n) - MR_typeclass_info_num_superclasses(tci))            \
+        <= MR_typeclass_info_num_params(tci))                       \
+    ? (((MR_Word *)(tci))[                                          \
+        MR_typeclass_info_num_extra_instance_args(tci) + (n)])      \
+    : MR_typeclass_ref_error((tci), (n), "MR_typeclass_info_param_type_info"))
+#else
+  #define MR_typeclass_info_superclass_info(tci, n)                 \
     (((MR_Word *)(tci))[MR_typeclass_info_num_extra_instance_args(tci) + (n)])
-#define MR_typeclass_info_type_info(tci, n)                         \
+  #define MR_typeclass_info_param_type_info(tci, n)                 \
     (((MR_Word *)(tci))[MR_typeclass_info_num_extra_instance_args(tci) + (n)])
+#endif
+
+/*
+** Report an attempt to access a typeclass_info with incorrect parameters,
+** and abort. MR_typeclass_ref_error doesn't return; the return value is there
+** only to appease the C typechecker.
+*/
+
+extern  MR_Word MR_typeclass_ref_error(MR_Word tci, int n, const char *msg);
 
 /*---------------------------------------------------------------------------*/
 
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list