[m-rev.] for review: improve error reporting for foreign_type pragmas
Julien Fischer
jfischer at opturion.com
Mon Mar 13 21:26:35 AEDT 2017
Hi Zoltan,
On Mon, 13 Mar 2017, Zoltan Somogyi wrote:
> On Mon, 13 Mar 2017 16:55:26 +1100 (AEDT), Julien Fischer <jfischer at opturion.com> wrote:
>> diff --git a/compiler/parse_pragma.m b/compiler/parse_pragma.m
>> index f7732bd..a3e3fb4 100644
>> --- a/compiler/parse_pragma.m
>> +++ b/compiler/parse_pragma.m
>> @@ -411,6 +404,7 @@ parse_pragma_foreign_type(ModuleName, VarSet, ErrorTerm, PragmaTerms,
>> ),
>> Assertions = foreign_type_assertions(AssertionsSet),
>> ( if
>> + MaybeForeignLang = ok1(_),
>> MaybeMaybeUC = ok1(MaybeUC),
>> MaybeForeignType = ok1(ForeignType),
>> MaybeTypeDefnHead = ok2(MercuryTypeSymName, MercuryParams),
>> @@ -427,6 +421,7 @@ parse_pragma_foreign_type(ModuleName, VarSet, ErrorTerm, PragmaTerms,
>> Specs = get_any_errors1(MaybeMaybeUC) ++
>> get_any_errors1(MaybeForeignType) ++
>> get_any_errors2(MaybeTypeDefnHead) ++
>> + get_any_errors1(MaybeForeignLang) ++
>> AssertionSpecs,
>> MaybeIOM = error1(Specs)
>> )
>
> I put the tests for ok/1 and the get_any_errors calls in the *same* order.
Done. I have also reordered them to match the argument order of the
pragma.
>> @@ -454,10 +449,13 @@ parse_foreign_type_assertions(VarSet, Term, !Assertions, !Specs) :-
>> then
>> true
>> else
>> - TermStr = mercury_term_to_string(VarSet, print_name_only,
>> - Term),
>> - Pieces = [words("Error: foreign type assertion"),
>> - quote(TermStr), words("is repeated."), nl],
>> + HeadTermStr = mercury_term_to_string(VarSet, print_name_only,
>> + HeadTerm),
>> + Pieces = [
>> + words("In fourth argument of"), pragma_decl("foreign_type"),
>> + words("declaration: error:"), words("foreign type assertion"),
>> + quote(HeadTermStr), words("is repeated.")
>> + ],
>
> Here and elsewhere: I think this code would be more robust in the face of
> possible future changes in syntax if the "In the nth arg of xxx:" part of that
> error message was passed in by the caller as ContextPieces. That way,
> the code that picks up the nth arg and the code decides on the context pieces
> are next to each other.
Done.
>> + ;
>> + MaybeLanguage = error1(_),
>> + MaybeForeignLangType = error1([]) % Dummy value.
>> )
>
> I think this calls for a comment to say that if get here, MaybeForeignLang
> will be error, and give the user the required error message.
Done.
>> --- a/compiler/parse_type_defn.m
>> +++ b/compiler/parse_type_defn.m
>> @@ -38,13 +38,22 @@
>> list(term)::in, prog_context::in, int::in, is_solver_type::in,
>> maybe1(item_or_marker)::out) is det.
>>
>> - % parse_type_defn_head(ModuleName, VarSet, Head, HeadResult):
>> + % Are we parsing the type defn head in a `:- type' declaration or the in
>> + % the second argument of a foreign_type pragma?
>
> "the in"
Fixed.
>> + EndTermStr = describe_error_term(VarSet, EndTerm),
>> + Pieces = [
>> + words("In"), pragma_decl("foreign_type"),
>> + words("declaration: error:"),
>> + words("unrecognized or unexpected"), quote("where"),
>> + words("attribute"), quote(EndTermStr), suffix("."), nl],
>
> "unrecognized or unexpected": pick only one.
The existing error message used that wording; I have changed it to just
"unrecognized".
> I would also add a verbose_only message component that lists
> the two attributes that *are* expected in this posititon.
Done, the verbose part reads as follows:
bad_foreign_type.m:066: Recognized `where' attributes have the form
bad_foreign_type.m:066: `equality is <<equality pred name>>' and
bad_foreign_type.m:066: `comparison is <<comparison pred name>>'.
(We should do something similar for regular type declarations as well.)
>> @@ -1358,16 +1376,37 @@ maybe_unify_compare(MaybeEqPred, MaybeCmpPred) =
>> % Predicates useful for parsing several kinds of type definitions.
>> %
>>
>> -parse_type_defn_head(ModuleName, VarSet, HeadTerm, MaybeTypeCtorAndArgs) :-
>> +parse_type_defn_head(ParseContext, ModuleName, VarSet, HeadTerm,
>> + MaybeTypeCtorAndArgs) :-
>> (
>> - HeadTerm = term.variable(_, Context),
>> - Pieces = [words("Error: variable on LHS of type definition."), nl],
>> + HeadTerm = term.variable(Var, Context),
>> + (
>> + ParseContext = tdhpc_type_defn,
>> + Pieces = [words("Error: variable on LHS of type definition."), nl]
>> + ;
>> + ParseContext = tdhpc_foreign_type_pragma,
>> + VarName = varset.lookup_name(VarSet, Var),
>> + Pieces = [
>> + words("In second argument of"), pragma_decl("foreign_type"),
>> + words("declaration: error: expected a type name declared"),
>> + words("using a"), decl("type"), words("declaration, got"),
>> + words("type variable"), quote(VarName), suffix(".")
>> + ]
>> + ),
>
> Again, I would pass the ContextPieces here, as an argument of tdhpc_foreign_type_pragma.
Done.
> Also, I would expand LHS in the error message for tdhpc_type_defn.
I've left this for a separate change as it isn't related to foreign_type
pragmas.
>> Spec = error_spec(severity_error, phase_term_to_parse_tree,
>> [simple_msg(Context, [always(Pieces)])]),
>> MaybeTypeCtorAndArgs = error2([Spec])
>> ;
>> HeadTerm = term.functor(_, _, HeadContext),
>> - ContextPieces = cord.singleton(words("In type definition:")),
>> + (
>> + ParseContext = tdhpc_type_defn,
>> + ContextPieces = cord.singleton(words("In type definition:"))
>> + ;
>> + ParseContext = tdhpc_foreign_type_pragma,
>> + ContextPieces = cord.from_list([
>> + words("In"), pragma_decl("foreign_type"), words("declaration:")
>> + ])
>> + ),
>
> You could use the ContextPieces here as well, and they would be more precise,
> since they would give the argument number.
Done.
>> +bad_foreign_type.m:029: In `:- pragma foreign_type' declaration: error: atom
>> +bad_foreign_type.m:029: expected at 1111.
>> +bad_foreign_type.m:033: In third argument of `:- pragma foreign_type'
>> +bad_foreign_type.m:033: declaration: error: invalid foreign type descriptor
>> +bad_foreign_type.m:033: `2222'.
>
> This may be separate from your change, but I think I would prefer to word
> both of those messages following the "expected abc, got def" template.
Addressing the first one will require changing how the predicates in
compiler/parse_sym_name.m handle errors. That's definitely a separate
change as they're used all over the place.
I've changed the second one so that it now reads as follows:
bad_foreign_type.m:033: In third argument of `:- pragma foreign_type'
bad_foreign_type.m:033: declaration: error: expected a string specifying the
bad_foreign_type.m:033: foreign type descriptor, got `2222'.
> Apart from that, the diff is fine.
Thanks for the review,
Julien.
More information about the reviews
mailing list