[m-rev.] for review: `uppercase' attribute for pragma foreign_export_enum

Julien Fischer juliensf at csse.unimelb.edu.au
Wed Feb 27 18:41:25 AEDT 2008


Estimated hours taken: 1.5
Branches: main

Add a new attribute to foreign_export_enum pragmas, `uppercase', that
converts the alphabetic characters in a Mercury enumeration constant
into uppercase when generating the foreign language constant name.
(Note that user supplied names for foreign constants are not affected
by this attribute - presumably if the programmer wanted those names
to be uppercase they would have done so themselves.)

compiler/prog_io_pragma.m:
compiler/prog_data.m:
 	Parse the new attribute.

compiler/add_pragma.m:
 	If the new attribute is present then apply the conversion
 	to the constructor names when generating the foreign
 	names.

doc/reference_manual.texi:
 	Document the new attribute.

tests/hard_coded/Makefile:
tests/hard_coded/uc_export_enum.m:
tests/hard_coded/uc_export_enum.exp:
 	Test the new attribute.

Julien.

Index: compiler/add_pragma.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/add_pragma.m,v
retrieving revision 1.81
diff -u -r1.81 add_pragma.m
--- compiler/add_pragma.m	15 Feb 2008 02:26:53 -0000	1.81
+++ compiler/add_pragma.m	27 Feb 2008 07:31:52 -0000
@@ -671,7 +671,8 @@
                      ; DuTypeKind = du_type_kind_foreign_enum(_)
                      ; DuTypeKind = du_type_kind_direct_dummy
                      ),
