[m-rev.] for review: type class constraint info in du functor descriptors

Fergus Henderson fjh at cs.mu.OZ.AU
Thu Feb 5 13:41:37 AEDT 2004


On 27-Jan-2004, Zoltan Somogyi <zs at cs.mu.OZ.AU> wrote:
> Index: compiler/mlds_to_gcc.m
...
> +:- pred build_tc_constr_type(gcc__type::out, io__state::di, io__state::uo)
> +	is det.
> +
> +build_tc_constr_type(MR_TypeClassConstraint) -->
> +	build_tc_constr_struct_type(5, MR_TypeClassConstraint5Struct),
> +	gcc__build_pointer_type(MR_TypeClassConstraint5Struct,
> +		MR_TypeClassConstraint).

There should be at least a comment here explaining where the magic number 5
comes from.

After staring at this code here and the code in mercury_type_info.h
for a while, I figured out that this code must be corresponding to the C code

  MR_DEFINE_TYPECLASS_CONSTRAINT_STRUCT(MR_TypeClassConstraint_5, 5);

  typedef MR_TypeClassConstraint_5Struct          MR_TypeClassConstraintStruct;
  typedef const MR_TypeClassConstraintStruct      *MR_TypeClassConstraint;

in mercury_type_info.h.  Could you please add this C code as a comment here,
as is done for the other types defined in mlds_to_gcc.m, so that the
correspondence is clearer?

> Index: compiler/rtti.m
> @@ -1345,6 +1384,9 @@
> +rtti__pred_or_func_to_string(predicate, "MR_PREDICATE").
> +rtti__pred_or_func_to_string(function,  "MR_FUNCTION").
> +
>  rtti__sectag_locn_to_string(sectag_none,   "MR_SECTAG_NONE").
>  rtti__sectag_locn_to_string(sectag_local,  "MR_SECTAG_LOCAL").
>  rtti__sectag_locn_to_string(sectag_remote, "MR_SECTAG_REMOTE").

This change (together with the changes to rtti_to_mlds.m to generate
these) requires appropriate support in the Java back-end, in particular
defining a PredFunc class in java/runtime/PredFunc.java analagous to
the way Sectag_Locn is defined in java/runtime/Sectag_Locn.java.

> +++ compiler/rtti_out.m	22 Jan 2004 23:33:16 -0000
> @@ -271,7 +271,7 @@
>  
>  output_type_class_instance_defn(Instance, !DeclSet, !IO) :-
>  	Instance = tc_instance(TCName, TCTypes, NumTypeVars, Constraints,
> -		MethodProcLabels),
> +		_MethodProcLabels),
>  	list__foldl2(output_maybe_pseudo_type_info_defn, TCTypes,
>  		!DeclSet, !IO),
>  	TCTypeRttiDatas = list__map(maybe_pseudo_type_info_to_rtti_data,
> @@ -301,21 +301,21 @@
>  			ConstraintIds, !IO),
>  		io__write_string("};\n", !IO)
>  	),
> -	TCInstanceMethodsRttiId = tc_rtti_id(
> -		type_class_instance_methods(TCName, TCTypes)),
> -	(
> -		MethodProcLabels = []
> -	;
> -		MethodProcLabels = [_ | _],
> -		MethodCodeAddrs = list__map(make_code_addr, MethodProcLabels),
> -		list__foldl2(output_code_addr_decls, MethodCodeAddrs,
> -			!DeclSet, !IO),
> -		output_generic_rtti_data_defn_start(TCInstanceMethodsRttiId,
> -			!DeclSet, !IO),
> -		io__write_string(" = {\n", !IO),
> -		list__foldl(output_code_addr_in_list, MethodCodeAddrs, !IO),
> -		io__write_string("};\n", !IO)
> -	),
> +%	TCInstanceMethodsRttiId = tc_rtti_id(
> +%		type_class_instance_methods(TCName, TCTypes)),
> +%	(
> +%		MethodProcLabels = []
> +%	;
> +%		MethodProcLabels = [_ | _],
> +%		MethodCodeAddrs = list__map(make_code_addr, MethodProcLabels),
> +%		list__foldl2(output_code_addr_decls, MethodCodeAddrs,
> +%			!DeclSet, !IO),
> +%		output_generic_rtti_data_defn_start(TCInstanceMethodsRttiId,
> +%			!DeclSet, !IO),
> +%		io__write_string(" = {\n", !IO),
> +%		list__foldl(output_code_addr_in_list, MethodCodeAddrs, !IO),
> +%		io__write_string("};\n", !IO)
> +%	),

There should be a comment here (not just in the CVS log message)
explaining why this code is commented out.

>  	TCDeclRttiId = tc_rtti_id(type_class_decl(TCName)),
>  	output_rtti_id_decls(TCDeclRttiId, "", "", 0, _, !DeclSet, !IO),
>  	TCInstanceRttiId = tc_rtti_id(type_class_instance(TCName, TCTypes)),
> @@ -336,15 +336,15 @@
>  		Constraints = [_ | _],
>  		output_rtti_id(TCInstanceConstraintsRttiId, !IO)
>  	),
> -	io__write_string(",\n\t", !IO),
> -	(
> -		MethodProcLabels = [],
> -		io__write_string("NULL", !IO)
> -	;
> -		MethodProcLabels = [_ | _],
> -		io__write_string("&", !IO),
> -		output_rtti_id(TCInstanceMethodsRttiId, !IO)
> -	),
> +%	io__write_string(",\n\t", !IO),
> +%	(
> +%		MethodProcLabels = [],
> +%		io__write_string("NULL", !IO)
> +%	;
> +%		MethodProcLabels = [_ | _],
> +%		io__write_string("&", !IO),
> +%		output_rtti_id(TCInstanceMethodsRttiId, !IO)
> +%	),

