[m-dev.] pragma foreign_export_enum
zoltan.somogyi at runbox.com
Tue Nov 28 07:50:16 AEDT 2017
I have been working on making the infrastructure for type representations
more flexible, since this is needed to enable more compact data representations.
In the process, I have come across something odd that I need resolved.
Section 14.5 of the language reference manual, for foreign_export_enum pragmas,
states (near the end) that
"It is an error if the mapping between constructors and symbolic names
does not form a bijection. A program can contain multiple ‘pragma foreign_export_enum’
declarations for a single Mercury type. The implementation is not required to check
that the symbolic names generated by separate ‘pragma foreign_export_enum’
declarations are unique."
The second sentence is a bit ambiguous; it does not say whether you can have
code like this:
:- pragma foreign_export_enum("C", type_foo/0, [prefix("FOO_")]).
:- pragma foreign_export_enum("C", type_foo/0, [prefix("BAR_")]).
or whether having two foreign_export_enum (fee for short) pragmas for the
same type is allowed ONLY if they are for different target languages.
As it happens, the implementation allows more than one fee pragma for
a type even if they are for the same target language.
However, this contradicts the first sentence, because given the
pragmas above, any function symbol in type_foo will have TWO separate
representations in C: one starting with FOO_ and one starting with BAR_.
Such a mapping cannot be a bijection.
I think that what we actually WANT to require is that for any generated
symbolic name in any given target language, there should be at most one
function symbol of ANY Mercury type that maps to that symbolic name.
This means we require only surjection, not bijection, but we require it
over all types with fee pragmas at once, not for each type separately.
Does anyone disagree?
If I am right, then the compiler COULD build a map from target language/
symbolic name pairs back to type_ctor/cons_id pairs, and then check whether
it maps any key to more than one value. Of course, it can build that map only
for the fee pragmas in the module currently being compiled, and thus
wouldn't be able to detect clashes between fee pragmas in different modules,
but some error checking is better than none.
Or, we could simply say that simply having more than one fee pragma
for a given type/language pair in a module is an error. Can anyone
think of a reasonable use case for such duplicates? I can't, yet
I don't see any reason to forbid it, due to the following.
Having both a foreign_enum and a foreign_export_enum pragma
for the same type and the same language is required to be allowed by
tests/hard_coded/exported_foreign_enum.m, though I can't see anything
in the reference manual that expressly allows it. And having both
will generate more than one target language name for a given constructor,
just like multiple fee pragmas would.
Any opinions, especially from people who have used these pragmas
in real application programs?
More information about the developers