[m-rev.] for review: do not allow (mostly-)unique or free mutables

Julien Fischer juliensf at csse.unimelb.edu.au
Mon Sep 25 19:18:11 AEST 2006


This is in response to the following thread:

<http://www.mercury.csse.unimelb.edu.au/mailing-lists/mercury-reviews/mercury-reviews.200609/0048.html>

plus some discussion with Ralph this afternoon.

Estimated hours taken: 2
Branches: main

Restrict the insts that are allowed to appear in mutable declarations. 
In particular mutables are now no longer allowed to have the insts
(mostly-)unique or free.

doc/reference_manual.texi:
 	The inst in a mutable should not be, nor should it contain components
 	that are, unique, mostly_unique, free, dead or mostly_dead.  For
 	most of these it doesn't actually make a lot of sense and for some
 	of them, e.g. mostly_unique mutables, the code we currently generate
 	for mutables ends up being mode incorrect.

 	XXX If we supported partial instaniation then it might make sense
 	for mutables to have insts that contain free components but we'll
 	cross that bridge when we come to it.

 	Reword the restriction on typeclass constraints on mutables; as
 	written it looks like the typeclass constraints are being applied to
 	the inst variables.

compiler/hlds_code_util.m:
 	s/hlds/HLDS in a comment.

 	Add a predicate that tests if an inst is valid inst for a mutable
 	declaration.

compiler/make_hlds_passes.m:
 	Check that the inst in a mutable declaration conforms to the above
 	rules and emit an error message if it does not.

 	Turn an if-then-else into a switch.

 	Fix an overlong line.

compiler/prog_mode.m:
 	Fix some formatting.

tests/invalid/Mmakefile:
tests/invalid/uniq_mutable.{m,err_exp}:
 	Test case for the above.
Julien.

Index: compiler/hlds_code_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_code_util.m,v
retrieving revision 1.30
diff -u -r1.30 hlds_code_util.m
--- compiler/hlds_code_util.m	22 Aug 2006 05:03:46 -0000	1.30
+++ compiler/hlds_code_util.m	25 Sep 2006 07:50:29 -0000
@@ -8,7 +8,7 @@
  %
  % File: hlds_code_util.m.
  % 
-% Various utilities routines for use during hlds generation.
+% Various utilities routines for use during HLDS generation.
  %
  %-----------------------------------------------------------------------------%
  %-----------------------------------------------------------------------------%
@@ -39,11 +39,17 @@
      %
  :- pred make_instance_string(list(mer_type)::in, string::out) is det.

+    % Succeeds iff this inst is one that can be used in a valid
+    % mutable declaration.
+    %
+:- pred is_valid_mutable_inst(module_info::in, mer_inst::in) is semidet.
+
  %-----------------------------------------------------------------------------%
  %-----------------------------------------------------------------------------%

  :- implementation.

+:- import_module check_hlds.mode_util.
  :- import_module check_hlds.type_util.
  :- import_module hlds.hlds_pred.
  :- import_module libs.compiler_util.
@@ -58,6 +64,7 @@
  :- import_module char.
  :- import_module map.
  :- import_module pair.
+:- import_module set.
  :- import_module string.
  :- import_module term.

@@ -158,6 +165,27 @@

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

+is_valid_mutable_inst(ModuleInfo, Inst) :-
+    set.init(Expansions),
+    is_valid_mutable_inst_2(ModuleInfo, Inst, Expansions).
+
+:- pred is_valid_mutable_inst_2(module_info::in, mer_inst::in,
+    set(inst_name)::in) is semidet.
+
+is_valid_mutable_inst_2(_, any(shared), _).
+is_valid_mutable_inst_2(ModuleInfo, bound(shared, BoundInsts), Expansions) :-
+    list.member(bound_functor(_, Insts), BoundInsts),
+    list.member(Inst, Insts),
+    is_valid_mutable_inst_2(ModuleInfo, Inst, Expansions).
+is_valid_mutable_inst_2(_, ground(shared, _), _).
+is_valid_mutable_inst_2(ModuleInfo, defined_inst(InstName), Expansions0) :-
+    not set.member(InstName, Expansions0),
+    Expansions = set.insert(Expansions0, InstName),
+    inst_lookup(ModuleInfo, InstName, Inst),
+    is_valid_mutable_inst_2(ModuleInfo, Inst, Expansions).
+
+%----------------------------------------------------------------------------%
+
  :- func this_file = string.

  this_file = "hlds_code_util.m".
Index: compiler/hlds_out.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_out.m,v
retrieving revision 1.403
diff -u -r1.403 hlds_out.m
--- compiler/hlds_out.m	10 Sep 2006 23:39:00 -0000	1.403
+++ compiler/hlds_out.m	25 Sep 2006 08:33:49 -0000
@@ -125,7 +125,7 @@

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

