[m-rev.] for review: pure mutable access predicates

Julien Fischer juliensf at cs.mu.OZ.AU
Wed Oct 5 02:52:14 AEST 2005


For review by Ralph or Ian.

Estimated hours taken: 7
Branches: main

Add optional support for generating a pure interface to mutables.  This is
done by adding a new mutable attribute, `pure'.  If this attribute is
specified in the mutable declaration then in addition to the usual non-pure
access predicates, the compiler will also add a pair of access predicates that
take the IO state.

compiler/prog_data.m:
	Add the `pure' mutable attribute.

	Add the necessary access predicates for the mutable_var_attributes
	structure.

compiler/prog_io.m:
	Parse the `pure' attribute.

compiler/prog_mutable.m:
	Shift some of the code for constructing items related to mutables to
	this module from make_hlds_passes.  This reduces unnecessary clutter in
	the latter.

	Remove the XXX comment about needing to mangle the names of the
	globals - we now do that.

compiler/make_hlds_passes.m:
	If a mutable has the `pure` attribute specified then create the pure
	access predicates in addition to the non-pure ones.

compiler/modules.m:
	If we are generating the pure access predicates then output the
	declarations for these predicates in private interfaces.

compiler/type_util.m:
	Replace the use of ':' as a module qualifier in some comments.

doc/reference_manual.texi:
	Document the `pure' mutable attribute.

vim/syntax/mercury.vim:
	Highlight various mutable attributes appropriately.

tests/hard_coded/Mmakefile:
tests/hard_coded/pure_mutable.m:
tests/hard_coded/pure_mutable.exp:
	Test mutables with pure access predicates.

tests/hard_coded/ppc_bug.m:
	Unrelated change: update the comments in this test case so
	they describe what the cause of the bug and the fix were.

Julien.

Index: compiler/make_hlds_passes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds_passes.m,v
retrieving revision 1.14
diff -u -r1.14 make_hlds_passes.m
--- compiler/make_hlds_passes.m	4 Oct 2005 07:20:17 -0000	1.14
+++ compiler/make_hlds_passes.m	4 Oct 2005 16:43:50 -0000
@@ -450,18 +450,42 @@
 add_item_decl_pass_1(Item, Context, !Status, !ModuleInfo, no, !IO) :-
     % We add the initialise decl and the foreign_decl on the second pass and
     % the foreign_proc clauses on the third pass.
