[mercury-users] Destructive map_replace

Julien Fischer juliensf at csse.unimelb.edu.au
Mon Jan 5 22:53:27 AEDT 2009


On Mon, 5 Jan 2009, Michael Day wrote:

> Hi Julien,
>
>> When the first argument of call_pred needs to use RTTI you will be ;-)
>
> What if the argument to call_pred is always a predicate with a fully 
> specified non-parametric type?
>
> If I did want to pass in the real type info, how would I get it?

type_desc.type_of/1 and friends.

Here's an example, where we have a value of type xml_parser(T) and we
want the type descriptor (type_info) for T.  (The definition of
xml_parser(T) doesn't matter here, although for the sake of interest
it's a foreign type.)

     :- pred get_parser_arg_type_desc(xml_parser(T)::unused, type_desc::out)
             is det.

     get_parser_arg_type_desc(Parser, TypeDescForT) :-
         ParserTypeDesc = type_of(Parser),
         type_ctor_and_args(ParserTypeDesc, _, Args),
         (
             Args = [TypeDescForT]
         ;
             ( Args = []
             ; Args = [_, _ | _]
             ),
             Msg = $pred ++
                 ": incorrect number of args for type_ctor xml_parser/1",
             throw(software_error(Msg))
         ).

> Make a 
> Mercury wrapper predicate that uses RTTI to get it and passes it in as an 
> extra argument to the foreign proc?

Yes, here is the relevant section from the reference manual, ``Using
pragma foreign_export for C'':

     Calling polymorphically typed Mercury procedures from C is a little bit
     more difficult than calling ordinary (monomorphically typed) Mercury
     procedures. The simplest method is to just create monomorphic forwarding
     procedures that call the polymorphic procedures, and export them, rather
     than exporting the polymorphic procedures.

     If you do export a polymorphically typed Mercury procedure, the compiler
     will prepend one `type_info' argument to the parameter list of the C
     interface function for each polymorphic type variable in the Mercury
     procedure's type signature. The caller must arrange to pass in
     appropriate `type_info' values corresponding to the types of the other
     arguments passed. These `type_info' arguments can be obtained using the
     Mercury `type_of' function in the Mercury standard library module
     `type_desc'.

> Also, is it safe if the argument to call_pred throws an exception?

For C grades that use the MLDS backend, e.g. hlc.gc, hl.gc etc, it's
fine, the reason being that Mercury programs in those grades use
the C stack and implement exceptions using setjmp() and longjmp().

For C grades that use the LLDS backend, e.g. asm_fast.gc, reg.gc,
none.gc etc, it won't work since the stacks are handled differently
in those grades.  That's what the following comment at the top of
exception.m is referring to:

     Note that throwing an exception across the C interface won't work.  That
     is, if a Mercury procedure that is exported to C using `pragma
     foreign_export' throws an exception which is not caught within that
     procedure, then you will get undefined behaviour.

You could do it an a grade independent manner by catching the exception
within call_pred and propagating the error across the Mercury-C boundary
by hand, but doing so would not be very efficient.

Cheers,
Julien.
--------------------------------------------------------------------------
mercury-users mailing list
Post messages to:       mercury-users at csse.unimelb.edu.au
Administrative Queries: owner-mercury-users at csse.unimelb.edu.au
Subscriptions:          mercury-users-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the users mailing list