[m-dev.] diff: fix bug with negation and mostly unique modes
Fergus Henderson
fjh at cs.mu.OZ.AU
Fri Nov 19 22:18:24 AEDT 1999
Estimated hours taken: 1.5
Fix a bug with unique mode analysis of negations
that was reported by Ralph Becket.
compiler/modes.m:
compiler/unique_modes.m:
When processing negations, set the forward-live variables
set to empty, because nothing is forward-live after
the negated goal -- if the negated goal succeeds,
execution will immediately backtrack.
tests/valid/Mmakefile:
tests/valid/mostly_uniq_neg.m:
Add a regression test to make sure that the compiler
now accepts the code that it should, i.e. code
using backtrackable destructive assignment inside
a negation.
tests/invalid/Mmakefile:
tests/invalid/uniq_neg.m:
tests/invalid/uniq_neg.err_exp:
Add a test to make sure that the above change does
not make the compiler accept code that it shouldn't,
i.e. code using non-backtrackable destructive assignment
inside a negation.
Workspace: /home/mercury0/fjh/mercury
Index: compiler/modes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modes.m,v
retrieving revision 1.236
diff -u -d -r1.236 modes.m
--- modes.m 1999/10/29 07:22:25 1.236
+++ modes.m 1999/11/19 10:46:11
@@ -1040,6 +1040,10 @@
{ goal_info_get_nonlocals(GoalInfo0, NonLocals) },
{ goal_get_nonlocals(B0, B_Vars) },
mode_info_dcg_get_instmap(InstMap0),
+ %
+ % We need to lock the non-local variables, to ensure
+ % that the condition of the if-then-else does not bind them.
+ %
mode_info_lock_vars(if_then_else, NonLocals),
mode_info_add_live_vars(B_Vars),
modecheck_goal(A0, A),
@@ -1068,8 +1072,26 @@
mode_checkpoint(enter, "not"),
{ goal_info_get_nonlocals(GoalInfo0, NonLocals) },
mode_info_dcg_get_instmap(InstMap0),
+ %
+ % when analyzing a negated goal, nothing is forward-live
+ % (live on forward executution after that goal), because
+ % if the goal succeeds then execution will immediately backtrack.
+ % So we need to set the live variables set to empty here.
+ % This allows those variables to be backtrackably
+ % destructively updated. (If you try to do non-backtrackable
+ % destructive update on such a variable, it will be caught
+ % later on by unique_modes.m.)
+ %
+ =(ModeInfo),
+ { mode_info_get_live_vars(ModeInfo, LiveVars0) },
+ mode_info_set_live_vars([]),
+ %
+ % We need to lock the non-local variables, to ensure
+ % that the negation does not bind them.
+ %
mode_info_lock_vars(negation, NonLocals),
modecheck_goal(A0, A),
+ mode_info_set_live_vars(LiveVars0),
mode_info_unlock_vars(negation, NonLocals),
mode_info_set_instmap(InstMap0),
mode_checkpoint(exit, "not").
Index: compiler/unique_modes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/unique_modes.m,v
retrieving revision 1.59
diff -u -d -r1.59 unique_modes.m
--- unique_modes.m 1999/10/25 03:49:50 1.59
+++ unique_modes.m 1999/11/19 10:58:34
@@ -388,15 +388,34 @@
unique_modes__check_goal_2(not(A0), GoalInfo0, not(A)) -->
mode_checkpoint(enter, "not"),
- { goal_info_get_nonlocals(GoalInfo0, NonLocals) },
mode_info_dcg_get_instmap(InstMap0),
+ %
+ % We need to mark all the variables which are live
+ % after the negation as nondet-live for the negated
+ % goal, since if the negated goal fails, then the
+ % negation will succeed, and so these variables
+ % can be accessed again after backtracking.
+ %
+ { goal_info_get_nonlocals(GoalInfo0, NonLocals) },
{ set__to_sorted_list(NonLocals, NonLocalsList) },
=(ModeInfo),
{ select_live_vars(NonLocalsList, ModeInfo, LiveNonLocals) },
make_var_list_mostly_uniq(LiveNonLocals),
+ %
+ % But nothing is forward-live for the negated goal, since
+ % if the goal succeeds then execution will immediately backtrack.
+ % So we need to set the live variables set to empty here.
+ %
+ { mode_info_get_live_vars(ModeInfo, LiveVars0) },
+ mode_info_set_live_vars([]),
+ %
+ % We need to lock the non-local variables, to ensure
+ % that the negation does not bind them.
+ %
mode_info_lock_vars(negation, NonLocals),
unique_modes__check_goal(A0, A),
mode_info_unlock_vars(negation, NonLocals),
+ mode_info_set_live_vars(LiveVars0),
mode_info_set_instmap(InstMap0),
mode_checkpoint(exit, "not").
Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.52
diff -u -d -r1.52 Mmakefile
--- Mmakefile 1999/11/11 23:17:55 1.52
+++ Mmakefile 1999/11/19 11:10:12
@@ -72,6 +72,7 @@
undef_type.m \
unify_mode_error.m \
uniq_modes.m \
+ uniq_neg.m \
uu_type.m \
vars_in_wrong_places.m
Index: tests/invalid/uniq_neg.err_exp
===================================================================
RCS file: uniq_neg.err_exp
diff -N uniq_neg.err_exp
--- /dev/null Fri Nov 19 22:05:11 1999
+++ uniq_neg.err_exp Fri Nov 19 22:10:39 1999
@@ -0,0 +1,5 @@
+uniq_neg.m:025: In clause for `unify(in, in, in, in, di, uo)':
+uniq_neg.m:025: in argument 3 of call to predicate `uniq_neg:occurs/4':
+uniq_neg.m:025: mode error: variable `DCG_0' has instantiatedness `mostly_unique',
+uniq_neg.m:025: expected instantiatedness was `unique'.
+For more information, try recompiling with `-E'.
Index: tests/invalid/uniq_neg.m
===================================================================
RCS file: uniq_neg.m
diff -N uniq_neg.m
--- /dev/null Fri Nov 19 22:05:11 1999
+++ uniq_neg.m Fri Nov 19 22:09:49 1999
@@ -0,0 +1,27 @@
+% A regression test, adapted from a bug report by Ralph Becket.
+% Mercury 0.8.1 and earlier reported a spurious mode error
+% for this code.
+
+:- module uniq_neg.
+:- interface.
+:- import_module list, store.
+
+:- type term(S) == mutvar(term_type(S), S).
+:- type var(S) == term(S).
+:- type term_type(S) ---> free ; functor(string, int, list(term(S))).
+
+
+:- pred unify(term(S), term_type(S), term(S), term_type(S), store(S), store(S)).
+:- mode unify(in, in, in, in, di, uo) is semidet.
+
+:- implementation.
+
+:- pred occurs(var(S), list(term(S)), store(S), store(S)).
+:- mode occurs(in, in, di, uo) is semidet.
+
+:- external(occurs/4).
+
+unify(T1, free, _T2, functor(Name2, Arity2, Args2)) -->
+ \+ occurs(T1, Args2),
+ store__set_mutvar(T1, functor(Name2, Arity2, Args2)).
+
Index: tests/valid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/valid/Mmakefile,v
retrieving revision 1.48
diff -u -d -r1.48 Mmakefile
--- Mmakefile 1999/11/14 02:29:19 1.48
+++ Mmakefile 1999/11/19 11:13:38
@@ -88,6 +88,7 @@
module_c.m \
module_d.m \
module_e.m \
+ mostly_uniq_neg.m \
mostly_uniq_mode_inf.m \
multidet_prune1.m \
multidet_test.m \
Index: tests/valid/mostly_uniq_neg.m
===================================================================
RCS file: mostly_uniq_neg.m
diff -N mostly_uniq_neg.m
--- /dev/null Fri Nov 19 22:05:11 1999
+++ mostly_uniq_neg.m Fri Nov 19 22:14:49 1999
@@ -0,0 +1,32 @@
+% A regression test, adapted from a bug report by Ralph Becket.
+% Mercury 0.8.1 and earlier reported a spurious mode error
+% for this code.
+
+:- module mostly_uniq_neg.
+:- interface.
+:- import_module list, store.
+
+:- type term(S) == mutvar(term_type(S), S).
+:- type var(S) == term(S).
+:- type term_type(S) ---> free ; functor(string, int, list(term(S))).
+
+
+:- pred unify(term(S), term_type(S), term(S), term_type(S), store(S), store(S)).
+:- mode unify(in, in, in, in, mdi, muo) is semidet.
+
+:- implementation.
+
+:- pred occurs(var(S), list(term(S)), store(S), store(S)).
+:- mode occurs(in, in, mdi, muo) is semidet.
+
+:- external(occurs/4).
+
+:- pred tr_store_set_mutvar(mutvar(T, S), T, store(S), store(S)).
+:- mode tr_store_set_mutvar(in, in, mdi, muo) is det.
+
+:- external(tr_store_set_mutvar/4).
+
+unify(T1, free, _T2, functor(Name2, Arity2, Args2)) -->
+ \+ occurs(T1, Args2),
+ tr_store_set_mutvar(T1, functor(Name2, Arity2, Args2)).
+
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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