[m-rev.] for review: fix bug with state vars and nested closures

Julien Fischer juliensf at cs.mu.OZ.AU
Tue Jun 20 16:47:25 AEST 2006


For review by Ralph.

Estimated hours taken: 3
Branches: main, release

Fix a bug with state variables and closures nested more than one level deep
reported by valery at freesurf.fr.  The problem was that the map that kept track
of which state variables came from the scope enclosing a lambda expression
(and are hence read-only inside the lambda expressiong), was being incorrectly
overwritten when a nested lambda expression was encountered.  The fix is to
merge the set of state variables from the body of the lambda with those from
the enclosing scope before processing the nested lambda.  (Actually in order
to ensure that we get things correct if the same variable is used in multiple
scopes we overlay the maps rather than merge them.)

compiler/state_var.m:
	When preparing to process a lambda expression don't throw away any

	state variables mappings from enclosing scopes.

tests/hard_coded/Mmakefile:
tests/hard_coded/sv_nested_closures.{m,exp}:
	Test case for the above.

Julien.

Index: compiler/state_var.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/state_var.m,v
retrieving revision 1.11
diff -u -r1.11 state_var.m
--- compiler/state_var.m	24 Apr 2006 09:36:24 -0000	1.11
+++ compiler/state_var.m	20 Jun 2006 06:23:05 -0000
@@ -5,10 +5,10 @@
 % This file may only be copied under the terms of the GNU General
 % Public License - see the file COPYING in the Mercury distribution.
 %-----------------------------------------------------------------------------%
-
+%
 % File: state_var.m.
 % Main author: rafe.
-
+%
 %-----------------------------------------------------------------------------%

 :- module hlds.make_hlds.state_var.
@@ -129,12 +129,11 @@
     %
 :- pred prepare_for_head(svar_info::out) is det.

-    % We need to make the current !.Xs external
-    % ("read-only") and clear the !.Xs and !:Xs.
+    % We need to add the current !.Xs to the set of external ("read-only")
+    % state variables and clear the !.Xs and !:Xs.
     %
-    % While processing the head, any state variables therein are
-    % implicitly scoped over the body and have !. and !: mappings
-    % set up.
+    % While processing the head, any state variables therein are implicitly
+    % scoped over the body and have !. and !: mappings set up.
     %
 :- pred prepare_for_lambda(svar_info::in, svar_info::out) is det.

@@ -433,7 +432,15 @@
 %-----------------------------------------------------------------------------%

 prepare_for_lambda(!SInfo) :-
-    !:SInfo = ( new_svar_info ^ external_dot := !.SInfo ^ dot ).
+    %
+    % Construct the new external_dots mapping by overlaying the current dots
+    % mapping onto the existing external_dots one.  We cannot just throw the
+    % existing external_dots mapping away because otherwise the referring to
+    % externals from within closures that are nested more than one level deep
+    % will not work.
+    %
+    NewExternals = map.overlay(!.SInfo ^ external_dot, !.SInfo ^ dot),
+    !:SInfo = ( new_svar_info ^ external_dot := NewExternals).

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

Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.286
diff -u -r1.286 Mmakefile
--- tests/hard_coded/Mmakefile	26 Apr 2006 03:06:28 -0000	1.286
+++ tests/hard_coded/Mmakefile	20 Jun 2006 06:26:21 -0000
@@ -187,6 +187,7 @@
 	string_string \
 	string_strip \
 	string_suffix_bug \
+	sv_nested_closures \
 	switch_detect \
 	system_sort \
 	target_mlobjs \
Index: tests/hard_coded/sv_nested_closures.exp
===================================================================
RCS file: tests/hard_coded/sv_nested_closures.exp
diff -N tests/hard_coded/sv_nested_closures.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/sv_nested_closures.exp	20 Jun 2006 06:25:52 -0000
@@ -0,0 +1,5 @@
+17
+(baz) !.Y = -200
+(BazFoo) !.Y = 700
+(BazBar) !.Y = 700
+-200
Index: tests/hard_coded/sv_nested_closures.m
===================================================================
RCS file: tests/hard_coded/sv_nested_closures.m
diff -N tests/hard_coded/sv_nested_closures.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/sv_nested_closures.m	20 Jun 2006 06:25:52 -0000
@@ -0,0 +1,42 @@
+% vim: ft=mercury ts=4 sw=4 et
+:- module sv_nested_closures.
+:- interface.
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module int.
+:- import_module list.
+:- import_module string.
+
+main(!IO) :-
+    some [!X] (
+        !:X = 10,
+        Foo = (pred(I::in, !.IO::di, !:IO::uo) is det :-
+            Bar = (pred(J::in, !.IO::di, !:IO::uo) is det :-
+                Result = J + I + !.X,
+                io.write_int(Result, !IO),
+                io.nl(!IO)
+            ),
+            Bar(4, !IO)
+        ),
+        Foo(3, !IO)
+    ),
+    baz(-200, X, !IO),
+    io.write_int(X, !IO),
+    io.nl(!IO).
+
+:- pred baz(int::in, int::out, io::di, io::uo) is det.
+
+baz(!Y, !IO) :-
+    io.format("(baz) !.Y = %d\n", [i(!.Y)], !IO),
+    BazFoo = (pred(!.Y::in, !:Y::out, !.IO::di, !:IO::uo) is det :-
+        io.format("(BazFoo) !.Y = %d\n", [i(!.Y)], !IO),
+        BazBar = (pred(!.Z::in, !:Z::out, !.IO::di, !:IO::uo) is det :-
+            io.format("(BazBar) !.Y = %d\n", [i(!.Y)], !IO)
+        ),
+        BazBar(400, _, !IO)
+    ),
+    BazFoo(700, _, !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