[m-rev.] for review: insts for type constructors

Julien Fischer jfischer at opturion.com
Sun Oct 4 15:39:16 AEDT 2015


Hi Zoltan,

> Add syntax for saying what type an inst is for.
> 
> As agreed on the developers mailing dist, this syntax is
> 
> :- inst i(...) for tc/n
>     --->    f1(...)
>     ;       f2(...)
>     ...
>     ;       fn(...).
> 
> It also works on the equivalent syntax
> 
> :- inst i(...) for tc/n == bound(...).
> 
> The type constructor may be specified only for insts that are being
> defined to be equivalent to bound insts, since only for these can we
> check that the top level function symbols belong to the specified type
> constructor.
> 
> There is no documentation of the new language extension yet, since it is
> not yet really useful. That would come later, when we check that an inst
> specified as for being for a specific type is used only on values
> of that type. We would also need to resolve the two issues marked with
> "XXX IFTC" in the diff.
> 
> compiler/prog_item.m:
>     Add a field to the parse tree representation of inst definitions
>     to record the absence or presence of the "for type" type constructor.
> 
> compiler/hlds_data.m:
>     Modify the representation of inst definitions to allow the recording

Delete the second "the" there.

>     the fact that an inst is declared to be for a specified type constructor,
>     to allow recording the presence of an error in this regard (the inst
>     is not for the type, or the inst is exported to places where the type
>     is not visible). Differentiate between no type constructor being associated
>     with the type because (a) it would not make sense, and (b) it would make
>     sense, but no type constructor was specified. (After type-constructor-
>     specific insts have been in the language long enough, we may want to
>     generate a warning or even an error for the latter.)
> 
> library/ops.m:
>     Add "for" as an operator, as discussed on the mailing list.

The addition of "for" as an operator is potentially going to break existing
code.  The operator table in the reference manual should be updated now and
there should be an entry in the news file mentioning that "for" is now an
operator.

...

> diff --git a/compiler/equiv_type.m b/compiler/equiv_type.m
> index 0091446..270ca8c 100644
> --- a/compiler/equiv_type.m
> +++ b/compiler/equiv_type.m
> @@ -219,15 +219,15 @@ build_eqv_maps_in_item(Item, !TypeEqvMap, !InstEqvMap) :-
>      ( if
>          Item = item_type_defn(ItemTypeDefn),
>          ItemTypeDefn = item_type_defn_info(Name, Args,
> -            parse_tree_eqv_type(Body), VarSet, _, _SeqNum)
> +            parse_tree_eqv_type(Body), VarSet, _Context, _SeqNum)
>     then
>          list.length(Args, Arity),
>          TypeCtor = type_ctor(Name, Arity),
>          map.set(TypeCtor, eqv_type_body(VarSet, Args, Body), !TypeEqvMap)
>      else if
>          Item = item_inst_defn(ItemInstDefn),
> -        ItemInstDefn = item_inst_defn_info(Name, Args,
> -            eqv_inst(Body), VarSet, _, _SeqNum)
> +        ItemInstDefn = item_inst_defn_info(Name, Args, _IFTC,
> +            eqv_inst(Body), VarSet, _Context, _SeqNum)
>      then
>          list.length(Args, Arity),
>          InstId = inst_id(Name, Arity),
> @@ -335,6 +335,26 @@ replace_in_item(ModuleName, TypeEqvMap, InstEqvMap, MaybeRecord,
>              ItemTypeDefn0, ItemTypeDefn, !RecompInfo, !UsedModules, Specs),
>          Item = item_type_defn(ItemTypeDefn)
>      ;
> +        Item0 = item_inst_defn(_ItemInstDefn0),
> +        % XXX IFTC
> +        % We *should* do two kinds of replacements on _ItemInstDefn0.
> +        %
> +        % (1) If inst i1's body contains inst i2, and i2 has been defined
> +        % to be equivalent to some other inst i3, then we should replace
> +        % i2 with i3 in i1's body. We haven't ever done this, and it is
> +        % a bit surprising that it has never been a problem so far.

It isn't that surprising.  Most Mercury programs I'm aware of either don't
define their own insts or, if they do, are not very ambitious about what
insts they define (since being ambitious in this respect tends to run into
limitations of the mode checker :-( )

> +        % (2) If inst i1 is for type t2, and t2 has been defined to be
> +        % equivalent to type t3, then we should record that i1 is really
> +        % for t3. However, while t2 is required to be just a type_ctor
> +        % and arity, t3 may be more complex. The obvious thing to do would be
> +        % to record that i1 is for t3's top type_ctor and its arity. Whether

Are there any specific non-obvious things you had in mind?

> +        % that is good enough depends on what *exactly* we will do with the
> +        % "inst for type ctor" information. We don't yet know the answer
> +        % to that question.
> +        Item = Item0,
> +        Specs = []
> +    ;

One thing we should be able to do with the "inst for type ctor" information is
(finally) fix  bug #89 -- inst subtyping involving existentially quantified
data constructors.

>          Item0 = item_pred_decl(ItemPredDecl0),
>          replace_in_pred_decl_info(ModuleName, MaybeRecord,
>              TypeEqvMap, InstEqvMap,



...


> diff --git a/compiler/recompilation.check.m b/compiler/recompilation.check.m
> index 180addf..42a70e5 100644
> --- a/compiler/recompilation.check.m
> +++ b/compiler/recompilation.check.m
> @@ -929,52 +929,59 @@ check_item_for_ambiguities(NeedQualifier, OldTimestamp, VersionNumbers, Item,
>          unexpected($module, $pred, "clause")
>      ;
>          Item = item_type_defn(ItemTypeDefn),
> -        ItemTypeDefn = item_type_defn_info(Name, Params, Body, _, _, _),
> -        Arity = list.length(Params),
> +        ItemTypeDefn = item_type_defn_info(TypeSymName, TypeParams, TypeBody,
> +            _, _, _),
> +        list.length(TypeParams, TypeArity),
>          check_for_simple_item_ambiguity(NeedQualifier, OldTimestamp,
> -            VersionNumbers, type_abstract_item, Name, Arity, NeedsCheck,
> -            !Info),
> +            VersionNumbers, type_abstract_item, TypeSymName, TypeArity,
> +            NeedsCheck, !Info),
>          (
>              NeedsCheck = yes,
>              check_type_defn_ambiguity_with_functor(NeedQualifier,
> -                type_ctor(Name, Arity), Body, !Info)
> +                type_ctor(TypeSymName, TypeArity), TypeBody, !Info)
>          ;
>              NeedsCheck = no
>          )
>      ;
>          Item = item_inst_defn(ItemInstDefn),
> -        ItemInstDefn = item_inst_defn_info(Name, Params, _, _, _, _),
> +        % XXX IFTC Do we need to check _MaybeForTypeCtor?

I'm not sure, but *if* we do then we possibly also need to do so for the
various pragmas that refer to type ctors as well (e.g. foreign_enum).

The diff looks fine.

Julien.



More information about the reviews mailing list