-                    Attributes = export_enum_attributes(MaybePrefix),
+                    Attributes = export_enum_attributes(MaybePrefix,
+                        MakeUpperCase),
                      (
                          MaybePrefix = yes(Prefix)
                      ;
@@ -683,7 +684,7 @@
                      (
                          MaybeOverridesMap = yes(OverridesMap),
                          build_export_enum_name_map(ContextPieces, Lang,
-                            TypeName, TypeArity, Context, Prefix,
+                            TypeName, TypeArity, Context, Prefix, MakeUpperCase,
                              OverridesMap, Ctors, MaybeMapping, !Specs),
                          (
                              MaybeMapping = yes(Mapping),
@@ -790,12 +791,12 @@

  :- pred build_export_enum_name_map(format_components::in,
      foreign_language::in, sym_name::in, arity::in, prog_context::in,
-    string::in, map(sym_name, string)::in, list(constructor)::in,
+    string::in, bool::in, map(sym_name, string)::in, list(constructor)::in,
      maybe(map(sym_name, string))::out,
      list(error_spec)::in, list(error_spec)::out) is det.

  build_export_enum_name_map(ContextPieces, Lang, TypeName, TypeArity,
-        Context, Prefix, Overrides0, Ctors, MaybeMapping, !Specs) :-
+        Context, Prefix, MakeUpperCase, Overrides0, Ctors, MaybeMapping, !Specs) :-
      (
          TypeName = qualified(TypeModuleQual, _)
      ;
@@ -804,7 +805,8 @@
          unexpected(this_file, "unqualified type name for foreign_export_enum")
      ),

-    list.foldl3(add_ctor_to_name_map(Lang, Prefix, TypeModuleQual),
+    list.foldl3(
+        add_ctor_to_name_map(Lang, Prefix, MakeUpperCase, TypeModuleQual),
          Ctors, Overrides0, Overrides, map.init, NameMap, [], BadCtors),
      %
      % Check for any remaining user-specified renamings that didn't
@@ -915,13 +917,13 @@
      %   !BadCtors):
      %
  :- pred add_ctor_to_name_map(foreign_language::in,
-    string::in, sym_name::in, constructor::in,
+    string::in, bool::in, sym_name::in, constructor::in,
      map(sym_name, string)::in, map(sym_name, string)::out,
      map(sym_name, string)::in, map(sym_name, string)::out,
      list(sym_name)::in, list(sym_name)::out) is det.

-add_ctor_to_name_map(Lang, Prefix, _TypeModQual, Ctor, !Overrides, !NameMap,
-        !BadCtors) :-
+add_ctor_to_name_map(Lang, Prefix, MakeUpperCase, _TypeModQual, Ctor,
+        !Overrides, !NameMap, !BadCtors) :-
      CtorSymName = Ctor ^ cons_name,
      (
          % All of the constructor sym_names should be module qualified by now.
@@ -943,7 +945,13 @@
      ;
          % Otherwise try to derive a name automatically from the
          % constructor name.
-        ForeignName1 = UnqualCtorName
+        (
+            MakeUpperCase = yes,
+            ForeignName1 = string.to_upper(UnqualCtorName)
+        ;
+            MakeUpperCase = no,
+            ForeignName1 = UnqualCtorName
+        )
      ),
      ForeignName = Prefix ++ ForeignName1,
      (
Index: compiler/prog_data.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_data.m,v
retrieving revision 1.206
diff -u -r1.206 prog_data.m
--- compiler/prog_data.m	15 Feb 2008 08:31:59 -0000	1.206
+++ compiler/prog_data.m	27 Feb 2008 07:31:52 -0000
@@ -617,10 +617,10 @@
  % Stuff for the `foreign_export_enum' pragma
  %

-
  :- type export_enum_attributes
      --->    export_enum_attributes(
-                ee_attr_prefix :: maybe(string)
+                ee_attr_prefix :: maybe(string),
+                ee_attr_upper  :: bool
              ).

  :- func default_export_enum_attributes = export_enum_attributes.
@@ -2313,7 +2313,7 @@
  % Stuff for the `foreign_export_enum' pragma
  %

-default_export_enum_attributes = export_enum_attributes(no).
+default_export_enum_attributes = export_enum_attributes(no, no).

  %-----------------------------------------------------------------------------%
  %-----------------------------------------------------------------------------%
Index: compiler/prog_io_pragma.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_io_pragma.m,v
retrieving revision 1.133
diff -u -r1.133 prog_io_pragma.m
--- compiler/prog_io_pragma.m	15 Feb 2008 02:26:57 -0000	1.133
+++ compiler/prog_io_pragma.m	27 Feb 2008 07:31:52 -0000
@@ -506,7 +506,8 @@
      parse_export_enum_attributes(AttributesTerm, MaybeAttributes).

  :- type collected_export_enum_attribute
-    --->    ee_attr_prefix(maybe(string)).
+    --->    ee_attr_prefix(maybe(string))
+    ;       ee_attr_upper(bool).

  :- pred parse_export_enum_attributes(term::in,
      maybe1(export_enum_attributes)::out) is det.
@@ -554,8 +555,14 @@
  :- pred process_export_enum_attribute(collected_export_enum_attribute::in,
      export_enum_attributes::in, export_enum_attributes::out) is det.

-process_export_enum_attribute(ee_attr_prefix(MaybePrefix), _, Attributes) :-
-    Attributes = export_enum_attributes(MaybePrefix).
+process_export_enum_attribute(ee_attr_prefix(MaybePrefix), !Attributes) :-
+    % We have already checked that the prefix attribute is not specified
+    % multiple times so it is safe to ignore it in the input here.
+    !.Attributes = export_enum_attributes(_, MakeUpperCase),
+    !:Attributes = export_enum_attributes(MaybePrefix, MakeUpperCase).
+process_export_enum_attribute(ee_attr_upper(MakeUpperCase), !Attributes) :-
+    !.Attributes = export_enum_attributes(MaybePrefix, _),
+    !:Attributes = export_enum_attributes(MaybePrefix, MakeUpperCase).

  :- pred parse_export_enum_attr(term::in,
      maybe1(collected_export_enum_attribute)::out) is det.
@@ -568,6 +575,10 @@
      ->
          Result = ok1(ee_attr_prefix(yes(Prefix)))
      ;
+        Term = functor(atom("uppercase"), [], _)
+    ->
+        Result = ok1(ee_attr_upper(yes))
+    ;
          Msg = "unrecognised attribute in foreign_export_enum pragma",
          Result = error1([Msg - Term])
      ).
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.422
diff -u -r1.422 reference_manual.texi
--- doc/reference_manual.texi	1 Feb 2008 05:45:28 -0000	1.422
+++ doc/reference_manual.texi	27 Feb 2008 07:31:52 -0000
@@ -7026,22 +7026,35 @@
  The argument @var{Attributes} is a list of optional attributes.
  If empty, it may be omitted from the @samp{pragma foreign_export_enum}
  declaration.
-The following attribute must be supported by all Mercury implementations.
+The following attributes must be supported by all Mercury implementations.

  @table @asis

  @item @samp{prefix(Prefix)}
  Prefix each symbolic name, regardless of how it was generated, with
  the string @var{Prefix}.
-This occurs @emph{before} the validity of the symbolic name in the
-foreign language is checked, i.e. the effect of the @samp{prefix}
-attribute may cause an otherwise valid symbolic name to become invalid or
-vice versa.
  At most one @samp{prefix} attribute may be specified for a
  @samp{pragma foreign_export_enum} declaration.

+ at item @samp{uppercase}
+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 @var{Overrides}
+are not affected by this attribute.
+If the @samp{prefix} attribute is also specified, then the prefix
+is added to the symbolic name @emph{after} the conversion to
+uppercase has been performed, i.e. the characters in the prefix
+are not affected by the @samp{uppercase} attribute.
+
  @end table

+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.
+
  It is an error if the mapping between constructors and symbolic names
  does not form a bijection.
  A program can contain multiple @samp{pragma foreign_export_enum}
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.340
diff -u -r1.340 Mmakefile
--- tests/hard_coded/Mmakefile	1 Feb 2008 05:45:29 -0000	1.340
+++ tests/hard_coded/Mmakefile	27 Feb 2008 07:31:53 -0000
@@ -242,6 +242,7 @@
  	type_spec_ho_term \
  	type_spec_modes \
  	type_to_term_bug \
+	uc_export_enum \
  	unicode_test \
  	unify_existq_cons \
  	unify_expression \
Index: tests/hard_coded/uc_export_enum.exp
===================================================================
RCS file: tests/hard_coded/uc_export_enum.exp
diff -N tests/hard_coded/uc_export_enum.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/uc_export_enum.exp	27 Feb 2008 07:31:53 -0000
@@ -0,0 +1,3 @@
+test_uc - succeeded.
+test_lc - succeeded.
+test_or - succeeded.
Index: tests/hard_coded/uc_export_enum.m
===================================================================
RCS file: tests/hard_coded/uc_export_enum.m
diff -N tests/hard_coded/uc_export_enum.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/uc_export_enum.m	27 Feb 2008 07:31:53 -0000
@@ -0,0 +1,85 @@
+% vim: ft=mercury ts=4 sw=4 et
+% Check the `uppercase' attribute with foreign_export_enum pragmas.
+
+:- module uc_export_enum.
+:- interface.
+
+:- import_module io.
+:- pred main(io::di, io::uo) is det.
+
+%----------------------------------------------------------------------------%
+%----------------------------------------------------------------------------%
+
+:- implementation.
+
+main(!IO) :-
+    test_uc(UC),
+    ( UC = foo ->
+        io.write_string("test_uc - succeeded.\n", !IO)
+    ;
+        io.write_string("test_uc - failed.\n", !IO)
+    ),
+    test_lc(LC),
+    ( LC = foo ->
+        io.write_string("test_lc - succeeded.\n", !IO)
+    ;
+        io.write_string("test_lc - failed.\n", !IO)
+    ),
+    test_or(X, Y, Z),
+    ( X = foo, Y = bar, Z = baz ->
+        io.write_string("test_or - succeeded.\n", !IO)
+    ;
+        io.write_string("test_or - failed.\n", !IO)
+    ).
+
+:- pred test_uc(foo::out) is det.
+:- pragma foreign_proc("C",
+    test_uc(X::out),
+    [will_not_call_mercury, promise_pure],
+"
+    X = UC_foo_FOO;
+").
+
+:- pred test_lc(foo::out) is det.
+:- pragma foreign_proc("C",
+    test_lc(X::out),
+    [will_not_call_mercury, promise_pure],
+"
+    X = LC_foo_foo;
+").
+
+:- pred test_or(foo::out, foo::out, foo::out) is det.
+:- pragma foreign_proc("C",
+    test_or(X::out, Y::out, Z::out),
+    [will_not_call_mercury, promise_pure],
+"
+    X = OR_foo_lowercase_foo;
+    Y = OR_foo_mixed1234_bAr;
+    Z = OR_foo_BAZ;
+").
+
+%----------------------------------------------------------------------------%
+
+:- type foo
+    --->    foo
+    ;       bar
+    ;       baz.
+
+    % Check that uppercase applies only the constructors and not to the prefix.
+    %
+:- pragma foreign_export_enum("C", foo/0, [prefix("UC_foo_"), uppercase]).
+
+    % Check that uppercase applies only when the uppercase attribute is specified.
+    %
+:- pragma foreign_export_enum("C", foo/0, [prefix("LC_foo_")]).
+
+    % Check that the uppercase attribute does not apply to user supplied foreign
+    % names.
+    %
+:- pragma foreign_export_enum("C", foo/0, [prefix("OR_foo_"), uppercase], [
+    foo - "lowercase_foo",
+    bar  - "mixed1234_bAr"
+]).
+
+%----------------------------------------------------------------------------%
+%----------------------------------------------------------------------------%

--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list