[mercury-users] Working with exported types

Julien Fischer juliensf at csse.unimelb.edu.au
Thu Jul 27 15:48:30 AEST 2006


On Thu, 27 Jul 2006, Jonathan Morgan wrote:

> Say I have an enum something like the following.
>
> :- type my_enum --->
>   value1 ;
>   value2 ;
>   value3.
>
> If I am working with such a type in foreign code there are a couple of
> ways I could do it.
>
> 1. Assume that value1, value2 and value3 map to the values 0, 1 and 2,
> and then just test against or assign these values.  Efficient, but may
> be broken by change in representation.

At the moment the only thing that is likely to break this representation
is using the .rt grades (and they're deprecated anyhow).  (Actually,
I changing the current representation of enums will break the standard
library.)

> 2. Export Mercury predicates that work on this type, and use these
> exported predicate exclusively.
>
> For example:
>
> :- pragma export(my_enum_is_value1(in), "module_my_enum_is_value1").
> :- pred my_enum_is_value1(my_enum::in) is semidet.
> my_enum_is_value1(value1).
>
> :- pragma export(my_enum_is_value2(in), "module_my_enum_is_value2").
> :- pred my_enum_is_value2(my_enum::in) is semidet.
> my_enum_is_value2(value2).
>
> :- pragma export(my_enum_is_value3(in), "module_my_enum_is_value3").
> :- pred my_enum_is_value3(my_enum::in) is semidet.
> my_enum_is_value3(value3).
>
> :- pragma export(my_enum_value1 = out, "module_my_enum_value1").
> :- func my_enum_value1 = my_enum.
> my_enum_value1 = value1.
>
> :- pragma export(my_enum_value2 = out, "module_my_enum_value2").
> :- func my_enum_value2 = my_enum.
> my_enum_value2 = value2.
>
> :- pragma export(my_enum_value3 = out, "module_my_enum_value3").
> :- func my_enum_value3 = my_enum.
> my_enum_value3 = value3.
>
> This second way will not break if the representation changes, but is
> very cumbersome to use.  Interestingly, mtcltk uses both of these
> methods when dealing with tcl_status - when writing to a variable it
> uses method one, but when reading from it it uses method two.
>
> Which of these methods is likely to be better?

The second one is very heavyweight.  Setting up calls back to Mercury adds
all sorts of code for setting up and saving the state of the Mercury engine.

A third alternative is the one used by the OpenGL binding.  Add a function
that maps the Mercury enums onto integers and pass the integers to C.

Another approach that I have thought about adding (because doing the above
in the OpenGL binding was fairly tedious), is to add a foreign_enum pragma
that would allow you to safely use the values of Mercury enums on the other
side of the foreign language interface, something like:

 	:- type foo
 		--->	foo
 		;	bar
 		;	baz

 	:- pragma foreign_enum("C", [
 		foo - "FOO",
 		bar - "BAR",
 		baz - "BAZ"]).

The compiler would then add the following to the modules .mh file:

 	#define FOO <representation of foo>
 	#define BAR <representation of bar>
 	#define BAZ (representation of baz>

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