[m-rev.] for post-commit review: improve error messages for foreign language interface pragmas

Julien Fischer jfischer at opturion.com
Thu Mar 16 11:05:41 AEDT 2017


Improve error messages for foreign language interface pragmas.

compiler/parse_pragma.m:
 	Provide more context for error messages concerning invalid
  	foreign language arguments in pragmas.

 	Improve the error message for invalid second arguments of
 	`foreign_enum' and `foreign_export_enum' pragmas.

tests/invalid/bad_foreign_enum.err_exp:
tests/invalid/bad_foreign_export_enum.err_exp:
tests/invalid/bad_foreign_export.err_exp:
tests/invalid/bad_foreign_import_module.err_exp:
tests/invalid/bad_foreign_type.err_exp:
     Conform to the above change.

Julien.

diff --git a/compiler/parse_pragma.m b/compiler/parse_pragma.m
index be936e0..12d2a2d 100644
--- a/compiler/parse_pragma.m
+++ b/compiler/parse_pragma.m
@@ -387,7 +387,11 @@ parse_pragma_foreign_type(ModuleName, VarSet, ErrorTerm, PragmaTerms,
              MaybeAssertionTerm = yes(AssertionTerm0)
          )
      then
-        parse_foreign_language("foreign_type", VarSet, LangTerm,
+        LangContextPieces = cord.from_list([
+            words("In first argument of"), pragma_decl("foreign_type"),
+            words("declaration")
+        ]),
+        parse_foreign_language(LangContextPieces, VarSet, LangTerm,
              MaybeForeignLang),
          TypeDefnHeadContextPieces = cord.from_list([
              words("In second argument of"), pragma_decl("foreign_type"),
@@ -542,9 +546,17 @@ parse_pragma_foreign_export_enum(VarSet, ErrorTerm, PragmaTerms,
              MaybeOverridesTerm = yes(OverridesTerm)
          )
      then
-        parse_foreign_language("foreign_export_enum", VarSet, LangTerm,
+        LangContextPieces = cord.from_list([
+            words("In first argument of"),
+            pragma_decl("foreign_export_enum"), words("declaration:")
+        ]),
+        parse_foreign_language(LangContextPieces, VarSet, LangTerm,
              MaybeForeignLang),
-        parse_type_ctor_name_arity("foreign_export_enum", MercuryTypeTerm,
+        TypeContextPieces = cord.from_list([
+            words("In second argument of"),
+            pragma_decl("foreign_export_enum"), words("declaration:")
+        ]),
+        parse_type_ctor_name_arity(TypeContextPieces, VarSet, MercuryTypeTerm,
              MaybeTypeCtor),
          maybe_parse_export_enum_attributes(VarSet, MaybeAttributesTerm,
              MaybeAttributes),
@@ -730,9 +742,17 @@ parse_pragma_foreign_enum(VarSet, ErrorTerm, PragmaTerms, Context, SeqNum,
          MaybeIOM) :-
      ( if PragmaTerms = [LangTerm, MercuryTypeTerm, ValuesTerm] then

-        parse_foreign_language("foreign_enum", VarSet, LangTerm,
+        LangContextPieces = cord.from_list([
+            words("In first argument of"), pragma_decl("foreign_enum"),
+            words("declaration:")
+        ]),
+        parse_foreign_language(LangContextPieces, VarSet, LangTerm,
              MaybeForeignLang),
-        parse_type_ctor_name_arity("foreign_enum", MercuryTypeTerm,
+        TypeContextPieces = cord.from_list([
+            words("In second argument of"), pragma_decl("foreign_enum"),
+            words("declaration:")
+        ]),
+        parse_type_ctor_name_arity(TypeContextPieces, VarSet, MercuryTypeTerm,
              MaybeTypeCtor),

          UnrecognizedPieces =
@@ -796,34 +816,37 @@ parse_pragma_foreign_enum(VarSet, ErrorTerm, PragmaTerms, Context, SeqNum,

  %---------------------------------------------------------------------------%
  %
-% Common code for parsing foreign_export_enum and foreign_enum pragms.
+% Common code for parsing foreign language interface pragmas.
  %

-:- pred parse_foreign_language(string::in, varset::in, term::in,
-    maybe1(foreign_language)::out) is det.
+:- pred parse_foreign_language(cord(format_component)::in, varset::in,
+    term::in, maybe1(foreign_language)::out) is det.

-parse_foreign_language(PragmaName, VarSet, LangTerm, MaybeForeignLang) :-
+parse_foreign_language(ContextPieces, VarSet, LangTerm, MaybeForeignLang) :-
      ( if term_to_foreign_language(LangTerm, ForeignLang) then
          MaybeForeignLang = ok1(ForeignLang)
      else
-        LangPieces = [words("Error: invalid foreign language"),
-            quote(describe_error_term(VarSet, LangTerm)), words("in"),
-            pragma_decl(PragmaName), words("declaration."),
-            nl],
-       LangSpec = error_spec(severity_error, phase_term_to_parse_tree,
+        LangPieces = cord.list(ContextPieces) ++ [
+            words("error: invalid foreign language"),
+            quote(describe_error_term(VarSet, LangTerm)), suffix(".")
+        ],
+        LangSpec = error_spec(severity_error, phase_term_to_parse_tree,
              [simple_msg(get_term_context(LangTerm), [always(LangPieces)])]),
              MaybeForeignLang = error1([LangSpec])
      ).

-:- pred parse_type_ctor_name_arity(string::in, term::in,
-    maybe1(type_ctor)::out) is det.
+:- pred parse_type_ctor_name_arity(cord(format_component)::in, varset::in,
+    term::in, maybe1(type_ctor)::out) is det.

-parse_type_ctor_name_arity(PragmaName, TypeTerm, MaybeTypeCtor) :-
+parse_type_ctor_name_arity(ContextPieces, VarSet, TypeTerm, MaybeTypeCtor) :-
      ( if parse_name_and_arity_unqualified(TypeTerm, Name, Arity) then
          MaybeTypeCtor = ok1(type_ctor(Name, Arity))
      else
-        Pieces = [words("Error: expected name/arity for type in"),
-            pragma_decl(PragmaName), words("declaration."), nl],
+        TypeTermStr = describe_error_term(VarSet, TypeTerm),
+        Pieces = cord.list(ContextPieces) ++ [
+            words("error: expected name/arity for type, got"),
+            quote(TypeTermStr), suffix(".")
+        ],
          Spec = error_spec(severity_error, phase_term_to_parse_tree,
              [simple_msg(get_term_context(TypeTerm), [always(Pieces)])]),
          MaybeTypeCtor = error1([Spec])
@@ -840,7 +863,11 @@ parse_type_ctor_name_arity(PragmaName, TypeTerm, MaybeTypeCtor) :-
  parse_pragma_foreign_export(VarSet, ErrorTerm, PragmaTerms, Context, SeqNum,
          MaybeIOM) :-
      ( if PragmaTerms = [LangTerm, PredAndModesTerm, FunctionTerm] then
-        parse_foreign_language("foreign_export", VarSet, LangTerm,
+        LangContextPieces = cord.from_list([
+            words("In first argument of"), pragma_decl("foreign_export"),
+            words("declaration:")
+        ]),
+        parse_foreign_language(LangContextPieces, VarSet, LangTerm,
              MaybeForeignLang),
          PredAndModesContextPieces = cord.from_list([
              words("In second argument of"), pragma_decl("foreign_export"),
@@ -926,7 +953,11 @@ parse_pragma_foreign_import_module(VarSet, ErrorTerm, PragmaTerms, Context,
      ( if
          PragmaTerms = [LangTerm, ImportTerm]
      then
-        parse_foreign_language("foreign_import_module", VarSet, LangTerm,
+        LangContextPieces = cord.from_list([
+            words("In first argument of"),
+            pragma_decl("foreign_import_module"), words("declaration:")
+        ]),
+        parse_foreign_language(LangContextPieces, VarSet, LangTerm,
              MaybeForeignLang),
          ( if try_parse_sym_name_and_no_args(ImportTerm, Import0) then
              MaybeImportModule = ok1(Import0)
diff --git a/tests/invalid/bad_foreign_enum.err_exp b/tests/invalid/bad_foreign_enum.err_exp
index cd94e22..f50f636 100644
--- a/tests/invalid/bad_foreign_enum.err_exp
+++ b/tests/invalid/bad_foreign_enum.err_exp
@@ -3,14 +3,18 @@ bad_foreign_enum.m:044:   `:- pragma foreign_enum' declaration.
  bad_foreign_enum.m:048: Error: expected a non-empty list mapping constructors
  bad_foreign_enum.m:048:   to foreign values in `:- pragma foreign_enum'
  bad_foreign_enum.m:048:   declaration.
-bad_foreign_enum.m:048: Error: invalid foreign language `"InvalidLanguage"' in
-bad_foreign_enum.m:048:   `:- pragma foreign_enum' declaration.
-bad_foreign_enum.m:052: Error: expected name/arity for type in
-bad_foreign_enum.m:052:   `:- pragma foreign_enum' declaration.
-bad_foreign_enum.m:059: Error: invalid foreign language `"InvalidLanguage"' in
-bad_foreign_enum.m:059:   `:- pragma foreign_enum' declaration.
-bad_foreign_enum.m:060: Error: expected name/arity for type in
-bad_foreign_enum.m:060:   `:- pragma foreign_enum' declaration.
+bad_foreign_enum.m:048: In first argument of `:- pragma foreign_enum'
+bad_foreign_enum.m:048:   declaration: error: invalid foreign language
+bad_foreign_enum.m:048:   `"InvalidLanguage"'.
+bad_foreign_enum.m:052: In second argument of `:- pragma foreign_enum'
+bad_foreign_enum.m:052:   declaration: error: expected name/arity for type, got
+bad_foreign_enum.m:052:   `vegetable'.
+bad_foreign_enum.m:059: In first argument of `:- pragma foreign_enum'
+bad_foreign_enum.m:059:   declaration: error: invalid foreign language
+bad_foreign_enum.m:059:   `"InvalidLanguage"'.
+bad_foreign_enum.m:060: In second argument of `:- pragma foreign_enum'
+bad_foreign_enum.m:060:   declaration: error: expected name/arity for type, got
+bad_foreign_enum.m:060:   `meat'.
  bad_foreign_enum.m:061: Error: expected a non-empty list mapping constructors
  bad_foreign_enum.m:061:   to foreign values in `:- pragma foreign_enum'
  bad_foreign_enum.m:061:   declaration.
diff --git a/tests/invalid/bad_foreign_export.err_exp b/tests/invalid/bad_foreign_export.err_exp
index 05b1f5e..a1e40ff 100644
--- a/tests/invalid/bad_foreign_export.err_exp
+++ b/tests/invalid/bad_foreign_export.err_exp
@@ -6,10 +6,12 @@ bad_foreign_export.m:028: In third argument of `:- pragma foreign_export'
  bad_foreign_export.m:028:   declaration: error: expected a non-empty string for
  bad_foreign_export.m:028:   the foreign language name of the exported
  bad_foreign_export.m:028:   procedure, got `22222'.
-bad_foreign_export.m:032: Error: invalid foreign language `"InvalidLanguage"'
-bad_foreign_export.m:032:   in `:- pragma foreign_export' declaration.
-bad_foreign_export.m:037: Error: invalid foreign language `"InvalidLanguage"'
-bad_foreign_export.m:037:   in `:- pragma foreign_export' declaration.
+bad_foreign_export.m:032: In first argument of `:- pragma foreign_export'
+bad_foreign_export.m:032:   declaration: error: invalid foreign language
+bad_foreign_export.m:032:   `"InvalidLanguage"'.
+bad_foreign_export.m:037: In first argument of `:- pragma foreign_export'
+bad_foreign_export.m:037:   declaration: error: invalid foreign language
+bad_foreign_export.m:037:   `"InvalidLanguage"'.
  bad_foreign_export.m:038: In second argument of `:- pragma foreign_export'
  bad_foreign_export.m:038:   declaration: error: atom expected at 3333.
  bad_foreign_export.m:039: In third argument of `:- pragma foreign_export'
diff --git a/tests/invalid/bad_foreign_export_enum.err_exp b/tests/invalid/bad_foreign_export_enum.err_exp
index 8aec84f..0f3942d 100644
--- a/tests/invalid/bad_foreign_export_enum.err_exp
+++ b/tests/invalid/bad_foreign_export_enum.err_exp
@@ -1,15 +1,21 @@
  bad_foreign_export_enum.m:017: Error: wrong number of arguments in
  bad_foreign_export_enum.m:017:   `:- pragma foreign_export_enum' declaration.
-bad_foreign_export_enum.m:021: Error: invalid foreign language
-bad_foreign_export_enum.m:021:   `"InvalidLanguage"' in
-bad_foreign_export_enum.m:021:   `:- pragma foreign_export_enum' declaration.
-bad_foreign_export_enum.m:025: Error: expected name/arity for type in
-bad_foreign_export_enum.m:025:   `:- pragma foreign_export_enum' declaration.
-bad_foreign_export_enum.m:028: Error: invalid foreign language
-bad_foreign_export_enum.m:028:   `"InvalidLanguage"' in
-bad_foreign_export_enum.m:028:   `:- pragma foreign_export_enum' declaration.
-bad_foreign_export_enum.m:029: Error: expected name/arity for type in
-bad_foreign_export_enum.m:029:   `:- pragma foreign_export_enum' declaration.
+bad_foreign_export_enum.m:021: In first argument of
+bad_foreign_export_enum.m:021:   `:- pragma foreign_export_enum' declaration:
+bad_foreign_export_enum.m:021:   error: invalid foreign language
+bad_foreign_export_enum.m:021:   `"InvalidLanguage"'.
+bad_foreign_export_enum.m:025: In second argument of
+bad_foreign_export_enum.m:025:   `:- pragma foreign_export_enum' declaration:
+bad_foreign_export_enum.m:025:   error: expected name/arity for type, got
+bad_foreign_export_enum.m:025:   `fruit'.
+bad_foreign_export_enum.m:028: In first argument of
+bad_foreign_export_enum.m:028:   `:- pragma foreign_export_enum' declaration:
+bad_foreign_export_enum.m:028:   error: invalid foreign language
+bad_foreign_export_enum.m:028:   `"InvalidLanguage"'.
+bad_foreign_export_enum.m:029: In second argument of
+bad_foreign_export_enum.m:029:   `:- pragma foreign_export_enum' declaration:
+bad_foreign_export_enum.m:029:   error: expected name/arity for type, got
+bad_foreign_export_enum.m:029:   `fruit'.
  bad_foreign_export_enum.m:030: Error: malformed attributes list in
  bad_foreign_export_enum.m:030:   `:- pragma foreign_export_enum' declaration.
  bad_foreign_export_enum.m:031: Error: expected list of mapping elements, not
diff --git a/tests/invalid/bad_foreign_import_module.err_exp b/tests/invalid/bad_foreign_import_module.err_exp
index eda03f7..31f3aca 100644
--- a/tests/invalid/bad_foreign_import_module.err_exp
+++ b/tests/invalid/bad_foreign_import_module.err_exp
@@ -1,14 +1,14 @@
  bad_foreign_import_module.m:018: Error: wrong number of arguments in
  bad_foreign_import_module.m:018:   `:- pragma foreign_import_module'
  bad_foreign_import_module.m:018:   declaration.
-bad_foreign_import_module.m:022: Error: invalid foreign language
-bad_foreign_import_module.m:022:   `"InvalidForeignLang"' in
+bad_foreign_import_module.m:022: In first argument of
  bad_foreign_import_module.m:022:   `:- pragma foreign_import_module'
-bad_foreign_import_module.m:022:   declaration.
-bad_foreign_import_module.m:027: Error: invalid foreign language
-bad_foreign_import_module.m:027:   `"InvalidForeignLang"' in
+bad_foreign_import_module.m:022:   declaration: error: invalid foreign language
+bad_foreign_import_module.m:022:   `"InvalidForeignLang"'.
+bad_foreign_import_module.m:027: In first argument of
  bad_foreign_import_module.m:027:   `:- pragma foreign_import_module'
-bad_foreign_import_module.m:027:   declaration.
+bad_foreign_import_module.m:027:   declaration: error: invalid foreign language
+bad_foreign_import_module.m:027:   `"InvalidForeignLang"'.
  bad_foreign_import_module.m:028: Error: invalid module name `int(int)' in
  bad_foreign_import_module.m:028:   `:- pragma foreign_import_module'
  bad_foreign_import_module.m:028:   declaration.
diff --git a/tests/invalid/bad_foreign_type.err_exp b/tests/invalid/bad_foreign_type.err_exp
index 7618074..acb511a 100644
--- a/tests/invalid/bad_foreign_type.err_exp
+++ b/tests/invalid/bad_foreign_type.err_exp
@@ -2,8 +2,9 @@ bad_foreign_type.m:017: Error: wrong number of arguments in
  bad_foreign_type.m:017:   `:- pragma foreign_type' declaration.
  bad_foreign_type.m:021: Error: wrong number of arguments in
  bad_foreign_type.m:021:   `:- pragma foreign_type' declaration.
-bad_foreign_type.m:025: Error: invalid foreign language `"InvalidLanguage"' in
-bad_foreign_type.m:025:   `:- pragma foreign_type' declaration.
+bad_foreign_type.m:025: In first argument of `:- pragma foreign_type'
+bad_foreign_type.m:025:   declaration error: invalid foreign language
+bad_foreign_type.m:025:   `"InvalidLanguage"'.
  bad_foreign_type.m:029: In second argument of `:- pragma foreign_type'
  bad_foreign_type.m:029:   declaration: error: atom expected at 1111.
  bad_foreign_type.m:033: In third argument of `:- pragma foreign_type'
@@ -27,8 +28,9 @@ bad_foreign_type.m:055:   unrecognized `where' attribute `(foo is bar)'.
  bad_foreign_type.m:055:   Recognized `where' attributes have the form
  bad_foreign_type.m:055:   `equality is <<equality pred name>>' and
  bad_foreign_type.m:055:   `comparison is <<comparison pred name>>'.
-bad_foreign_type.m:060: Error: invalid foreign language `"InvalidLanguage"' in
-bad_foreign_type.m:060:   `:- pragma foreign_type' declaration.
+bad_foreign_type.m:060: In first argument of `:- pragma foreign_type'
+bad_foreign_type.m:060:   declaration error: invalid foreign language
+bad_foreign_type.m:060:   `"InvalidLanguage"'.
  bad_foreign_type.m:061: In second argument of `:- pragma foreign_type'
  bad_foreign_type.m:061:   declaration: error: atom expected at 9999.
  bad_foreign_type.m:062: In third argument of `:- pragma foreign_type'


More information about the reviews mailing list