-    Item = mutable(Name, Type, _InitValue, Inst, _Attrs),
+    Item = mutable(Name, Type, _InitValue, Inst, Attrs),
     !.Status = item_status(ImportStatus, _),
     ( status_defined_in_this_module(ImportStatus, yes) ->
         module_info_get_name(!.ModuleInfo, ModuleName),
-        GetPredDecl = prog_mutable.get_pred_decl(ModuleName, Name,
-            Type, Inst),
-        add_item_decl_pass_1(GetPredDecl, Context, !Status, !ModuleInfo, _,
-            !IO),
-        SetPredDecl = prog_mutable.set_pred_decl(ModuleName, Name,
-            Type, Inst),
-        add_item_decl_pass_1(SetPredDecl, Context, !Status, !ModuleInfo, _,
-            !IO),
+        %
+        % Create the non-pure access predicates.  These are always
+        % created, even if the `pure' attribute has been specified.
+        %
+        NonPureGetPredDecl = prog_mutable.nonpure_get_pred_decl(ModuleName,
+            Name, Type, Inst),
+        add_item_decl_pass_1(NonPureGetPredDecl, Context, !Status, !ModuleInfo,
+            _, !IO),
+        NonPureSetPredDecl = prog_mutable.nonpure_set_pred_decl(ModuleName,
+            Name, Type, Inst),
+        add_item_decl_pass_1(NonPureSetPredDecl, Context, !Status, !ModuleInfo,
+            _, !IO),
+        %
+        % If requested, create the pure access predicates as well.
+        %
+        CreatePureInterface = mutable_var_pure_interface(Attrs),
+        (
+            CreatePureInterface = yes,
+            PureGetPredDecl = prog_mutable.pure_get_pred_decl(ModuleName,
+                Name, Type, Inst),
+            add_item_decl_pass_1(PureGetPredDecl, Context, !Status,
+                !ModuleInfo, _, !IO),
+            PureSetPredDecl = prog_mutable.pure_set_pred_decl(ModuleName,
+                Name, Type, Inst),
+            add_item_decl_pass_1(PureSetPredDecl, Context, !Status,
+                !ModuleInfo, _, !IO)
+        ;
+            CreatePureInterface = no
+        ),
+        %
+        % Create the initialisation predicate.
+        %
         InitPredDecl = prog_mutable.init_pred_decl(ModuleName, Name),
         add_item_decl_pass_1(InitPredDecl, Context, !Status, !ModuleInfo, _,
             !IO)
@@ -620,12 +644,9 @@
         % XXX We don't currently support languages other than C.
         %
         module_info_get_name(!.ModuleInfo, ModuleName),
-        ForeignDecl = pragma(compiler(mutable_decl),
-            foreign_decl(c, foreign_decl_is_exported,
-                "extern MR_Word " ++ TargetMutableName ++ ";")),
+        ForeignDecl = get_global_foreign_decl(TargetMutableName),
         add_item_decl_pass_2(ForeignDecl, Context, !Status, !ModuleInfo, !IO),
-        ForeignCode = pragma(compiler(mutable_decl),
-            foreign_code(c, "MR_Word " ++ TargetMutableName ++ ";")),
+        ForeignCode = get_global_foreign_defn(TargetMutableName),
         add_item_decl_pass_2(ForeignCode, Context, !Status, !ModuleInfo, !IO)
     ;
         true
@@ -1099,7 +1120,7 @@
     Item = mutable(Name, _Type, InitTerm, Inst, MutAttrs),
     ( status_defined_in_this_module(!.Status, yes) ->
         module_info_get_name(!.ModuleInfo, ModuleName),
-        varset__new_named_var(varset__init, "X", X, VarSet),
+        varset__new_named_var(varset.init, "X", X, VarSet0),
         Attrs0 = default_attributes(c),
         set_may_call_mercury(will_not_call_mercury, Attrs0, Attrs1),
         ( mutable_var_thread_safe(MutAttrs) = thread_safe ->
@@ -1107,6 +1128,10 @@
         ;
             Attrs = Attrs1
         ),
+        %
+        % Add the `:- initialise' declaration and clause for the
+        % initialise predicate.
+        %
         add_item_clause(initialise(compiler(mutable_decl),
                 mutable_init_pred_sym_name(ModuleName, Name), 0 /* Arity */),
             !Status, Context, !ModuleInfo, !QualInfo, !IO),
@@ -1127,12 +1152,12 @@
                     ModuleName, Name, ForeignNames, TargetMutableName, !IO)
         ),
         set_purity((semipure), Attrs, GetAttrs),
