[m-rev.] for review: better error messages for bad inst and mode names
Julien Fischer
jfischer at opturion.com
Tue Apr 26 09:18:37 AEST 2016
Hi Zoltan,
On Fri, 22 Apr 2016, Zoltan Somogyi wrote:
> Generate better error messages for bad insts and modes.
>
> compiler/parse_inst_mode_name.m:
> When trying to parse an inst or mode name and failing, we used to just
> print the whole term (including the correct parts) and a message about
> the mode being invalid. We now print a message for each incorrect *part*
> of a term, and make its message specific to the particular problem.
...
> diff --git a/compiler/parse_class.m b/compiler/parse_class.m
> index d606a82..cde77bd 100644
> --- a/compiler/parse_class.m
> +++ b/compiler/parse_class.m
> @@ -567,9 +567,36 @@ parse_arbitrary_constraint_list(VarSet, HeadTerm, TailTerms, Result) :-
>
> parse_arbitrary_constraint(VarSet, ConstraintTerm, Result) :-
> ( if
> - parse_inst_constraint(ConstraintTerm, InstVar, Inst)
> + ConstraintTerm = term.functor(term.atom("=<"), [LHSTerm, RHSTerm], _)
> + then
> + (
> + LHSTerm = term.variable(InstVar0, _),
> + term.coerce_var(InstVar0, InstVar1),
> + MaybeInstVar = ok1(InstVar1)
> + ;
> + LHSTerm = term.functor(_, _, LHSContext),
> + LHSTermStr = describe_error_term(VarSet, LHSTerm),
> + LHSPieces = [words("Error: a non-variable inst such as"),
Add some commas there.
Error: a non-variable inst, such as `foo', may not be the
> diff --git a/compiler/parse_inst_mode_name.m b/compiler/parse_inst_mode_name.m
> index 489d710..6de7a7d 100644
> --- a/compiler/parse_inst_mode_name.m
> +++ b/compiler/parse_inst_mode_name.m
> @@ -15,39 +15,56 @@
...
>
> % XXX These predicates should take a ContextPieces argument, be det,
> % and return a maybe1(...) result.
> %
> -:- pred convert_mode_list(allow_constrained_inst_var::in, list(term)::in,
> - list(mer_mode)::out) is semidet.
> -:- pred convert_mode(allow_constrained_inst_var::in, term::in, mer_mode::out)
> - is semidet.
> +:- pred parse_modes(allow_constrained_inst_var::in, varset::in,
> + cord(format_component)::in, list(term)::in, maybe1(list(mer_mode))::out)
> + is det.
> +:- pred parse_mode(allow_constrained_inst_var::in, varset::in,
> + cord(format_component)::in, term::in, maybe1(mer_mode)::out) is det.
Presumably you can delete the XXX comment above now?
> %---------------------------------------------------------------------------%
> @@ -60,62 +77,137 @@
> :- import_module mdbcomp.prim_data.
> :- import_module mdbcomp.sym_name.
> :- import_module parse_tree.parse_sym_name.
> +:- import_module parse_tree.parse_tree_out_term.
> :- import_module parse_tree.parse_util.
> :- import_module parse_tree.prog_util.
>
> :- import_module bool.
> :- import_module set.
> +:- import_module string.
...
> +parse_mode(AllowConstrainedInstVar, VarSet, ContextPieces, Term, MaybeMode) :-
> + (
> + Term = term.variable(_, Context),
> + TermStr = describe_error_term(VarSet, Term),
> + Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
> + words("Error: a variable such as"), quote(TermStr),
> + words("is not a valid mode."), nl],
> + Spec = error_spec(severity_error, phase_term_to_parse_tree,
> + [simple_msg(Context, [always(Pieces)])]),
> + MaybeMode = error1([Spec])
> + ;
> + Term = term.functor(TermFunctor, ArgTerms0, Context),
> + (
> + (
> + TermFunctor = term.integer(_),
> + Name = "an integer"
> + ;
> + TermFunctor = term.big_integer(_, _),
> + Name = "an integer"
> + ;
> + TermFunctor = term.float(_),
> + Name = "a floating point number"
> + ;
> + TermFunctor = term.string(_),
> + Name = "a string"
> + ;
> + TermFunctor = term.implementation_defined(_),
> + Name = "an implementation defined literal"
> + ),
> + TermStr = describe_error_term(VarSet, Term),
> + Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
> + words("Error:"), words(Name), words("such as"), quote(TermStr),
Ditto w.r.t to commas.
...
> @@ -499,65 +787,199 @@ convert_higher_order_inst(AllowConstrainedInstVar, BeforeIsTerm, DetTerm,
> ;
> IsAny = yes,
> Inst = any(shared, higher_order(FuncInst))
> + ),
> + MaybeInst = ok1(Inst)
> + else
> + Specs = get_any_errors1(MaybeArgModes0)
> + ++ get_any_errors1(MaybeRetMode)
> + ++ get_any_errors1(MaybeDetism),
> + MaybeInst = error1(Specs)
> )
> + else
> + Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
> + words("Error: a higher-order ints should have"),
Typo: s/ints/inst/
> + words("one of the following forms:"), nl,
> + quote("pred(<inst1>, ...) is <detism>"), nl,
> + quote("any_pred(<inst1>, ...) is <detism>"), nl,
> + quote("func(<inst1>, ...) = <return_inst> is <detism>"), nl,
> + quote("any_func(<inst1>, ...) = <return_inst> is <detism>"), nl,
> + suffix("."), nl],
> + Spec = error_spec(severity_error, phase_term_to_parse_tree,
> + [simple_msg(get_term_context(BeforeIsTerm), [always(Pieces)])]),
> + MaybeInst = error1([Spec])
> ).
....
> + TermStr = describe_error_term(VarSet, Term),
> + Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
> + words("Error: an implementation defined literal"),
> + words("such as"), quote(TermStr),
Add commas.
> + words("may not be a used as a bound inst."), nl],
> + Spec = error_spec(severity_error, phase_term_to_parse_tree,
> + [simple_msg(Context, [always(Pieces)])]),
> + MaybeBoundInst = error1([Spec])
> ;
> ( Functor = term.integer(_)
> ; Functor = term.big_integer(_, _)
> ; Functor = term.float(_)
> ; Functor = term.string(_)
> ),
> - Args1 = Args0,
> - list.length(Args1, Arity),
> - make_functor_cons_id(Functor, Arity, ConsId)
> + (
> + ArgTerms0 = [],
> + det_make_functor_cons_id(Functor, 0, ConsId),
> + BoundInst = bound_functor(ConsId, []),
> + MaybeBoundInst = ok1(BoundInst)
> + ;
> + ArgTerms0 = [_ | _],
> + ( Functor = term.integer(_), FunctorStr = "integer"
> + ; Functor = term.big_integer(_, _), FunctorStr = "integer"
> + ; Functor = term.float(_), FunctorStr = "float"
> + ; Functor = term.string(_), FunctorStr = "string"
> ),
> - convert_inst_list(AllowConstrainedInstVar, Args1, Args),
> - BoundInst = bound_functor(ConsId, Args).
> + TermStr = describe_error_term(VarSet, Term),
> + Pieces = cord.list(ContextPieces) ++
> + [lower_case_next_if_not_first, words("Error:"),
> + words("a"), words(FunctorStr), words("such as"),
For FunctorStr = "integer", that should read "*an* integer" not "a integer".
Also, add commas around "such as ...".
> + quote(TermStr), words("may not have any arguments."), nl],
> + Spec = error_spec(severity_error, phase_term_to_parse_tree,
> + [simple_msg(Context, [always(Pieces)])]),
> + MaybeBoundInst = error1([Spec])
> + )
> + )
> + ).
...
> diff --git a/compiler/parse_item.m b/compiler/parse_item.m
> index 35d89c1..f708d53 100644
> --- a/compiler/parse_item.m
> +++ b/compiler/parse_item.m
> @@ -808,8 +808,11 @@ parse_pred_or_func_decl_item(ModuleName, VarSet, Functor, ArgTerms,
> ( if ArgTerms = [Term] then
> parse_determinism_suffix(VarSet, Term, BeforeDetismTerm,
> MaybeMaybeDetism),
> - parse_with_inst_suffix(BeforeDetismTerm, BeforeWithInstTerm,
> - MaybeWithInst),
> + WithInstContextPieces = cord.from_list([
> + words("In the with_inst annotation of a"),
Quote wth_inst.
> + words(pred_or_func_to_string(PredOrFunc)), words("declaration:")]),
> + parse_with_inst_suffix(VarSet, WithInstContextPieces,
> + BeforeDetismTerm, BeforeWithInstTerm, MaybeWithInst),
> parse_with_type_suffix(VarSet, BeforeWithInstTerm, BeforeWithTypeTerm,
> MaybeWithType),
> BaseTerm = BeforeWithTypeTerm,
The rest looks fine.
Julien.
More information about the reviews
mailing list