diff --git a/compiler/prog_io.m b/compiler/prog_io.m index a54bd929f..5fdfdf4bd 100644 --- a/compiler/prog_io.m +++ b/compiler/prog_io.m @@ -1044,14 +1044,6 @@ parse_decl_attribute("all", [TVars, Decl], quantifier(univ, TVarsList), Decl) :- parse_list_of_vars(TVars, TVarsList). -:- pred parse_list_of_vars(term, list(var)). -:- mode parse_list_of_vars(in, out) is semidet. - -parse_list_of_vars(term__functor(term__atom("[]"), [], _), []). -parse_list_of_vars(term__functor(term__atom("."), [Head, Tail], _), [V|Vs]) :- - Head = term__variable(V), - parse_list_of_vars(Tail, Vs). - :- pred check_no_attributes(maybe1(item), decl_attrs, maybe1(item)). :- mode check_no_attributes(in, in, out) is det. diff --git a/compiler/prog_io_goal.m b/compiler/prog_io_goal.m index a6cd8b3ac..3590fb34e 100644 --- a/compiler/prog_io_goal.m +++ b/compiler/prog_io_goal.m @@ -193,7 +193,7 @@ parse_goal_2("<=>", [A0, B0], V0, equivalent(A, B), V):- parse_goal(B0, V1, B, V). parse_goal_2("some", [Vars0, A0], V0, some(Vars, A), V):- - term__vars(Vars0, Vars), + parse_list_of_vars(Vars0, Vars), parse_goal(A0, V0, A, V). % The following is a temporary hack to handle `is' in @@ -227,9 +227,10 @@ parse_goal_with_purity(A0, V0, Purity, A, V) :- parse_some_vars_goal(A0, VarSet0, Vars, A, VarSet) :- ( - A0 = term__functor(term__atom("some"), [Vars0, A1], _Context) + A0 = term__functor(term__atom("some"), [Vars0, A1], _Context), + parse_list_of_vars(Vars0, Vars1) -> - term__vars(Vars0, Vars), + Vars = Vars1, parse_goal(A1, VarSet0, A, VarSet) ; Vars = [], diff --git a/compiler/prog_io_util.m b/compiler/prog_io_util.m index d3b36d6a9..e63aec8ef 100644 --- a/compiler/prog_io_util.m +++ b/compiler/prog_io_util.m @@ -42,6 +42,14 @@ :- pred add_context(maybe1(item), term__context, maybe_item_and_context). :- mode add_context(in, in, out) is det. +% +% Various predicates to parse small bits of syntax. +% These predicates simply fail if they encounter a syntax error. +% + +:- pred parse_list_of_vars(term, list(var)). +:- mode parse_list_of_vars(in, out) is semidet. + :- pred convert_mode_list(list(term), list(mode)). :- mode convert_mode_list(in, out) is semidet. @@ -51,9 +59,6 @@ :- pred convert_inst_list(list(term), list(inst)). :- mode convert_inst_list(in, out) is semidet. - % Parse an inst. - % Fails on syntax errors. - % :- pred convert_inst(term, inst). :- mode convert_inst(in, out) is semidet. @@ -102,6 +107,11 @@ add_context(error(M, T), _, error(M, T)). add_context(ok(Item), Context, ok(Item, Context)). +parse_list_of_vars(term__functor(term__atom("[]"), [], _), []). +parse_list_of_vars(term__functor(term__atom("."), [Head, Tail], _), [V|Vs]) :- + Head = term__variable(V), + parse_list_of_vars(Tail, Vs). + convert_mode_list([], []). convert_mode_list([H0|T0], [H|T]) :- convert_mode(H0, H), diff --git a/compiler/typecheck.m b/compiler/typecheck.m index 441f85d37..d5e0bc1f7 100644 --- a/compiler/typecheck.m +++ b/compiler/typecheck.m @@ -4705,6 +4705,14 @@ report_error_undef_pred(TypeCheckInfo, PredCallId) --> ; [] ) + ; + { PredName = unqualified("some"), Arity = 2 } + -> + io__write_string( + " syntax error in existential quantification: first\n"), + prog_out__write_context(Context), + io__write_string( + " argument of `some' should be a list of variables.\n") ; io__write_string(" error: undefined predicate `"), hlds_out__write_pred_call_id(PredCallId), @@ -4977,6 +4985,8 @@ language_builtin("<=", 2). language_builtin("call", _). language_builtin("impure", 1). language_builtin("semipure", 1). +language_builtin("all", 2). +language_builtin("some", 2). :- pred write_call_context(term__context, pred_call_id, int, unify_context, io__state, io__state). diff --git a/tests/invalid/Mmakefile b/tests/invalid/Mmakefile index cb270bdc6..34a0ab6ad 100644 --- a/tests/invalid/Mmakefile +++ b/tests/invalid/Mmakefile @@ -41,6 +41,7 @@ SOURCES= \ prog_io_erroneous.m \ qual_basic_test2.m \ qualified_cons_id2.m \ + some.m \ spurious_mode_error.m \ test_nested.m \ type_inf_loop.m \ diff --git a/tests/invalid/some.err_exp b/tests/invalid/some.err_exp new file mode 100644 index 000000000..9a8103bbe --- /dev/null +++ b/tests/invalid/some.err_exp @@ -0,0 +1,14 @@ +some.m:006: Error: unrecognized declaration: some junk pred p2(int :: in) is semidet. +some.m:012: In clause for predicate `some:p1/1': +some.m:012: in argument 1 of call to predicate `some/2': +some.m:012: error: undefined symbol `junk/0'. +some.m:012: In clause for predicate `some:p1/1': +some.m:012: syntax error in existential quantification: first +some.m:012: argument of `some' should be a list of variables. +some.m:013: In clause for predicate `some:p3/1': +some.m:013: in argument 1 of call to predicate `some/2': +some.m:013: error: undefined symbol `junk/0'. +some.m:013: In clause for predicate `some:p3/1': +some.m:013: syntax error in existential quantification: first +some.m:013: argument of `some' should be a list of variables. +For more information, try recompiling with `-E'. diff --git a/tests/invalid/some.m b/tests/invalid/some.m new file mode 100644 index 000000000..c64f7e0aa --- /dev/null +++ b/tests/invalid/some.m @@ -0,0 +1,14 @@ +:- module (some). + +:- interface. + +:- pred p1(int::in) is semidet. +:- some junk pred p2(int::in) is semidet. +:- pred p3(int::in) is semidet. + +:- implementation. +:- import_module int. + +p1(X) :- some junk p3(X). +p3(X) :- ( some junk X > 0 -> X = 42 ; X = -42 ). +