[m-rev.] for review: implement deconstruct of du types for Erlang backend

Peter Wang wangp at students.csse.unimelb.edu.au
Mon Jun 4 17:32:34 AEST 2007


On 04/06/07, Peter Ross <pro at missioncriticalit.com> wrote:
> Peter Wang,
>
> Can you have a look at this?
>
>
> ===================================================================
>
>
> Estimated hours taken: 8
> Branches: main
>
> Implement the RTTI for calling deconstruct on du types.
>
> compiler/erl_rtti.m:
>         Fix a bug where we gave the incorrect arity of notag functors.
>         Give the correct ordinal to enum and du functors.
>         Rewrite rtti_type_info_to_elds and rtti_pseudo_type_info_to_elds
>         so that we no longer generate code which causes an infinite loop
>         when constructing these types.

Briefly mention how.

> Index: compiler/erl_rtti.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/erl_rtti.m,v
> retrieving revision 1.7
> diff -u -r1.7 erl_rtti.m
> --- compiler/erl_rtti.m 1 Jun 2007 06:05:43 -0000       1.7
> +++ compiler/erl_rtti.m 4 Jun 2007 06:40:58 -0000

> @@ -165,7 +165,8 @@
>      NoTagFunctor = notag_functor(Name, TypeInfo, ArgName),
>      ArgTypeInfo = convert_to_rtti_maybe_pseudo_type_info_or_self(TypeInfo),
>      ArgInfos = [du_arg_info(ArgName, ArgTypeInfo)],
> -    DUFunctor = erlang_du_functor(Name, 0, 1, Name, ArgInfos, no),
> +    DUFunctor =
> +        erlang_du_functor(Name, 1, 1, erlang_atom_raw(Name), ArgInfos, no),
>      Details = erlang_du([DUFunctor]).
>  erlang_type_ctor_details_2(eqv(Type)) = erlang_eqv(Type).
>  erlang_type_ctor_details_2(builtin(Builtin)) = erlang_builtin(Builtin).
> @@ -178,8 +179,8 @@
>      %
>  :- func convert_enum_functor(enum_functor) = erlang_du_functor.
>
> -convert_enum_functor(enum_functor(Name, _)) =
> -    erlang_du_functor(Name, 0, 1, Name, [], no).
> +convert_enum_functor(enum_functor(Name, Ordinal)) =
> +    erlang_du_functor(Name, 0, Ordinal, erlang_atom_raw(Name), [], no).
>
>      %
>      % Convert a du_functor into the equivalent erlang_du_functor
> @@ -187,7 +188,8 @@
>  :- func convert_du_functor(du_functor) = erlang_du_functor.
>
>  convert_du_functor(du_functor(Name, Arity, Ordinal, _, ArgInfos, Exist)) =
> -    erlang_du_functor(Name, Arity, Ordinal + 1, Name, ArgInfos, Exist).
> +    erlang_du_functor(Name, Arity,
> +        Ordinal, erlang_atom_raw(Name), ArgInfos, Exist).
>
>  :- func convert_to_rtti_maybe_pseudo_type_info_or_self(
>      rtti_maybe_pseudo_type_info) = rtti_maybe_pseudo_type_info_or_self.
> @@ -387,53 +389,51 @@
>  :- pred rtti_type_info_to_elds(module_info::in, rtti_type_info::in,
>      list(elds_rtti_defn)::out) is det.
>
> -rtti_type_info_to_elds(_ModuleInfo, TypeInfo, RttiDefns) :-
> -    TypeInfo = plain_arity_zero_type_info(RttiTypeCtor),
> -
> -    TypeCtorRttiId = elds_rtti_type_ctor_id(RttiTypeCtor),
> -    ELDSTypeInfo = elds_rtti_ref(TypeCtorRttiId),
> -
> -    RttiId = elds_rtti_type_info_id(TypeInfo),
> -    IsExported = no,
> -    RttiDefn = elds_rtti_defn(RttiId, IsExported, varset.init,
> -        elds_clause([], ELDSTypeInfo)),
> -
> -    RttiDefns = [RttiDefn].
> -
>  rtti_type_info_to_elds(ModuleInfo, TypeInfo, RttiDefns) :-
> -    TypeInfo = plain_type_info(TypeCtor, ArgTypeInfos),
> -
> -    rtti_type_info_to_elds_2(ModuleInfo,
> -            ArgTypeInfos, ELDSArgTypeInfos, ArgRttiDefns),
> +    (
> +        TypeInfo = plain_arity_zero_type_info(RttiTypeCtor),
>
> -    ELDSTypeInfo = elds_tuple(
> -        [elds_rtti_ref(elds_rtti_type_ctor_id(TypeCtor)) | ELDSArgTypeInfos]),
> +        TypeCtorRttiId = elds_rtti_type_ctor_id(RttiTypeCtor),
> +        ELDSTypeInfo = elds_rtti_ref(TypeCtorRttiId),
>
> -    RttiId = elds_rtti_type_info_id(TypeInfo),
> -    IsExported = no,
> -    RttiDefn = elds_rtti_defn(RttiId, IsExported, varset.init,
> -        elds_clause([], elds_term(ELDSTypeInfo))),
> +        ArgRttiDefns = []
> +    ;
> +        TypeInfo = plain_type_info(TypeCtor, ArgTypeInfos),
>
> -    RttiDefns = [RttiDefn | ArgRttiDefns ].
> +        rtti_type_info_to_elds_2(ModuleInfo,
> +                ArgTypeInfos, ELDSArgTypeInfos, ArgRttiDefns),
>
> -rtti_type_info_to_elds(ModuleInfo, TypeInfo, RttiDefns) :-
> -    TypeInfo = var_arity_type_info(VarCtorId, ArgTypeInfos),
> -    TypeCtor = var_arity_id_to_rtti_type_ctor(VarCtorId),
> +        ELDSTypeInfo = elds_term(elds_tuple([
> +            elds_rtti_ref(elds_rtti_type_ctor_id(TypeCtor)) |
> +            ELDSArgTypeInfos]))
> +    ;
> +        TypeInfo = var_arity_type_info(VarCtorId, ArgTypeInfos),
> +        TypeCtor = var_arity_id_to_rtti_type_ctor(VarCtorId),
>
> -    rtti_type_info_to_elds_2(ModuleInfo,
> -            ArgTypeInfos, ELDSArgTypeInfos, ArgRttiDefns),
> +        rtti_type_info_to_elds_2(ModuleInfo,
> +                ArgTypeInfos, ELDSArgTypeInfos, ArgRttiDefns),
>
> -    ELDSTypeInfo = elds_tuple([
> -        elds_rtti_ref(elds_rtti_type_ctor_id(TypeCtor)),
> -        elds_term(elds_int(list.length(ArgTypeInfos))) |
> -        ELDSArgTypeInfos]),
> +        ELDSTypeInfo = elds_term(elds_tuple([
> +            elds_rtti_ref(elds_rtti_type_ctor_id(TypeCtor)),
> +            elds_term(elds_int(list.length(ArgTypeInfos))) |
> +            ELDSArgTypeInfos]))
> +    ),
>
> +        %
> +        % A type_info can contain a call to construct a type_ctor_info
> +        % which requires this type_info, leading to infinite recursion,