-    % Print out an entire hlds structure.
+    % Print out an entire HLDS structure.
      %
  :- pred write_hlds(int::in, module_info::in, io::di, io::uo) is det.

Index: compiler/make_hlds_passes.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make_hlds_passes.m,v
retrieving revision 1.54
diff -u -r1.54 make_hlds_passes.m
--- compiler/make_hlds_passes.m	15 Sep 2006 11:14:33 -0000	1.54
+++ compiler/make_hlds_passes.m	25 Sep 2006 08:59:34 -0000
@@ -97,6 +97,7 @@
  :- import_module backend_libs.
  :- import_module backend_libs.foreign.
  :- import_module check_hlds.clause_to_proc.
+:- import_module hlds.hlds_code_util.
  :- import_module hlds.hlds_data.
  :- import_module hlds.hlds_out.
  :- import_module hlds.make_hlds.add_class.
@@ -536,7 +537,8 @@
      item_status::in, item_status::out, module_info::in, module_info::out,
      list(error_spec)::in, list(error_spec)::out) is det.

-add_solver_type_mutable_items_pass_1([], _Context, !Status, !ModuleInfo, !Specs).
+add_solver_type_mutable_items_pass_1([], _Context, !Status, !ModuleInfo,
+        !Specs).
  add_solver_type_mutable_items_pass_1([Item | Items], Context, !Status,
          !ModuleInfo, !Specs) :-
      add_item_decl_pass_1(Item, Context, !Status, !ModuleInfo, _, !Specs),
@@ -685,7 +687,7 @@
          true
      ).
  add_item_decl_pass_2(Item, Context, !Status, !ModuleInfo, !Specs) :-
