[m-dev.] for review: func decls with determinism, but no modes

Tyson Dowd trd at cs.mu.OZ.AU
Tue Feb 15 18:46:38 AEDT 2000


Hi,

Anyone familiar with the compiler front end can review this one.

I got annoyed at how much trouble it was to write tests for predicates
like list__filter.  This allows you to write semidet functions very
easily.

===================================================================


Estimated hours taken: 12 

Allow functions to be declared by supplying the determinism but not the
modes (we assume the default modes).  

compiler/make_hlds.m:
	Assume default modes if determinism is declared without modes
	in the :- func declaration.

compiler/prog_io.m:
	Don't give an error message for determinism without modes for
	function.

compiler/prog_io_goal.m:
	Update documentation to reflect default mode syntax.
	Assume default modes if determinism is declared without modes
	in lambda expressions.

compiler/prog_util.m:
	Mention that declaring modes for some but not all of the
	arguments of a function will be noticed in prog_io, so shouldn't
	be a concern in this code.

doc/reference_manual.texi:
	Document the new syntax.

tests/valid/Mmakefile:
tests/valid/func_default_modes.m:
	A test case for the new syntax.


Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.323
diff -u -r1.323 make_hlds.m
--- compiler/make_hlds.m	2000/02/08 06:59:24	1.323
+++ compiler/make_hlds.m	2000/02/14 05:38:07
@@ -2233,12 +2233,29 @@
 	;
 		DeclStatus = Status
 	},
-	{ split_types_and_modes(TypesAndModes, Types, MaybeModes) },
-	{ split_type_and_mode(RetTypeAndMode, RetType, MaybeRetMode) },
+
+	{ split_types_and_modes(TypesAndModes, Types, MaybeModes0) },
+	{ split_type_and_mode(RetTypeAndMode, RetType, MaybeRetMode0) },
 	{ list__append(Types, [RetType], Types1) },
 	add_new_pred(Module0, TypeVarSet, ExistQVars, FuncName, Types1, Cond,
 		Purity, ClassContext, Markers, Context, DeclStatus, NeedQual,
 		function, Module1),
+	{
+		% If there are no modes, but there is a determinism
+		% declared, assume the function has the default modes.
+		(MaybeModes0 = no ; MaybeRetMode0 = no),
+		MaybeDet = yes(_)
+	->
+		list__length(Types, Arity),
+		in_mode(InMode),
+		list__duplicate(Arity, InMode, InModes),
+		MaybeModes = yes(InModes),
+		out_mode(OutMode),
+		MaybeRetMode = yes(OutMode)
+	;
+		MaybeModes = MaybeModes0,
+		MaybeRetMode = MaybeRetMode0
+	},
 	(
 		{ MaybeModes = yes(Modes) },
 		{ MaybeRetMode = yes(RetMode) }
Index: compiler/prog_io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_io.m,v
retrieving revision 1.186
diff -u -r1.186 prog_io.m
--- compiler/prog_io.m	2000/01/13 06:16:49	1.186
+++ compiler/prog_io.m	2000/02/15 07:36:33
@@ -1914,13 +1914,6 @@
 		"function result has mode, but function arguments don't",
 					FuncTerm)
 			;
-				ReturnType = type_only(_),
-				MaybeDet = yes(_)
-			->
-				Result = error(
-"function declaration specifies a determinism but does not specify the mode",
-					FuncTerm)
-			;
 				% note: impure or semipure functions are not
 				% allowed
 				Purity = (pure),
Index: compiler/prog_io_goal.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_io_goal.m,v
retrieving revision 1.17
diff -u -r1.17 prog_io_goal.m
--- compiler/prog_io_goal.m	1999/07/13 08:53:24	1.17
+++ compiler/prog_io_goal.m	2000/02/08 06:01:30
@@ -69,7 +69,17 @@
 	% of their corresponding modes, and a determinism.  The syntax
 	% of a higher-order func expression is
 	% 	`(func(Var1::Mode1, ..., VarN::ModeN) = (VarN1::ModeN1) is Det
-	%		:- Goal)'.
+	%		:- Goal)'
+	% or
+	% 	`(func(Var1, ..., VarN) = (VarN1) is Det :- Goal)'
+	% 		where the modes are assumed to be `in' for the
+	% 		function arguments and `out' for the result
+	% or
+	% 	`(func(Var1, ..., VarN) = (VarN1) :- Goal)'
+	% 		where the modes are assumed as above, and the
+	% 		determinism is assumed to be det
+	% or
+	% 	`(func(Var1, ..., VarN) = (VarN1). '
 	%
 :- pred parse_func_expression(term, lambda_eval_method, list(prog_term),
 		list(mode), determinism).
@@ -324,16 +334,33 @@
 	standard_det(DetString, Det),
 	parse_lambda_eval_method(FuncEvalArgsTerm, EvalMethod, FuncArgsTerm),
 	FuncArgsTerm = term__functor(term__atom("func"), FuncArgsList, _),
-	parse_pred_expr_args(FuncArgsList, Args0, Modes0),
-	parse_lambda_arg(RetTerm, RetArg, RetMode),
-	list__append(Args0, [RetArg], Args),
-	list__append(Modes0, [RetMode], Modes).
+
+	( parse_pred_expr_args(FuncArgsList, Args0, Modes0) ->
+		parse_lambda_arg(RetTerm, RetArg, RetMode),
+		list__append(Args0, [RetArg], Args),
+		list__append(Modes0, [RetMode], Modes)
+	;
+		%
+		% the argument modes default to `in',
+		% the return mode defaults to `out'
+		%
+		in_mode(InMode),
+		out_mode(OutMode),
+		list__length(FuncArgsList, NumArgs),
+		list__duplicate(NumArgs, InMode, Modes0),
+		RetMode = OutMode,
+		list__append(Modes0, [RetMode], Modes),
+		list__append(FuncArgsList, [RetTerm], Args1),
+		list__map(term__coerce, Args1, Args)
+	).
+
+
 parse_func_expression(FuncTerm, EvalMethod, Args, Modes, Det) :-
 	%
 	% parse a func expression with unspecified modes and determinism
 	%
 	FuncTerm = term__functor(term__atom("="),
-		[FuncEvalArgsTerm, RetArg], _),
+		[FuncEvalArgsTerm, RetTerm], _),
 	parse_lambda_eval_method(FuncEvalArgsTerm, EvalMethod, FuncArgsTerm),
 	FuncArgsTerm = term__functor(term__atom("func"), Args0, _),
 	%