full stop

> @@ -751,42 +739,92 @@
>      ).
>
>
> -:- pred erlang_du_functor(module_info::in, erlang_du_functor::in,
> -    elds_expr::out, list(elds_rtti_defn)::in, list(elds_rtti_defn)::out) is det.
> +%-----------------------------------------------------------------------------%
> +%-----------------------------------------------------------------------------%
>
> -erlang_du_functor(ModuleInfo, Functor, elds_term(Term), !Defns) :-
> -    Functor = erlang_du_functor(Name, Arity, Ord, Rep, ArgInfos, MaybeExist),
> +:- import_module deconstruct.
> +:- import_module exception.

Move these to the top of the file.

>
> -    list.map_foldl(du_arg_info(ModuleInfo), ArgInfos, ELDSArgInfos, !Defns),
> -    ELDSExist = convert_to_elds_term(MaybeExist),
> +    %
> +    % rtti_to_elds_expr(MI, T, Expr, !Defns)
> +    %
> +    % Given some T which is a representation of the RTTI data,
> +    % it generates the elds_expr which would represent that T as an erlang
> +    % term.

I suggest

   Return the ELDS expression, Expr, that represents the RTTI data, T, as
   an Erlang term.

and writing MI in full.

> +:- pred convert_arg_to_elds_expr(module_info::in, T::in, int::in,
>      elds_expr::out, list(elds_rtti_defn)::in, list(elds_rtti_defn)::out) is det.
>
> -du_arg_info(ModuleInfo, du_arg_info(MaybeName, TI), elds_term(Term), !Defns) :-
> -    (
> -        MaybeName = yes(Name),
> -        NameTerm = elds_string(Name)
> +convert_arg_to_elds_expr(MI, Term, Index, ELDS, !Defns) :-
> +    ( arg(Term, do_not_allow, Index, Arg) ->
> +        rtti_to_elds_expr(MI, Arg, ELDS, !Defns)

Module qualify that I think.

> +:- pred convert_maybe_pseudo_type_info_to_elds(module_info::in,
> +    rtti_maybe_pseudo_type_info::in,
> +    elds_expr::out, list(elds_rtti_defn)::in, list(elds_rtti_defn)::out) is det.
> +
> +convert_maybe_pseudo_type_info_to_elds(MI, TI, Expr, !Defns) :-
> +    maybe_pseudo_type_info_to_elds(MI, TI, RttiId, Defns),
> +    !:Defns = list.sort_and_remove_dups(Defns ++ !.Defns),
> +    Expr = elds_rtti_ref(RttiId).

Rename Defns to distinguish it from !Defns.

> @@ -102,17 +105,19 @@
>                  edu_name            :: string,
>                  edu_orig_arity      :: int,
>
> -                    % Size of the tuple needed to represent the
> -                    % functor.
> +                    % The declaration order of the functor.
>                  edu_ordinal         :: int,
>
>                      % erlang atom which represents the functor
>                      % currently encoded version of name
>                      % in the future maybe name_arity
> -                edu_rep             :: string,
> +                edu_rep             :: erlang_atom_raw,
>                  edu_arg_infos       :: list(du_arg_info),
>                  edu_exist_info      :: maybe(exist_info)
>              ).
> +
> +:- type erlang_atom_raw
> +    ---> erlang_atom_raw(string).

Indent that and add a comment that it's needed for rtti_to_elds_expr.

> Index: library/erlang_rtti_implementation.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/library/erlang_rtti_implementation.m,v
> retrieving revision 1.3
> diff -u -r1.3 erlang_rtti_implementation.m
> --- library/erlang_rtti_implementation.m        1 Jun 2007 08:30:58 -0000       1.3
> +++ library/erlang_rtti_implementation.m        4 Jun 2007 06:40:58 -0000
> @@ -285,7 +285,12 @@
>          Functor, Arity, Arguments) :-
>      (
>          TypeCtorRep = etcr_du,
> -        Functor = "XXX", Arity = 0, Arguments = []
> +        FunctorReps = TypeCtorInfo ^ type_ctor_functors,
> +        FunctorRep = matching_du_functor(FunctorReps, Term),
> +        Functor = FunctorRep ^ edu_name,
> +        Arity = FunctorRep ^ edu_orig_arity,
> +        Arguments = list.map(
> +            get_du_functor_arg(TypeInfo, FunctorRep, Term), 1 .. Arity)
>      ;
>          TypeCtorRep = etcr_list,
>          Functor = "XXX", Arity = 0, Arguments = []
> @@ -366,8 +371,8 @@
>                  Arity = 0,
>                  Arguments = []
>              ;
> -                deconstruct_2(Term, TypeInfo, TypeCtorInfo, etcr_foreign, NonCanon,
> -                        Functor, Arity, Arguments)
> +                deconstruct_2(Term, TypeInfo, TypeCtorInfo,
> +                    etcr_foreign, NonCanon, Functor, Arity, Arguments)
>              )
>          )
>      ;
> @@ -389,6 +394,132 @@
>      ).
>
>      %
> +    % matching_du_functor(Functors, Term)
> +    %
> +    % finds the erlang_du_functor in the list Functors which describes
> +    % the given Term.
> +    %
> +:- func matching_du_functor(list(erlang_du_functor), T) = erlang_du_functor.
> +
> +matching_du_functor([], _) = func_error(this_file ++ " matching_du_functor/2").
> +matching_du_functor([F | Fs], T) =
> +    ( matches_du_functor(T, F) ->
> +        F
> +    ;
> +        matching_du_functor(Fs, T)
> +    ).
> +
> +    %
> +    % A functor matches a term, if the first argument of the term
> +    % is the same erlang atom as the recorded in the edu_rep field,

