[m-rev.] Extend recognition of field access syntax

Ralph Becket rafe at cs.mu.OZ.AU
Wed Dec 18 12:30:40 AEDT 2002


This could be extended further to make (A ^ f(...) = X) and
((A0 ^ f(...) := X) = A) recognised *everywhere* as synonyms
for the desugared forms.  Is it worth it?

Estimated hours taken: 3
Branches: main

Allow field access syntax at the top-level of func and mode declarations and
in function clause heads.

NEWS:
	Report the new feature.

doc/reference_manual.texi:
	Document the new feature.

compiler/prog_io.m:
	Implement the new feature.

tests/hard_coded/Mmakefile:
tests/hard_coded/field_syntax.exp:
tests/hard_coded/field_syntax.m:
	Added a test case.

Index: NEWS
===================================================================
RCS file: /home/mercury1/repository/mercury/NEWS,v
retrieving revision 1.291
diff -u -r1.291 NEWS
--- NEWS	5 Dec 2002 03:52:27 -0000	1.291
+++ NEWS	17 Dec 2002 08:07:08 -0000
@@ -6,6 +6,9 @@
 
 Changes to the Mercury language:
 * Infix `.' is now accepted as a module name separator.
+* Field access syntax can now be used at the top-level in func and mode
+  declarations and in the head of a clause for a user-defined field access
+  function.
 
 Changes to the Mercury compiler:
 * Nothing yet.
@@ -31,6 +34,14 @@
   same thing as io__write_string and list__member, for instance.  This
   has required changing the associativity of `.' from xfy to yfx and
   from precedence 600 to 10.
+
+* Field access notation can now be used at the top-level in func and
+  mode declarations and in the head of a clause for a user-defined
+  field access function.  That is, one can now write
+
+  	:- func a ^ f(b) = c.
+	:- mode a ^ f(b) = c is <detism>.
+	A ^ f(B) = ...
 
 Changes to the Mercury standard library:
 
Index: compiler/prog_io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_io.m,v
retrieving revision 1.213
diff -u -r1.213 prog_io.m
--- compiler/prog_io.m	5 Dec 2002 03:52:28 -0000	1.213
+++ compiler/prog_io.m	17 Dec 2002 02:40:19 -0000
@@ -979,7 +979,8 @@
 		parse_goal(Body, ProgVarSet, Body2, ProgVarSet2),
 		(
 			Head = term__functor(term__atom("="),
-					[FuncHead, FuncResult], _)
+					[FuncHead0, FuncResult], _),
+			FuncHead = desugar_field_access(FuncHead0)
 		->
 			parse_implicitly_qualified_term(ModuleName,
 				FuncHead, Head, "equation head", R2),
@@ -2327,7 +2328,8 @@
 		ExistQVars, Constraints, InstConstraints, Attributes, Result) :-
 	(
 		Term = term__functor(term__atom("="),
-				[FuncTerm, ReturnTypeTerm], _Context)
+				[FuncTerm0, ReturnTypeTerm], _Context),
+		FuncTerm = desugar_field_access(FuncTerm0)
 	->
 		parse_implicitly_qualified_term(ModuleName, FuncTerm, Term,
 			"`:- func' declaration", R),
@@ -2338,7 +2340,6 @@
 		Result = error("`=' expected in `:- func' declaration", Term)
 	).
 
-
 :- pred process_func_3(maybe_functor, term, term, term, varset,
 	maybe(determinism), condition, existq_tvars, class_constraints,
 	inst_var_sub, decl_attrs, maybe1(item)).
@@ -2404,6 +2405,32 @@
 
 %-----------------------------------------------------------------------------%
 
+	% Perform one of the following field-access syntax rewrites if
+	% possible:
+	%
+	% 	A ^ f(B, ...)		--->	f(B, ..., A)
+	% 	(A ^ f(B, ...) := X)	--->	'f :='(B, ..., A, X)
+	%
+:- func desugar_field_access(term) = term.
+
+desugar_field_access(Term) =
+	( if
+		Term = functor(atom("^"), [A, RHS], _),
+		RHS  = functor(atom(FieldName), Bs, Context)
+	  then
+	  	functor(atom(FieldName), Bs ++ [A], Context)
+	  else if
+		Term = functor(atom(":="), [LHS, X], _),
+		LHS  = functor(atom("^"), [A, RHS], Context),
+		RHS  = functor(atom(FieldName), Bs, Context)
+	  then
+	  	functor(atom(FieldName ++ " :="), Bs ++ [A, X], Context)
+	  else
+	  	Term
+	).
+
+%-----------------------------------------------------------------------------%
+
 	% parse a `:- mode p(...)' declaration
 
 :- pred process_mode(module_name, varset, term, condition, decl_attrs,
@@ -2415,7 +2442,8 @@
 	(
 		WithInst = no,
 		Term = term__functor(term__atom("="),
-				[FuncTerm, ReturnTypeTerm], _Context)
+				[FuncTerm0, ReturnTypeTerm], _Context),
+		FuncTerm = desugar_field_access(FuncTerm0)
 	->
 		parse_implicitly_qualified_term(ModuleName, FuncTerm, Term,
 				"function `:- mode' declaration", R),
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.263
diff -u -r1.263 reference_manual.texi
--- doc/reference_manual.texi	7 Nov 2002 06:14:09 -0000	1.263
+++ doc/reference_manual.texi	17 Dec 2002 08:16:48 -0000
@@ -1994,6 +1994,17 @@
 :- func elem(K, map(K, V)) = V is semidet.
 :- func 'elem :='(K, map(K, V), V) = map(K, V).
 @end example