-        GetClause = pragma(compiler(mutable_decl), foreign_proc(GetAttrs,
+        NonPureGetClause = pragma(compiler(mutable_decl), foreign_proc(GetAttrs,
             mutable_get_pred_sym_name(ModuleName, Name), predicate,
-            [pragma_var(X, "X", out_mode(Inst))], VarSet,
+            [pragma_var(X, "X", out_mode(Inst))], VarSet0,
             ordinary("X = " ++ TargetMutableName ++ ";", yes(Context)))),
-        add_item_clause(GetClause, !Status, Context, !ModuleInfo, !QualInfo,
-            !IO),
+        add_item_clause(NonPureGetClause, !Status, Context, !ModuleInfo,
+            !QualInfo, !IO),
         TrailMutableUpdates = mutable_var_trailed(MutAttrs),
         (
             TrailMutableUpdates = untrailed,
@@ -1160,13 +1185,63 @@
                 TrailCode = ""
             )
         ),
-        SetClause = pragma(compiler(mutable_decl), foreign_proc(Attrs,
+        NonPureSetClause = pragma(compiler(mutable_decl), foreign_proc(Attrs,
             mutable_set_pred_sym_name(ModuleName, Name), predicate,
-            [pragma_var(X, "X", in_mode(Inst))], VarSet,
+            [pragma_var(X, "X", in_mode(Inst))], VarSet0,
             ordinary(TrailCode ++ TargetMutableName ++ " = X;",
                 yes(Context)))),
-        add_item_clause(SetClause, !Status, Context, !ModuleInfo, !QualInfo,
-            !IO)
+        add_item_clause(NonPureSetClause, !Status, Context, !ModuleInfo, !QualInfo,
+            !IO),
+        %
+        % Create pure access predicates for the mutable if requested.
+        %
+        % XXX We don't define these directly in terms of the non-pure
+        % access predicates because I/O tabling doesn't currently work
+        % for impure/semipure predicates.  At the moment we just generate
+        % another pair of foreign_procs.
+        %
+        ( mutable_var_pure_interface(MutAttrs) = yes ->
+            set_tabled_for_io(tabled_for_io, Attrs0, PureIntAttrs0),
+            set_purity(pure, PureIntAttrs0, PureIntAttrs),
+            varset.new_named_var(VarSet0, "IO0", IO0, VarSet1),
+            varset.new_named_var(VarSet1, "IO",  IO,  VarSet),
+            PureSetClause = pragma(compiler(mutable_decl),
+                foreign_proc(PureIntAttrs,
+                    mutable_set_pred_sym_name(ModuleName, Name), predicate,
+                    [
+                        pragma_var(X,   "X",   in_mode(Inst)),
+                        pragma_var(IO0, "IO0", di_mode),
+                        pragma_var(IO,  "IO",  uo_mode)
+                    ], VarSet,
+                    ordinary(
+                                TargetMutableName ++ " = X; " ++
+                                "IO = IO0;",
+                                yes(Context)
+                    )
+                )
+            ),
+            add_item_clause(PureSetClause, !Status, Context, !ModuleInfo,
+                !QualInfo, !IO),
+            PureGetClause = pragma(compiler(mutable_decl),
+                foreign_proc(PureIntAttrs,
+                    mutable_get_pred_sym_name(ModuleName, Name), predicate,
+                    [
+                        pragma_var(X,   "X",   out_mode(Inst)),
+                        pragma_var(IO0, "IO0", di_mode),
+                        pragma_var(IO,  "IO",  uo_mode)
+                    ], VarSet,
+                    ordinary(
+                                "X = " ++ TargetMutableName ++ ";" ++
+                                "IO = IO0;",
+                                yes(Context)
+                    )
+                )
+            ),
+            add_item_clause(PureGetClause, !Status, Context, !ModuleInfo,
+                !QualInfo, !IO)
+        ;
+            true
+        )
     ;
         true
     ).
Index: compiler/modules.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.348
diff -u -r1.348 modules.m
--- compiler/modules.m	4 Oct 2005 07:20:18 -0000	1.348
+++ compiler/modules.m	4 Oct 2005 07:20:36 -0000
@@ -1331,13 +1331,27 @@
     item_and_context::in, item_list::in, item_list::out) is det.

 handle_mutable_in_private_interface(ModuleName, Item - Context, !Items) :-
-    ( Item = mutable(MutableName, Type, _Value, Inst, _Attrs) ->
-        GetPredDecl = prog_mutable.get_pred_decl(ModuleName, MutableName,
-            Type, Inst),
-        list.cons(GetPredDecl - Context, !Items),
-        SetPredDecl = prog_mutable.set_pred_decl(ModuleName, MutableName,
-            Type, Inst),
-        list.cons(SetPredDecl - Context, !Items)
+    ( Item = mutable(MutableName, Type, _Value, Inst, Attrs) ->
+        NonPureGetPredDecl =
+            prog_mutable.nonpure_get_pred_decl(ModuleName, MutableName,
+                Type, Inst),
+        list.cons(NonPureGetPredDecl - Context, !Items),
+        NonPureSetPredDecl =
+            prog_mutable.nonpure_set_pred_decl(ModuleName, MutableName,
+                Type, Inst),
+        list.cons(NonPureSetPredDecl - Context, !Items),
+        ( mutable_var_pure_interface(Attrs) = yes ->
+            PureGetPredDecl =
+                prog_mutable.pure_get_pred_decl(ModuleName, MutableName,
+                   Type, Inst),
+            list.cons(PureGetPredDecl - Context, !Items),
+            PureSetPredDecl =
+                prog_mutable.pure_set_pred_decl(ModuleName, MutableName,
+                    Type, Inst),
+            list.cons(PureSetPredDecl - Context, !Items)
+        ;
+            true
+        )
     ;
         list.cons(Item - Context, !Items)
     ).
Index: compiler/prog_data.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_data.m,v
retrieving revision 1.140
diff -u -r1.140 prog_data.m
--- compiler/prog_data.m	4 Oct 2005 07:20:19 -0000	1.140
+++ compiler/prog_data.m	4 Oct 2005 15:07:12 -0000
@@ -220,14 +220,31 @@
 		% used for items that should be ignored (for the
 		% purposes of backwards compatibility etc)

+	% Attributes that a mutable can have (part of the `:- mutable'
+	% declaration).
+	%
+:- type mutable_attr
+	--->	untrailed		% Updates are not trailed (default).
+
+	;	trailed			% Updates are trailed.
+
+	;	thread_safe		% Access is considered thread safe.
+
+	;	not_thread_safe		% Access is considered not thread safe
+					% (default).
+					%
+	;	pure.			% Generate a pure version of the
+					% mutable access predicates that take
+					% the IO state.
+
 	% Indicates the type of information the compiler should get from the
 	% declaration's clause.
 	%
 :- type promise_type
 		% promise ex declarations
-	--->	exclusive		% each disjunct is mutually exclusive
-	;	exhaustive		% disjunction cannot fail
-	;	exclusive_exhaustive	% both of the above
+	--->	exclusive		% Each disjunct is mutually exclusive.
+	;	exhaustive		% Disjunction cannot fail.
+	;	exclusive_exhaustive	% Both of the above.

 		% assertions
 	; 	true.			% promise goal is true
@@ -310,6 +327,7 @@
 :- func mutable_var_trailed(mutable_var_attributes) = trailed.
 :- func mutable_var_maybe_foreign_names(mutable_var_attributes)
 	= maybe(list(foreign_name)).
+:- func mutable_var_pure_interface(mutable_var_attributes) = bool.

 :- pred set_mutable_var_thread_safe(thread_safe::in,
 	mutable_var_attributes::in, mutable_var_attributes::out) is det.
@@ -320,6 +338,9 @@
 :- pred set_mutable_add_foreign_name(foreign_name::in,
 	mutable_var_attributes::in, mutable_var_attributes::out) is det.

+:- pred set_mutable_var_pure_interface(bool::in,
+	mutable_var_attributes::in, mutable_var_attributes::out) is det.
+
 %-----------------------------------------------------------------------------%
 %
 % Pragmas
@@ -2091,17 +2112,19 @@
 	%
 :- type mutable_var_attributes
 	---> mutable_var_attributes(
-		mutable_trailed       :: trailed,
-		mutable_thread_safe   :: thread_safe,
-		mutable_foreign_names :: maybe(list(foreign_name))
+		mutable_trailed        :: trailed,
+		mutable_thread_safe    :: thread_safe,
+		mutable_foreign_names  :: maybe(list(foreign_name)),
+		mutable_pure_interface :: bool
 	).

 default_mutable_attributes =
-	mutable_var_attributes(trailed, not_thread_safe, no).
+	mutable_var_attributes(trailed, not_thread_safe, no, no).

 mutable_var_thread_safe(MVarAttrs) = MVarAttrs ^ mutable_thread_safe.
 mutable_var_trailed(MVarAttrs) = MVarAttrs ^ mutable_trailed.
 mutable_var_maybe_foreign_names(MVarAttrs) = MVarAttrs ^ mutable_foreign_names.
+mutable_var_pure_interface(MVarAttrs) = MVarAttrs ^ mutable_pure_interface.

 set_mutable_var_thread_safe(ThreadSafe, !Attributes) :-
 	!:Attributes = !.Attributes ^ mutable_thread_safe := ThreadSafe.
@@ -2119,6 +2142,8 @@
 	),
 	!:Attributes =
 		!.Attributes ^ mutable_foreign_names := MaybeForeignNames.
+set_mutable_var_pure_interface(CreatePureInterface, !Attributes) :-
+	!:Attributes = !.Attributes ^ mutable_pure_interface := CreatePureInterface.

 %-----------------------------------------------------------------------------%

Index: compiler/prog_io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_io.m,v
retrieving revision 1.253
diff -u -r1.253 prog_io.m
--- compiler/prog_io.m	4 Oct 2005 07:20:19 -0000	1.253
+++ compiler/prog_io.m	4 Oct 2005 07:20:36 -0000
@@ -1983,7 +1983,8 @@
 :- type collected_mutable_attribute
 	--->	trailed(trailed)
 	;	thread_safe(thread_safe)
-	;	foreign_name(foreign_name).
+	;	foreign_name(foreign_name)
+	;	pure(bool).

 :- pred parse_mutable_attrs(term::in,
 	maybe1(mutable_var_attributes)::out) is det.
@@ -2032,6 +2033,8 @@
 	set_mutable_var_trailed(Trailed, !Attributes).
 process_mutable_attribute(foreign_name(ForeignName), !Attributes) :-
 	set_mutable_add_foreign_name(ForeignName, !Attributes).
+process_mutable_attribute(pure(CreatePureInterface), !Attributes) :-
+	set_mutable_var_pure_interface(CreatePureInterface, !Attributes).

 :- pred parse_mutable_attr(term::in,
 	maybe1(collected_mutable_attribute)::out) is det.
@@ -2045,8 +2048,11 @@
 		;
 			String = "trailed",
 			MutAttr = trailed(trailed)
+		;
+			String  = "pure",
+			MutAttr = pure(yes)
 		;
-			String  = "thread_safe",
+			String = "thread_safe",
 			MutAttr = thread_safe(thread_safe)
 		;
 			String = "not_thread_safe",
Index: compiler/prog_mutable.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_mutable.m,v
retrieving revision 1.2
diff -u -r1.2 prog_mutable.m
--- compiler/prog_mutable.m	28 Sep 2005 09:02:14 -0000	1.2
+++ compiler/prog_mutable.m	4 Oct 2005 15:12:52 -0000
@@ -20,16 +20,40 @@

 %-----------------------------------------------------------------------------%

-:- func prog_mutable.get_pred_decl(module_name, string, (type), (inst))
-	= item.
+	% Create a predmode declaration for a non-pure mutable get predicate.
+	% (This is the default get predicate.)
+	%
+:- func nonpure_get_pred_decl(module_name, string, (type), (inst)) = item.
+
+	% Create a predmode declaration for a non-pure mutable set predicate.
+	% (This is the default set predicate.)
+	%
+:- func nonpure_set_pred_decl(module_name, string, (type), (inst)) = item.
+
+	% Create a predmode declaration for a pure mutable get predicate.
+	% (This is only created if the `pure' mutable attribute is given.)
+	%
+:- func pure_get_pred_decl(module_name, string, (type), (inst)) = item.
+
+	% Create a predmode declaration for a pure mutable set predicate.
+	% (This is only create the `pure' mutable attribute is give.)
+	%
+:- func pure_set_pred_decl(module_name, string, (type), (inst)) = item.
+
+	% Create a predmode declaration for the mutable initialisation
+	% predicate.
+	%
+:- func init_pred_decl(module_name, string) = item.
+
+	% Create the foreign_decl for the mutable.
+	%
+:- func get_global_foreign_decl(string) = item.
+
+	% Create the foreign_code that defines the mutable.
+	%
+:- func get_global_foreign_defn(string) = item.

-:- func prog_mutable.set_pred_decl(module_name, string, (type), (inst))
-	= item.

-:- func prog_mutable.init_pred_decl(module_name, string) = item.
-
-    % XXX We should probably mangle Name for safety...
-    %
 :- func mutable_get_pred_sym_name(sym_name, string) = sym_name.

 :- func mutable_set_pred_sym_name(sym_name, string) = sym_name.
@@ -43,6 +67,7 @@

 :- implementation.

+:- import_module libs.globals.
 :- import_module parse_tree.prog_foreign.
 :- import_module parse_tree.prog_mode.
 :- import_module list.
@@ -51,7 +76,7 @@

 %-----------------------------------------------------------------------------%

-get_pred_decl(ModuleName, Name, Type, Inst) = GetPredDecl :-
+nonpure_get_pred_decl(ModuleName, Name, Type, Inst) = GetPredDecl :-
 	VarSet = varset__init,
 	InstVarSet = varset__init,
 	ExistQVars = [],
@@ -62,7 +87,7 @@
 	    no /* with_type */, no /* with_inst */, yes(det),
 	    true /* condition */, (semipure), Constraints).

-set_pred_decl(ModuleName, Name, Type, Inst) = SetPredDecl :-
+nonpure_set_pred_decl(ModuleName, Name, Type, Inst) = SetPredDecl :-
 	VarSet = varset__init,
 	InstVarSet = varset__init,
 	ExistQVars = [],
@@ -73,6 +98,43 @@
             no /* with_type */, no /* with_inst */, yes(det),
             true /* condition */, (impure), Constraints).

+pure_get_pred_decl(ModuleName, Name, Type, Inst) = GetPredDecl :-
+	VarSet = varset__init,
+	InstVarSet = varset__init,
+	ExistQVars = [],
+	Constraints = constraints([], []),
+	GetPredDecl = pred_or_func(VarSet, InstVarSet, ExistQVars, predicate,
+	    mutable_get_pred_sym_name(ModuleName, Name),
+	    [
+	    	type_and_mode(Type, out_mode(Inst)),
+		type_and_mode(io_state_type, di_mode),
+		type_and_mode(io_state_type, uo_mode)
+	    ],
+	    no /* with_type */, no /* with_inst */, yes(det),
+	    true /* condition */, pure, Constraints).
+
+pure_set_pred_decl(ModuleName, Name, Type, Inst) = SetPredDecl :-
+	VarSet = varset__init,
+	InstVarSet = varset__init,
+	ExistQVars = [],
+	Constraints = constraints([], []),
+	SetPredDecl = pred_or_func(VarSet, InstVarSet, ExistQVars, predicate,
+            mutable_set_pred_sym_name(ModuleName, Name),
+            [
+	    	type_and_mode(Type, in_mode(Inst)),
+		type_and_mode(io_state_type, di_mode),
+		type_and_mode(io_state_type, uo_mode)
+	    ],
+            no /* with_type */, no /* with_inst */, yes(det),
+            true /* condition */, pure, Constraints).
+
+	% Return the type io.state.
+	% XXX Perhaps this should be in prog_type?
+	%
+:- func io_state_type = (type).
+
+io_state_type = defined(qualified(unqualified("io"), "state"), [], star).
+
 init_pred_decl(ModuleName, Name) = InitPredDecl :-
 	VarSet = varset__init,
 	InstVarSet = varset__init,
@@ -83,6 +145,19 @@
     		[], no /* with_type */, no /* with_inst */, yes(det),
     		true /* condition */, (impure), Constraints).

+%-----------------------------------------------------------------------------%
+
+get_global_foreign_decl(TargetMutableName) =
+	pragma(compiler(mutable_decl),
+            foreign_decl(c, foreign_decl_is_exported,
+                "extern MR_Word " ++ TargetMutableName ++ ";")).
+
+get_global_foreign_defn(TargetMutableName) =
+	pragma(compiler(mutable_decl),
+            foreign_code(c, "MR_Word " ++ TargetMutableName ++ ";")).
+
+%-----------------------------------------------------------------------------%
+
 mutable_get_pred_sym_name(ModuleName, Name) =
     qualified(ModuleName, "get_" ++ Name).

Index: compiler/type_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/type_util.m,v
retrieving revision 1.156
diff -u -r1.156 type_util.m
--- compiler/type_util.m	30 Sep 2005 08:08:36 -0000	1.156
+++ compiler/type_util.m	30 Sep 2005 09:40:19 -0000
@@ -786,9 +786,9 @@
 % The list of dummy types should be kept in sync with MR_is_dummy_type
 % in trace/mercury_trace.c.
 %
-% XXX should we include aditi:state/0 in this list?
-type_util__is_dummy_argument_type_2("io", "state", 0).    % io:state/0
-type_util__is_dummy_argument_type_2("store", "store", 1). % store:store/1.
+% XXX should we include aditi.state/0 in this list?
+type_util__is_dummy_argument_type_2("io", "state", 0).    % io.state/0
+type_util__is_dummy_argument_type_2("store", "store", 1). % store.store/1.

 type_util__constructors_are_dummy_argument_type([Ctor]) :-
 	Ctor = ctor([], [], qualified(unqualified("io"), "state"), [_]).
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.332
diff -u -r1.332 reference_manual.texi
--- doc/reference_manual.texi	4 Oct 2005 07:20:20 -0000	1.332
+++ doc/reference_manual.texi	4 Oct 2005 15:31:44 -0000
@@ -4671,7 +4671,7 @@
 @end example

 This constructs a new mutable variable with access predicates that have the
-following signatures.
+following signatures:

 @example
 :- semipure get_varname(vartype::out(varinst)) is det.
@@ -4700,6 +4700,18 @@
 the effects of @samp{set_varname/1} can be undone on backtracking.  The
 default, in case none is specified, is @samp{trailed}.

+ at item @samp{pure}
+This attribute cause the compiler to also construct pure access predicates
+for the mutable.  The pure access predicates have the following signatures:
+
+ at example
+:- pred get_varname(vartype::out(varinst), io::di, io::uo) is det.
+:- pred set_varname(vartype::in(varinst),  io::di, io::uo) is det.
+ at end example
+
+The pure access predicates will not be constructed unless the @samp{pure}
+attribute is specified.
+
 @end table

 The Melbourne Mercury compiler also supports the following attribute.
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.270
diff -u -r1.270 Mmakefile
--- tests/hard_coded/Mmakefile	4 Oct 2005 07:20:21 -0000	1.270
+++ tests/hard_coded/Mmakefile	4 Oct 2005 16:26:48 -0000
@@ -141,6 +141,7 @@
 	pretty_printing \
 	promise_equivalent_solutions_test \
 	promise_equiv_with_svars \
+	pure_mutable \
 	qual_adv_test \
 	qual_basic_test \
 	qual_is_test \
Index: tests/hard_coded/ppc_bug.m
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/ppc_bug.m,v
retrieving revision 1.1
diff -u -r1.1 ppc_bug.m
--- tests/hard_coded/ppc_bug.m	2 Dec 2004 07:51:28 -0000	1.1
+++ tests/hard_coded/ppc_bug.m	4 Oct 2005 16:33:35 -0000
@@ -1,10 +1,13 @@
-% The following program compiles incorrectly on PPC/MacOS X
-% in grade reg.gc.  find_nth_yes/4 ends up throwing an
-% exception instead of returning `YesPos = 3'.  Passing
-% `--no-optimize-fulljumps' causes the test to pass.
+% The following program compiles incorrectly on PPC/MacOS X in grade reg.gc.
+% find_nth_yes/4 ends up throwing an exception instead of returning `YesPos =
+% 3'.  Passing `--no-optimize-fulljumps' causes the test to pass.
 %
-% The test passes with gcc 2.95.2 (Apple version)
-% but fails with gcc 3.3 (Apple version).
+% The test passes with gcc 2.95.2 (Apple version) but fails with gcc 3.3
+% (Apple version).
+%
+% The problem was that gcc's `-floop-optimize' options was incompatible
+% with our use of global registers.  The fix is to make sure that option
+% is disabled on powerpc-apple-darwin.

 :- module ppc_bug.

Index: tests/hard_coded/pure_mutable.exp
===================================================================
RCS file: tests/hard_coded/pure_mutable.exp
diff -N tests/hard_coded/pure_mutable.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/pure_mutable.exp	4 Oct 2005 15:49:18 -0000
@@ -0,0 +1,2 @@
+Initial value of global = 561
+Final value of global = 562
Index: tests/hard_coded/pure_mutable.m
===================================================================
RCS file: tests/hard_coded/pure_mutable.m
diff -N tests/hard_coded/pure_mutable.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/pure_mutable.m	4 Oct 2005 15:49:18 -0000
@@ -0,0 +1,22 @@
+:- module pure_mutable.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module int.
+:- import_module list.
+:- import_module string.
+
+:- mutable(global, int, 561, ground, [untrailed, thread_safe, pure]).
+
+main(!IO) :-
+	get_global(X0, !IO),
+	io.format("Initial value of global = %d\n", [i(X0)], !IO),
+	set_global(X0 + 1, !IO),
+	get_global(X, !IO),
+	io.format("Final value of global = %d\n", [i(X)], !IO).
Index: vim/syntax/mercury.vim
===================================================================
RCS file: /home/mercury1/repository/mercury/vim/syntax/mercury.vim,v
retrieving revision 1.16
diff -u -r1.16 mercury.vim
--- vim/syntax/mercury.vim	4 Oct 2005 07:20:24 -0000	1.16
+++ vim/syntax/mercury.vim	4 Oct 2005 07:20:53 -0000
@@ -52,7 +52,7 @@
 syn keyword mercuryCInterface   may_call_mercury will_not_call_mercury
 syn keyword mercuryCInterface   thread_safe not_thread_safe maybe_thread_safe
 syn keyword mercuryCInterface   promise_pure promise_semipure
-syn keyword mercuryCInterface   tabled_for_io local untrailed
+syn keyword mercuryCInterface   tabled_for_io local untrailed trailed pure
 syn keyword mercuryCInterface   can_pass_as_mercury_type stable
 syn keyword mercuryCInterface   will_not_throw_exception
 syn keyword mercuryCInterface   export import

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