as recorded

> +    % and the size of the term matches the calculated size of term.

of Term.

> +    %
> +    % Note we have to do this second step because a functor is distinguished
> +    % by both it's name and arity.

its

> +    %
> +    % Note it is possible for this code to do the wrong thing, see the comment
> +    % at the top of erl_unify_gen.m.
> +    %

Add to the comment in erl_unify_gen that this comment should be deleted
once that's fixed.

> +:- pred matches_du_functor(T::in, erlang_du_functor::in) is semidet.
> +
> +matches_du_functor(Term, Functor) :-
> +    check_functor(Term, Functor ^ edu_rep, Size),
> +    Functor ^ edu_orig_arity + 1 + extra_args(Functor) = Size.
> +
> +:- pred check_functor(T::in, erlang_atom::in, int::out) is semidet.
> +:- pragma foreign_proc("Erlang", check_functor(Term::in, Atom::in, Size::out),
> +        [will_not_call_mercury, promise_pure, thread_safe], "

Move the quote down.

> @@ -584,6 +727,10 @@
>      [promise_pure],
>  "
>      % TypeInfo_for_U to avoid compiler warning
> +
> +    %io:format(""get_subterm(~p, ~p, ~p, ~p)~n"",
> +    %    [TypeInfo, Term, Index, ExtraArgs]),
> +

Delete that.

>      TypeInfo_for_T = TypeInfo,
>      Arg = element(Index + ExtraArgs, Term)
>  ").
> @@ -672,7 +819,7 @@
>
>  semidet_unimplemented(S) :-
>      ( semidet_succeed ->
> -        error("rtti_implementation: unimplemented: " ++ S)
> +        error(this_file ++ ": unimplemented: " ++ S)
>      ;
>          semidet_succeed
>      ).
> @@ -681,7 +828,7 @@
>
>  det_unimplemented(S) :-
>      ( semidet_succeed ->
> -        error("rtti_implementation: unimplemented: " ++ S)
> +        error(this_file ++ ": unimplemented: " ++ S)
>      ;
>          true
>      ).
> @@ -788,6 +935,117 @@
>      type_to_univ(Term, Univ),
>      det_univ_to_type(Univ, Actual).
>
> +%-----------------------------------------------------------------------------%
> +%-----------------------------------------------------------------------------%
> +%
> +% These types have to be kept in sync with the corresponding types in
> +% compiler/erlang_rtti.m
> +%
> +
> +:- import_module maybe.

Move that up.

> +:- type maybe_pseudo_type_info
> +    --->    pseudo(pseudo_type_info_thunk)
> +    ;       plain(type_info_thunk).
> +
> +% XXX
> +:- type pseudo_type_info_thunk.
> +:- pragma foreign_type("Erlang", pseudo_type_info_thunk, "").
> +:- type pseudo_type_info_thunk ---> pseudo_type_info_thunk.

Any reason?

> +
> +:- type type_info_thunk.
> +:- pragma foreign_type("Erlang", type_info_thunk, "").
> +:- type type_info_thunk ---> type_info_thunk.
> +
> +:- type evaluated_type_info_thunk
> +    --->    universal_type_info(int)
> +    ;       existential_type_info(int)
> +    ;       type_info(type_info)
> +    .
> +
> +:- func eval_type_info(type_info_thunk) = evaluated_type_info_thunk.
> +:- pragma foreign_proc("Erlang", eval_type_info(Thunk::in) = (TypeInfo::out),
> +        [will_not_call_mercury, thread_safe, promise_pure], "

Reformat that.

> +    MaybeTypeInfo = Thunk(),
> +    TypeInfo =
> +        if
> +            is_integer(MaybeTypeInfo), MaybeTypeInfo < 512 ->
> +                { universal_type_info, MaybeTypeInfo };
> +            is_integer(MaybeTypeInfo) ->
> +                { existential_type_info, MaybeTypeInfo - 512 };
> +            true ->
> +                { type_info, MaybeTypeInfo }
> +        end,
> +    % io:format(""eval_type_info: ~p~n"", [TypeInfo]),
> +    void

Delete that.


Peter
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list