[m-dev.] for review: use MR_CHECK_EXPR_TYPE() macro
Fergus Henderson
fjh at cs.mu.OZ.AU
Mon Mar 27 04:06:52 AEST 2000
Another place where the MR_CHECK_EXPR_TYPE() macro
might be useful is in the various macros that we
use for the trailing interface. But that can be
a separate change...
----------
Estimated hours taken: 1
Improve the static type checking and readability of
some of the macros that we define, by using a new
MR_CHECK_EXPR_TYPE() macro.
runtime/mercury_std.h:
Define the MR_CHECK_EXPR_TYPE() macro.
runtime/mercury_type_info.h:
library/std_util.m:
Make use of it.
library/std_util.m:
Add a few comments, and reorder some macro definitions
do improve readability. Delete an incorrect XXX comment.
runtime/mercury_make_type_info_body.h:
Add a type cast, where we were using an MR_TypeInfo
as an MR_PseudoTypeInfo.
Workspace: /home/mercury0/fjh/mercury
Index: library/std_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/std_util.m,v
retrieving revision 1.186
diff -u -d -r1.186 std_util.m
--- library/std_util.m 2000/03/26 07:22:27 1.186
+++ library/std_util.m 2000/03/26 17:07:27
@@ -1212,6 +1212,7 @@
** values of type `private_builtin:type_info' (this representation is
** documented in compiler/polymorphism.m). Some parts of the library
** (e.g. the gc initialization code) depend on this.
+** The C type corresponding to these Mercury types is `MR_TypeInfo'.
**
** Values of type `std_util:type_ctor_desc' are not guaranteed to be
** represented the same way as values of type `private_builtin:type_ctor_info'.
@@ -1220,58 +1221,80 @@
** containing a pointer to the type_ctor_info for pred/0 or func/0 and an
** arity, we have a single small encoded integer. This integer is double
** the arity, plus zero or one; plus zero encodes a predicate, plus one encodes
-** a function.
-**
-** The maximum arity that can be encoded should be set to twice the maximum
-** number of general purpose registers, since an predicate or function having
-** more arguments that this would run out of registers when passing the input
-** arguments, or the output arguments, or both.
-**
-** XXX This scheme does not properly handle the type_desc for the type
-** private_builtin:type_info, since that type also has a variable arity
-** (and because the current implementation lies about the arity).
+** a function. The maximum arity that can be encoded is given by
+** MR_MAX_HO_ARITY (see below).
+** The C type corresponding to std_util:type_ctor_desc is `MR_TypeCtorInfo'.
+*/
+
+/*
+** Declare the MR_TypeCtorDesc ADT.
**
-** Note that MR_TypeCtorDesc is declared as a pointer to a dummy structure
-** only in order to allow the C compiler to catch errors in which things other
+** Note that `struct MR_TypeCtorDesc_Struct' is deliberately left undefined.
+** MR_TypeCtorDesc is declared as a pointer to a dummy structure only
+** in order to allow the C compiler to catch errors in which things other
** than MR_TypeCtorDescs are given as arguments to macros that depend on their
** arguments being MR_TypeCtorDescs. The actual value is either a small integer
** or a pointer to a MR_TypeCtorInfo_Struct structure, as described above.
*/
-
-typedef struct {
- Unsigned type_ctor_desc_dummy_field;
-} *MR_TypeCtorDesc;
+typedef struct MR_TypeCtorDesc_Struct *MR_TypeCtorDesc;
+/*
+** The maximum arity that can be encoded should be set to twice the maximum
+** number of general purpose registers, since an predicate or function having
+** more arguments that this would run out of registers when passing the input
+** arguments, or the output arguments, or both.
+*/
#define MR_MAX_HO_ARITY (2 * MAX_VIRTUAL_REG)
-
-#define MR_TYPECTOR_DESC_UNSIGNED(T) \
- ( (Unsigned) &(T)->type_ctor_desc_dummy_field )
-#define MR_TYPECTOR_DESC_GET_FIRST_ORDER_TYPE_CTOR_INFO(T) \
- ( (MR_TypeCtorInfo) &(T)->type_ctor_desc_dummy_field )
-#define MR_TYPECTOR_DESC_IS_HIGHER_ORDER(T) \
- ( MR_TYPECTOR_DESC_UNSIGNED(T) <= (2 * MR_MAX_HO_ARITY + 1) )
+/*
+** Constructors for the MR_TypeCtorDesc ADT
+*/
#define MR_TYPECTOR_DESC_MAKE_PRED(Arity) \
( (MR_TypeCtorDesc) ((Arity) * 2) )
#define MR_TYPECTOR_DESC_MAKE_FUNC(Arity) \
( (MR_TypeCtorDesc) ((Arity) * 2 + 1) )
#define MR_TYPECTOR_DESC_MAKE_FIRST_ORDER(type_ctor_info) \
- ( (MR_TypeCtorDesc) &type_ctor_info->arity )
+ ( MR_CHECK_EXPR_TYPE(type_ctor_info, MR_TypeCtorInfo), \
+ (MR_TypeCtorDesc) type_ctor_info )
+
+/*
+** Access macros for the MR_TypeCtor ADT.
+**
+** The MR_TYPECTOR_DESC_GET_HOT_* macros should only be called if
+** MR_TYPECTOR_DESC_IS_HIGHER_ORDER() returns true.
+** The MR_TYPECTOR_DESC_GET_FIRST_ORDER_TYPE_CTOR_INFO() macro
+** should only be called if MR_TYPECTOR_DESC_IS_HIGHER_ORDER() returns false.
+*/
+#define MR_TYPECTOR_DESC_IS_HIGHER_ORDER(T) \
+ ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc), \
+ (Unsigned) (T) <= (2 * MR_MAX_HO_ARITY + 1) )
+#define MR_TYPECTOR_DESC_GET_FIRST_ORDER_TYPE_CTOR_INFO(T) \
+ ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc), \
+ (MR_TypeCtorInfo) (T) )
#define MR_TYPECTOR_DESC_GET_HOT_ARITY(T) \
- ( MR_TYPECTOR_DESC_UNSIGNED(T) / 2 )
+ ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc), \
+ (Unsigned) (T) / 2 )
#define MR_TYPECTOR_DESC_GET_HOT_NAME(T) \
- ((ConstString) ((MR_TYPECTOR_DESC_UNSIGNED(T) % 2 != 0) \
+ ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc), \
+ (ConstString) (((Unsigned) (T) % 2 != 0) \
? ""func"" \
: ""pred"" ))
#define MR_TYPECTOR_DESC_GET_HOT_MODULE_NAME(T) \
- ((ConstString) ""builtin"")
+ ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc), \
+ (ConstString) ""builtin"" )
#define MR_TYPECTOR_DESC_GET_HOT_TYPE_CTOR_INFO(T) \
- ((MR_TYPECTOR_DESC_UNSIGNED(T) % 2 != 0) \
- ? (MR_TypeCtorInfo) (Word) \
+ ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc), \
+ ((Unsigned) (T) % 2 != 0) \
+ ? (MR_TypeCtorInfo) \
&mercury_data___type_ctor_info_func_0 \
- : (MR_TypeCtorInfo) (Word) \
+ : (MR_TypeCtorInfo) \
&mercury_data___type_ctor_info_pred_0 )
+%-----------------------------------------------------------------------------%
+
+/*
+** Macros dealing with the MR_TypeCtorInfo type.
+*/
#define MR_TYPE_CTOR_INFO_HO_PRED \
((MR_TypeCtorInfo) &mercury_data___type_ctor_info_pred_0)
#define MR_TYPE_CTOR_INFO_HO_FUNC \
@@ -1287,6 +1310,8 @@
").
+%-----------------------------------------------------------------------------%
+
:- pragma c_header_code("
/* The `#ifndef ... #define ... #endif' guards against multiple inclusion */
@@ -1330,7 +1355,7 @@
").
% A type_ctor_desc is really just a subtype of type_desc,
- % but we should hide this from users as it is an implementation
+ % but we hide this from users, since it is an implementation
% detail.
:- type type_ctor_desc == type_desc.
Index: runtime/mercury_make_type_info_body.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_make_type_info_body.h,v
retrieving revision 1.1
diff -u -d -r1.1 mercury_make_type_info_body.h
--- runtime/mercury_make_type_info_body.h 2000/03/24 10:27:49 1.1
+++ runtime/mercury_make_type_info_body.h 2000/03/26 17:56:06
@@ -44,7 +44,9 @@
expanded_type_info = MR_get_arg_type_info(type_info_params,
pseudo_type_info, data_value, functor_desc);
- if (MR_PSEUDO_TYPEINFO_IS_VARIABLE(expanded_type_info)) {
+ if (MR_PSEUDO_TYPEINFO_IS_VARIABLE(
+ (MR_PseudoTypeInfo) expanded_type_info))
+ {
fatal_error(exist_func_string
": unbound type variable");
}
@@ -84,7 +86,9 @@
data_value, functor_desc
MAYBE_PASS_ALLOC_ARG);
- if (MR_PSEUDO_TYPEINFO_IS_VARIABLE(expanded_type_info)) {
+ if (MR_PSEUDO_TYPEINFO_IS_VARIABLE(
+ (MR_PseudoTypeInfo) expanded_type_info))
+ {
fatal_error(exist_func_string
": unbound type variable");
}
Index: runtime/mercury_std.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_std.h,v
retrieving revision 1.10
diff -u -d -r1.10 mercury_std.h
--- runtime/mercury_std.h 2000/03/10 13:38:12 1.10
+++ runtime/mercury_std.h 2000/03/26 16:09:25
@@ -123,6 +123,26 @@
#define MR_PASTE7(a,b,c,d,e,f,g) MR_PASTE7_2(a,b,c,d,e,f,g)
#define MR_PASTE7_2(a,b,c,d,e,f,g) a##b##c##d##e##f##g
+/*
+** MR_CHECK_EXPR_TYPE(expr, type):
+** This macro checks that the given expression has a type
+** which is compatible with (assignable to) the specified type,
+** forcing a compile error if it does not.
+** It does not evaluate the expression.
+** Note that the specified type must be a complete type,
+** i.e. it must not be a pointer to a struct which has
+** not been defined.
+**
+** This macro is useful for defining type-safe function-like macros.
+**
+** The implementation of this macro looks like it dereferences
+** a null pointer, but because that code is inside sizeof(), it will
+** not get executed; the compiler will instead just check that it is
+** type-correct.
+*/
+#define MR_CHECK_EXPR_TYPE(expr, type) \
+ ((void) sizeof(*(type *)NULL = (expr)))
+
/*---------------------------------------------------------------------------*/
#endif /* not MERCURY_STD_H */
Index: runtime/mercury_type_info.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_type_info.h,v
retrieving revision 1.42
diff -u -d -r1.42 mercury_type_info.h
--- runtime/mercury_type_info.h 2000/03/26 15:57:35 1.42
+++ runtime/mercury_type_info.h 2000/03/26 17:52:49
@@ -147,26 +147,41 @@
** A MR_TypeInfoParams array serves this purpose. Because type variables
** start at one, MR_TypeInfoParams arrays also start at one.
*/
-
typedef MR_TypeInfo *MR_TypeInfoParams;
#define MR_PSEUDOTYPEINFO_EXIST_VAR_BASE 512
#define MR_PSEUDOTYPEINFO_MAX_VAR 1024
+/*
+** Macros for accessing pseudo_type_infos.
+**
+** The MR_TYPE_VARIABLE_* macros should only be called if
+** MR_PSEUDO_TYPEINFO_IS_VARIABLE() returns TRUE.
+*/
+
#define MR_PSEUDO_TYPEINFO_IS_VARIABLE(T) \
- ( (Unsigned) T <= MR_PSEUDOTYPEINFO_MAX_VAR )
+ ( MR_CHECK_EXPR_TYPE((T), MR_PseudoTypeInfo), \
+ (Unsigned) (T) <= MR_PSEUDOTYPEINFO_MAX_VAR )
#define MR_TYPE_VARIABLE_IS_EXIST_QUANT(T) \
- ( (Word) (T) > MR_PSEUDOTYPEINFO_EXIST_VAR_BASE )
+ ( MR_CHECK_EXPR_TYPE((T), MR_PseudoTypeInfo), \
+ (Word) (T) > MR_PSEUDOTYPEINFO_EXIST_VAR_BASE )
#define MR_TYPE_VARIABLE_IS_UNIV_QUANT(T) \
- ( (Word) (T) <= MR_PSEUDOTYPEINFO_EXIST_VAR_BASE )
+ ( MR_CHECK_EXPR_TYPE((T), MR_PseudoTypeInfo), \
+ (Word) (T) <= MR_PSEUDOTYPEINFO_EXIST_VAR_BASE )
+/*
+** This macro converts a pseudo_type_info to a type_info.
+** It should only be called if the pseudo_type_info is ground,
+** i.e. contains no type variables.
+*/
#define MR_pseudo_type_info_is_ground(pseudo_type_info) \
- ((MR_TypeInfo) &pseudo_type_info->MR_pti_type_ctor_info)
+ ( MR_CHECK_EXPR_TYPE((pseudo_type_info), MR_PseudoTypeInfo), \
+ (MR_TypeInfo) (pseudo_type_info) ) \
- /*
- ** Macros for retrieving things from type_infos and pseudo_type_infos.
- */
+/*
+** Macros for retrieving things from type_infos and pseudo_type_infos.
+*/
#define MR_TYPEINFO_GET_TYPE_CTOR_INFO(type_info) \
(((type_info)->MR_ti_type_ctor_info != NULL) \
@@ -191,9 +206,9 @@
#define MR_TYPEINFO_GET_FIRST_ORDER_ARG_VECTOR(type_info) \
((MR_TypeInfoParams) &(type_info)->MR_ti_type_ctor_info)
- /*
- ** Macros for creating type_infos.
- */
+/*
+** Macros for creating type_infos.
+*/
#define MR_first_order_type_info_size(arity) \
(1 + (arity))
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to: mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions: mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------
More information about the developers
mailing list