[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