[m-dev.] for discussion: foreign_export_enum syntax
Bartlomiej Szymczak
rhywek at gmail.com
Mon Jul 2 23:29:13 AEST 2007
On 7/2/07, Jonathan Morgan <jonmmorgan at gmail.com> wrote:
> On 7/2/07, Julien Fischer <juliensf at csse.unimelb.edu.au> wrote:
> >
> > On Mon, 2 Jul 2007, Jonathan Morgan wrote:
> >
> > > On 6/27/07, Julien Fischer <juliensf at csse.unimelb.edu.au> wrote:
> > >> I have been working on the change to allow Mercury enumeration constants
> > >> to be exported to foreign languages. The majority of the changes to
> > >> the compiler were made last year; what remains undecided is the
> > >> concrete syntax. Below is change to the reference manual that describes
> > >> the current version of this new feature. Here is a small example of
> > >> how it would look and work in the case where C is the foreign language.
> > >
> > > I've been considering bringing this up again in the last couple of
> > > weeks, so you've saved me the trouble of doing that.
> >
> > Glad to be of help!
> >
> > >> Example
> > >> -------
> > >>
> > >> :- type foo
> > >> ---> foo
> > >> ; bar
> > >> ; baz.
> > >>
> > >> :- pragma foreign_export_enum("C", foo, [bar - "BAR],
> > >> [prefix("MR_"]).
> > >>
> > >> would cause the following declaration to be generated in the .mh file.
> > >>
> > >> enum {
> > >> MR_foo = 0,
> > >> MR_BAR = 1,
> > >> MR_baz = 2
> > >> };
> > >
> > > Is there any particular reason for choosing enums over #define's?
> >
> > Not particularly.
> >
> > > I would expect #define's to be a better option as they do not specify
> > > any type for the resultant constant, whereas an enum specifies an enum
> > > type for the constant, which is probably different from the standard
> > > Mercury type (MR_Word?).
> >
> > Identifiers used as enumeration constants in C have type int.
> >
> > > While this may not be a problem with C's
> > > weak type system, it could potentially cause problems with C++ or
> > > C/C++ compilers (are there any plans to support a C++ compiler with
> > > any of the high-level C grades?).
> >
> > Not in the immediate future (see comments in mlds_to_c.m if you are
> > interested in a C++ backend), but since we want the code the in the .mh
> > files to be compatible with C++ for the purposes of interoperability, we
> > should probably use #defines.
> >
> > >> +For each foreign language there is a default mapping between the name
> > >> +of a Mercury constructor and its symbolic name in the language @var{Lang}.
> > >> +This default mapping is not required to map every valid constructor name
> > >> +to a valid name in language @var{Lang}; where it does not the programmer
> > >> +must specify a valid symbolic name.
> > >> +The programmer may also choose to map a constructor to a symbolic name
> > >> +that differs from the one supplied by the default mapping for language
> > >> + at var{Lang}.
> > >> + at var{Overrides} is a list of pairs of constructor names and strings of
> > >> +the following form:
> > >> +
> > >> + at example
> > >> +[consI - "symbolI", ..., consJ - "symbolJ"]
> > >> + at end example
> > >> +
> > >> +This can be used to provide either a valid symbolic name where the
> > >> +default mapping does not, or to override a valid symbolic name
> > >> +generated by the default mapping.
> > >
> > > Do you have to specify an empty list if there are no renamings? i
> >
> > No, you should be able to omit it in that case; unless you have attributes.
> > (That might seem confusing but it's the same thing we do with mutable
> > declarations; maybe it would be better to swap the position of those two
> > arguments?)
>
> It depends on which one is more likely. I suspect that (with a
> reasonable choice of default name and a use of prefixes) very few
> overrides will be necessary, while most users will use prefixes, so
> switching the order would probably work well.
>
> > > (I can imagine that requirement being potentially confusing if most uses
> > > of the pragma didn't do any renaming). An alternative (for if renaming
> > > was scarce) would be to make each renaming a separate attribute (e.g.
> > > rename(x, "X")), though I don't think that it would really help.
> >
> > Another choice, would be to make overrides into an attribute and have
> > something like:
> >
> > :- pragma foreign_export_enum("C",
> > foo,
> > [
> > prefix("MR_"),
> > overrides([foo - "FOO", bar - "BAR"])
> > ]).
> >
> > I'm not so keen on that one, but I guess I could live with it.
>
> I'm not keen on either of them, but they would make your intentions
> more explicit if you only rename some constructors.
>
I think that it's best to use higher order function here. Instead of
taking a list of renaming as parameter, pragma foreign_export_enum
should take a predicate pred(string::in,string::out) as input. Then
this predicate would be mapped on the list of Mercury constructors'
names to produce a list of C constant names.
So if I wanted to upper case all of them, I would just do:
:- pragma foreign_export_enum("C",foo,string.to_upper_case).
If I wanted to add prefix to all of them, I would just do:
:-pred enum_translation(string::in,string::out) is det.
enum_translation(S,E):-
string.to_upper_case(S,U),
string.append("ME_",U,E).
:- pragma foreign_export_enum("C",foo,enum_translation).
Otherwise I would just use identity function if I don't care about renaming.
Best regards,
--
Bartlomiej Antoni Szymczak
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to: mercury-developers at csse.unimelb.edu.au
Administrative Queries: owner-mercury-developers at csse.unimelb.edu.au
Subscriptions: mercury-developers-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the developers
mailing list