@@ -348,7 +375,7 @@
 	RetMode = OutMode,
 	Det = det,
 	list__append(Modes0, [RetMode], Modes),
-	list__append(Args0, [RetArg], Args1),
+	list__append(Args0, [RetTerm], Args1),
 	list__map(term__coerce, Args1, Args).
 
 parse_lambda_eval_method(Term0, EvalMethod, Term) :-
Index: compiler/prog_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_util.m,v
retrieving revision 1.48
diff -u -r1.48 prog_util.m
--- compiler/prog_util.m	2000/01/13 06:17:01	1.48
+++ compiler/prog_util.m	2000/02/08 09:28:00
@@ -219,6 +219,8 @@
 	% if a pred declaration specifies modes for some but
 	% not all of the arguments, then the modes are ignored
 	% - should this be an error instead?
+	% trd: this should never happen because prog_io.m will detect
+	% these cases
 
 :- pred split_type_and_mode(type_and_mode, bool, type, mode, bool).
 :- mode split_type_and_mode(in, in, out, out, out) is det.
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.172
diff -u -r1.172 reference_manual.texi
--- doc/reference_manual.texi	2000/02/11 05:04:05	1.172
+++ doc/reference_manual.texi	2000/02/15 04:54:33
@@ -878,6 +878,7 @@
 pred(Arg1::Mode1, Arg2::Mode2, @dots{}) is Det :- Goal
 pred(Arg1::Mode1, Arg2::Mode2, @dots{}, DCGMode0, DCGMode1) is Det --> DCGGoal
 func(Arg1::Mode1, Arg2::Mode2, @dots{}) = (Result::Mode) is Det :- Goal
+func(Arg1, Arg2, @dots{}) = (Result) is Det :- Goal
 func(Arg1, Arg2, @dots{}) = Result :- Goal
 @end example
 
@@ -1991,6 +1992,10 @@
 (and similarly for functions).
 In particular, this is necessary
 if a predicate does not have any argument variables.
+If the determinism declaration is given on a @code{:- func} declaration
+without the mode, the function is assumed to have the default mode
+(see @ref{Modes} for more information on default modes of functions).
+
 For example:
 
 @example
Index: tests/valid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/valid/Mmakefile,v
retrieving revision 1.51
diff -u -r1.51 Mmakefile
--- tests/valid/Mmakefile	2000/01/31 03:59:07	1.51
+++ tests/valid/Mmakefile	2000/02/14 05:34:34
@@ -47,6 +47,7 @@
 	fail_ite.m \
 	followcode_det_problem.m \
 	func_int_bug_main.m \
+	func_default_modes.m \
 	headvar_not_found.m \
 	higher_order.m \
 	higher_order2.m \
Index: tests/valid/func_default_modes.exp
===================================================================
RCS file: func_default_modes.exp
diff -N func_default_modes.exp
--- /dev/null	Thu Mar  4 04:20:11 1999
+++ func_default_modes.exp	Mon Feb 14 16:35:30 2000
@@ -0,0 +1,3 @@
+[7]
+[7]
+[7]
Index: tests/valid/func_default_modes.m
===================================================================
RCS file: func_default_modes.m
diff -N func_default_modes.m
--- /dev/null	Thu Mar  4 04:20:11 1999
+++ func_default_modes.m	Mon Feb 14 16:34:20 2000
@@ -0,0 +1,41 @@
+
+% This test ensures that functions can be declared with a determinism,
+% but without the modes.  The compiler should give them the default
+% modes of `in' for the arguments and `out' for the return value.
+%
+% We test :- func definitions, lambda expressions and type class
+% methods.
+
+:- module func_default_modes.
+:- interface.
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+:- import_module list.
+
+:- func bar(int) = (int) is semidet.
+
+:- typeclass tc(T) where [
+	func method1(T) = int is semidet
+].
+
+:- instance tc(int) where [
+	func(method1/1) is bar
+].
+
+main --> 
+	{ A = (func(X) = Y is semidet :- X = 4, Y = 7) },
+	{ B = (func(X) = (Y) is semidet :- Y = method1(X)) },
+	io__write(list__filter_map(A, [1,2,3,4,5,6])),
+	io__nl,
+	io__write(list__filter_map(bar, [1,2,3,4,5,6])),
+	io__nl,
+	io__write(list__filter_map(B, [1,2,3,4,5,6])),
+	io__nl.
+
+bar(4) = 7.
+
+


-- 
       Tyson Dowd           # 
                            #  Surreal humour isn't eveyone's cup of fur.
     trd at cs.mu.oz.au        # 
http://www.cs.mu.oz.au/~trd #
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list