[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