[m-dev.] cvs diff: type_info code.
Fergus Henderson
fjh at cs.mu.oz.au
Fri Apr 18 18:57:28 AEST 1997
Tyson Richard DOWD, you wrote:
>
> Fergus, could you please review this?
Sure.
BTW, your code was generally very well-documented --- thanks.
General comment: I'm not very comfortable with all this unnamed type
stuff. If you can get at it using type_of/1, and do all this sort of
stuff with it, then I think perhaps it would be better to name it. The
name to use would be `void'; it should probably be declared and defined
in mercury_builtin.m.
I think it would also be a good idea to enable the code in typecheck.m
that reports errors for uninstantiated type variables, with the error
changed to a warning (e.g. "Warning: type defaults to `void'.").
It would probably also be a good idea to avoid the special representation
as null typeinfo pointers and instead just use an ordinary typeinfo.
But don't worry about all that before committing. I might have a go
at doing that stuff after you've committed it.
> +typedef struct mercury_construct_info {
> + int vector_type;
> + int arity;
> + Word *functors_vector;
> + Word *argument_vector;
> + Word primary_tag;
> + Word secondary_tag;
> + ConstString functor_name;
> +} construct_info;
I think the coding standard says typedefs should be MixedCase.
> +static int get_num_functors(Word type_info);
> +static Word copy_argument_typeinfos(int arity, Word type_info,
> + Word *arg_vector);
> +static bool get_functors_check_range(int functor_number, Word type_info,
> + construct_info *info);
> +static void copy_arguments_from_list_to_vector(int arity, Word arg_list,
> + Word term_vector);
> +static int typecheck_arguments(Word type_info, int arity,
> + Word arg_list, Word* arg_vector);
> +static int get_functor_info(Word type_info, int functor_number,
> + construct_info *info);
> +static Word collapse_equivalences(Word maybe_equiv_type_info);
> +").
These should not be static, because if things are compiled with
--split-c-files, or if the pragma C code fragments that call them
are cross-module-inlined, then it will break.
> +:- pragma c_code(type_of(Type::unused) = (TypeInfo::out),
> + will_not_call_mercury, "
> +{
> + /*
> + ** Type isn't used in this c_code, but the compiler
> + ** gives a warning if you don't mention it.
> + */
s/Type/`Type'/
Actually, now that I think about it for a moment, that variable name is
misleading: you should also s/Type/Value/
> + /*
> + ** Check range of FunctorNum, get info for this
> + ** functor.
> + */
> + save_transient_registers();
> + SUCCESS_INDICATOR = get_functors_check_range(FunctorNumber,
> + TypeInfo, &info);
> + restore_transient_registers();
> +
> + /*
> + ** Type check list of arguments
> + */
> +
> + if (SUCCESS_INDICATOR) {
> + save_transient_registers();
> + SUCCESS_INDICATOR = typecheck_arguments(TypeInfo, info.arity,
> + ArgList, info.argument_vector);
> + restore_transient_registers();
> + }
It would be slightly more efficient to do
/*
** Check range of FunctorNum, get info for this
** functor, and then type check the list of arguments
*/
save_transient_registers();
SUCCESS_INDICATOR =
get_functors_check_range(FunctorNumber, TypeInfo, &info) &&
typecheck_arguments(TypeInfo, info.arity, ArgList,
info.argument_vector);
restore_transient_registers();
> + /*
> + ** typecheck_arguments:
> + **
> + ** Given a list of univs (`arg_list'), and an vector of
> + ** type_infos (`arg_vector'), checks that they are all of the
> + ** same type. `arg_vector' may contain type variables, these
> + ** will be filled in by the type arguments of `type_info' -
> + ** a type_info
I think that comment is incomplete.
> +int
> +typecheck_arguments(Word type_info, int arity, Word arg_list, Word* arg_vector)
> +{
> + int i, success;
> + Word arg_type_info, list_arg_type_info;
> +
> + success = TRUE;
> +
> + /* Type check list of arguments */
> +
> + for (i = 0; success && i < arity; i++) {
> + if (list_is_empty(arg_list)) {
> + success = FALSE;
> + break;
> + }
> + list_arg_type_info = field(0, (list_head(arg_list)),
> + UNIV_OFFSET_FOR_TYPEINFO);
> +
> + arg_type_info = (Word) create_type_info(
> + (Word *) type_info, (Word *) arg_vector[i]);
> +
> + success = (mercury_compare_type_info(
> + list_arg_type_info, arg_type_info) == COMPARE_EQUAL);
> + arg_list = list_tail(arg_list);
> + }
> +
> + /* List should now be empty */
> + if (!list_is_empty(arg_list)) {
> + success = FALSE;
> + }
> +
> + return success;
> +}
The code would be simpler if you got rid of the `success' variable,
and just did
if (list_is_empty(arg_list)) {
return FALSE;
}
in the loop and
return list_is_empty(arg_list);
at the end.
> +void
> +copy_arguments_from_list_to_vector(int arity, Word arg_list, Word term_vector)
> +{
> + int i;
> +
> + for (i = 0; i < arity; i++) {
> + field(mktag(0), term_vector, i) =
> + field(0, list_head(arg_list), UNIV_OFFSET_FOR_DATA);
> + arg_list = list_tail(arg_list);
> + }
> +}
How come one field has `mktag(0)' and the other uses just `0'?
Please be consistent.
> +bool
> +get_functors_check_range(int functor_number, Word type_info,
> + construct_info *info)
> +{
> + bool success;
> +
> + /* Check range of functor_number */
> + success = (functor_number <= get_num_functors(type_info)
> + && functor_number > 0);
> +
> + /* Get functors vector, check for specials */
> + if (success) {
> + success = get_functor_info(type_info, functor_number, info);
> + }
> + return success;
> +}
The code would be simpler if you just did
return functor_number <= get_num_functors(type_info) &&
functor_number > 0 &&
get_functor_info(type_info, functor_number, info);
> +Word
> +copy_argument_typeinfos(int arity, Word type_info, Word *arg_vector)
> +{
> + Word type_info_list, *functors;
> +
> + type_info_list = list_empty();
> +
> + restore_transient_registers();
The restore_transient_registers() call should come before the call
to list_empty(). Otherwise it could break if compiled with --no-tags.
> +int
> +get_num_functors(Word type_info)
> +{
> + Word *base_type_functors;
> + int Functors;
> +
> + base_type_functors = MR_BASE_TYPEINFO_GET_TYPEFUNCTORS(
> + MR_TYPEINFO_GET_BASE_TYPEINFO((Word *) type_info));
> +
> + switch ((int) MR_TYPEFUNCTORS_INDICATOR(base_type_functors)) {
...
> + case MR_TYPEFUNCTORS_UNIV:
> + fatal_error(""std_util:get_num_functors :""
> + "" found univ"");
> + break;
> +
> + default:
> + fatal_error(""std_util:get_num_functors :""
> + "" unknown indicator"");
Hmm, shouldn't you just return Functors = -1 for those cases?
Also, the indentation of your `break' statements is non-standard here
and elsewhere.
> + * If the substituted type parameters from the term_type_info
> + * were type variables, they will be replaced with references
> + * to the unnamed type (''/0).
I don't understand why that is done and I don't think it should be done.
> +typedef struct {
> + Word enum_or_comp_const;
> + Word num_sharers;
> + ConstString functor1;
> +/* other functors follow, num_sharers of them.
> +** ConstString functor2;
> +** ...
> +*/
> +} MR_TypeLayout_EnumVector;
> +
> +#define MR_TYPELAYOUT_ENUM_VECTOR_NUM_FUNCTORS(Vector) \
> + ((MR_TypeLayout_EnumVector *) (Vector))->num_sharers
> +
> +#define MR_TYPELAYOUT_ENUM_VECTOR_FUNCTOR_NAME(Vector, N) \
> + ((ConstString) (((Word *) \
> + &(((MR_TypeLayout_EnumVector *) (Vector))->functor1)) \
> + [(N) - 1]))
The parenthesization and casts are quite confusing here.
Why not just
#define MR_TYPELAYOUT_ENUM_VECTOR_FUNCTOR_NAME(Vector, N) \
( (&((MR_TypeLayout_EnumVector *)(Vector))->functor1) [(N) - 1] )
?
Can you please address the above issues, and then send around another diff?
--
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.
More information about the developers
mailing list