diff: det_report.m: report error for nondet functions

Fergus Henderson fjh at cs.mu.oz.au
Fri Jul 4 00:32:46 AEST 1997


Hi,

Zoltan, can you please review this one?

compiler/det_report.m:
	Report an error if a "forward" mode of a function,
	(a mode for which all the arguments are fully input)
	has determinism nondet, multi, cc_nondet or cc_multi.
	Such functions should be illegal because they break
	referential transparency.

doc/reference_manual.texi:
	Document the above change.

tests/invalid/Mmake:
tests/invalid/multisoln_func.m:
	Test cases for the above change.

Index: det_report.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/det_report.m,v
retrieving revision 1.36
diff -u -r1.36 det_report.m
--- det_report.m	1997/07/01 04:03:50	1.36
+++ det_report.m	1997/07/03 13:59:03
@@ -168,7 +168,60 @@
 	;
 		{ ModuleInfo2 = ModuleInfo1 }
 	),
-	global_checking_pass(Rest, ModuleInfo2, ModuleInfo).
+	% Functions can only have more than one solution if it is a
+	% non-standard mode.  Otherwise, they would not be referentially
+	% transparent.  (Nondeterministic "functions" like C's `rand()'
+	% function are not allowed.)
+	(
+		% if it is a mode for a function...
+		{ pred_info_get_is_pred_or_func(PredInfo, function) },
+		% ... that can succeed more than once ...
+		{ determinism_components(InferredDetism, _CanFail, NumSolns) },
+		{ NumSolns \= at_most_zero },
+		{ NumSolns \= at_most_one },
+		% ... but for which all the arguments are input ...
+		{ proc_info_argmodes(ProcInfo, PredArgModes) },
+		{ pred_args_to_func_args(PredArgModes,
+			FuncArgModes, _FuncResultMode) },
+		{ \+ (
+			list__member(FuncArgMode, FuncArgModes),
+			\+ mode_is_fully_input(ModuleInfo2, FuncArgMode)
+		  )
+	 	} 
+	->
+		% ... then it is an error.
+		{ pred_info_name(PredInfo, PredName) },
+		{ proc_info_context(ProcInfo, FuncContext) },
+		prog_out__write_context(FuncContext),
+		io__write_string("Error: invalid determinism for `"),
+		report_pred_name_mode(function, PredName, PredArgModes),
+		io__write_string("':\n"),
+		prog_out__write_context(FuncContext),
+		io__write_string(
+			"  the primary mode for a function cannot be `"),
+		mercury_output_det(InferredDetism),
+		io__write_string(
+			"'.\n"),
+		globals__io_lookup_bool_option(verbose_errors, VerboseErrors),
+		( { VerboseErrors = yes } ->
+			io__write_strings([
+"\tIn Mercury, a function is supposed to be a true mathematical function\n",
+"\tof its arguments; that is, the value of the function's result should\n",
+"\tbe determined only by the values of its arguments.\n",
+"\t(Allowing functions to have more than one result for the same\n",
+"\targuments would break referential transparency.)\n",
+"\tMost likely, this procedure should be a predicate, not a function.\n"
+			])
+		;
+			[]
+		),
+		{ module_info_incr_errors(ModuleInfo2,
+			ModuleInfo3) }
+		
+	;
+		{ ModuleInfo3 = ModuleInfo2 }
+	),
+	global_checking_pass(Rest, ModuleInfo3, ModuleInfo).
 
 det_check_lambda(DeclaredDetism, InferredDetism, Goal, GoalInfo, DetInfo,
 		Msgs) :-

Index: ../doc/reference_manual.texi
===================================================================
RCS file: /home/staff/zs/imp/mercury/doc/reference_manual.texi,v
retrieving revision 1.50
diff -u -r1.50 reference_manual.texi
--- reference_manual.texi	1997/04/22 03:11:57	1.50
+++ reference_manual.texi	1997/07/03 14:25:18
@@ -1515,6 +1515,14 @@
 If you want to write a partial function, i.e. one whose determinism
 is @samp{semidet}, then you must explicitly declare the mode and determinism.
 
+In Mercury, a function is supposed to be a true mathematical function
+of its arguments; that is, the value of the function's result should
+be determined only by the values of its arguments.  Hence, for
+any mode of a function that specifies that all the arguments are fully
+input (i.e. for which the initial inst of all the arguments is a ground inst),
+the determinism of that mode can only be
+ at samp{det}, @samp{semidet}, @samp{erroneous}, or @samp{failure}.
+
 The determinism categories form this lattice:
 
 @example

Index: Mmake
===================================================================
RCS file: /home/staff/zs/imp/tests/invalid/Mmake,v
retrieving revision 1.18
diff -u -r1.18 Mmake
--- Mmake	1997/06/27 04:05:20	1.18
+++ Mmake	1997/07/03 13:57:28
@@ -23,6 +23,7 @@
 	modes_erroneous.m \
 	mostly_uniq1.m \
 	mostly_uniq2.m \
+	multisoln_func.m \
 	occurs.m \
 	pragma_c_code_and_clauses1.m \
 	pragma_c_code_and_clauses2.m \
@@ -38,6 +39,8 @@
 #	prog_io_erroneous.m \
 #	qualified_cons_id2.m \
 #	types.m
+
+MCFLAGS-multisoln_func	=	--infer-types
 
 DEPS=		$(SOURCES:%.m=%.dep)
 DEPENDS=	$(SOURCES:%.m=%.depend)

:- module multisoln_func.
:- interface.
:- import_module io.

:- pred main(io__state::di, io__state::uo) is det.

:- implementation.
:- import_module int, list, std_util.

main --> [].

:- func f(int) = list(int).
:- mode f(in) = out is cc_multi.	% illegal

f(X) = L :-
	unsorted_solutions((pred(Y::out) is multi :- Y = X ; Y = X + 1), L).

:- func test = int.
:- mode test = out is cc_multi.	% illegal

test = 123.
test = 456.

% test type inference

:- mode test2 = out is multi.	% illegal
test2 = 123.
test2 = 456.

:- mode test3(in) = out is nondet.	% illegal
test3(1) = 123.
test3(1) = 456.

:- mode test3b(in) = out is cc_nondet.	% illegal
test3b(1) = 123.
test3b(1) = 456.

% this one is legal
:- func test4(int::out) = (int::out) is multi.
test4(1) = 1.
test4(2) = 2.

% this one is legal
:- func test5(int::out) = (int::in) is cc_nondet.
test5(1) = 42.
test5(2) = 42.

multisoln_func.m:026: Inferred :- func test2 = int.
multisoln_func.m:030: Inferred :- func test3(int) = int.
multisoln_func.m:034: Inferred :- func test3b(int) = int.
multisoln_func.m:013: Error: invalid determinism for `f(in) = out'.
multisoln_func.m:013:   The primary mode for a function cannot be `cc_multi'.
multisoln_func.m:019: Error: invalid determinism for `test = out'.
multisoln_func.m:019:   The primary mode for a function cannot be `cc_multi'.
multisoln_func.m:026: Error: invalid determinism for `test2 = out'.
multisoln_func.m:026:   The primary mode for a function cannot be `multi'.
multisoln_func.m:030: Error: invalid determinism for `test3(in) = out'.
multisoln_func.m:030:   The primary mode for a function cannot be `nondet'.
multisoln_func.m:034: Error: invalid determinism for `test3b(in) = out'.
multisoln_func.m:034:   The primary mode for a function cannot be `cc_nondet'.
For more information, try recompiling with `-E'.

-- 
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