Likewise.

> Index: compiler/rtti_to_mlds.m
...
> +gen_type_class_decl_defn(TCDecl, RttiId, ModuleInfo, Init, SubDefns) :-
...
> +	(
> +		Supers = [],
> +		SuperDefns = [],
> +		SupersInit = gen_init_null_pointer(
> +			mlds__rtti_type(item_type(MethodIdsRttiId)))
> +	;
> +		Supers = [_ | _],
> +		list__map_foldl2(gen_tc_constraint(ModuleInfo,
> +			make_decl_super_id(TCName)), Supers, SuperRttiIds,
> +			counter__init(1), _, [], SuperConstrDefns),
> +		SuperArrayRttiId = tc_rtti_id(SuperArrayRttiName),
> +		ElementType = mlds__rtti_type(element_type(SuperArrayRttiId)),
> +		SuperArrayInit = gen_init_array(
> +			gen_init_cast_rtti_id(ElementType, ModuleName),
> +			SuperRttiIds),
> +		SuperArrayRttiName = type_class_decl_supers(TCName),
> +		rtti_id_and_init_to_defn(SuperArrayRttiId, SuperArrayInit,
> +			SuperDefn),
> +		list__append(SuperConstrDefns, [SuperDefn], SuperDefns),
> +		SupersInit = gen_init_null_pointer(
> +			mlds__rtti_type(item_type(MethodIdsRttiId)))
> +	),

The definition of "SupersInit" appears to be the same in both cases,
so it would be simpler to move that to after this switch on "Supers".

But I don't understand -- why is SupersInit always a null pointer?

> +gen_tc_constraint(ModuleInfo, MakeRttiId, Constraint, RttiId, !Counter,
> +		!Defns) :-
> +	Constraint = tc_constraint(TCName, Types),
> +	list__length(Types, Arity),
> +	counter__allocate(TCNum, !Counter),
> +	MakeRttiId(TCNum, Arity, RttiId),
> +	TCDeclRttiName = type_class_decl(TCName),
> +	module_info_name(ModuleInfo, ModuleName),
> +	TypeRttiDatas = list__map(maybe_pseudo_type_info_to_rtti_data, Types),
> +	gen_pseudo_type_info_array(ModuleInfo, TypeRttiDatas, PTIInits,
> +		PTIDefns),
> + 	Init = init_struct(mlds__rtti_type(item_type(RttiId)), [
> +		gen_init_tc_rtti_name(ModuleName, TCDeclRttiName),
> +		PTIInits
> + 	]),
> +	rtti_id_and_init_to_defn(RttiId, Init, ConstrDefn),
> +	list__append(PTIDefns, [ConstrDefn], NewDefns),
> +	list__append(!.Defns, NewDefns, !:Defns).

The last two lines would IMHO be better written as

	!:Defns = !.Defns ++ PTIDefns ++ [ConstrDefn].

Using infix ++ rather than a sequence of list__append operations makes
it easier to see the order in which the different parts will get placed,
avoiding bugs like the one in polymorphism.m that James Goddard recently
fixed.

> Index: runtime/mercury_type_info.h
...
> @@ -702,6 +686,44 @@
>  /*---------------------------------------------------------------------------*/
>  
>  /*
> +** A typeclass constraint asserts the membership of a possibly nonground
> +** vector of types in a type class, as one may find constraining a typeclass
> +** declaration, an instance declaration, or a predicate/function declaration.
> +**
> +** Type class constraints for type classes with arity N will be of type
> +** MR_TypeClassConstraint_N. Generic code will manipulate them as if they were
> +** of type MR_TypeClassConstraint, getting the actual number of arguments from
> +** MR_tc_constr_type_class_info->MR_tc_decl_id->MR_tc_id_arity.
> +**
> +** Note that the arity cannot be zero, so we do not have to worry about
> +** zero-size arrays. On the other hand, type classes with more than even two
> +** arguments can be expected to be very rare, so having five as a fixed limit
> +** should not be a problem. If it is, we can lift the limit by defining
> +** MR_TypeClassConstraint_N on demand for all N > 5.
> +**
> +** We will have to rethink this structure once we start supporting constructor
> +** classes.
> +*/
> +
> +#define MR_DEFINE_TYPECLASS_CONSTRAINT_STRUCT(NAME, ARITY)                  \
> +    typedef struct MR_PASTE2(NAME, _Struct) {                               \
> +        MR_TypeClassDecl    MR_tc_constr_type_class;                        \
> +        MR_PseudoTypeInfo   MR_tc_constr_arg_ptis[ARITY];                   \
> +    } MR_PASTE2(NAME, Struct)
> +
> +MR_DEFINE_TYPECLASS_CONSTRAINT_STRUCT(MR_TypeClassConstraint_1, 1);
> +MR_DEFINE_TYPECLASS_CONSTRAINT_STRUCT(MR_TypeClassConstraint_2, 2);
> +MR_DEFINE_TYPECLASS_CONSTRAINT_STRUCT(MR_TypeClassConstraint_3, 3);
> +MR_DEFINE_TYPECLASS_CONSTRAINT_STRUCT(MR_TypeClassConstraint_4, 4);
> +MR_DEFINE_TYPECLASS_CONSTRAINT_STRUCT(MR_TypeClassConstraint_5, 5);
> +
> +typedef MR_TypeClassConstraint_5Struct          MR_TypeClassConstraintStruct;

Shouldn't the definition of the generic version use MR_VARIABLE_SIZED?
i.e.

	MR_DEFINE_TYPECLASS_CONSTRAINT_STRUCT(MR_TypeClassConstraint, 
		MR_VARIABLE_SIZED);


Otherwise that all looks fine.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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