+Field access syntax may be used at the top-level of @code{func} and
+ at code{mode} declarations and in the head of clauses.  For instance:
+ at example
+:- func map(K, V) ^ elem(K) = V.
+:- mode in        ^ in      = out is semidet.
+Map ^ elem(Key) = map__lookup(Map, Key).
+
+:- func (map(K, V) ^ elem(K) := V)  = V.
+:- mode (in        ^ in      := in) = out is semidet.
+(Map ^ elem(Key) := Value) = map__set(Map, Key, Value).
+ at end example
 
 The Mercury standard library modules @code{array} and @code{bt_array}
 define similar functions.
@@ -2022,20 +2033,20 @@
 The functions generated for the other fields are similar.
 
 @example
-:- func field1(type1) = type2.
-field1(type1(Field1, _)) = Field1.
+:- func type1 ^ field1 = type2.
+type1(Field1, _) ^ field1 = Field1.
 
-:- func 'field1 :='(type1, type2) = type1.
-'field1 :='(type1(_, Field2), Field1) = type1(Field1, Field2).
+:- func (type1 ^ field1 := type2) = type1.
+(type1(_, Field2) ^ field1 := Field1) = type1(Field1, Field2).
 @end example
 
 Using these functions and the syntactic sugar described in
 @ref{Record syntax}, programmers can write code such as
 
 @example
-:- func increment_field3(type1) = type1.
+:- func type1 ~ increment_field3 = type1.
 
-increment_field3(Term0) =
+Term0 ^ increment_field3 =
         Term0 ^ field1 ^ field3 := Term0 ^ field1 ^ field3 + 1.
 @end example
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.179
diff -u -r1.179 Mmakefile
--- hard_coded/Mmakefile	4 Dec 2002 01:57:29 -0000	1.179
+++ hard_coded/Mmakefile	18 Dec 2002 01:25:42 -0000
@@ -50,6 +50,7 @@
 	export_test \
 	factt \
 	failure_unify \
+	field_syntax \
 	float_consistency \
 	float_field \
 	float_map \
Index: tests/hard_coded/field_syntax.exp
===================================================================
RCS file: hard_coded/field_syntax.exp
diff -N hard_coded/field_syntax.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ hard_coded/field_syntax.exp	18 Dec 2002 01:25:49 -0000
@@ -0,0 +1,4 @@
+A                           = array([1, 2, 3])
+A ^ elem(0)                 = 1
+A ^ elem_from_end(0)        = 3
+(A ^ elem_from_end(2) := 4) = array([4, 2, 3])
Index: tests/hard_coded/field_syntax.m
===================================================================
RCS file: hard_coded/field_syntax.m
diff -N hard_coded/field_syntax.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ hard_coded/field_syntax.m	18 Dec 2002 01:04:54 -0000
@@ -0,0 +1,56 @@
+%-----------------------------------------------------------------------------%
+% field_syntax.m
+% Ralph Becket <rafe at cs.mu.oz.au>
+% Tue Dec 17 14:13:23 EST 2002
+% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
+%
+%-----------------------------------------------------------------------------%
+
+:- module field_syntax.
+
+:- interface.
+
+:- import_module io.
+
+
+
+:- pred main(io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module array, int, list, string.
+
+%-----------------------------------------------------------------------------%
+
+:- func array(T) ^ elem_from_end(int) = T.
+:- mode array_ui ^ elem_from_end(in)  = out is det.
+
+A ^ elem_from_end(I) = A ^ elem(max(A) - I).
+
+%-----------------------------------------------------------------------------%
+
+:- func (array(T) ^ elem_from_end(int) := T)  = array(T).
+:- mode (array_di ^ elem_from_end(in)  := in) = array_uo is det.
+
+(A ^ elem_from_end(I) := X) = (A ^ elem(max(A) - I) := X).
+
+%-----------------------------------------------------------------------------%
+
+main(!IO) :-
+    A = array([1, 2, 3]),
+    io.format("A                           = ", [], !IO),
+    io.print(A, !IO),
+    io.nl(!IO),
+    io.format("A ^ elem(0)                 = %d\n",
+        [i(A ^ elem(0))],          !IO),
+    io.format("A ^ elem_from_end(0)        = %d\n",
+        [i(A ^ elem_from_end(0))], !IO),
+    io.format("(A ^ elem_from_end(2) := 4) = ", [], !IO),
+    io.print(A ^ elem_from_end(2) := 4, !IO),
+    io.nl(!IO).
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list