A ‘pragma foreign_enum’ declaration imports the values of the constants of an enumeration type into Mercury. However, sometimes one needs the reverse: the ability to export the values of the constants of an enumeration type (whether those values were assigned by ‘foreign_enum’ pragmas or not) from Mercury to foreign language code in ‘foreign_proc’ and ‘foreign_code’ pragmas. This is what ‘pragma foreign_export_enum’ declarations are for.
These pragmas have the following general form:
:- pragma foreign_export_enum("Lang", MercuryType, Attributes, Overrides).
When given such a pragma, the compiler will define a symbolic name in language Lang for each of the constructors of MercuryType (which must be an enumeration type). Each symbolic name allows code in that foreign language to create a value corresponding to that of the constructor it represents. (The exact mechanism used depends upon the foreign language; see the language specific information below for further details.)
For each foreign language, there is a default mapping between the name of a Mercury constructor and its symbolic name in the language Lang. This default mapping is not required to map every valid constructor name to a valid name in language 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 Lang. Overrides is a list whose elements are pairs of constructor names and strings. The latter specify the name that the implementation should use as the symbolic name in the foreign language. Overrides has the following form:
[cons_I - "symbol_I", …, cons_J - "symbol_J"]
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. This argument may be omitted if Overrides is empty.
The argument Attributes is a list of optional attributes. If empty, it may be omitted from the ‘pragma foreign_export_enum’ declaration if the Overrides argument is also omitted. The following attributes must be supported by all Mercury implementations.
Prefix each symbolic name, regardless of how it was generated, with the string Prefix. A ‘pragma foreign_export_enum’ declaration may contain at most one ‘prefix’ attribute.
Convert any alphabetic characters in a Mercury constructor name to uppercase when generating the symbolic name using the default mapping. Symbolic names specified by the programmer using Overrides are not affected by this attribute. If the ‘prefix’ attribute is also specified, then the prefix is added to the symbolic name after the conversion to uppercase has been performed, i.e. the characters in the prefix are not affected by the ‘uppercase’ attribute.
The implementation does not check the validity of a symbolic name in the foreign language until after the effects of any attributes have been applied. This means that attributes may cause an otherwise valid symbolic name to become invalid, or vice versa.
A Mercury module may contain ‘pragma foreign_export_enum’ declarations that refer to imported types, subject to the usual visibility restrictions.
A Mercury module, or program, may contain more than one ‘pragma foreign_export_enum’ declaration for a given Mercury type for a given language. This can be useful when a project is transitioning from using one naming scheme for Mercury constants in foreign code to another naming scheme.
It is an error if the mapping between constructors and symbolic names in a ‘pragma foreign_export_enum’ declaration does not form a bijection. It is also an error if two separate ‘pragma foreign_export_enum’ declarations for a given foreign language, whether or not for the same type, specify the same symbolic name, since in that case, the Mercury compiler would generate two conflicting definitions for that symbolic name. However, the Mercury implementation is not required to check either condition.
A ‘pragma foreign_export_enum’ declaration may occur only in the implementation section of a module.