-    Item = item_mutable(Name, _Type, _InitTerm, _Inst, MutAttrs, _MutVarset),
+    Item = item_mutable(Name, _Type, _InitTerm, Inst, MutAttrs, _MutVarset),
      !.Status = item_status(ImportStatus, _),
      ( ImportStatus = status_exported ->
          error_is_exported(Context, "`mutable' declaration", !Specs)
@@ -705,7 +707,8 @@

          % XXX We don't currently support the foreign_name attribute
          % for languages other than C.
-        ( CompilationTarget = target_c ->
+        ( 
+            CompilationTarget = target_c,
              mutable_var_maybe_foreign_names(MutAttrs) = MaybeForeignNames,
              module_info_get_name(!.ModuleInfo, ModuleName),
              (
@@ -737,6 +740,10 @@
                  IOStateInterface = no
              )
          ;
+            ( CompilationTarget = target_il
+            ; CompilationTarget = target_java
+            ; CompilationTarget = target_asm
+            ),
              Pieces = [words("Error: foreign_name mutable attribute not yet"),
                  words("implemented for the"),
                  fixed(compilation_target_string(CompilationTarget)),
@@ -744,6 +751,31 @@
              Msg = simple_msg(Context, [always(Pieces)]),
              Spec = error_spec(severity_error, phase_parse_tree_to_hlds, [Msg]),
              !:Specs = [Spec | !.Specs]
+        ),
+        %
+        % Check that the inst in the mutable delcaration is a valid inst for a
+        % mutable declaration.
+        %
+        ( is_valid_mutable_inst(!.ModuleInfo, Inst) ->
+            true
+        ;
+            % It is okay to pass a dummy varset in here since any attempt
+            % to use inst variables in a mutable declaration should already
+            % been dealt with when the mutable declaration was parsed.
+            DummyInstVarset = varset.init, 
+            InstStr = mercury_expanded_inst_to_string(Inst, DummyInstVarset,
+                !.ModuleInfo),
+            InvalidInstPieces = [
+                words("Error: the inst"),
+                quote(InstStr),
+                words("is not a valid inst for a mutable declaration.") 
+            ],
+            % XXX we could provide more information about exactly *why* the
+            % inst was not valid here as well.
+            InvalidInstMsg = simple_msg(Context, [always(InvalidInstPieces)]),
+            InvalidInstSpec = error_spec(severity_error,
+                phase_parse_tree_to_hlds, [InvalidInstMsg]),
+            !:Specs = [ InvalidInstSpec | !.Specs ]
          )
      ;
          DefinedThisModule = no
Index: compiler/prog_mode.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_mode.m,v
retrieving revision 1.16
diff -u -r1.16 prog_mode.m
--- compiler/prog_mode.m	20 Aug 2006 08:21:26 -0000	1.16
+++ compiler/prog_mode.m	25 Sep 2006 05:20:22 -0000
@@ -5,13 +5,13 @@
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %-----------------------------------------------------------------------------%
-
+%
  % File: prog_mode.m.
  % Main author: fjh.
-
+%
  % Utility predicates dealing with modes and insts that do not require access
  % to the HLDS. (The predicates that do are in mode_util.m.)
-
+%
  %-----------------------------------------------------------------------------%

  :- module parse_tree.prog_mode.
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.367
diff -u -r1.367 reference_manual.texi
--- doc/reference_manual.texi	20 Sep 2006 09:33:08 -0000	1.367
+++ doc/reference_manual.texi	25 Sep 2006 09:01:52 -0000
@@ -4789,11 +4789,19 @@
  @end example

  The initial value of @samp{varname} is @samp{initial_value}, which is set
-before the program's @samp{main/2} predicate is executed.  The type
- at samp{vartype} is not allowed to contain any type variables and the inst
- at samp{varinst} is not allowed to contain any inst variables or have any type
-class constraints; @samp{initial_value} can be any Mercury expression with
-type @samp{vartype} and inst @samp{varinst}.
+before the program's @samp{main/2} predicate is executed. 
+
+The type @samp{vartype} is not allowed to contain any type variables or
+have any type class constraints.
+
+The inst @samp{varinst} is not allowed to contain any inst variables.
+It is also not allowed to be equivalent to, or contain components that
+are equivalent to, the builtin insts @samp{free}, @samp{unique},
+ at samp{mostly_unique}, @samp{dead} or @samp{mostly_dead}.
+
+The initial value of a mutable, @samp{inital_value}, may be any Mercury
+expression with type @samp{vartype} and inst @samp{varinst} subject to
+the above restrictions.

  The following @samp{attributes} must be supported:

Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.196
diff -u -r1.196 Mmakefile
--- tests/invalid/Mmakefile	1 Aug 2006 23:36:59 -0000	1.196
+++ tests/invalid/Mmakefile	25 Sep 2006 08:49:01 -0000
@@ -203,6 +203,7 @@
  	unicode2 \
  	unify_mode_error \
  	uniq_modes \
+	uniq_mutable \
  	uniq_neg \
  	unsatisfiable_constraint \
  	unsatisfiable_super \
Index: tests/invalid/uniq_mutable.err_exp
===================================================================
RCS file: tests/invalid/uniq_mutable.err_exp
diff -N tests/invalid/uniq_mutable.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/uniq_mutable.err_exp	25 Sep 2006 08:49:12 -0000
@@ -0,0 +1,10 @@
+uniq_mutable.m:012: Error: the inst `unique' is not a valid inst for a mutable
+uniq_mutable.m:012:   declaration.
+uniq_mutable.m:013: Error: the inst `mostly_unique' is not a valid inst for a
+uniq_mutable.m:013:   mutable declaration.
+uniq_mutable.m:014: Error: the inst `free' is not a valid inst for a mutable
+uniq_mutable.m:014:   declaration.
+uniq_mutable.m:015: Error: the inst `clobbered' is not a valid inst for a
+uniq_mutable.m:015:   mutable declaration.
+uniq_mutable.m:016: Error: the inst `mostly_clobbered' is not a valid inst for
+uniq_mutable.m:016:   a mutable declaration.
Index: tests/invalid/uniq_mutable.m
===================================================================
RCS file: tests/invalid/uniq_mutable.m
diff -N tests/invalid/uniq_mutable.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/uniq_mutable.m	25 Sep 2006 08:48:35 -0000
@@ -0,0 +1,27 @@
+:- module uniq_mutable.
+:- interface.
+
+:- type foo ---> foo.
+
+:- implementation.
+
+:- import_module io.
+
+	% Some invalid mutable insts - we should get error messages.
+	%
+:- mutable(alpha, int, 3, unique, [untrailed]).
+:- mutable(beta,  int, 4, mostly_unique, [untrailed]).
+:- mutable(gamma, int, _, free, [untrailed]).
+:- mutable(delta, int, _, dead, [untrailed]).
+:- mutable(epsilon, int, _, mostly_dead, [untrailed]).
+ 
+	% Some valid mutable insts - we should get no error messages.
+	%
+:- mutable(zeta, int, 7, ground, [untrailed]).
+:- mutable(eta,  int, _, any, [untrailed]).
+:- mutable(theta, pred(foo), get_foo, (pred(out) is det), [untrailed]). 
+:- mutable(iota, pred(io, io), io.nl, (pred(di, uo) is det), [untrailed]).
+
+:- pred get_foo(foo::out) is det.
+
+get_foo(foo).

--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list