[m-rev.] diff: improve error messages for variables used as type class method names
Julien Fischer
jfischer at opturion.com
Sun Dec 29 12:52:10 AEDT 2019
Improve error messages for variables used as type class method names.
compiler/parse_item.m:
Generate specific error messages for variables used as type class
method names.
tests/invalid/var_as_pred_name.{m,err_exp}:
Extend this test to cover pred, func and mode declarations
occurring in type class definitions.
Julien.
diff --git a/compiler/parse_item.m b/compiler/parse_item.m
index 32bfe6a..711f2e7 100644
--- a/compiler/parse_item.m
+++ b/compiler/parse_item.m
@@ -916,14 +916,14 @@ parse_pred_or_func_decl_item(ModuleName, VarSet, Functor, ArgTerms,
WithType = no
then
parse_func_decl_base(ModuleName, VarSet,
- BaseTerm, MaybeDetism,
+ BaseTerm, MaybeDetism, IsInClass,
Context, SeqNum, PurityAttrs, QuantConstrAttrs,
MaybeIOM)
else
parse_pred_decl_base(PredOrFunc, ModuleName, VarSet,
BaseTerm, WithType, WithInst, MaybeDetism,
- Context, SeqNum, PurityAttrs, QuantConstrAttrs,
- MaybeIOM)
+ IsInClass, Context, SeqNum, PurityAttrs,
+ QuantConstrAttrs, MaybeIOM)
)
)
else
@@ -950,12 +950,12 @@ parse_pred_or_func_decl_item(ModuleName, VarSet, Functor, ArgTerms,
%
:- pred parse_pred_decl_base(pred_or_func::in, module_name::in, varset::in,
term::in, maybe(mer_type)::in, maybe(mer_inst)::in,
- maybe(determinism)::in, prog_context::in, int::in,
+ maybe(determinism)::in, decl_in_class::in, prog_context::in, int::in,
list(purity_attr)::in, list(quant_constr_attr)::in,
maybe1(item_or_marker)::out) is det.
parse_pred_decl_base(PredOrFunc, ModuleName, VarSet, PredTypeTerm,
- WithType, WithInst, MaybeDet, Context, SeqNum,
+ WithType, WithInst, MaybeDet, IsInClass, Context, SeqNum,
PurityAttrs, QuantConstrAttrs, MaybeIOM) :-
ContextPieces = cord.singleton(words("In")) ++
cord.from_list(pred_or_func_decl_pieces(PredOrFunc)) ++
@@ -970,8 +970,8 @@ parse_pred_decl_base(PredOrFunc, ModuleName, VarSet, PredTypeTerm,
then
% The term parser turns "X(a, b)" into "`'(X, a, b)".
( if
- is_the_name_a_variable(VarSet, vtk_type_decl_pred, PredTypeTerm,
- Spec)
+ is_the_name_a_variable(VarSet, vtk_type_decl_pred(IsInClass),
+ PredTypeTerm, Spec)
then
MaybeIOM = error1([Spec])
else
@@ -1057,12 +1057,12 @@ parse_pred_decl_base(PredOrFunc, ModuleName, VarSet, PredTypeTerm,
% Parse a `:- func p(...)' declaration *without* a with_type clause.
%
:- pred parse_func_decl_base(module_name::in, varset::in, term::in,
- maybe(determinism)::in, prog_context::in, int::in,
+ maybe(determinism)::in, decl_in_class::in, prog_context::in, int::in,
list(purity_attr)::in, list(quant_constr_attr)::in,
maybe1(item_or_marker)::out) is det.
-parse_func_decl_base(ModuleName, VarSet, Term, MaybeDet, Context, SeqNum,
- PurityAttrs, QuantConstrAttrs, MaybeIOM) :-
+parse_func_decl_base(ModuleName, VarSet, Term, MaybeDet, IsInClass, Context,
+ SeqNum, PurityAttrs, QuantConstrAttrs, MaybeIOM) :-
ContextPieces = cord.from_list([words("In"), decl("func"),
words("declaration:"), nl]),
get_class_context_and_inst_constraints_from_attrs(ModuleName, VarSet,
@@ -1078,7 +1078,7 @@ parse_func_decl_base(ModuleName, VarSet, Term, MaybeDet, Context, SeqNum,
then
% The term parser turns "X(a, b)" into "`'(X, a, b)".
( if
- is_the_name_a_variable(VarSet, vtk_type_decl_func,
+ is_the_name_a_variable(VarSet, vtk_type_decl_func(IsInClass),
MaybeSugaredFuncTerm, Spec)
then
MaybeIOM = error1([Spec])
@@ -1340,8 +1340,9 @@ parse_mode_decl(ModuleName, VarSet, Term, IsInClass, Context, SeqNum,
get_term_context(Term), Pieces),
MaybeIOM = error1([Spec])
else
- parse_mode_decl_base(ModuleName, VarSet, BaseTerm, Context, SeqNum,
- WithInst, MaybeDetism, QuantConstrAttrs,MaybeIOM)
+ parse_mode_decl_base(ModuleName, VarSet, BaseTerm, IsInClass,
+ Context, SeqNum, WithInst, MaybeDetism, QuantConstrAttrs,
+ MaybeIOM)
)
else
Specs = get_any_errors1(MaybeMaybeDetism)
@@ -1350,10 +1351,11 @@ parse_mode_decl(ModuleName, VarSet, Term, IsInClass, Context, SeqNum,
).
:- pred parse_mode_decl_base(module_name::in, varset::in, term::in,
- prog_context::in, int::in, maybe(mer_inst)::in, maybe(determinism)::in,
- list(quant_constr_attr)::in, maybe1(item_or_marker)::out) is det.
+ decl_in_class::in, prog_context::in, int::in, maybe(mer_inst)::in,
+ maybe(determinism)::in, list(quant_constr_attr)::in,
+ maybe1(item_or_marker)::out) is det.
-parse_mode_decl_base(ModuleName, VarSet, Term, Context, SeqNum,
+parse_mode_decl_base(ModuleName, VarSet, Term, IsInClass, Context, SeqNum,
WithInst, MaybeDet, QuantConstrAttrs, MaybeIOM) :-
( if
WithInst = no,
@@ -1362,7 +1364,7 @@ parse_mode_decl_base(ModuleName, VarSet, Term, Context, SeqNum,
then
% The term parser turns "X(a, b)" into "`'(X, a, b)".
( if
- is_the_name_a_variable(VarSet, vtk_mode_decl_func,
+ is_the_name_a_variable(VarSet, vtk_mode_decl_func(IsInClass),
MaybeSugaredFuncTerm, Spec)
then
MaybeIOM = error1([Spec])
@@ -1385,7 +1387,8 @@ parse_mode_decl_base(ModuleName, VarSet, Term, Context, SeqNum,
else
% The term parser turns "X(a, b)" into "`'(X, a, b)".
( if
- is_the_name_a_variable(VarSet, vtk_mode_decl_pred, Term, Spec)
+ is_the_name_a_variable(VarSet, vtk_mode_decl_pred(IsInClass),
+ Term, Spec)
then
MaybeIOM = error1([Spec])
else
@@ -1935,10 +1938,10 @@ parse_implicitly_qualified_module_name(DefaultModuleName, VarSet, Term,
%---------------------------------------------------------------------------%
:- type var_term_kind
- ---> vtk_type_decl_pred
- ; vtk_type_decl_func
- ; vtk_mode_decl_pred
- ; vtk_mode_decl_func
+ ---> vtk_type_decl_pred(decl_in_class)
+ ; vtk_type_decl_func(decl_in_class)
+ ; vtk_mode_decl_pred(decl_in_class)
+ ; vtk_mode_decl_func(decl_in_class)
; vtk_clause_pred
; vtk_clause_func.
@@ -1963,17 +1966,41 @@ is_the_name_a_variable(VarSet, Kind, Term, Spec) :-
VarPieces = []
),
(
- Kind = vtk_type_decl_pred,
- WhatPieces = [words("a predicate")]
+ Kind = vtk_type_decl_pred(IsInClass),
+ (
+ IsInClass = decl_is_not_in_class,
+ WhatPieces = [words("a predicate")]
+ ;
+ IsInClass = decl_is_in_class,
+ WhatPieces = [words("a type class predicate method")]
+ )
;
- Kind = vtk_type_decl_func,
- WhatPieces = [words("a function")]
+ Kind = vtk_type_decl_func(IsInClass),
+ (
+ IsInClass = decl_is_not_in_class,
+ WhatPieces = [words("a function")]
+ ;
+ IsInClass = decl_is_in_class,
+ WhatPieces = [words("a type class function method")]
+ )
;
- Kind = vtk_mode_decl_pred,
- WhatPieces = [words("a mode for a predicate")]
+ Kind = vtk_mode_decl_pred(IsInClass),
+ (
+ IsInClass = decl_is_not_in_class,
+ WhatPieces = [words("a mode for a predicate")]
+ ;
+ IsInClass = decl_is_in_class,
+ WhatPieces = [words("a mode for a type class predicate method")]
+ )
;
- Kind = vtk_mode_decl_func,
- WhatPieces = [words("a mode for a function")]
+ Kind = vtk_mode_decl_func(IsInClass),
+ (
+ IsInClass = decl_is_not_in_class,
+ WhatPieces = [words("a mode for a function")]
+ ;
+ IsInClass = decl_is_in_class,
+ WhatPieces = [words("a mode for a type class function method")]
+ )
;
Kind = vtk_clause_pred,
WhatPieces = [words("a clause for a predicate")]
@@ -1990,7 +2017,8 @@ is_the_name_a_variable(VarSet, Kind, Term, Spec) :-
fail
).
-%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
:- func in_pred_or_func_decl_desc(pred_or_func) = string.
in_pred_or_func_decl_desc(pf_function) = "in function declaration".
diff --git a/tests/invalid/var_as_pred_name.err_exp b/tests/invalid/var_as_pred_name.err_exp
index 335feb9..694ce5a 100644
--- a/tests/invalid/var_as_pred_name.err_exp
+++ b/tests/invalid/var_as_pred_name.err_exp
@@ -20,8 +20,22 @@ var_as_pred_name.m:022: Error: you cannot declare a predicate whose name is a
var_as_pred_name.m:022: variable such as `U'.
var_as_pred_name.m:023: Error: you cannot declare a predicate whose name is a
var_as_pred_name.m:023: variable such as `V'.
-var_as_pred_name.m:029: Error: you cannot declare a clause for a function whose
-var_as_pred_name.m:029: name is a variable such as `X'.
-var_as_pred_name.m:032: Error: you cannot declare a clause for a predicate
-var_as_pred_name.m:032: whose name is a variable such as `Y'.
+var_as_pred_name.m:026: Error: you cannot declare a type class predicate method
+var_as_pred_name.m:026: whose name is a variable such as `MA'.
+var_as_pred_name.m:027: Error: you cannot declare a mode for a type class
+var_as_pred_name.m:027: predicate method whose name is a variable such as
+var_as_pred_name.m:027: `MA'.
+var_as_pred_name.m:028: Error: you cannot declare a type class predicate method
+var_as_pred_name.m:028: whose name is a variable such as `MB'.
+var_as_pred_name.m:029: Error: you cannot declare a type class function method
+var_as_pred_name.m:029: whose name is a variable such as `MC'.
+var_as_pred_name.m:030: Error: you cannot declare a mode for a type class
+var_as_pred_name.m:030: function method whose name is a variable such as
+var_as_pred_name.m:030: `MC'.
+var_as_pred_name.m:031: Error: you cannot declare a type class function method
+var_as_pred_name.m:031: whose name is a variable such as `MD'.
+var_as_pred_name.m:038: Error: you cannot declare a clause for a function whose
+var_as_pred_name.m:038: name is a variable such as `X'.
+var_as_pred_name.m:041: Error: you cannot declare a clause for a predicate
+var_as_pred_name.m:041: whose name is a variable such as `Y'.
For more information, recompile with `-E'.
diff --git a/tests/invalid/var_as_pred_name.m b/tests/invalid/var_as_pred_name.m
index 51bf2d5..a076664 100644
--- a/tests/invalid/var_as_pred_name.m
+++ b/tests/invalid/var_as_pred_name.m
@@ -22,6 +22,15 @@
:- pred U(string::in, int::out).
:- pred V(string::in, int::out) is det.
+:- typeclass foo(T) where [
+ pred MA(T, T),
+ mode MA(in, in) is semidet,
+ pred MB(T::in, T::in) is semidet,
+ func MC(T) = T,
+ mode MC(in) = out is semidet,
+ func MD(T::in) = (T::out) is semidet
+].
+
:- implementation.
:- import_module string.
More information about the reviews
mailing list