diff: improved error messages for some syntax errors

Fergus Henderson fjh at hydra.cs.mu.oz.au
Sun Nov 2 23:27:12 AEDT 1997


Estimated hours taken: 1

Improve the error messages for certain kinds of syntax errors,
where variables occur in places that they shouldn't.

compiler/prog_io_goal.m:
	Change parse_qualified_term to take an extra argument,
	the "containing" term, in case the term being parsed
	is a term__variable, which will not have a term__context.
	Use the new argument to give better error messages.

compiler/make_hlds.m:
compiler/prog_io.m:
compiler/prog_io_dcg.m:
compiler/prog_io_pragma.m:
compiler/prog_io_util.m:
	Changed calls to parse_qualified_term to pass the new argument.

tests/invalid/Mmakefile:
tests/invalid/vars_in_wrong_places.m:
tests/invalid/vars_in_wrong_places.err_exp:
	Test cases for the above change.

cvs diff -N compiler/make_hlds.m compiler/prog_io.m compiler/prog_io_dcg.m compiler/prog_io_goal.m compiler/prog_io_pragma.m compiler/prog_io_util.m tests/invalid/Mmakefile tests/invalid/vars_in_wrong_places.err_exp tests/invalid/vars_in_wrong_places.m
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/make_hlds.m,v
retrieving revision 1.242
diff -u -r1.242 make_hlds.m
--- make_hlds.m	1997/10/09 09:38:48	1.242
+++ make_hlds.m	1997/11/02 11:56:38
@@ -2849,10 +2849,10 @@
 	%	NewVar3 = A3.
 	% In the trivial case `X = c', no unravelling occurs.
 
-unravel_unification(term__variable(X), Rhs,
+unravel_unification(term__variable(X), RHS,
 			Context, MainContext, SubContext, VarSet0,
 			Goal, VarSet, Info0, Info) -->
-	{ Rhs = term__functor(F, Args, FunctorContext) },
+	{ RHS = term__functor(F, Args, FunctorContext) },
 	(
 		% Handle explicit type qualification.
 		{ semidet_fail },
@@ -2996,7 +2996,7 @@
 		{ goal_info_set_context(GoalInfo0, Context, GoalInfo) },
 		{ Goal = IfThenElse - GoalInfo }
 	;
-		{ parse_qualified_term(Rhs, "", MaybeFunctor) },
+		{ parse_qualified_term(RHS, RHS, "", MaybeFunctor) },
 		(
 			{ MaybeFunctor = ok(FunctorName, FunctorArgs) },
 			{ list__length(FunctorArgs, Arity) },
Index: compiler/prog_io.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/prog_io.m,v
retrieving revision 1.164
diff -u -r1.164 prog_io.m
--- prog_io.m	1997/10/09 09:39:07	1.164
+++ prog_io.m	1997/11/02 11:55:11
@@ -461,12 +461,12 @@
 			Head = term__functor(term__atom("="),
 					[FuncHead, FuncResult], _)
 		->
-			parse_qualified_term(ModuleName, FuncHead,
+			parse_qualified_term(ModuleName, FuncHead, Head,
 				"equation head", R2),
 			process_func_clause(R2, FuncResult, VarSet2, Body2, R3)
 		;
-			parse_qualified_term(ModuleName, Head, "clause head",
-				R2),
+			parse_qualified_term(ModuleName, Head, Term,
+				"clause head", R2),
 			process_pred_clause(R2, VarSet2, Body2, R3)
 		),
 		add_context(R3, TheContext, Result)
@@ -978,9 +978,19 @@
 :- mode check_for_errors(in, in, in, out) is det.
 check_for_errors(ModuleName, Head, Body, Result) :-
 	( Head = term__variable(_) ->
-		Result = error("variable on LHS of type definition", Head)
+		%
+		% `Head' has no term__context, so we need to get the
+		% context from `Body'
+		%
+		( Body = term__functor(_, _, Context) ->
+			dummy_term_with_context(Context, ErrorTerm)
+		;
+			dummy_term(ErrorTerm)
+		),
+		Result = error("variable on LHS of type definition", ErrorTerm)
 	;
-		parse_qualified_term(ModuleName, Head, "type definition", R),
+		parse_qualified_term(ModuleName, Head, Head,
+			"type definition", R),
 		check_for_errors_2(R, Body, Head, Result)
 	).
 
@@ -1059,7 +1069,7 @@
 	;
 		Term2 = Term
 	),
-	parse_qualified_term(ModuleName, Term2, "constructor definition",
+	parse_qualified_term(ModuleName, Term2, Term, "constructor definition",
 		ok(F, As)),
 	convert_constructor_arg_list(As, Args),
 	Result = F - Args.
@@ -1073,7 +1083,8 @@
 :- mode process_pred(in, in, in, in, in, out) is det.
 
 process_pred(ModuleName, VarSet, PredType, Cond, MaybeDet, Result) :-
-	parse_qualified_term(ModuleName, PredType, "`:- pred' declaration", R),
+	parse_qualified_term(ModuleName, PredType, PredType,
+		"`:- pred' declaration", R),
 	process_pred_2(R, PredType, VarSet, MaybeDet, Cond, Result).
 
 :- pred process_pred_2(maybe_functor, term, varset, maybe(determinism),
@@ -1135,7 +1146,7 @@
 		Term = term__functor(term__atom("="),
 				[FuncTerm, ReturnTypeTerm], _Context)
 	->
-		parse_qualified_term(ModuleName, FuncTerm,
+		parse_qualified_term(ModuleName, FuncTerm, Term,
 			"`:- func' declaration", R),
 		process_func_2(R, FuncTerm, ReturnTypeTerm, VarSet, MaybeDet,
 				Cond, Result)
@@ -1203,12 +1214,12 @@
 		Term = term__functor(term__atom("="),
 				[FuncTerm, ReturnTypeTerm], _Context)
 	->
-		parse_qualified_term(ModuleName, FuncTerm,
+		parse_qualified_term(ModuleName, FuncTerm, Term,
 				"function `:- mode' declaration", R),
 		process_func_mode(R, FuncTerm, ReturnTypeTerm, VarSet, MaybeDet,
 				Cond, Result)
 	;
-		parse_qualified_term(ModuleName, Term,
+		parse_qualified_term(ModuleName, Term, Term,
 				"predicate `:- mode' declaration", R),
 		process_pred_mode(R, Term, VarSet, MaybeDet, Cond, Result)
 	).
@@ -1296,7 +1307,7 @@
 :- pred convert_inst_defn(string, term, term, maybe1(inst_defn)).
 :- mode convert_inst_defn(in, in, in, out) is det.
 convert_inst_defn(ModuleName, Head, Body, Result) :-
-	parse_qualified_term(ModuleName, Head, "inst definition", R),
+	parse_qualified_term(ModuleName, Head, Body, "inst definition", R),
 	convert_inst_defn_2(R, Head, Body, Result).
 
 :- pred convert_inst_defn_2(maybe_functor, term, term, maybe1(inst_defn)).
@@ -1356,7 +1367,7 @@
 :- pred convert_abstract_inst_defn(string, term, maybe1(inst_defn)).
 :- mode convert_abstract_inst_defn(in, in, out) is det.
 convert_abstract_inst_defn(ModuleName, Head, Result) :-
-	parse_qualified_term(ModuleName, Head, "inst definition", R),
+	parse_qualified_term(ModuleName, Head, Head, "inst definition", R),
 	convert_abstract_inst_defn_2(R, Head, Result).
 
 :- pred convert_abstract_inst_defn_2(maybe_functor, term, maybe1(inst_defn)).
@@ -1419,7 +1430,7 @@
 :- pred convert_mode_defn(string, term, term, maybe1(mode_defn)).
 :- mode convert_mode_defn(in, in, in, out) is det.
 convert_mode_defn(ModuleName, Head, Body, Result) :-
-	parse_qualified_term(ModuleName, Head, "mode definition", R),
+	parse_qualified_term(ModuleName, Head, Head, "mode definition", R),
 	convert_mode_defn_2(R, Head, Body, Result).
 
 :- pred convert_mode_defn_2(maybe_functor, term, term, maybe1(mode_defn)).
@@ -1754,7 +1765,7 @@
 	parse_symbol_name_specifier(Term, NameResult),
         process_maybe1(make_arity_predicate_specifier, NameResult, Result)
     ;
-	parse_qualified_term(Term, "predicate specifier", TermResult),
+	parse_qualified_term(Term, Term, "predicate specifier", TermResult),
 	process_typed_predicate_specifier(TermResult, Result)
     ).
 
@@ -1786,7 +1797,7 @@
 	parse_symbol_name_specifier(Term, NameResult),
         process_maybe1(make_arity_predicate_specifier, NameResult, Result)
     ;
-	parse_qualified_term(Term, "constructor specifier", TermResult),
+	parse_qualified_term(Term, Term, "constructor specifier", TermResult),
 	process_typed_predicate_specifier(TermResult, Result)
     ).
 
Index: compiler/prog_io_dcg.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/prog_io_dcg.m,v
retrieving revision 1.6
diff -u -r1.6 prog_io_dcg.m
--- prog_io_dcg.m	1997/10/06 22:18:13	1.6
+++ prog_io_dcg.m	1997/11/02 11:56:53
@@ -42,7 +42,7 @@
 	new_dcg_var(VarSet0, 0, VarSet1, N0, DCG_0_Var),
 	parse_dcg_goal(DCG_Body, VarSet1, N0, DCG_0_Var,
 			Body, VarSet, _N, DCG_Var),
-	parse_qualified_term(ModuleName, DCG_Head, "DCG clause head",
+	parse_qualified_term(ModuleName, DCG_Head, DCG_Body, "DCG clause head",
 			HeadResult),
 	process_dcg_clause(HeadResult, VarSet, DCG_0_Var, DCG_Var, Body, R),
 	add_context(R, DCG_Context, Result).
Index: compiler/prog_io_goal.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/prog_io_goal.m,v
retrieving revision 1.6
diff -u -r1.6 prog_io_goal.m
--- prog_io_goal.m	1997/10/06 22:18:16	1.6
+++ prog_io_goal.m	1997/11/02 12:10:25
@@ -85,23 +85,29 @@
 :- pred sym_name_and_args(term, sym_name, list(term)).
 :- mode sym_name_and_args(in, out, out) is semidet.
 
-	% parse_qualified_term takes a term and an error message,
+	% parse_qualified_term/4 takes a term (and also the containing
+	% term, and a string describing the context from which it
+	% was called [e.g. "clause head"] and the containing term)
 	% and returns a sym_name and a list of argument terms.
 	% Returns an error on ill-formed input.
-:- pred parse_qualified_term(term, string, maybe_functor).
-:- mode parse_qualified_term(in, in, out) is det.
+:- pred parse_qualified_term(term, term, string, maybe_functor).
+:- mode parse_qualified_term(in, in, in, out) is det.
 
-	% parse_qualified_term(DefaultModName, Term, Msg, Result).
-	% parse_qualified_term takes a default module name and a term,
+	% parse_qualified_term(DefaultModName, Term,
+	%	ContainingTerm, Msg, Result):
+	%
+	% parse_qualified_term/5 takes a default module name and a term,
+	% (and also the containing term, and a string describing
+	% the context from which it was called (e.g. "clause head"),
 	% and returns a sym_name and a list of argument terms.
 	% Returns an error on ill-formed input or a module qualifier that
 	% doesn't match the DefaultModName, if DefaultModName is not ""
 	% and not "mercury_builtin".
-	% parse_qualified_term/3 calls parse_qualified_term/4, and is 
+	% parse_qualified_term/4 calls parse_qualified_term/5, and is 
 	% used when no default module name exists.
 
-:- pred parse_qualified_term(string, term, string, maybe_functor).
-:- mode parse_qualified_term(in, in, in, out) is det.
+:- pred parse_qualified_term(string, term, term, string, maybe_functor).
+:- mode parse_qualified_term(in, in, in, in, out) is det.
 
 %-----------------------------------------------------------------------------%
 
@@ -353,12 +359,12 @@
 %-----------------------------------------------------------------------------%
 
 sym_name_and_args(Term, SymName, Args) :-
-	parse_qualified_term(Term, "", ok(SymName, Args)).
+	parse_qualified_term(Term, Term, "", ok(SymName, Args)).
 
-parse_qualified_term(Term, Msg, Result) :-
-	parse_qualified_term("", Term, Msg, Result).
+parse_qualified_term(Term, ContainingTerm, Msg, Result) :-
+	parse_qualified_term("", Term, ContainingTerm, Msg, Result).
 
-parse_qualified_term(DefaultModName, Term, Msg, Result) :-
+parse_qualified_term(DefaultModName, Term, ContainingTerm, Msg, Result) :-
     (
        	Term = term__functor(term__atom(":"), [ModuleTerm, NameArgsTerm],
 		_Context)
@@ -416,7 +422,17 @@
 	    )
         ;
 	    string__append("atom expected in ", Msg, ErrorMsg),
-            Result = error(ErrorMsg, Term)
+	    %
+	    % since variables don't have any term__context,
+	    % if Term is a variable, we use ContainingTerm instead
+	    % (hopefully that _will_ have a term__context).
+	    %
+	    ( Term = term__variable(_) ->
+	    	ErrorTerm = ContainingTerm
+	    ;
+	    	ErrorTerm = Term
+	    ),
+	    Result = error(ErrorMsg, ErrorTerm)
         )
     ).
 
Index: compiler/prog_io_pragma.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/prog_io_pragma.m,v
retrieving revision 1.7
diff -u -r1.7 prog_io_pragma.m
--- prog_io_pragma.m	1997/10/09 09:39:10	1.7
+++ prog_io_pragma.m	1997/11/02 12:02:18
@@ -163,7 +163,7 @@
 		    PredAndModesTerm = term__functor(term__atom("="),
 				[FuncAndArgModesTerm, RetModeTerm], _)
 		->
-		    parse_qualified_term(FuncAndArgModesTerm,
+		    parse_qualified_term(FuncAndArgModesTerm, PredAndModesTerm,
 			"pragma export declaration", FuncAndArgModesResult),  
 		    (
 		        FuncAndArgModesResult = ok(FuncName, ArgModeTerms),
@@ -185,7 +185,7 @@
 		        Result = error(Msg, Term)
 		    )
 		;
-		    parse_qualified_term(PredAndModesTerm,
+		    parse_qualified_term(PredAndModesTerm, ErrorTerm,
 			"pragma export declaration", PredAndModesResult),  
 		    (
 		        PredAndModesResult = ok(PredName, ModeTerms),
@@ -267,7 +267,7 @@
 					term__atom("function"), [], _),
 			PredOrFunc = function 
 		),
-		parse_qualified_term(PredNameTerm,
+		parse_qualified_term(PredNameTerm, ErrorTerm,
 			"predicate name", PredNameResult),
 		PredNameResult = ok(PredName, []),
 		convert_int_list(UnusedArgsTerm, UnusedArgsResult),
@@ -290,7 +290,8 @@
 	    ->
 	    	(
 		    parse_qualified_term(ModuleName, PredNameTerm,
-			    "pragma fact_table declaration", ok(PredName, [])),
+		            PredAndArityTerm, "pragma fact_table declaration",
+			    ok(PredName, [])),
 		    ArityTerm = term__functor(term__integer(Arity), [], _)
 		->
 		    (
@@ -347,7 +348,7 @@
 		PredAndModesTerm = PredAndModesTerm0,
 		FuncResultTerm = []
 	    ),
-	    parse_qualified_term(ModuleName, PredAndModesTerm,
+	    parse_qualified_term(ModuleName, PredAndModesTerm, ErrorTerm,
 		"`pragma termination_info' declaration", PredNameResult),
 	    PredNameResult = ok(PredName, ModeListTerm0),
 	    (
@@ -445,8 +446,8 @@
 	    		[PredNameTerm, ArityTerm], _)
 	    ->
 		(
-		    parse_qualified_term(ModuleName, PredNameTerm, "",
-							ok(PredName, [])),
+		    parse_qualified_term(ModuleName, PredNameTerm, ErrorTerm,
+		    		"", ok(PredName, [])),
 		    ArityTerm = term__functor(term__integer(Arity), [], _)
 		->
 		    call(MakePragma, PredName, Arity, Pragma),
@@ -518,7 +519,7 @@
 	    PredAndVarsTerm = PredAndVarsTerm0,
 	    FuncResultTerms = []
 	),
-	parse_qualified_term(ModuleName, PredAndVarsTerm,
+	parse_qualified_term(ModuleName, PredAndVarsTerm, PredAndVarsTerm0,
 			"pragma c_code declaration", PredNameResult),
 	(
 	    PredNameResult = ok(PredName, VarList0),
Index: compiler/prog_io_util.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/prog_io_util.m,v
retrieving revision 1.5
diff -u -r1.5 prog_io_util.m
--- prog_io_util.m	1997/07/27 15:01:30	1.5
+++ prog_io_util.m	1997/11/02 12:08:25
@@ -155,7 +155,7 @@
 		Inst = ground(shared, yes(FuncInstInfo)),
 		Mode = (Inst -> Inst)
 	;
-		parse_qualified_term(Term, "mode definition", R),
+		parse_qualified_term(Term, Term, "mode definition", R),
 		R = ok(Name, Args),	% should improve error reporting
 		convert_inst_list(Args, ConvertedArgs),
 		Mode = user_defined_mode(Name, ConvertedArgs)
@@ -167,7 +167,8 @@
 	convert_inst_list(T0, T).
 
 convert_inst(term__variable(V), inst_var(V)).
-convert_inst(term__functor(Name, Args0, Context), Result) :-
+convert_inst(Term, Result) :-
+	Term = term__functor(Name, Args0, _Context),
 	% `free' insts
 	( Name = term__atom("free"), Args0 = [] ->
 		Result = free
@@ -250,8 +251,8 @@
 
 	% anything else must be a user-defined inst
 	;
-		parse_qualified_term(term__functor(Name, Args0, Context),
-			"inst", ok(QualifiedName, Args1)),
+		parse_qualified_term(Term, Term, "inst",
+			ok(QualifiedName, Args1)),
 		convert_inst_list(Args1, Args),
 		Result = defined_inst(user_inst(QualifiedName, Args))
 	).
@@ -287,7 +288,8 @@
 convert_bound_inst(InstTerm, functor(ConsId, Args)) :-
 	InstTerm = term__functor(Functor, Args0, _),
 	( Functor = term__atom(_) ->
-		parse_qualified_term(InstTerm, "inst", ok(SymName, Args1)),
+		parse_qualified_term(InstTerm, InstTerm, "inst",
+			ok(SymName, Args1)),
 		list__length(Args1, Arity),
 		ConsId = cons(SymName, Arity)
 	;
Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/tests/invalid/Mmakefile,v
retrieving revision 1.2
diff -u -r1.2 Mmakefile
--- Mmakefile	1997/10/14 06:38:30	1.2
+++ Mmakefile	1997/11/02 12:20:54
@@ -36,7 +36,8 @@
 	unbound_inst_var.m \
 	undef_lambda_mode.m \
 	undef_mode.m \
-	undef_type.m
+	undef_type.m \
+	vars_in_wrong_places.m
 
 # we do not yet pass the following tests:
 #	freefree.m \
Index: tests/invalid/vars_in_wrong_places.err_exp
===================================================================
RCS file: vars_in_wrong_places.err_exp
diff -N vars_in_wrong_places.err_exp
--- /dev/null	Tue Jan  1 15:00:00 1980
+++ vars_in_wrong_places.err_exp	Sun Nov  2 23:21:38 1997
@@ -0,0 +1,8 @@
+vars_in_wrong_places.m:002: Error: atom expected in clause head: _0 :- blah.
+vars_in_wrong_places.m:003: Error: atom expected in equation head: _0 = 42.
+vars_in_wrong_places.m:004: Error: atom expected in equation head: _0 = 42.
+Error: atom expected in `:- pred' declaration: _0.
+vars_in_wrong_places.m:006: Error: atom expected in `:- func' declaration: _0 = int.
+Error: atom expected in predicate `:- mode' declaration: _0.
+vars_in_wrong_places.m:008: Error: atom expected in function `:- mode' declaration: _0 = int.
+For more information, try recompiling with `-E'.
Index: tests/invalid/vars_in_wrong_places.m
===================================================================
RCS file: vars_in_wrong_places.m
diff -N vars_in_wrong_places.m
--- /dev/null	Tue Jan  1 15:00:00 1980
+++ vars_in_wrong_places.m	Sun Nov  2 23:21:18 1997
@@ -0,0 +1,8 @@
+:- module vars_in_wrong_places.
+Oops1 :- blah.
+Oops2 = 42 :- blah.
+Oops3 = 42.
+:- pred Oops4.
+:- func Oops5 = int.
+:- mode Oops6.
+:- mode Oops7 = int.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3         |     -- the last words of T. S. Garp.



More information about the developers mailing list