[m-rev.] for review: promise scopes (part 1)

Zoltan Somogyi zs at cs.mu.OZ.AU
Mon Mar 21 16:45:01 AEDT 2005


For review by Ralph. I would like feedback on the reference manual
in particular.

Zoltan.

Replace the some() HLDS goal with a more general scope() goal, which can be
used not just for existential quantification but also for other purposes.

The main such purposes are new goal types that allow the programmer
to annotate arbitrary goals, and not just whole procedure bodies, with the
equivalents of promise_pure/promise_semipure and promise_only_solution:

	promise_pure ( <impure/semipure goal> )
	promise_semipure ( <impure goal> )

	promise_equivalent_solution [OutVar1, OutVar2] (
		<cc_multi/cc_nondet goal that computed OutVar1 & OutVar2>
	)

Both are intended to be helpful in writing constraint solvers, as well as in
other situations.

doc/reference_manual.texi:
	Document the new constructs.

library/ops.m:
	Add the keywords of the new constructs to the list of operators.
	Since they work similarly to the "some" operatior, they have the same
	precedence.

compiler/hlds_goal.m:
	Replace the some(Vars, SubGoal) HLDS construct, with its optional
	keep_this_commit attribute, with the new scope(Reason, SubGoal)
	construct. The Reason argument may say that this scope is an
	existential quantification, but it can also say that it represents
	a purity promise, the introduction of a single-solution context
	with promise_equivalent_solution, or a decision by a compiler pass.

	It can also say that the scope represents a set of goals that all arise
	from the unraveling of a unification between a variable and a ground
	term. This was intended to speed up mode checking by significantly
	reducing the number of delays and wakeups, but the cost of the scopes
	themselves turned out to be bigger than the gain in modechecking speed.

	Update the goal_path_step type to refer to scope goals instead of just
	existential quantification.

compiler/prog_data.m:
	Add new function symbols to the type we use to represent goals in items
	to stand for the new Mercury constructs.

compiler/prog_io_goal.m:
	Add code to read in the new language constructs.

compiler/prog_io_util.m:
	Add a utility predicate for use by the new code in prog_io_goal.m.

compiler/make_hlds.m:
	Convert the item representation of the new constructs to the HLDS
	representation.

	Document how the from_ground_term scope reason would work, but do not
	enable the code.

compiler/purity.m:
	Check code that uses the 

compiler/det_analysis.m:
	Make the insides of promise_equivalent_solution goals single solution
	contexts.

compiler/det_report.m:
	Provide mechanisms for reporting inappropriate usage of
	promise_equivalent_solution goals.

compiler/instmap.m:
	Add a utility predicate for use by one of the modules above.

compiler/deep_profiling.m:
	Use one of the new scope reasons to prevent simplify from optimizing
	away commits of goals that have been made impure, instead of the old
	keep_this_commit goal feature.

compiler/modes.m:
	Handle from_ground_term scopes when present; for now, they won't be
	present, since make_hlds isn't creating them.

compiler/options.m:
	Add two new compiler options, for use by implementors only, to allow
	finer control over the amount of output one gets with --debug-modes.
	(I used them when debugging the performance of the from_ground_term
	scope reason.) The options are --debug-modes-minimal and
	--debug-modes-verbose.

compiler/handle_options.m:
	Make the options that are meaningful only in the presence of
	--debug-modes imply --debug-modes, since this allows more convenient
	(shorter) invocations.

compiler/mode_debug.m:
	Respect the new options when deciding how much data to print
	when debugging of the mode checking process is enabled.

compiler/switch_detect.m:
	Rename a predicate to make it differ from another predicate by more
	than just its arity.

compiler/passes_aux.m:
	Bring this module up to date with ur current style guidelines,
	by using state variable syntax where appropriate.

compiler/*.m:
	Minor changes to conform to the change in the HLDS and/or parse tree
	goal type.

mdbcomp/program_representation.m:
	Rename the some goal to the scope goal, and the same for path steps,
	to keep them in sync with the HLDS.

browser/declarative_tree.m:
	Conform to the change in goal representations.

tests/hard_coded/promise_equivalent_solution_test.{m,exp}:	
	A new test case to test the handling of the promise_equivalent_solution
	construct.

tests/hard_coded/Mmakefile:	
	Enable the new test.

tests/hard_coded/purity/promise_pure_test.{m,exp}:	
	A new test case to test the handling of the promise_pure and
	promise_semipure constructs.

tests/hard_coded/purity/Mmakefile:	
	Enable the new test.

tests/warnings/promise_equivalent_solution.{m,exp}:	
	A new test case to test the error messages for improper use of the
	promise_pure and promise_semipure constructs.

tests/warnings/Mmakefile:	
	Enable the new test.

cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing browser
Index: browser/declarative_tree.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/browser/declarative_tree.m,v
retrieving revision 1.22
diff -u -r1.22 declarative_tree.m
--- browser/declarative_tree.m	12 Mar 2005 04:46:29 -0000	1.22
+++ browser/declarative_tree.m	16 Mar 2005 11:40:58 -0000
@@ -1103,8 +1103,8 @@
 			Contour, MaybeEnd, ArgNum, TotalArgs, HeadVars, 
 			AllTraced, Primitives0)
 	;
-		Goal = some_rep(InnerGoal, MaybeCut),
-		InnerPath = list.append(Path, [exist(MaybeCut)]),
+		Goal = scope_rep(InnerGoal, MaybeCut),
+		InnerPath = list.append(Path, [scope(MaybeCut)]),
 		InnerAndPath = goal_and_path(InnerGoal, InnerPath),
 		MaybePrims = make_primitive_list(Store, 
 			[InnerAndPath | GoalPaths],
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/add_heap_ops.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/add_heap_ops.m,v
retrieving revision 1.15
diff -u -r1.15 add_heap_ops.m
--- compiler/add_heap_ops.m	19 Jan 2005 03:10:28 -0000	1.15
+++ compiler/add_heap_ops.m	15 Feb 2005 16:28:07 -0000
@@ -166,8 +166,8 @@
 	NewOuterGoal = if_then_else([], InnerGoal, ThenGoal, True),
 	goal_expr_add_heap_ops(NewOuterGoal, OuterGoalInfo, Goal, !Info).
 
-goal_expr_add_heap_ops(some(A, B, Goal0), GoalInfo,
-		some(A, B, Goal) - GoalInfo, !Info) :-
+goal_expr_add_heap_ops(scope(Reason, Goal0), GoalInfo,
+		scope(Reason, Goal) - GoalInfo, !Info) :-
 	goal_add_heap_ops(Goal0, Goal, !Info).
 
 goal_expr_add_heap_ops(if_then_else(A, Cond0, Then0, Else0), GoalInfo,
Index: compiler/add_trail_ops.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/add_trail_ops.m,v
retrieving revision 1.17
diff -u -r1.17 add_trail_ops.m
--- compiler/add_trail_ops.m	19 Jan 2005 03:10:28 -0000	1.17
+++ compiler/add_trail_ops.m	15 Feb 2005 16:28:29 -0000
@@ -154,7 +154,7 @@
 	NewOuterGoal = if_then_else([], InnerGoal, ThenGoal, True),
 	goal_expr_add_trail_ops(NewOuterGoal, OuterGoalInfo, Goal, !Info).
 
-goal_expr_add_trail_ops(some(A, B, Goal0), OuterGoalInfo,
+goal_expr_add_trail_ops(scope(Reason, Goal0), OuterGoalInfo,
 		Goal - OuterGoalInfo, !Info) :-
 	Goal0 = _ - InnerGoalInfo,
 	goal_info_get_code_model(InnerGoalInfo, InnerCodeModel),
@@ -200,7 +200,7 @@
 		fail_goal(Context, FailGoal),
 
 		% put it all together
-		Goal2 = some(A, B, Goal1) - OuterGoalInfo,
+		Goal2 = scope(Reason, Goal1) - OuterGoalInfo,
 		SuccCode = conj([Goal2, ResetTicketCommitGoal,
 			PruneTicketsToGoal]) - OuterGoalInfo,
 		( OuterCodeModel = model_semi ->
@@ -214,7 +214,7 @@
 		Goal = conj([MarkTicketStackGoal, StoreTicketGoal, Goal3])
 	;
 		goal_add_trail_ops(Goal0, Goal1, !Info),
-		Goal = some(A, B, Goal1)
+		Goal = scope(Reason, Goal1)
 	).
 
 goal_expr_add_trail_ops(if_then_else(A, Cond0, Then0, Else0), GoalInfo,
Index: compiler/aditi_builtin_ops.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/aditi_builtin_ops.m,v
retrieving revision 1.13
diff -u -r1.13 aditi_builtin_ops.m
--- compiler/aditi_builtin_ops.m	21 Jan 2005 03:27:34 -0000	1.13
+++ compiler/aditi_builtin_ops.m	15 Feb 2005 14:24:29 -0000
@@ -147,8 +147,8 @@
 		), Cases0, Cases).
 transform_aditi_builtins_in_goal_expr(not(Goal0), _, not(Goal)) -->
 	transform_aditi_builtins_in_goal(Goal0, Goal).
-transform_aditi_builtins_in_goal_expr(some(A, B, Goal0), _,
-		some(A, B, Goal)) -->
+transform_aditi_builtins_in_goal_expr(scope(Reason, Goal0), _,
+		scope(Reason, Goal)) -->
 	transform_aditi_builtins_in_goal(Goal0, Goal).
 transform_aditi_builtins_in_goal_expr(Goal, _, Goal) -->
 	{ Goal = foreign_proc(_, _, _, _, _, _) }.
Index: compiler/assertion.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/assertion.m,v
retrieving revision 1.33
diff -u -r1.33 assertion.m
--- compiler/assertion.m	21 Jan 2005 06:20:35 -0000	1.33
+++ compiler/assertion.m	15 Feb 2005 17:23:15 -0000
@@ -216,8 +216,8 @@
 		% There may or may not be a some [] depending on whether
 		% the user explicity qualified the call or not.
 	(
-		P = some(_, _, conj(PCalls0) - _) - _PGoalInfo,
-		Q = some(_, _, conj(QCalls0) - _) - _QGoalInfo
+		P = scope(_, conj(PCalls0) - _) - _PGoalInfo,
+		Q = scope(_, conj(QCalls0) - _) - _QGoalInfo
 	->
 		PCalls = PCalls0,
 		QCalls = QCalls0
@@ -342,8 +342,8 @@
 		% There may or may not be an explicit some [Vars] there,
 		% as quantification now works correctly.
 	(
-		P = some(_, _, conj(PCalls0) - _) - _PGoalInfo,
-		Q = some(_, _, conj(QCalls0) - _) - _QGoalInfo
+		P = scope(_, conj(PCalls0) - _) - _PGoalInfo,
+		Q = scope(_, conj(QCalls0) - _) - _QGoalInfo
 	->
 		PCalls = PCalls0,
 		QCalls = QCalls0
@@ -543,9 +543,8 @@
 	equal_goals_list(GoalAs, GoalBs, !Subst).
 equal_goals(not(GoalA) - _, not(GoalB) - _, !Subst) :-
 	equal_goals(GoalA, GoalB, !Subst).
-equal_goals(some(VarsA, _, GoalA) - _, some(VarsB, _, GoalB) - _,
-		!Subst) :-
-	equal_vars(VarsA, VarsB, !Subst),
+equal_goals(scope(ReasonA, GoalA) - _, scope(ReasonB, GoalB) - _, !Subst) :-
+	equal_reason(ReasonA, ReasonB, !Subst),
 	equal_goals(GoalA, GoalB, !Subst).
 equal_goals(if_then_else(VarsA, IfA, ThenA, ElseA) - _,
 		if_then_else(VarsB, IfB, ThenB, ElseB) - _, !Subst) :-
@@ -570,6 +569,16 @@
 	equal_goals_shorthand(ShorthandGoalA - GoalInfoA,
 		ShorthandGoalB - GoalInfoB, !Subst).
 
+:- pred equal_reason(scope_reason::in, scope_reason::in, subst::in, subst::out)
+	is semidet.
+
+equal_reason(exist_quant(VarsA), exist_quant(VarsB), !Subst) :-
+	equal_vars(VarsA, VarsB, !Subst).
+equal_reason(barrier(Removable), barrier(Removable), !Subst).
+equal_reason(commit(ForcePruning), commit(ForcePruning), !Subst).
+equal_reason(from_ground_term(VarA), from_ground_term(VarB), !Subst) :-
+	equal_var(VarA, VarB, !Subst).
+
 :- pred equal_goals_shorthand(pair(shorthand_goal_expr, hlds_goal_info)::in,
 	pair(shorthand_goal_expr, hlds_goal_info)::in, subst::in, subst::out)
 	is semidet.
@@ -579,19 +588,24 @@
 	equal_goals(LeftGoalA, LeftGoalB, !Subst),
 	equal_goals(RightGoalA, RightGoalB, !Subst).
 
-:- pred equal_vars(prog_vars::in, prog_vars::in, subst::in, subst::out)
+:- pred equal_var(prog_var::in, prog_var::in, subst::in, subst::out)
 	is semidet.
 
-equal_vars([], [], !Subst).
-equal_vars([VA | VAs], [VB | VBs], !Subst) :-
+equal_var(VA, VB, !Subst) :-
 	( map__search(!.Subst, VA, SubstVA) ->
-		SubstVA = VB,
-		equal_vars(VAs, VBs, !Subst)
+		SubstVA = VB
 	;
-		map__insert(!.Subst, VA, VB, !:Subst),
-		equal_vars(VAs, VBs, !Subst)
+		map__insert(!.Subst, VA, VB, !:Subst)
 	).
 
+:- pred equal_vars(prog_vars::in, prog_vars::in, subst::in, subst::out)
+	is semidet.
+
+equal_vars([], [], !Subst).
+equal_vars([VA | VAs], [VB | VBs], !Subst) :-
+	equal_var(VA, VB, !Subst),
+	equal_vars(VAs, VBs, !Subst).
+
 :- pred equal_unification(unify_rhs::in, unify_rhs::in, subst::in, subst::out)
 	is semidet.
 
@@ -671,7 +685,8 @@
 	assertion__normalise_goals(Goal0s, Goals).
 assertion__normalise_goal(not(Goal0) - GI, not(Goal) - GI) :-
 	assertion__normalise_goal(Goal0, Goal).
-assertion__normalise_goal(some(A,B,Goal0) - GI, some(A,B,Goal) - GI) :-
+assertion__normalise_goal(scope(Reason, Goal0) - GI,
+		scope(Reason, Goal) - GI) :-
 	assertion__normalise_goal(Goal0, Goal).
 assertion__normalise_goal(if_then_else(A, If0, Then0, Else0) - GI,
 		if_then_else(A, If, Then, Else) - GI) :-
@@ -771,7 +786,7 @@
 	assertion__in_interface_check_list(Goals, PredInfo, !Module, !IO).
 assertion__in_interface_check(not(Goal) - _, PredInfo, !Module, !IO) :-
 	assertion__in_interface_check(Goal, PredInfo, !Module, !IO).
-assertion__in_interface_check(some(_, _, Goal) - _, PredInfo, !Module, !IO) :-
+assertion__in_interface_check(scope(_, Goal) - _, PredInfo, !Module, !IO) :-
 	assertion__in_interface_check(Goal, PredInfo, !Module, !IO).
 assertion__in_interface_check(if_then_else(_, If, Then, Else) - _,
 		PredInfo, !Module, !IO) :-
Index: compiler/build_mode_constraints.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/build_mode_constraints.m,v
retrieving revision 1.2
diff -u -r1.2 build_mode_constraints.m
--- compiler/build_mode_constraints.m	25 Feb 2005 12:13:04 -0000	1.2
+++ compiler/build_mode_constraints.m	5 Mar 2005 07:59:21 -0000
@@ -283,7 +283,7 @@
 		add_mc_vars_for_goal(
 			PredId, ProgVarset, Goal, !Varset, !VarMap
 		)
-	;	GoalExpr = some(_, _, Goal),
+	;	GoalExpr = scope(_, Goal),
 		add_mc_vars_for_goal(
 			PredId, ProgVarset, Goal, !Varset, !VarMap
 		)
@@ -588,7 +588,7 @@
 	% some Xs Goal
 	%
 goal_expr_constraints(ModuleInfo, VarMap, PredId,
-	some(_ExistVars, _CanRemove, Goal),
+	scope(_Reason, Goal),
 	GoalPath, Nonlocals, Constraints) :-
 	Goal = _ - SomeGoalInfo,
 	goal_info_get_goal_path(SomeGoalInfo, SomeGoalPath),
Index: compiler/bytecode_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/bytecode_gen.m,v
retrieving revision 1.87
diff -u -r1.87 bytecode_gen.m
--- compiler/bytecode_gen.m	21 Jan 2005 06:20:35 -0000	1.87
+++ compiler/bytecode_gen.m	15 Feb 2005 14:24:33 -0000
@@ -227,7 +227,7 @@
 			tree(SomeCode,
 			     EndofCode))
 	;
-		GoalExpr = some(_, _, Goal),
+		GoalExpr = scope(_, Goal),
 		bytecode_gen__goal(Goal, !ByteInfo, SomeCode),
 		bytecode_gen__get_next_temp(Temp, !ByteInfo),
 		EnterCode = node([enter_commit(Temp)]),
Index: compiler/code_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/code_gen.m,v
retrieving revision 1.135
diff -u -r1.135 code_gen.m
--- compiler/code_gen.m	1 Feb 2005 07:11:28 -0000	1.135
+++ compiler/code_gen.m	15 Feb 2005 17:03:36 -0000
@@ -1277,8 +1277,7 @@
 		GoalInfo, CodeModel, Code, !CI) :-
 	switch_gen__generate_switch(CodeModel, Var, CanFail, CaseList,
 		GoalInfo, Code, !CI).
-code_gen__generate_goal_2(some(_Vars, _, Goal), _GoalInfo, CodeModel, Code,
-		!CI) :-
+code_gen__generate_goal_2(scope(_, Goal), _GoalInfo, CodeModel, Code, !CI) :-
 	commit_gen__generate_commit(CodeModel, Goal, Code, !CI).
 code_gen__generate_goal_2(generic_call(GenericCall, Args, Modes, Det),
 		GoalInfo, CodeModel, Code, !CI) :-
Index: compiler/code_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/code_util.m,v
retrieving revision 1.154
diff -u -r1.154 code_util.m
--- compiler/code_util.m	19 Jan 2005 03:10:30 -0000	1.154
+++ compiler/code_util.m	15 Feb 2005 16:16:53 -0000
@@ -246,7 +246,7 @@
 	% that expand to mktempframe and variants thereof. The performance
 	% impact of being too conservative is probably not too bad.
 code_util__goal_may_alloc_temp_frame_2(foreign_proc(_, _, _, _, _, _), yes).
-code_util__goal_may_alloc_temp_frame_2(some(_Vars, _, Goal), May) :-
+code_util__goal_may_alloc_temp_frame_2(scope(_, Goal), May) :-
 	Goal = _ - GoalInfo,
 	goal_info_get_code_model(GoalInfo, CodeModel),
 	( CodeModel = model_non ->
Index: compiler/constraint.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/constraint.m,v
retrieving revision 1.58
diff -u -r1.58 constraint.m
--- compiler/constraint.m	16 Oct 2004 15:05:51 -0000	1.58
+++ compiler/constraint.m	15 Feb 2005 15:10:11 -0000
@@ -156,9 +156,8 @@
 	propagate_disj(Goals0, [], Goals, !Info),
 	flatten_constraints(Constraints0, Constraints).
 
-propagate_conj_sub_goal_2(some(Vars, CanRemove, Goal0) - GoalInfo,
-		Constraints, [some(Vars, CanRemove, Goal) - GoalInfo], !Info)
-		:-
+propagate_conj_sub_goal_2(scope(Reason, Goal0) - GoalInfo, Constraints,
+		[scope(Reason, Goal) - GoalInfo], !Info) :-
 	propagate_goal(Goal0, Constraints, Goal, !Info).
 
 propagate_conj_sub_goal_2(not(NegGoal0) - GoalInfo, Constraints0,
@@ -719,7 +718,7 @@
 	(
 		goal_is_atomic(GoalExpr)
 	;
-		( GoalExpr = some(_, _, SubGoal)
+		( GoalExpr = scope(_, SubGoal)
 		; GoalExpr = not(SubGoal)
 		),
 		goal_is_simple(SubGoal)
@@ -808,8 +807,8 @@
 		    ), Cases0).
 strip_constraint_markers_expr(not(Goal)) =
 		not(strip_constraint_markers(Goal)).
-strip_constraint_markers_expr(some(Vars, Remove, Goal)) =
-		some(Vars, Remove, strip_constraint_markers(Goal)).
+strip_constraint_markers_expr(scope(Reason, Goal)) =
+		scope(Reason, strip_constraint_markers(Goal)).
 strip_constraint_markers_expr(if_then_else(Vars, If, Then, Else)) =
 		if_then_else(Vars, strip_constraint_markers(If),
 			strip_constraint_markers(Then),
Index: compiler/cse_detection.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/cse_detection.m,v
retrieving revision 1.79
diff -u -r1.79 cse_detection.m
--- compiler/cse_detection.m	14 Jun 2004 04:15:59 -0000	1.79
+++ compiler/cse_detection.m	15 Feb 2005 14:24:58 -0000
@@ -90,16 +90,18 @@
 
 detect_cse_in_proc(ProcId, PredId, !ModuleInfo, !IO) :-
 	detect_cse_in_proc_2(ProcId, PredId, Redo, !ModuleInfo),
-	( Redo = no ->
-		true
-		;
+	(
+		Redo = no
+	;
+		Redo = yes,
 		globals__io_lookup_bool_option(very_verbose, VeryVerbose, !IO),
-		( VeryVerbose = yes ->
+		(
+			VeryVerbose = yes,
 			io__write_string("% Repeating mode check for ", !IO),
 			hlds_out__write_pred_id(!.ModuleInfo, PredId, !IO),
 			io__write_string("\n", !IO)
 		;
-			true
+			VeryVerbose = no
 		),
 		modecheck_proc(ProcId, PredId, !ModuleInfo, Errs, _Changed,
 			!IO),
@@ -108,22 +110,24 @@
 		;
 			true
 		),
-		( VeryVerbose = yes ->
+		(
+			VeryVerbose = yes,
 			io__write_string("% Repeating switch detection for ",
 				!IO),
 			hlds_out__write_pred_id(!.ModuleInfo, PredId, !IO),
 			io__write_string("\n", !IO)
 		;
-			true
+			VeryVerbose = no
 		),
 		detect_switches_in_proc(ProcId, PredId, !ModuleInfo),
-		( VeryVerbose = yes ->
+		(
+			VeryVerbose = yes,
 			io__write_string("% Repeating common " ++
 				"deconstruction detection for ", !IO),
 			hlds_out__write_pred_id(!.ModuleInfo, PredId, !IO),
 			io__write_string("\n", !IO)
 		;
-			true
+			VeryVerbose = no
 		),
 		detect_cse_in_proc(ProcId, PredId, !ModuleInfo, !IO)
 	).
@@ -211,8 +215,7 @@
 
 detect_cse_in_goal_1(Goal0 - GoalInfo, InstMap0, !CseInfo, Redo,
 		Goal - GoalInfo, InstMap) :-
-	detect_cse_in_goal_2(Goal0, GoalInfo, InstMap0, !CseInfo,
-		Redo, Goal),
+	detect_cse_in_goal_2(Goal0, GoalInfo, InstMap0, !CseInfo, Redo, Goal),
 	goal_info_get_instmap_delta(GoalInfo, InstMapDelta),
 	instmap__apply_instmap_delta(InstMap0, InstMapDelta, InstMap).
 
@@ -246,8 +249,8 @@
 detect_cse_in_goal_2(not(Goal0), _GoalInfo, InstMap, !CseInfo, Redo,
 		not(Goal)) :-
 	detect_cse_in_goal(Goal0, InstMap, !CseInfo, Redo, Goal).
-detect_cse_in_goal_2(some(Vars, CanRemove, Goal0), _GoalInfo, InstMap,
-		!CseInfo, Redo, some(Vars, CanRemove, Goal)) :-
+detect_cse_in_goal_2(scope(Reason, Goal0), _GoalInfo, InstMap,
+		!CseInfo, Redo, scope(Reason, Goal)) :-
 	detect_cse_in_goal(Goal0, InstMap, !CseInfo, Redo, Goal).
 detect_cse_in_goal_2(conj(Goals0), _GoalInfo, InstMap, !CseInfo, Redo,
 		conj(Goals)) :-
Index: compiler/dead_proc_elim.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/dead_proc_elim.m,v
retrieving revision 1.95
diff -u -r1.95 dead_proc_elim.m
--- compiler/dead_proc_elim.m	21 Jan 2005 06:20:36 -0000	1.95
+++ compiler/dead_proc_elim.m	15 Feb 2005 15:10:21 -0000
@@ -419,7 +419,7 @@
 	dead_proc_elim__examine_goals(Goals, CurrProc, !Queue, !Needed).
 dead_proc_elim__examine_expr(not(Goal), CurrProc, !Queue, !Needed) :-
 	dead_proc_elim__examine_goal(Goal, CurrProc, !Queue, !Needed).
-dead_proc_elim__examine_expr(some(_, _, Goal), CurrProc, !Queue, !Needed) :-
+dead_proc_elim__examine_expr(scope(_, Goal), CurrProc, !Queue, !Needed) :-
 	dead_proc_elim__examine_goal(Goal, CurrProc, !Queue, !Needed).
 dead_proc_elim__examine_expr(switch(_, _, Cases), CurrProc, !Queue, !Needed) :-
 	dead_proc_elim__examine_cases(Cases, CurrProc, !Queue, !Needed).
@@ -888,7 +888,7 @@
 pre_modecheck_examine_goal(generic_call(_,_,_,_) - _, !DeadInfo).
 pre_modecheck_examine_goal(not(Goal) - _, !DeadInfo) :-
 	pre_modecheck_examine_goal(Goal, !DeadInfo).
-pre_modecheck_examine_goal(some(_, _, Goal) - _, !DeadInfo) :-
+pre_modecheck_examine_goal(scope(_, Goal) - _, !DeadInfo) :-
 	pre_modecheck_examine_goal(Goal, !DeadInfo).
 pre_modecheck_examine_goal(call(_, _, _, _, _, PredName) - _, !DeadInfo) :-
 	dead_pred_info_add_pred_name(PredName, !DeadInfo).
Index: compiler/deep_profiling.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/deep_profiling.m,v
retrieving revision 1.31
diff -u -r1.31 deep_profiling.m
--- compiler/deep_profiling.m	21 Jan 2005 03:27:36 -0000	1.31
+++ compiler/deep_profiling.m	16 Mar 2005 10:05:18 -0000
@@ -184,13 +184,12 @@
 	apply_tail_recursion_info::in, hlds_goal::out, bool::in, bool::out,
 	maybe(list(prog_var))::out) is det.
 
-apply_tail_recursion_to_goal(Goal0, ApplyInfo, Goal,
-		FoundTailCall0, FoundTailCall, Continue) :-
+apply_tail_recursion_to_goal(Goal0, ApplyInfo, Goal, !FoundTailCall,
+		Continue) :-
 	Goal0 = GoalExpr0 - GoalInfo0,
 	(
 		GoalExpr0 = foreign_proc(_, _, _, _, _, _),
 		Goal = Goal0,
-		FoundTailCall = FoundTailCall0,
 		Continue = no
 	;
 		GoalExpr0 = call(PredId, ProcId, Args,
@@ -215,21 +214,18 @@
 				Builtin, UnifyContext, SymName),
 			goal_info_add_feature(GoalInfo0, tailcall, GoalInfo),
 			Goal = GoalExpr - GoalInfo,
-			FoundTailCall = yes
+			!:FoundTailCall = yes
 		;
-			Goal = Goal0,
-			FoundTailCall = FoundTailCall0
+			Goal = Goal0
 		),
 		Continue = no
 	;
 		GoalExpr0 = generic_call(_, _, _, _),
 		Goal = Goal0,
-		FoundTailCall = FoundTailCall0,
 		Continue = no
 	;
 		GoalExpr0 = unify(_, _, _, Unify0, _),
 		Goal = Goal0,
-		FoundTailCall = FoundTailCall0,
 		(
 			Unify0 = assign(ToVar, FromVar)
 		->
@@ -241,47 +237,44 @@
 		)
 	;
 		GoalExpr0 = conj(Goals0),
-		apply_tail_recursion_to_conj(Goals0, ApplyInfo,
-			Goals, FoundTailCall0, FoundTailCall, Continue),
+		apply_tail_recursion_to_conj(Goals0, ApplyInfo, Goals,
+			!FoundTailCall, Continue),
 		GoalExpr = conj(Goals),
 		Goal = GoalExpr - GoalInfo0
 	;
 		GoalExpr0 = disj(Goals0),
-		apply_tail_recursion_to_disj(Goals0, ApplyInfo,
-			Goals, FoundTailCall0, FoundTailCall),
+		apply_tail_recursion_to_disj(Goals0, ApplyInfo, Goals,
+			!FoundTailCall),
 		GoalExpr = disj(Goals),
 		Goal = GoalExpr - GoalInfo0,
 		Continue = no
 	;
 		GoalExpr0 = switch(Var, CanFail, Cases0),
-		apply_tail_recursion_to_cases(Cases0, ApplyInfo,
-			Cases, FoundTailCall0, FoundTailCall),
+		apply_tail_recursion_to_cases(Cases0, ApplyInfo, Cases,
+			!FoundTailCall),
 		GoalExpr = switch(Var, CanFail, Cases),
 		Goal = GoalExpr - GoalInfo0,
 		Continue = no
 	;
 		GoalExpr0 = if_then_else(Vars, Cond, Then0, Else0),
-		apply_tail_recursion_to_goal(Then0, ApplyInfo,
-			Then, FoundTailCall0, FoundTailCall1, _),
-		apply_tail_recursion_to_goal(Else0, ApplyInfo,
-			Else, FoundTailCall1, FoundTailCall, _),
+		apply_tail_recursion_to_goal(Then0, ApplyInfo, Then,
+			!FoundTailCall, _),
+		apply_tail_recursion_to_goal(Else0, ApplyInfo, Else,
+			!FoundTailCall, _),
 		GoalExpr = if_then_else(Vars, Cond, Then, Else),
 		Goal = GoalExpr - GoalInfo0,
 		Continue = no
 	;
 		GoalExpr0 = par_conj(_),
 		Goal = Goal0,
-		FoundTailCall = FoundTailCall0,
 		Continue = no
 	;
-		GoalExpr0 = some(_, _, _),
+		GoalExpr0 = scope(_, _),
 		Goal = Goal0,
-		FoundTailCall = FoundTailCall0,
 		Continue = no
 	;
 		GoalExpr0 = not(_),
 		Goal = Goal0,
-		FoundTailCall = FoundTailCall0,
 		Continue = no
 	;
 		GoalExpr0 = shorthand(_),
@@ -306,20 +299,19 @@
 	bool::in, bool::out, maybe(list(prog_var))::out) is det.
 
 apply_tail_recursion_to_conj([], ApplyInfo, [],
-		FoundTailCall, FoundTailCall, yes(ApplyInfo ^ outputs)).
+		!FoundTailCall, yes(ApplyInfo ^ outputs)).
 apply_tail_recursion_to_conj([Goal0 | Goals0], ApplyInfo0, [Goal | Goals],
-		FoundTailCall0, FoundTailCall, Continue) :-
+		!FoundTailCall, Continue) :-
 	apply_tail_recursion_to_conj(Goals0, ApplyInfo0, Goals,
-		FoundTailCall0, FoundTailCall1, Continue1),
+		!FoundTailCall, Continue1),
 	(
 		Continue1 = yes(Outputs),
 		apply_tail_recursion_to_goal(Goal0,
 			ApplyInfo0 ^ outputs := Outputs, Goal,
-			FoundTailCall1, FoundTailCall, Continue)
+			!FoundTailCall, Continue)
 	;
 		Continue1 = no,
 		Goal = Goal0,
-		FoundTailCall = FoundTailCall1,
 		Continue = no
 	).
 
@@ -327,29 +319,27 @@
 	apply_tail_recursion_info::in, list(hlds_goal)::out,
 	bool::in, bool::out) is det.
 
-apply_tail_recursion_to_disj([], _, [], FoundTailCall, FoundTailCall).
+apply_tail_recursion_to_disj([], _, [], !FoundTailCall).
 apply_tail_recursion_to_disj([Goal0], ApplyInfo, [Goal],
-		FoundTailCall0, FoundTailCall) :-
+		!FoundTailCall) :-
 	apply_tail_recursion_to_goal(Goal0, ApplyInfo, Goal,
-		FoundTailCall0, FoundTailCall, _).
+		!FoundTailCall, _).
 apply_tail_recursion_to_disj([Goal0 | Goals0], ApplyInfo, [Goal0 | Goals],
-		FoundTailCall0, FoundTailCall) :-
+		!FoundTailCall) :-
 	Goals0 = [_ | _],
-	apply_tail_recursion_to_disj(Goals0, ApplyInfo, Goals,
-		FoundTailCall0, FoundTailCall).
+	apply_tail_recursion_to_disj(Goals0, ApplyInfo, Goals, !FoundTailCall).
 
 :- pred apply_tail_recursion_to_cases(list(case)::in,
 	apply_tail_recursion_info::in, list(case)::out,
 	bool::in, bool::out) is det.
 
-apply_tail_recursion_to_cases([], _,
-		[], FoundTailCall, FoundTailCall).
+apply_tail_recursion_to_cases([], _, [], !FoundTailCall).
 apply_tail_recursion_to_cases([case(ConsId, Goal0) | Cases0], ApplyInfo,
-		[case(ConsId, Goal) | Cases], FoundTailCall0, FoundTailCall) :-
+		[case(ConsId, Goal) | Cases], !FoundTailCall) :-
 	apply_tail_recursion_to_goal(Goal0, ApplyInfo, Goal,
-		FoundTailCall0, FoundTailCall1, _),
+		!FoundTailCall, _),
 	apply_tail_recursion_to_cases(Cases0, ApplyInfo, Cases,
-		FoundTailCall1, FoundTailCall).
+		!FoundTailCall).
 
 %-----------------------------------------------------------------------------%
 
@@ -405,7 +395,7 @@
 		figure_out_rec_call_numbers_in_goal_list(Goals,
 			!N, !TailCallSites)
 	;
-		GoalExpr = some(_, _, Goal1),
+		GoalExpr = scope(_, Goal1),
 		figure_out_rec_call_numbers(Goal1, !N, !TailCallSites)
 	;
 		GoalExpr = not(Goal1),
@@ -953,28 +943,44 @@
 	transform_goal([neg | Path], Goal0, Goal, AddedImpurity, !DeepInfo),
 	add_impurity_if_needed(AddedImpurity, GoalInfo0, GoalInfo).
 
-transform_goal(Path, some(QVars, CanRemove, Goal0) - GoalInfo0,
-		some(QVars, CanRemove, Goal) - GoalInfo, AddedImpurity,
-		!DeepInfo) :-
-	Goal0 = _ - InnerInfo,
+transform_goal(Path, scope(Reason0, SubGoal0) - GoalInfo0, Goal,
+		AddedImpurity, !DeepInfo) :-
+	SubGoal0 = _ - InnerInfo,
 	goal_info_get_determinism(GoalInfo0, OuterDetism),
 	goal_info_get_determinism(InnerInfo, InnerDetism),
 	( InnerDetism = OuterDetism ->
-		GoalInfo1 = GoalInfo0,
-		MaybeCut = no_cut
-	;
-		% Given a subgoal containing both nondet code and impure code,
-		% determinism analysis will remove the `some' wrapped around
-		% that subgoal if it is allowed to. If we get here, then the
-		% subgoal inside the `some' contains nondet code, and the deep
-		% profiling transformation will make it impure as well.
-
-		goal_info_add_feature(GoalInfo0, keep_this_commit, GoalInfo1),
-		MaybeCut = cut
+		MaybeCut = no_cut,
+		Reason = Reason0,
+		AddForceCommit = no
+	;
+		% Given a subgoal containing both at_most_many code and
+		% impure code, determinism analysis will remove the `scope'
+		% wrapped around that subgoal if it is allowed to. If we get
+		% here, then the subgoal inside the `scope' contains
+		% at_most_many code (which means that removing the scope
+		% will change its determinism) and the deep profiling
+		% transformation will make it impure as well.
+
+		MaybeCut = cut,
+		( Reason0 = commit(_) ->
+			Reason = commit(force_pruning),
+			AddForceCommit = no
+		;
+			Reason = Reason0,
+			AddForceCommit = yes
+		)
 	),
-	transform_goal([exist(MaybeCut) | Path], Goal0, Goal, AddedImpurity,
-		!DeepInfo),
-	add_impurity_if_needed(AddedImpurity, GoalInfo1, GoalInfo).
+	transform_goal([scope(MaybeCut) | Path], SubGoal0, SubGoal,
+		AddedImpurity, !DeepInfo),
+	add_impurity_if_needed(AddedImpurity, GoalInfo0, GoalInfo),
+	(
+		AddForceCommit = no,
+		Goal = scope(Reason, SubGoal) - GoalInfo
+	;
+		AddForceCommit = yes,
+		InnerGoal = scope(Reason, SubGoal) - GoalInfo,
+		Goal = scope(commit(force_pruning), InnerGoal) - GoalInfo
+	).
 
 transform_goal(Path, if_then_else(IVars, Cond0, Then0, Else0) - GoalInfo0,
 		if_then_else(IVars, Cond, Then, Else) - GoalInfo,
Index: compiler/deforest.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/deforest.m,v
retrieving revision 1.46
diff -u -r1.46 deforest.m
--- compiler/deforest.m	7 Feb 2005 15:10:32 -0000	1.46
+++ compiler/deforest.m	15 Feb 2005 15:10:33 -0000
@@ -326,8 +326,8 @@
 deforest__goal(not(Goal0) - Info, not(Goal) - Info, !PDInfo, !IO) :-
 	deforest__goal(Goal0, Goal, !PDInfo, !IO).
 
-deforest__goal(some(Vs, CanRemove, Goal0) - Info,
-		some(Vs, CanRemove, Goal) - Info, !PDInfo, !IO) :-
+deforest__goal(scope(Reason, Goal0) - Info,
+		scope(Reason, Goal) - Info, !PDInfo, !IO) :-
 	deforest__goal(Goal0, Goal, !PDInfo, !IO).
 
 deforest__goal(Goal0, Goal, !PDInfo, !IO) :-
Index: compiler/delay_construct.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/delay_construct.m,v
retrieving revision 1.8
diff -u -r1.8 delay_construct.m
--- compiler/delay_construct.m	14 Jun 2004 04:16:00 -0000	1.8
+++ compiler/delay_construct.m	15 Feb 2005 15:10:47 -0000
@@ -146,9 +146,9 @@
 		delay_construct_in_goal(Else0, InstMap0, DelayInfo, Else),
 		Goal = if_then_else(Vars, Cond, Then, Else) - GoalInfo0
 	;
-		GoalExpr0 = some(Var, CanRemove, SubGoal0),
+		GoalExpr0 = scope(Reason, SubGoal0),
 		delay_construct_in_goal(SubGoal0, InstMap0, DelayInfo, SubGoal),
-		Goal = some(Var, CanRemove, SubGoal) - GoalInfo0
+		Goal = scope(Reason, SubGoal) - GoalInfo0
 	;
 		GoalExpr0 = generic_call(_, _, _, _),
 		Goal = GoalExpr0 - GoalInfo0
Index: compiler/dependency_graph.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/dependency_graph.m,v
retrieving revision 1.74
diff -u -r1.74 dependency_graph.m
--- compiler/dependency_graph.m	19 Jan 2005 03:10:32 -0000	1.74
+++ compiler/dependency_graph.m	15 Feb 2005 15:10:59 -0000
@@ -388,8 +388,7 @@
 dependency_graph__add_arcs_in_goal_2(not(Goal), Caller, !DepGraph) :-
 	dependency_graph__add_arcs_in_goal(Goal, Caller, !DepGraph).
 
-dependency_graph__add_arcs_in_goal_2(some(_Vars, _, Goal), Caller,
-		!DepGraph) :-
+dependency_graph__add_arcs_in_goal_2(scope(_, Goal), Caller, !DepGraph) :-
 	dependency_graph__add_arcs_in_goal(Goal, Caller, !DepGraph).
 
 dependency_graph__add_arcs_in_goal_2(generic_call(_, _, _, _), _, !DepGraph).
@@ -800,7 +799,7 @@
 	process_aditi_goal(yes, Cond, !Map, !Info),
 	process_aditi_goal(IsNeg, Then, !Map, !Info),
 	process_aditi_goal(IsNeg, Else, !Map, !Info).
-process_aditi_goal(IsNeg, some(_, _, Goal) - _, !Map, !Info) :-
+process_aditi_goal(IsNeg, scope(_, Goal) - _, !Map, !Info) :-
 	process_aditi_goal(IsNeg, Goal, !Map, !Info).
 process_aditi_goal(_IsNeg, not(Goal) - _, !Map, !Info) :-
 	process_aditi_goal(yes, Goal, !Map, !Info).
Index: compiler/det_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/det_analysis.m,v
retrieving revision 1.173
diff -u -r1.173 det_analysis.m
--- compiler/det_analysis.m	6 Jan 2005 04:30:54 -0000	1.173
+++ compiler/det_analysis.m	16 Mar 2005 12:48:01 -0000
@@ -367,16 +367,26 @@
 		SolnContext = SolnContext0
 	),
 
-	% Some other part of the compiler has determined that we need to keep
-	% the cut represented by this quantification. This can happen e.g.
-	% when deep profiling adds impure code to the goal inside the some;
-	% it doesn't want to change the behavior of the some, even though
-	% the addition of impurity would make the if-then-else treat it
-	% differently.
 
 	(
-		Goal0 = some(_, _, _),
-		goal_info_has_feature(GoalInfo0, keep_this_commit)
+		Goal0 = scope(ScopeReason, _),
+		(
+			% Some other part of the compiler has determined
+			% that we need to keep the cut represented by this
+			% quantification. This can happen e.g. when deep
+			% profiling adds impure code to the goal inside the
+			% scope; it doesn't want to change the behavior of
+			% the scope, even though the addition of impurity
+			% would make the if-then-else treat it differently.
+
+			ScopeReason = commit(force_pruning)
+		;
+			% If all solutions are promised to be equivalent
+			% according to the relevant equality theory, we want
+			% to prune away all but one of those solutions.
+
+			ScopeReason = promise_equivalent_solution(_)
+		)
 	->
 		Prune = yes
 	;
@@ -483,17 +493,17 @@
 		Goal1 \= disj(_),
 
 		% do we already have a commit?
-		Goal1 \= some(_, _, _)
+		Goal1 \= scope(_, _)
 	->
-		% a commit needed - we must introduce an explicit `some'
+		% a commit needed - we must introduce an explicit `commit'
 		% so that the code generator knows to insert the appropriate
 		% code for pruning
 		goal_info_set_determinism(GoalInfo0,
 			FinalInternalDetism, InnerInfo),
-		Goal = some([], can_remove, Goal1 - InnerInfo),
+		Goal = scope(commit(dont_force_pruning), Goal1 - InnerInfo),
 		Msgs = Msgs1
 	;
-		% either no commit needed, or a `some' already present
+		% either no commit needed, or a `scope' already present
 		Goal = Goal1,
 		Msgs = Msgs1
 	).
@@ -750,10 +760,48 @@
 	% but we cannot rely on explicit quantification to detect this.
 	% Therefore cuts are handled in det_infer_goal.
 
-det_infer_goal_2(some(Vars, CanRemove, Goal0), _, InstMap0, SolnContext,
-		DetInfo, _, _, some(Vars, CanRemove, Goal), Det, Msgs) :-
+det_infer_goal_2(scope(Reason, Goal0), GoalInfo0, InstMap0, SolnContext0,
+		DetInfo, _, _, scope(Reason, Goal), Det, Msgs) :-
+	( Reason = promise_equivalent_solution(Vars) ->
+		SolnContext = first_soln,
+		goal_info_get_instmap_delta(GoalInfo0, InstmapDelta),
+		instmap_delta_changed_vars(InstmapDelta, ChangedVars),
+		det_info_get_module_info(DetInfo, ModuleInfo),
+		set__divide(var_is_ground_in_instmap(ModuleInfo, InstMap0),
+			ChangedVars, _GroundAtStartVars, BoundVars),
+
+		goal_info_get_context(GoalInfo0, Context),
+		det_get_proc_info(DetInfo, ProcInfo),
+		proc_info_varset(ProcInfo, VarSet),
+
+		% Which vars were bound inside the scope but not listed
+		% in the promise_equivalent_solution?
+		set__difference(BoundVars, set__list_to_set(Vars), BugVars),
+		( set__empty(BugVars) ->
+			ScopeMsgs1 = []
+		;
+			ScopeMsg1 = promise_equivalent_solution_missing_vars(
+				Context, VarSet, BugVars),
+			ScopeMsgs1 = [ScopeMsg1]
+		),
+		% Which vars were listed in the promise_equivalent_solution
+		% but not bound inside the scope?
+		set__difference(set__list_to_set(Vars), BoundVars, ExtraVars),
+		( set__empty(ExtraVars) ->
+			ScopeMsgs2 = []
+		;
+			ScopeMsg2 = promise_equivalent_solution_extra_vars(
+				Context, VarSet, ExtraVars),
+			ScopeMsgs2 = [ScopeMsg2]
+		),
+		ScopeMsgs = ScopeMsgs1 ++ ScopeMsgs2
+	;
+		SolnContext = SolnContext0,
+		ScopeMsgs = []
+	),
 	det_infer_goal(Goal0, InstMap0, SolnContext, DetInfo,
-		Goal, Det, Msgs).
+		Goal, Det, SubMsgs),
+	list__append(SubMsgs, ScopeMsgs, Msgs).
 
 	% pragma foregin_codes are handled in the same way as predicate calls
 det_infer_goal_2(foreign_proc(Attributes, PredId, ProcId, Args, ExtraArgs,
@@ -768,7 +816,8 @@
 	( MaybeDetism = yes(Detism0) ->
 		determinism_components(Detism0, CanFail, NumSolns0),
 		( 
-			may_throw_exception(Attributes) = will_not_throw_exception,
+			may_throw_exception(Attributes) =
+				will_not_throw_exception,
 			Detism0 = erroneous
 		->
 			Msgs0 = [will_not_throw_with_erroneous(PredId, ProcId)]
Index: compiler/det_report.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/det_report.m,v
retrieving revision 1.98
diff -u -r1.98 det_report.m
--- compiler/det_report.m	27 Jan 2005 03:38:06 -0000	1.98
+++ compiler/det_report.m	16 Mar 2005 12:48:48 -0000
@@ -20,7 +20,7 @@
 :- import_module hlds__hlds_pred.
 :- import_module parse_tree__prog_data.
 
-:- import_module io, list.
+:- import_module io, list, set.
 
 :- type det_msg	--->
 			% warnings
@@ -61,10 +61,14 @@
 				hlds_goal_info, list(hlds_goal))
 		; 	pragma_c_code_without_det_decl(pred_id, proc_id)
 		;	has_io_state_but_not_det(pred_id, proc_id)
-		;	will_not_throw_with_erroneous(pred_id, proc_id)	
-		;	export_model_non_proc(pred_id, proc_id, determinism).
+		;	will_not_throw_with_erroneous(pred_id, proc_id)
+		;	export_model_non_proc(pred_id, proc_id, determinism)
 				% Procedure with multi or nondet detism
 				% exported via :- pragma export ...
+		;	promise_equivalent_solution_missing_vars(prog_context,
+				prog_varset, set(prog_var))
+		;	promise_equivalent_solution_extra_vars(prog_context,
+				prog_varset, set(prog_var)).
 
 :- type seen_call_id
 	--->	seen_call(pred_id, proc_id)
@@ -108,7 +112,7 @@
 	;	any_mode.	% the warning should be reported
 				% if it occurs in any mode of the predicate
 
-	% Return `yes' if the warning should be reported if it occurs in
+	% Decide if the warning should be reported if it occurs in
 	% any mode of the predicate, not only if it occurs in all modes.
 :- pred det_msg_is_any_mode_msg(det_msg::in, msg_modes::out) is det.
 
@@ -152,8 +156,16 @@
 :- import_module parse_tree__prog_util.
 :- import_module parse_tree__prog_type.
 
-:- import_module assoc_list, bool, int, map, set, std_util, require, string.
-:- import_module getopt_io, term, varset.
+:- import_module assoc_list.
+:- import_module bool.
+:- import_module getopt_io.
+:- import_module int.
+:- import_module map.
+:- import_module require.
+:- import_module std_util.
+:- import_module string.
+:- import_module term.
+:- import_module varset.
 
 %-----------------------------------------------------------------------------%
 
@@ -655,7 +667,7 @@
 		Diagnosed = no
 	).
 
-det_diagnose_goal_2(some(_Vars, _, Goal), _, Desired, Actual,
+det_diagnose_goal_2(scope(_, Goal), _, Desired, Actual,
 		SwitchContext, DetInfo, Diagnosed, !IO) :-
 	Goal = _ - GoalInfo,
 	goal_info_get_determinism(GoalInfo, Internal),
@@ -1066,6 +1078,8 @@
 det_msg_get_type(has_io_state_but_not_det(_, _), error).
 det_msg_get_type(will_not_throw_with_erroneous(_, _), error).
 det_msg_get_type(export_model_non_proc(_, _, _), error).
+det_msg_get_type(promise_equivalent_solution_missing_vars(_, _, _), error).
+det_msg_get_type(promise_equivalent_solution_extra_vars(_, _, _), error).
 
 det_msg_is_any_mode_msg(multidet_disj(_, _), all_modes).
 det_msg_is_any_mode_msg(det_disj(_, _), all_modes).
@@ -1091,6 +1105,10 @@
 det_msg_is_any_mode_msg(has_io_state_but_not_det(_, _), any_mode).
 det_msg_is_any_mode_msg(will_not_throw_with_erroneous(_, _), any_mode).
 det_msg_is_any_mode_msg(export_model_non_proc(_, _, _), any_mode).
+det_msg_is_any_mode_msg(promise_equivalent_solution_missing_vars(_, _, _),
+	any_mode).
+det_msg_is_any_mode_msg(promise_equivalent_solution_extra_vars(_, _, _),
+	any_mode).
 
 :- pred det_report_msg(det_msg::in, module_info::in, io::di, io::uo) is det.
 
@@ -1407,7 +1425,7 @@
 			Context)
 	->
 		Pieces = [words("Error: "),
-			  fixed(":- pragam export' declaration"),
+			  fixed(":- pragma export' declaration"),
 			  words("for a procedure that has"),
 			  words("a determinism of"),
 			  fixed(hlds_out.determinism_to_string(Detism)
@@ -1418,7 +1436,47 @@
 		unexpected(this_file, "Cannot find proc in table of "
 			++ "pragma exported procs")
 	).
+det_report_msg(promise_equivalent_solution_missing_vars(Context, VarSet, Vars),
+		_, !IO) :-
+	VarNames = list.map(lookup_var_name_in_varset(VarSet),
+		set.to_sorted_list(Vars)),
+	(
+		VarNames = [],
+		error("det_report_msg: " ++
+			"promise_equivalent_solution_missing_vars empty")
+	;
+		VarNames = [_],
+		ListStr = "a variable that is not listed:"
+	;
+		VarNames = [_, _ | _],
+		ListStr = "some variables that are not listed:"
+	),
+	Pieces = [words("Error: the promise_equivalent_solution goal binds "),
+		  words(ListStr)] ++ list_to_pieces(VarNames) ++ [suffix(".")],
+	error_util.write_error_pieces(Context, 0, Pieces, !IO).
+det_report_msg(promise_equivalent_solution_extra_vars(Context, VarSet, Vars),
+		_, !IO) :-
+	VarNames = list.map(lookup_var_name_in_varset(VarSet),
+		set.to_sorted_list(Vars)),
+	(
+		VarNames = [],
+		error("det_report_msg: " ++
+			"promise_equivalent_solution_extra_vars empty")
+	;
+		VarNames = [_],
+		ListStr = "an extra variable:"
+	;
+		VarNames = [_, _ | _],
+		ListStr = "some extra variables:"
+	),
+	Pieces = [words("Error: the promise_equivalent_solution goal lists "),
+		  words(ListStr)] ++ list_to_pieces(VarNames) ++ [suffix(".")],
+	error_util.write_error_pieces(Context, 0, Pieces, !IO).
 
+:- func lookup_var_name_in_varset(prog_varset, prog_var) = string.
+
+lookup_var_name_in_varset(VarSet, Var) =
+	mercury_var_to_string(Var, VarSet, no).
 
 :- pred get_exported_proc_context(list(pragma_exported_proc)::in,
 	pred_id::in, proc_id::in, prog_context::out) is semidet.
Index: compiler/dnf.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/dnf.m,v
retrieving revision 1.56
diff -u -r1.56 dnf.m
--- compiler/dnf.m	21 Jan 2005 06:20:37 -0000	1.56
+++ compiler/dnf.m	15 Feb 2005 14:31:05 -0000
@@ -204,11 +204,11 @@
 		GoalExpr0 = par_conj(_Goals0),
 		error("sorry, dnf of parallel conjunction not implemented")
 	;
-		GoalExpr0 = some(Vars, CanRemove, SomeGoal0),
+		GoalExpr0 = scope(Reason, SomeGoal0),
 		dnf__make_goal_literal(SomeGoal0, InstMap0, MaybeNonAtomic,
 			!ModuleInfo, no, yes, counter__init(0), _, DnfInfo,
 			SomeGoal, !NewPredIds),
-		Goal = some(Vars, CanRemove, SomeGoal) - GoalInfo
+		Goal = scope(Reason, SomeGoal) - GoalInfo
 	;
 		GoalExpr0 = not(NegGoal0),
 		dnf__make_goal_literal(NegGoal0, InstMap0, MaybeNonAtomic,
@@ -453,11 +453,13 @@
 		IsAtomic = no
 	).
 dnf__is_atomic_expr(MaybeNonAtomic, InNeg, InSome,
-		some(_, _, GoalExpr - _), IsAtomic) :-
-	( InSome = no ->
+		scope(_, GoalExpr - _), IsAtomic) :-
+	(
+		InSome = no,
 		dnf__is_atomic_expr(MaybeNonAtomic, InNeg, yes,
 			GoalExpr, IsAtomic)
 	;
+		InSome = yes,
 		IsAtomic = no
 	).
 dnf__is_atomic_expr(_, _, _, if_then_else(_, _, _, _), no).
@@ -465,15 +467,13 @@
 dnf__is_atomic_expr(MaybeNonAtomic, InNeg, InSome, shorthand(ShorthandGoal),
 		IsAtomic) :-
 	dnf__is_atomic_expr_shorthand(MaybeNonAtomic, InNeg, InSome,
-			ShorthandGoal, IsAtomic).
-
+		ShorthandGoal, IsAtomic).
 
 :- pred dnf__is_atomic_expr_shorthand(maybe(set(pred_proc_id))::in, bool::in,
-		bool::in, shorthand_goal_expr::in, bool::out) is det.
+	bool::in, shorthand_goal_expr::in, bool::out) is det.
 
 dnf__is_atomic_expr_shorthand(_, _, _, bi_implication(_,_), no).
 
-
 :- pred dnf__free_of_nonatomic(hlds_goal::in,
 	set(pred_proc_id)::in) is semidet.
 
@@ -500,7 +500,7 @@
 	dnf__goals_free_of_nonatomic(Goals, NonAtomic).
 dnf__free_of_nonatomic(not(Goal) - _, NonAtomic) :-
 	dnf__free_of_nonatomic(Goal, NonAtomic).
-dnf__free_of_nonatomic(some(_, _, Goal) - _, NonAtomic) :-
+dnf__free_of_nonatomic(scope(_, Goal) - _, NonAtomic) :-
 	dnf__free_of_nonatomic(Goal, NonAtomic).
 dnf__free_of_nonatomic(if_then_else(_, Cond, Then, Else) - GoalInfo,
 		NonAtomic) :-
@@ -511,8 +511,7 @@
 	dnf__free_of_nonatomic(Cond, NonAtomic),
 	dnf__free_of_nonatomic(Then, NonAtomic),
 	dnf__free_of_nonatomic(Else, NonAtomic).
-dnf__free_of_nonatomic(foreign_proc(_, _, _, _, _, _) - _,
-		_NonAtomic).
+dnf__free_of_nonatomic(foreign_proc(_, _, _, _, _, _) - _, _NonAtomic).
 
 :- pred dnf__goals_free_of_nonatomic(list(hlds_goal)::in,
 	set(pred_proc_id)::in) is semidet.
Index: compiler/equiv_type_hlds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/equiv_type_hlds.m,v
retrieving revision 1.10
diff -u -r1.10 equiv_type_hlds.m
--- compiler/equiv_type_hlds.m	21 Jan 2005 06:20:37 -0000	1.10
+++ compiler/equiv_type_hlds.m	15 Feb 2005 15:12:17 -0000
@@ -695,10 +695,10 @@
 	( Changed = yes, Goal = not(NegGoal)
 	; Changed = no, Goal = Goal0
 	).
-replace_in_goal_expr(EqvMap, Goal0 @ some(A, B, SomeGoal0), Goal,
+replace_in_goal_expr(EqvMap, Goal0 @ scope(Reason, SomeGoal0), Goal,
 		Changed, !Info) :-
 	replace_in_goal(EqvMap, SomeGoal0, SomeGoal, Changed, !Info),
-	( Changed = yes, Goal = some(A, B, SomeGoal)
+	( Changed = yes, Goal = scope(Reason, SomeGoal)
 	; Changed = no, Goal = Goal0
 	).
 replace_in_goal_expr(EqvMap, Goal0 @ if_then_else(Vars, Cond0, Then0, Else0),
@@ -760,7 +760,7 @@
 		hlds_data__get_type_defn_body(TypeDefn, Body),
 		Body = eqv_type(_),
 		type_to_ctor_and_args(VarType, _TypeInfoCtor,
-				[TypeInfoArgType])
+			[TypeInfoArgType])
 	->
 		Changed = yes,
 		pred_info_set_typevarset(!.Info ^ tvarset,
Index: compiler/exception_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/exception_analysis.m,v
retrieving revision 1.6
diff -u -r1.6 exception_analysis.m
--- compiler/exception_analysis.m	9 Feb 2005 04:51:41 -0000	1.6
+++ compiler/exception_analysis.m	15 Feb 2005 15:12:26 -0000
@@ -325,8 +325,7 @@
 	!:Result = !.Result ^ status := may_throw(user_exception).
 check_goal_for_exceptions_2(SCC, Module, VarTypes, not(Goal), !Result) :-
 	check_goal_for_exceptions(SCC, Module, VarTypes, Goal, !Result).
-check_goal_for_exceptions_2(SCC, Module, VarTypes, some(_, _, Goal),
-		!Result) :-
+check_goal_for_exceptions_2(SCC, Module, VarTypes, scope(_, Goal), !Result) :-
 	check_goal_for_exceptions(SCC, Module, VarTypes, Goal, !Result).
 check_goal_for_exceptions_2(_, _, _,
 		foreign_proc(Attributes, _, _, _, _, _), !Result) :-
Index: compiler/follow_code.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/follow_code.m,v
retrieving revision 1.71
diff -u -r1.71 follow_code.m
--- compiler/follow_code.m	30 Jun 2004 02:47:59 -0000	1.71
+++ compiler/follow_code.m	15 Feb 2005 16:26:02 -0000
@@ -111,8 +111,8 @@
 	move_follow_code_in_goal(Cond0, Cond, Flags, !R),
 	move_follow_code_in_goal(Then0, Then, Flags, !R),
 	move_follow_code_in_goal(Else0, Else, Flags, !R).
-move_follow_code_in_goal_2(some(Vars, CanRemove, Goal0),
-		some(Vars, CanRemove, Goal), Flags, !R) :-
+move_follow_code_in_goal_2(scope(Remove, Goal0),
+		scope(Remove, Goal), Flags, !R) :-
 	move_follow_code_in_goal(Goal0, Goal, Flags, !R).
 move_follow_code_in_goal_2(Goal @ generic_call(_, _, _, _), Goal, _, !R).
 move_follow_code_in_goal_2(Goal @ call(_, _, _, _, _, _), Goal, _, !R).
Index: compiler/follow_vars.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/follow_vars.m,v
retrieving revision 1.69
diff -u -r1.69 follow_vars.m
--- compiler/follow_vars.m	7 Jun 2004 09:06:38 -0000	1.69
+++ compiler/follow_vars.m	15 Feb 2005 16:27:01 -0000
@@ -189,9 +189,9 @@
 
 	goal_info_set_store_map(GoalInfo0, FollowVarsMap0, GoalInfo).
 
-find_follow_vars_in_goal_expr(some(Vars, CanRemove, Goal0),
-		some(Vars, CanRemove, Goal), GoalInfo, GoalInfo,
-		VarTypes, ModuleInfo, !FollowVarsMap, !NextNonReserved) :-
+find_follow_vars_in_goal_expr(scope(Reason, Goal0), scope(Reason, Goal),
+		GoalInfo, GoalInfo, VarTypes, ModuleInfo,
+		!FollowVarsMap, !NextNonReserved) :-
 	find_follow_vars_in_goal(Goal0, Goal, VarTypes, ModuleInfo,
 		!FollowVarsMap, !NextNonReserved).
 
Index: compiler/goal_form.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/goal_form.m,v
retrieving revision 1.11
diff -u -r1.11 goal_form.m
--- compiler/goal_form.m	16 Oct 2004 15:05:51 -0000	1.11
+++ compiler/goal_form.m	15 Feb 2005 15:22:17 -0000
@@ -172,7 +172,7 @@
 		).
 goal_cannot_loop_expr(MaybeModuleInfo, not(Goal)) :-
 	goal_cannot_loop_aux(MaybeModuleInfo, Goal).
-goal_cannot_loop_expr(MaybeModuleInfo, some(_Vars, _, Goal)) :-
+goal_cannot_loop_expr(MaybeModuleInfo, scope(_, Goal)) :-
 	goal_cannot_loop_aux(MaybeModuleInfo, Goal).
 goal_cannot_loop_expr(MaybeModuleInfo,
 		if_then_else(_Vars, Cond, Then, Else)) :-
@@ -222,7 +222,7 @@
 		goal_cannot_throw_aux(MaybeModuleInfo, Goal).
 goal_cannot_throw_expr(MaybeModuleInfo, not(Goal)) :-
 	goal_cannot_throw_aux(MaybeModuleInfo, Goal).
-goal_cannot_throw_expr(MaybeModuleInfo, some(_Vars, _, Goal)) :-
+goal_cannot_throw_expr(MaybeModuleInfo, scope(_, Goal)) :-
 	goal_cannot_throw_aux(MaybeModuleInfo, Goal).
 goal_cannot_throw_expr(MaybeModuleInfo, if_then_else(_, Cond, Then, Else)) :-
 	goal_cannot_throw_aux(MaybeModuleInfo, Cond),
@@ -258,7 +258,7 @@
 	contains_only_builtins_cases(Cases).
 contains_only_builtins_expr(not(Goal)) :-
 	contains_only_builtins(Goal).
-contains_only_builtins_expr(some(_Vars, _, Goal)) :-
+contains_only_builtins_expr(scope(_, Goal)) :-
 	contains_only_builtins(Goal).
 contains_only_builtins_expr(if_then_else(_Vars, Cond, Then, Else)) :-
 	contains_only_builtins(Cond),
@@ -301,7 +301,7 @@
 	goal_is_flat_list(Goals).
 goal_is_flat_expr(not(Goal)) :-
 	goal_is_flat(Goal).
-goal_is_flat_expr(some(_Vars, _, Goal)) :-
+goal_is_flat_expr(scope(_, Goal)) :-
 	goal_is_flat(Goal).
 goal_is_flat_expr(generic_call(_, _, _, _)).
 goal_is_flat_expr(call(_, _, _, _, _, _)).
@@ -349,7 +349,7 @@
 	% XXX although you could make it an attribute of the foreign code and
 	% trust the programmer
 goal_may_allocate_heap_2(foreign_proc(_, _, _, _, _, _), yes).
-goal_may_allocate_heap_2(some(_Vars, _, Goal), May) :-
+goal_may_allocate_heap_2(scope(_, Goal), May) :-
 	goal_may_allocate_heap(Goal, May).
 goal_may_allocate_heap_2(not(Goal), May) :-
 	goal_may_allocate_heap(Goal, May).
@@ -503,7 +503,7 @@
 
 count_recursive_calls_2(not(Goal), PredId, ProcId, Min, Max) :-
 	count_recursive_calls(Goal, PredId, ProcId, Min, Max).
-count_recursive_calls_2(some(_, _, Goal), PredId, ProcId, Min, Max) :-
+count_recursive_calls_2(scope(_, Goal), PredId, ProcId, Min, Max) :-
 	count_recursive_calls(Goal, PredId, ProcId, Min, Max).
 count_recursive_calls_2(unify(_, _, _, _, _), _, _, 0, 0).
 count_recursive_calls_2(generic_call(_, _, _, _), _, _, 0, 0).
Index: compiler/goal_path.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/goal_path.m,v
retrieving revision 1.21
diff -u -r1.21 goal_path.m
--- compiler/goal_path.m	20 Dec 2004 01:15:37 -0000	1.21
+++ compiler/goal_path.m	16 Mar 2005 11:31:07 -0000
@@ -101,7 +101,7 @@
 mode_equiv_step(Step) :-
 	( Step = disj(_)
 	; Step = neg
-	; Step = exist(_)
+	; Step = scope(_)
 	; Step = ite_else
 	).
 
@@ -131,8 +131,8 @@
 	fill_switch_slots(Cases0, Path0, 0, NumCases, SlotInfo, Cases).
 fill_expr_slots(not(Goal0), _, Path0, SlotInfo, not(Goal)) :-
 	fill_goal_slots(Goal0, [neg | Path0], SlotInfo, Goal).
-fill_expr_slots(some(A, B, Goal0), OuterInfo, Path0, SlotInfo,
-		some(A, B, Goal)) :-
+fill_expr_slots(scope(Reason, Goal0), OuterInfo, Path0, SlotInfo,
+		scope(Reason, Goal)) :-
 	Goal0 = _ - InnerInfo,
 	goal_info_get_determinism(OuterInfo, OuterDetism),
 	goal_info_get_determinism(InnerInfo, InnerDetism),
@@ -141,7 +141,7 @@
 	;
 		MaybeCut = cut
 	),
-	fill_goal_slots(Goal0, [exist(MaybeCut) | Path0], SlotInfo, Goal).
+	fill_goal_slots(Goal0, [scope(MaybeCut) | Path0], SlotInfo, Goal).
 fill_expr_slots(if_then_else(A, Cond0, Then0, Else0), _, Path0, SlotInfo,
 		if_then_else(A, Cond, Then, Else)) :-
 	fill_goal_slots(Cond0, [ite_cond | Path0], SlotInfo, Cond),
Index: compiler/goal_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/goal_util.m,v
retrieving revision 1.103
diff -u -r1.103 goal_util.m
--- compiler/goal_util.m	15 Feb 2005 05:22:16 -0000	1.103
+++ compiler/goal_util.m	16 Mar 2005 09:58:13 -0000
@@ -450,9 +450,30 @@
 goal_util__rename_vars_in_goal_expr(not(Goal0), Must, Subn, not(Goal)) :-
 	goal_util__rename_vars_in_goal(Goal0, Must, Subn, Goal).
 
-goal_util__rename_vars_in_goal_expr(some(Vars0, CanRemove, Goal0), Must, Subn,
-		some(Vars, CanRemove, Goal)) :-
-	goal_util__rename_var_list(Vars0, Must, Subn, Vars),
+goal_util__rename_vars_in_goal_expr(scope(Reason0, Goal0), Must, Subn,
+		scope(Reason, Goal)) :-
+	(
+		Reason0 = exist_quant(Vars0),
+		goal_util__rename_var_list(Vars0, Must, Subn, Vars),
+		Reason = exist_quant(Vars)
+	;
+		Reason0 = promise_purity(_),
+		Reason = Reason0
+	;
+		Reason0 = promise_equivalent_solution(Vars0),
+		goal_util__rename_var_list(Vars0, Must, Subn, Vars),
+		Reason = promise_equivalent_solution(Vars)
+	;
+		Reason0 = barrier(_),
+		Reason = Reason0
+	;
+		Reason0 = commit(_),
+		Reason = Reason0
+	;
+		Reason0 = from_ground_term(Var0),
+		goal_util__rename_var(Var0, Must, Subn, Var),
+		Reason = from_ground_term(Var)
+	),
 	goal_util__rename_vars_in_goal(Goal0, Must, Subn, Goal).
 
 goal_util__rename_vars_in_goal_expr(
@@ -709,8 +730,23 @@
 	set__insert(!.Set, Var, !:Set),
 	goal_util__cases_goal_vars(Cases, !Set).
 
-goal_util__goal_vars_2(some(Vars, _, Goal - _), !Set) :-
-	set__insert_list(!.Set, Vars, !:Set),
+goal_util__goal_vars_2(scope(Reason, Goal - _), !Set) :-
+	(
+		Reason = exist_quant(Vars),
+		set__insert_list(!.Set, Vars, !:Set)
+	;
+		Reason = promise_purity(_)
+	;
+		Reason = promise_equivalent_solution(Vars),
+		set__insert_list(!.Set, Vars, !:Set)
+	;
+		Reason = barrier(_)
+	;
+		Reason = commit(_)
+	;
+		Reason = from_ground_term(Var),
+		set__insert(!.Set, Var, !:Set)
+	),
 	goal_util__goal_vars_2(Goal, !Set).
 
 goal_util__goal_vars_2(not(Goal - _GoalInfo), !Set) :-
@@ -818,9 +854,9 @@
 		attach_features_to_all_goals(Features, Goal0, Goal),
 		GoalExpr = not(Goal)
 	;
-		GoalExpr0 = some(Vars, CanRemove, Goal0),
+		GoalExpr0 = scope(Reason, Goal0),
 		attach_features_to_all_goals(Features, Goal0, Goal),
-		GoalExpr = some(Vars, CanRemove, Goal)
+		GoalExpr = scope(Reason, Goal)
 	;
 		GoalExpr0 = call(_, _, _, _, _, _),
 		GoalExpr = GoalExpr0
@@ -937,7 +973,7 @@
 goal_expr_size(not(Goal), Size) :-
 	goal_size(Goal, Size1),
 	Size = Size1 + 1.
-goal_expr_size(some(_, _, Goal), Size) :-
+goal_expr_size(scope(_, Goal), Size) :-
 	goal_size(Goal, Size1),
 	Size = Size1 + 1.
 goal_expr_size(call(_, _, _, _, _, _), 1).
@@ -1010,7 +1046,7 @@
 	).
 goal_expr_calls(not(Goal), PredProcId) :-
 	goal_calls(Goal, PredProcId).
-goal_expr_calls(some(_, _, Goal), PredProcId) :-
+goal_expr_calls(scope(_, Goal), PredProcId) :-
 	goal_calls(Goal, PredProcId).
 goal_expr_calls(call(PredId, ProcId, _, _, _, _), proc(PredId, ProcId)).
 
@@ -1070,7 +1106,7 @@
 	).
 goal_expr_calls_pred_id(not(Goal), PredId) :-
 	goal_calls_pred_id(Goal, PredId).
-goal_expr_calls_pred_id(some(_, _, Goal), PredId) :-
+goal_expr_calls_pred_id(scope(_, Goal), PredId) :-
 	goal_calls_pred_id(Goal, PredId).
 goal_expr_calls_pred_id(call(PredId, _, _, _, _, _), PredId).
 
@@ -1097,7 +1133,7 @@
 	goals_contain_reconstruction([Cond, Then, Else]).
 goal_expr_contains_reconstruction(not(Goal)) :-
 	goal_contains_reconstruction(Goal).
-goal_expr_contains_reconstruction(some(_, _, Goal)) :-
+goal_expr_contains_reconstruction(scope(_, Goal)) :-
 	goal_contains_reconstruction(Goal).
 goal_expr_contains_reconstruction(unify(_, _, _, Unify, _)) :-
 	Unify = construct(_, _, _, _, HowToConstruct, _, _),
@@ -1123,7 +1159,7 @@
 	% direct_subgoal(Goal, SubGoal) is true iff SubGoal is
 	% a direct sub-goal of Goal.
 	%
-direct_subgoal(some(_, _, Goal), Goal).
+direct_subgoal(scope(_, Goal), Goal).
 direct_subgoal(not(Goal), Goal).
 direct_subgoal(if_then_else(_, If, Then, Else), Goal) :-
 	( Goal = If
@@ -1223,7 +1259,7 @@
 		CondMaxSoln = at_most_one,
 		determinism_components(CondDetism, CondCanFail0, CondMaxSoln),
 		goal_info_set_determinism(CondInfo0, CondDetism, CondInfo),
-		Cond = some([], can_remove, Cond0) - CondInfo
+		Cond = scope(commit(dont_force_pruning), Cond0) - CondInfo
 	;
 		CondDetism = CondDetism0,
 		CondInfo = CondInfo0,
@@ -1234,7 +1270,8 @@
 	( MaybeNegCondDet = yes(NegCondDet1) ->
 		NegCondDet = NegCondDet1
 	;
-		error("goal_util__if_then_else_to_disjunction: inappropriate determinism in a negation.")
+		error("goal_util__if_then_else_to_disjunction: " ++
+			"inappropriate determinism in a negation.")
 	),
 	determinism_components(NegCondDet, _, NegCondMaxSoln),
 	( NegCondMaxSoln = at_most_zero ->
Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.222
diff -u -r1.222 handle_options.m
--- compiler/handle_options.m	6 Mar 2005 05:17:27 -0000	1.222
+++ compiler/handle_options.m	16 Mar 2005 14:04:45 -0000
@@ -697,6 +697,10 @@
 	option_implies(very_verbose, verbose, bool(yes)),
 	option_implies(verbose, verbose_commands, bool(yes)),
 
+	option_implies(debug_modes_minimal, debug_modes, bool(yes)),
+	option_implies(debug_modes_verbose, debug_modes, bool(yes)),
+	option_implies(debug_modes_statistics, debug_modes, bool(yes)),
+
 	globals__io_lookup_int_option(debug_liveness, DebugLiveness),
 	(
 		{ DebugLiveness >= 0 },
Index: compiler/hhf.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hhf.m,v
retrieving revision 1.4
diff -u -r1.4 hhf.m
--- compiler/hhf.m	21 Jan 2005 03:27:37 -0000	1.4
+++ compiler/hhf.m	15 Feb 2005 15:27:04 -0000
@@ -205,7 +205,7 @@
 		!HI).
 hhf__goal_expr(_, _, shorthand(_), _, !HI) :-
 	error("hhf_goal_expr: found shorthand").
-hhf__goal_expr(NonLocals, _, some(A, B, Goal0), some(A, B, Goal), !HI) :-
+hhf__goal_expr(NonLocals, _, scope(Reason, Goal0), scope(Reason, Goal), !HI) :-
 	hhf__goal(NonLocals, Goal0, Goal, !HI).
 hhf__goal_expr(_, _, disj(Goals0), disj(Goals), !HI) :-
 	list__map_foldl(hhf__goal_use_own_nonlocals, Goals0, Goals, !HI).
Index: compiler/higher_order.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/higher_order.m,v
retrieving revision 1.124
diff -u -r1.124 higher_order.m
--- compiler/higher_order.m	1 Feb 2005 07:11:28 -0000	1.124
+++ compiler/higher_order.m	15 Feb 2005 15:12:42 -0000
@@ -535,8 +535,8 @@
 traverse_goal_2(not(NegGoal0) - GoalInfo, not(NegGoal) - GoalInfo, !Info) :-
 	traverse_goal_2(NegGoal0, NegGoal, !Info).
 
-traverse_goal_2(some(Vars, CanRemove, Goal0) - GoalInfo,
-		some(Vars, CanRemove, Goal) - GoalInfo, !Info) :-
+traverse_goal_2(scope(Reason, Goal0) - GoalInfo,
+		scope(Reason, Goal) - GoalInfo, !Info) :-
 	traverse_goal_2(Goal0, Goal, !Info).
 
 traverse_goal_2(Goal, Goal, !Info) :-
Index: compiler/hlds_goal.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_goal.m,v
retrieving revision 1.126
diff -u -r1.126 hlds_goal.m
--- compiler/hlds_goal.m	6 Mar 2005 05:17:28 -0000	1.126
+++ compiler/hlds_goal.m	16 Mar 2005 11:31:37 -0000
@@ -128,19 +128,14 @@
 		% A negation
 	;	not(hlds_goal)
 
-		% An explicit quantification.
-		% Quantification information is stored in the `non_locals'
-		% field of the goal_info, so these get ignored
-		% (except to recompute the goal_info quantification).
-		% `all Vs' gets converted to `not some Vs not'.
-		% The second argument is `can_remove' if the quantification
-		% is allowed to be removed; see the docs for the can_remove
-		% type.
-	;	{ some(
-			some_exist_vars	:: list(prog_var),
-			some_can_remove	:: can_remove,
+		% A scope which may be the scope of a quantification,
+		% or may be introduced by a compiler transformation.
+		% See the documentation of scope_reason for what the
+		% compiler may do with the scope.
+	;	scope(
+			scope_reason	:: scope_reason,
 			some_goal	:: hlds_goal
-		) }
+		)
 
 		% An if-then-else,
 		% `if some <Vars> <Condition> then <Then> else <Else>'.
@@ -201,6 +196,88 @@
 		% then the quantification would be wrong
 	--->	bi_implication(hlds_goal, hlds_goal).
 
+:- type scope_reason
+		% The goal inside the scope construct has the listed variables
+		% existentially quantified. The compiler may do whatever
+		% preserves this fact.
+	--->	exist_quant(list(prog_var))
+
+		% Even though the code inside the scope may have multiple
+		% solutions, the creater of the scope (which may be the user
+		% or a compiler pass) promises that all these solutions are
+		% equivalent relative to the relevant equality theory.
+		% (This need not be an equality theory known to the compiler.)
+		% The scope goal will therefore act as a single solution
+		% context, and the determinism of the scope() goal itself
+		% will indicate that it cannot succeed more than once.
+		%
+		% This acts like the builtin.promise_only_solution predicate,
+		% but without requiring the construction of a closure, a
+		% higher order call, and the squeezing of all outputs into
+		% a single variable.
+		%
+		% The promise is valid only if the list of outputs of the goal
+		% inside the scope is a subset of the variables listed here.
+		% If it is not valid, the compiler must emit an error message.
+	;	promise_equivalent_solution(list(prog_var))
+
+		% The goal inside the scope implements an interface of the
+		% specified purity, even if its implementation uses less pure
+		% components.
+		%
+		% Works the same way as a promise_pure or promise_semipure
+		% pragma, except that it applies to arbitrary goals and not
+		% just whole procedure bodies.
+	;	promise_purity(purity)
+
+		% This scope exists to delimit a piece of code
+		% with at_most_many components but with no outputs,
+		% whose overall determinism is thus at_most_one,
+		% or a piece of code that cannot succeed but some of whose
+		% components are at_most_many (regardless of the number of
+		% outputs).
+		%
+		% If the argument is force_pruning, then the outer goal will
+		% succeed at most once even if the inner goal is impure.
+	;	commit(force_pruning)
+
+		% The scope exists to prevent other compiler passes from
+		% arbitrarily moving computations in or out of the scope.
+		% This kind of scope can only be introduced by program
+		% transformations.
+		%
+		% The argument says whether other compiler passes are allowed
+		% to delete the scope.
+		%
+		% A non-removable explicit quantification may be introduced
+		% to keep related goals together where optimizations that
+		% separate the goals can only result in worse behaviour.
+		% An example is the closures for the builtin Aditi update
+		% predicates - they should be kept close to the update call
+		% where possible to make it easier to use indexes for the
+		% update.
+		%
+		% A barrier says nothing about the determinism of either
+		% the inner or the outer goal, or about pruning.
+	;	barrier(removable)
+
+		% The goal inside the scope, which should be a conjunction,
+		% results from the conversion of one ground term to
+		% superhomogeneous form. The variable specifies what the
+		% compiler calls that ground term.
+		%
+		% This kind of scope is not intended to be meaningful after
+		% mode analysis, and should be removed after mode analysis.
+	;	from_ground_term(prog_var).
+
+:- type removable
+	--->	removable
+	;	not_removable.
+
+:- type force_pruning
+	--->	force_pruning
+	;	dont_force_pruning.
+
 %-----------------------------------------------------------------------------%
 %
 % Information for calls
@@ -623,28 +700,6 @@
 
 %-----------------------------------------------------------------------------%
 %
-% Information for quantifications
-%
-
-	% The second argument of explicit quantification goals
-	% is `can_remove' if the quantification is allowed to
-	% be removed.  A non-removable explicit
-	% quantification may be introduced to keep related goals
-	% together where optimizations that separate the goals
-	% can only result in worse behaviour. An example is the
-	% closures for the builtin aditi update predicates -
-	% they should be kept close to the update call where
-	% possible to make it easier to use indexes for the update.
-	%
-	% See also the closely related `keep_this_commit' goal_feature.
-	% XXX Why do we have both cannot_remove and keep_this_commit?
-	%     Do we really need both?
-:- type can_remove
-	--->	can_remove
-	;	cannot_remove.
-
-%-----------------------------------------------------------------------------%
-%
 % Information for all kinds of goals
 %
 
@@ -801,16 +856,6 @@
 				% the value of this variable in its stack slot
 				% as soon as it is generated; this marker
 				% tells the code generator when this happens.
-	;	keep_this_commit
-				% This feature should be attached only to goals
-				% that represent commits (i.e. some() goals in
-				% which the inner and outer determinisms
-				% differ). It tells determinism analysis that
-				% some other part of the compiler wants the
-				% commit to stay, even if the usual rules of
-				% determinism analysis say that the
-				% nondeterminism inside the some() should be
-				% exposed to the environment outside.
 	;	preserve_backtrack_into
 				% Determinism analysis should preserve
 				% backtracking into goals marked with this
@@ -859,7 +904,7 @@
 				% unification after it, unifying the variables
 				% representing !.S and !:S. If code B doesn't
 				% refer to S, then quantification will restrict
-				% the scope of the variable representing !:S 
+				% the scope of the variable representing !:S
 				% to each disjunct, and the unification
 				% inserted after code A will refer to a
 				% singleton variable.
@@ -897,7 +942,7 @@
 			;	ite_then
 			;	ite_else
 			;	neg
-			;	exist(maybe_cut)
+			;	scope(maybe_cut)
 			;	first
 			;	later.
 
@@ -1649,8 +1694,8 @@
 goal_path_step_to_string(ite_then, "t;").
 goal_path_step_to_string(ite_else, "e;").
 goal_path_step_to_string(neg, "~;").
-goal_path_step_to_string(exist(cut), "q!;").
-goal_path_step_to_string(exist(no_cut), "q;").
+goal_path_step_to_string(scope(cut), "q!;").
+goal_path_step_to_string(scope(no_cut), "q;").
 goal_path_step_to_string(first, "f;").
 goal_path_step_to_string(later, "l;").
 
@@ -1804,7 +1849,7 @@
 		GoalExpr = not(Goal2),
 		HasForeign = goal_has_foreign(Goal2)
 	;
-		GoalExpr = some(_, _, Goal2),
+		GoalExpr = scope(_, Goal2),
 		HasForeign = goal_has_foreign(Goal2)
 	;
 		GoalExpr = if_then_else(_, Cond, Then, Else),
@@ -1938,8 +1983,7 @@
 				is det :-
 			set_goal_contexts(Context, Goal0, Goal)
 		), Cases0, Cases).
-set_goal_contexts_2(Context, some(Vars, CanRemove, Goal0),
-		some(Vars, CanRemove, Goal)) :-
+set_goal_contexts_2(Context, scope(Reason, Goal0), scope(Reason, Goal)) :-
 	set_goal_contexts(Context, Goal0, Goal).
 set_goal_contexts_2(Context, not(Goal0), not(Goal)) :-
 	set_goal_contexts(Context, Goal0, Goal).
Index: compiler/hlds_out.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_out.m,v
retrieving revision 1.349
diff -u -r1.349 hlds_out.m
--- compiler/hlds_out.m	15 Feb 2005 00:04:54 -0000	1.349
+++ compiler/hlds_out.m	16 Mar 2005 06:36:24 -0000
@@ -1590,18 +1590,59 @@
 	io__write_string(")", !IO),
 	io__write_string(Follow, !IO).
 
-hlds_out__write_goal_2(some(Vars, CanRemove, Goal), ModuleInfo, VarSet,
+hlds_out__write_goal_2(scope(Reason, Goal), ModuleInfo, VarSet,
 		AppendVarNums, Indent, Follow, TypeQual, !IO) :-
 	hlds_out__write_indent(Indent, !IO),
-	io__write_string("some [", !IO),
-	mercury_output_vars(Vars, VarSet, AppendVarNums, !IO),
-	io__write_string("] (", !IO),
-	( CanRemove = cannot_remove ->
-		io__write_string(" % (cannot remove)", !IO)
+	(
+		Reason = exist_quant(Vars),
+		io__write_string("some [", !IO),
+		mercury_output_vars(Vars, VarSet, AppendVarNums, !IO),
+		io__write_string("] (\n", !IO)
 	;
-		true
+		Reason = promise_purity(Purity),
+		(
+			Purity = pure,
+			io__write_string("promise_pure (\n", !IO)
+		;
+			Purity = (semipure),
+			io__write_string("promise_semipure (\n", !IO)
+		;
+			Purity = (impure),
+			io__write_string("promise_impure (\n", !IO)
+		)
+	;
+		Reason = promise_equivalent_solution(Vars),
+		io__write_string("promise_equivalent_solution [", !IO),
+		mercury_output_vars(Vars, VarSet, AppendVarNums, !IO),
+		io__write_string("] (\n", !IO)
+	;
+		Reason = barrier(removable),
+		io__write_string("(\n", !IO),
+		hlds_out__write_indent(Indent, !IO),
+		io__write_string("% barrier(removable)\n", !IO)
+	;
+		Reason = barrier(not_removable),
+		io__write_string("(\n", !IO),
+		hlds_out__write_indent(Indent, !IO),
+		io__write_string("% barrier(not_removable)\n", !IO)
+	;
+		Reason = commit(force_pruning),
+		io__write_string("(\n", !IO),
+		hlds_out__write_indent(Indent, !IO),
+		io__write_string("% commit(force_pruning)\n", !IO)
+	;
+		Reason = commit(dont_force_pruning),
+		io__write_string("(\n", !IO),
+		hlds_out__write_indent(Indent, !IO),
+		io__write_string("% commit(dont_force_pruning)\n", !IO)
+	;
+		Reason = from_ground_term(Var),
+		io__write_string("(\n", !IO),
+		hlds_out__write_indent(Indent, !IO),
+		io__write_string("% from_ground_term [", !IO),
+		mercury_output_var(Var, VarSet, AppendVarNums, !IO),
+		io__write_string("]\n", !IO)
 	),
-	io__nl(!IO),
 	hlds_out__write_goal_a(Goal, ModuleInfo, VarSet, AppendVarNums,
 		Indent + 1, "\n", TypeQual, !IO),
 	hlds_out__write_indent(Indent, !IO),
Index: compiler/inlining.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/inlining.m,v
retrieving revision 1.120
diff -u -r1.120 inlining.m
--- compiler/inlining.m	15 Feb 2005 05:22:17 -0000	1.120
+++ compiler/inlining.m	15 Feb 2005 15:12:59 -0000
@@ -356,7 +356,7 @@
 	inlining__is_flat_simple_goal_list(Goals).
 inlining__is_flat_simple_goal(not(Goal) - _) :-
 	inlining__is_flat_simple_goal(Goal).
-inlining__is_flat_simple_goal(some(_, _, Goal) - _) :-
+inlining__is_flat_simple_goal(scope(_, Goal) - _) :-
 	inlining__is_flat_simple_goal(Goal).
 inlining__is_flat_simple_goal(call(_, _, _, BuiltinState, _, _) - _) :-
 	BuiltinState = inline_builtin.
@@ -556,9 +556,9 @@
 		Goal = not(SubGoal),
 		GoalInfo = GoalInfo0
 	;
-		Goal0 = some(Vars, CanRemove, SubGoal0),
+		Goal0 = scope(Reason, SubGoal0),
 		inlining__inlining_in_goal(SubGoal0, SubGoal, !Info),
-		Goal = some(Vars, CanRemove, SubGoal),
+		Goal = scope(Reason, SubGoal),
 		GoalInfo = GoalInfo0
 	;
 		Goal0 = generic_call(_, _, _, _),
Index: compiler/instmap.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/instmap.m,v
retrieving revision 1.37
diff -u -r1.37 instmap.m
--- compiler/instmap.m	10 Jan 2005 05:23:39 -0000	1.37
+++ compiler/instmap.m	16 Mar 2005 07:08:42 -0000
@@ -293,6 +293,9 @@
 	pred(prog_var, inst, inst, T, T)::in(pred(in, in, out, in, out) is det),
 	instmap_delta::in, instmap_delta::out, T::in, T::out) is det.
 
+:- pred var_is_ground_in_instmap(module_info::in, instmap::in, prog_var::in)
+	is semidet.
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -1105,7 +1108,6 @@
 	instmap_delta_apply_sub_2(AL, Must, Sub, IM1, IM).
 
 %-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
 
 instmap__to_assoc_list(unreachable, []).
 instmap__to_assoc_list(reachable(InstMapping), AL) :-
@@ -1116,4 +1118,9 @@
 	map__to_assoc_list(InstMapping, AL).
 
 %-----------------------------------------------------------------------------%
+
+var_is_ground_in_instmap(ModuleInfo, InstMap, Var) :-
+	instmap__lookup_var(InstMap, Var, Inst),
+	inst_is_ground(ModuleInfo, Inst).
+
 %-----------------------------------------------------------------------------%
Index: compiler/intermod.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/intermod.m,v
retrieving revision 1.167
diff -u -r1.167 intermod.m
--- compiler/intermod.m	1 Feb 2005 07:11:30 -0000	1.167
+++ compiler/intermod.m	15 Feb 2005 15:13:12 -0000
@@ -509,8 +509,8 @@
 	intermod__module_qualify_unify_rhs(LVar, RHS0, RHS, DoWrite, !Info).
 intermod__traverse_goal(not(Goal0) - Info, not(Goal) - Info, DoWrite, !Info) :-
 	intermod__traverse_goal(Goal0, Goal, DoWrite, !Info).
-intermod__traverse_goal(some(Vars, CanRemove, Goal0) - Info,
-		some(Vars, CanRemove, Goal) - Info, DoWrite, !Info) :-
+intermod__traverse_goal(scope(Reason, Goal0) - Info,
+		scope(Reason, Goal) - Info, DoWrite, !Info) :-
 	intermod__traverse_goal(Goal0, Goal, DoWrite, !Info).
 intermod__traverse_goal(if_then_else(Vars, Cond0, Then0, Else0) - Info,
 		if_then_else(Vars, Cond, Then, Else) - Info, DoWrite, !Info) :-
Index: compiler/interval.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/interval.m,v
retrieving revision 1.1
diff -u -r1.1 interval.m
--- compiler/interval.m	6 Mar 2005 05:17:29 -0000	1.1
+++ compiler/interval.m	16 Mar 2005 06:00:52 -0000
@@ -262,8 +262,8 @@
 	leave_branch_start(ite, StartAnchor, BeforeId, MaybeResumeVars,
 		CondOpenIntervals, !IntervalInfo).
 
-build_interval_info_in_goal(some(_Vars, _CanRemove, Goal) - _GoalInfo,
-                !IntervalInfo, !Acc) :-
+build_interval_info_in_goal(scope(_Reason, Goal) - _GoalInfo, !IntervalInfo,
+		!Acc) :-
 	build_interval_info_in_goal(Goal, !IntervalInfo, !Acc).
 
 build_interval_info_in_goal(Goal - GoalInfo, !IntervalInfo, !Acc) :-
@@ -924,12 +924,33 @@
 	insert_goals_after(Goal1, Goal, !VarInfo, !:VarRename, EndInserts,
                 MaybeFeature).
 
-record_decisions_in_goal(some(Vars0, CanRemove, Goal0) - GoalInfo,
-		some(Vars, CanRemove, Goal) - GoalInfo, !VarInfo, !VarRename,
-		InsertMap, MaybeFeature) :-
-	rename_var_list(Vars0, no, !.VarRename, Vars),
-	record_decisions_in_goal(Goal0, Goal, !VarInfo, !VarRename,
-		InsertMap, MaybeFeature).
+record_decisions_in_goal(Goal0, Goal, !VarInfo, !VarRename, InsertMap,
+		MaybeFeature) :-
+	Goal0 = scope(Reason0, SubGoal0) - GoalInfo,
+	(
+		Reason0 = exist_quant(Vars0),
+		rename_var_list(Vars0, no, !.VarRename, Vars),
+		Reason = exist_quant(Vars)
+	;
+		Reason0 = promise_purity(_),
+		Reason = Reason0
+	;
+		Reason0 = promise_equivalent_solution(_),
+		Reason = Reason0
+	;
+		Reason0 = commit(_),
+		Reason = Reason0
+	;
+		Reason0 = barrier(_),
+		Reason = Reason0
+	;
+		Reason0 = from_ground_term(Var0),
+		rename_var(Var0, no, !.VarRename, Var),
+		Reason = from_ground_term(Var)
+	),
+	record_decisions_in_goal(SubGoal0, SubGoal, !VarInfo, !VarRename,
+		InsertMap, MaybeFeature),
+	Goal = scope(Reason, SubGoal) - GoalInfo.
 
 record_decisions_in_goal(Goal0, Goal, !VarInfo, !VarRename, InsertMap,
                 MaybeFeature) :-
Index: compiler/lambda.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/lambda.m,v
retrieving revision 1.95
diff -u -r1.95 lambda.m
--- compiler/lambda.m	21 Jan 2005 06:20:40 -0000	1.95
+++ compiler/lambda.m	15 Feb 2005 15:13:25 -0000
@@ -272,8 +272,8 @@
 lambda__process_goal_2(switch(Var, CanFail, Cases0), GoalInfo,
 		switch(Var, CanFail, Cases) - GoalInfo, !Info) :-
 	lambda__process_cases(Cases0, Cases, !Info).
-lambda__process_goal_2(some(Vars, CanRemove, Goal0), GoalInfo,
-		some(Vars, CanRemove, Goal) - GoalInfo, !Info) :-
+lambda__process_goal_2(scope(Reason, Goal0), GoalInfo,
+		scope(Reason, Goal) - GoalInfo, !Info) :-
 	lambda__process_goal(Goal0, Goal, !Info).
 lambda__process_goal_2(if_then_else(Vars, Cond0, Then0, Else0), GoalInfo,
 		if_then_else(Vars, Cond, Then, Else) - GoalInfo, !Info) :-
Index: compiler/lco.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/lco.m,v
retrieving revision 1.22
diff -u -r1.22 lco.m
--- compiler/lco.m	14 Jun 2004 04:16:11 -0000	1.22
+++ compiler/lco.m	15 Feb 2005 15:13:37 -0000
@@ -76,8 +76,7 @@
 		if_then_else(Vars, Cond, Then, Else)) :-
 	lco_in_goal(Then0, ModuleInfo, Then),
 	lco_in_goal(Else0, ModuleInfo, Else).
-lco_in_goal_2(some(Vars, CanRemove, Goal0), ModuleInfo,
-		some(Vars, CanRemove, Goal)) :-
+lco_in_goal_2(scope(Reason, Goal0), ModuleInfo, scope(Reason, Goal)) :-
 	lco_in_goal(Goal0, ModuleInfo, Goal).
 lco_in_goal_2(not(Goal), _ModuleInfo, not(Goal)).
 lco_in_goal_2(Goal @ generic_call(_, _, _, _), _ModuleInfo, Goal).
Index: compiler/live_vars.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/live_vars.m,v
retrieving revision 1.106
diff -u -r1.106 live_vars.m
--- compiler/live_vars.m	14 Jun 2004 04:16:11 -0000	1.106
+++ compiler/live_vars.m	15 Feb 2005 16:27:24 -0000
@@ -265,7 +265,7 @@
 	build_live_sets_in_goal(Goal0, Goal, ResumeVars0, AllocData,
 		!StackAlloc, !Liveness, !NondetLiveness).
 
-build_live_sets_in_goal_2(some(Vars, CR, Goal0), some(Vars, CR, Goal),
+build_live_sets_in_goal_2(scope(Reason, Goal0), scope(Reason, Goal),
 		GoalInfo, GoalInfo, ResumeVars0, AllocData,
 		!StackAlloc, !Liveness, !NondetLiveness) :-
 	NondetLiveness0 = !.NondetLiveness,
Index: compiler/liveness.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/liveness.m,v
retrieving revision 1.132
diff -u -r1.132 liveness.m
--- compiler/liveness.m	21 Feb 2005 05:34:37 -0000	1.132
+++ compiler/liveness.m	22 Feb 2005 01:04:04 -0000
@@ -398,8 +398,8 @@
 	add_liveness_after_goal(Then1, ResidueThen, Then),
 	add_liveness_after_goal(Else1, ResidueElse, Else).
 
-detect_liveness_in_goal_2(some(Vars, CanRemove, Goal0),
-		some(Vars, CanRemove, Goal), !Liveness, _, LiveInfo) :-
+detect_liveness_in_goal_2(scope(Reason, Goal0), scope(Reason, Goal),
+		!Liveness, _, LiveInfo) :-
 	detect_liveness_in_goal(Goal0, Goal, !Liveness, LiveInfo).
 
 detect_liveness_in_goal_2(generic_call(_, _, _, _), _, _, _, _, _) :-
@@ -635,8 +635,7 @@
 			CompletedNonLocalDeadness, yes, Else1, Else)
 	).
 
-detect_deadness_in_goal_2(some(Vars, CanRemove, Goal0),
-		some(Vars, CanRemove, Goal), _,
+detect_deadness_in_goal_2(scope(Reason, Goal0), scope(Reason, Goal), _,
 		!Deadness, Liveness0, LiveInfo) :-
 	detect_deadness_in_goal(Goal0, Goal, !Deadness, Liveness0, LiveInfo).
 
@@ -894,7 +893,7 @@
 	).
 update_liveness_expr(not(Goal), _, LiveInfo, !Liveness) :-
 	update_liveness_goal(Goal, LiveInfo, !Liveness).
-update_liveness_expr(some(_, _, Goal), _, LiveInfo, !Liveness) :-
+update_liveness_expr(scope(_, Goal), _, LiveInfo, !Liveness) :-
 	update_liveness_goal(Goal, LiveInfo, !Liveness).
 update_liveness_expr(shorthand(_), _, _, _, _) :-
 	error("update_liveness_expr: shorthand").
@@ -1080,10 +1079,10 @@
 			Else1 - DelayedDeadElse),
 		!:GoalExpr = if_then_else(QuantVars, Cond, Then, Else)
 	;
-		!.GoalExpr = some(QuantVars, CanRemove, Goal0),
+		!.GoalExpr = scope(Reason, Goal0),
 		delay_death_goal(Goal0, Goal, !.BornVars, _, !DelayedDead,
 			VarSet),
-		!:GoalExpr = some(QuantVars, CanRemove, Goal)
+		!:GoalExpr = scope(Reason, Goal)
 	;
 		!.GoalExpr = shorthand(_),
 		error("delay_death_goal_expr: shorthand")
@@ -1294,9 +1293,8 @@
 
 	require_equal(LivenessThen, LivenessElse, "if-then-else", LiveInfo).
 
-detect_resume_points_in_goal_2(some(Vars, CanRemove, Goal0),
-		some(Vars, CanRemove, Goal), !Liveness, _,
-		LiveInfo, ResumeVars0) :-
+detect_resume_points_in_goal_2(scope(Reason, Goal0), scope(Reason, Goal),
+		!Liveness, _, LiveInfo, ResumeVars0) :-
 	detect_resume_points_in_goal(Goal0, Goal, !Liveness,
 		LiveInfo, ResumeVars0).
 
Index: compiler/loop_inv.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/loop_inv.m,v
retrieving revision 1.17
diff -u -r1.17 loop_inv.m
--- compiler/loop_inv.m	14 Feb 2005 04:49:10 -0000	1.17
+++ compiler/loop_inv.m	15 Feb 2005 15:15:07 -0000
@@ -371,12 +371,12 @@
     invariant_goal_candidates_keeping_path_candidates(PPId, NegatedGoal, IGCs).
 
 invariant_goal_candidates_2(PPId,
-        some(_, _, QuantifiedGoal)                   - _GoalInfo, IGCs) =
+        scope(_, QuantifiedGoal)                     - _GoalInfo, IGCs) =
     invariant_goal_candidates_2(PPId, QuantifiedGoal, IGCs).
 
 invariant_goal_candidates_2(PPId,
-        if_then_else(_XVs, Cond, Then, Else)         - GoalInfo,  IGCs0) = IGCs
- :-
+        if_then_else(_XVs, Cond, Then, Else)         - GoalInfo,  IGCs0)
+        = IGCs :-
     CondThenGoal = conj([Cond, Then]) - GoalInfo,
     IGCs1        = invariant_goal_candidates_keeping_path_candidates(PPId,
                         CondThenGoal, IGCs0),
@@ -897,8 +897,8 @@
 gen_aux_proc_2(Info, not(NegatedGoal) - GoalInfo) =
     not(gen_aux_proc_2(Info, NegatedGoal)) - GoalInfo.
 
-gen_aux_proc_2(Info, some(XVars, CanRemove, QuantifiedGoal) - GoalInfo) =
-    some(XVars, CanRemove, gen_aux_proc_2(Info, QuantifiedGoal)) - GoalInfo.
+gen_aux_proc_2(Info, scope(Reason, QuantifiedGoal) - GoalInfo) =
+    scope(Reason, gen_aux_proc_2(Info, QuantifiedGoal)) - GoalInfo.
 
 gen_aux_proc_2(Info, if_then_else(XVars, Cond, Then, Else) - GoalInfo) =
     if_then_else(XVars,
@@ -1026,9 +1026,8 @@
     not(gen_out_proc_2(PPId, CallAux, NegatedGoal)) - GoalInfo.
 
 gen_out_proc_2(PPId, CallAux,
-        some(XVars, CanRemove, QuantifiedGoal)         - GoalInfo) =
-    some(XVars, CanRemove, gen_out_proc_2(PPId, CallAux, QuantifiedGoal)) -
-            GoalInfo.
+        scope(Reason, QuantifiedGoal)         - GoalInfo) =
+    scope(Reason, gen_out_proc_2(PPId, CallAux, QuantifiedGoal)) - GoalInfo.
 
 gen_out_proc_2(PPId, CallAux,
         if_then_else(XVars, Cond, Then, Else)          - GoalInfo) =
@@ -1137,7 +1136,7 @@
 uniquely_used_vars_2(MI, not(NegatedGoal) - _) =
     uniquely_used_vars_2(MI, NegatedGoal).
 
-uniquely_used_vars_2(MI, some(_, _, QuantifiedGoal) - _) =
+uniquely_used_vars_2(MI, scope(_, QuantifiedGoal) - _) =
     uniquely_used_vars_2(MI, QuantifiedGoal).
 
 uniquely_used_vars_2(MI, if_then_else(_, Cond, Then, Else) - _) =
@@ -1227,7 +1226,7 @@
 goal_inputs(_MI, not(_) - _) = _ :-
     unexpected(this_file, "goal_inputs/2: not/1 in hlds_goal").
 
-goal_inputs(_MI, some(_, _, _) - _) = _ :-
+goal_inputs(_MI, scope(_, _) - _) = _ :-
     unexpected(this_file, "goal_inputs/2: some/3 in hlds_goal").
 
 goal_inputs(_MI, if_then_else(_, _, _, _) - _) = _ :-
@@ -1310,7 +1309,7 @@
 goal_outputs(_MI, not(_) - _) = _ :-
     unexpected(this_file, "goal_outputs/2: not/1 in hlds_goal").
 
-goal_outputs(_MI, some(_, _, _) - _) = _ :-
+goal_outputs(_MI, scope(_, _) - _) = _ :-
     unexpected(this_file, "goal_outputs/2: some/3 in hlds_goal").
 
 goal_outputs(_MI, if_then_else(_, _, _, _) - _) = _ :-
Index: compiler/magic.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/magic.m,v
retrieving revision 1.50
diff -u -r1.50 magic.m
--- compiler/magic.m	21 Jan 2005 06:20:41 -0000	1.50
+++ compiler/magic.m	15 Feb 2005 14:32:03 -0000
@@ -1429,8 +1429,8 @@
 	;
 		{ Goals = [Goal0] }
 	).
-magic__preprocess_goal_2(some(Vars, CanRemove, Goal0) - Info,
-		[some(Vars, CanRemove, Goal) - Info], HOMap0, HOMap) -->
+magic__preprocess_goal_2(scope(Reason, Goal0) - Info,
+		[scope(Reason, Goal) - Info], HOMap0, HOMap) -->
 	{ Goal0 = _ - SomeGoalInfo },
 	magic__preprocess_goal(Goal0, SomeGoals, HOMap0, HOMap),
 	{ conj_list_to_goal(SomeGoals, SomeGoalInfo, Goal) }.
@@ -1564,7 +1564,7 @@
 		{
 			Goal = not(_) - _
 		;
-			Goal = some(_, _, _) - _
+			Goal = scope(_, _) - _
 		;
 			Goal = conj(_) - _
 		;
Index: compiler/magic_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/magic_util.m,v
retrieving revision 1.45
diff -u -r1.45 magic_util.m
--- compiler/magic_util.m	21 Jan 2005 06:20:41 -0000	1.45
+++ compiler/magic_util.m	15 Feb 2005 14:32:10 -0000
@@ -201,7 +201,7 @@
 	% and multiple nested quantifications are not considered
 	% atomic by dnf.m.
 	%
-	( Goal0 = some(_, _, Goal1) - _ ->
+	( Goal0 = scope(_, Goal1) - _ ->
 		Goal2 = Goal1
 	;
 		Goal2 = Goal0
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.503
diff -u -r1.503 make_hlds.m
--- compiler/make_hlds.m	20 Mar 2005 02:24:34 -0000	1.503
+++ compiler/make_hlds.m	20 Mar 2005 02:26:34 -0000
@@ -5732,22 +5732,27 @@
 
 warn_singletons_in_goal_2(Goal, GoalInfo, QuantVars, VarSet, PredCallId,
         MI, !IO) :-
-    Goal = some(Vars, _, SubGoal),
+    Goal = scope(Reason, SubGoal),
     %
     % warn if any quantified variables occur only in the quantifier
     %
     (
-        Vars = [_ | _],
+        ( Reason = exist_quant(Vars)
+        ; Reason = promise_equivalent_solution(Vars)
+        ),
+        Vars = [_ | _]
+    ->
         quantification__goal_vars(SubGoal, SubGoalVars),
         goal_info_get_context(GoalInfo, Context),
         set__init(EmptySet),
         warn_singletons(Vars, GoalInfo, EmptySet, SubGoalVars, VarSet,
-            Context, PredCallId, !IO)
+            Context, PredCallId, !IO),
+        set__insert_list(QuantVars, Vars, SubQuantVars)
     ;
-        Vars = []
+        SubQuantVars = QuantVars
     ),
-    set__insert_list(QuantVars, Vars, QuantVars1),
-    warn_singletons_in_goal(SubGoal, QuantVars1, VarSet, PredCallId, MI, !IO).
+    warn_singletons_in_goal(SubGoal, SubQuantVars, VarSet, PredCallId, MI,
+        !IO).
 
 warn_singletons_in_goal_2(Goal, GoalInfo, QuantVars, VarSet, PredCallId,
         MI, !IO) :-
@@ -6256,9 +6261,9 @@
     update_qual_info(TVarNameMap, TVarSet0, ExplicitVarTypes0, Status,
         !QualInfo),
     varset__merge_subst(VarSet0, CVarSet, VarSet1, Subst),
-    transform(Subst, HeadVars, Args, Body, Context, PredOrFunc, Arity,
-        GoalType, Goal0, VarSet1, VarSet, Warnings, !ModuleInfo, !QualInfo,
-        !IO),
+    add_clause_transform(Subst, HeadVars, Args, Body, Context, PredOrFunc,
+        Arity, GoalType, Goal0, VarSet1, VarSet, Warnings, !ModuleInfo,
+        !QualInfo, !IO),
     TVarSet = !.QualInfo ^ tvarset,
     qual_info_get_found_syntax_error(!.QualInfo, FoundError),
     qual_info_set_found_syntax_error(no, !QualInfo),
@@ -6522,15 +6527,15 @@
 
 %-----------------------------------------------------------------------------
 
-:- pred transform(prog_substitution::in, list(prog_var)::in,
+:- pred add_clause_transform(prog_substitution::in, list(prog_var)::in,
     list(prog_term)::in, goal::in, prog_context::in, pred_or_func::in,
     arity::in, goal_type::in, hlds_goal::out,
     prog_varset::in, prog_varset::out, list(quant_warning)::out,
     module_info::in, module_info::out, qual_info::in, qual_info::out,
     io::di, io::uo) is det.
 
-transform(Subst, HeadVars, Args0, Body0, Context, PredOrFunc, Arity, GoalType,
-        Goal, !VarSet, Warnings, !ModuleInfo, !QualInfo, !IO) :-
+add_clause_transform(Subst, HeadVars, Args0, Body0, Context, PredOrFunc, Arity,
+        GoalType, Goal, !VarSet, Warnings, !ModuleInfo, !QualInfo, !IO) :-
     some [!SInfo] (
         prepare_for_head(!:SInfo),
         term__apply_substitution_to_list(Args0, Subst, Args1),
@@ -6607,7 +6612,7 @@
         Context, Subst, Goal, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO).
 
 transform_goal_2(some(Vars0, Goal0), _, Subst,
-        some(Vars, can_remove, Goal) - GoalInfo,
+        scope(exist_quant(Vars), Goal) - GoalInfo,
         !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO) :-
     substitute_vars(Vars0, Subst, Vars),
     transform_goal(Goal0, Subst, Goal, !VarSet, !ModuleInfo, !QualInfo,
@@ -6615,7 +6620,7 @@
     goal_info_init(GoalInfo).
 
 transform_goal_2(some_state_vars(StateVars0, Goal0), _, Subst,
-        some(Vars, can_remove, Goal) - GoalInfo,
+        scope(exist_quant(Vars), Goal) - GoalInfo,
         !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO) :-
     BeforeSInfo = !.SInfo,
     substitute_vars(StateVars0, Subst, StateVars),
@@ -6625,6 +6630,21 @@
     finish_local_state_vars(StateVars, Vars, BeforeSInfo, !SInfo),
     goal_info_init(GoalInfo).
 
+transform_goal_2(promise_purity(Purity, Goal0), _, Subst,
+        scope(promise_purity(Purity), Goal) - GoalInfo,
+        !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO) :-
+    transform_goal(Goal0, Subst, Goal, !VarSet, !ModuleInfo, !QualInfo,
+        !SInfo, !IO),
+    goal_info_init(GoalInfo).
+
+transform_goal_2(promise_equivalent_solution(Vars0, Goal0), _, Subst,
+        scope(promise_equivalent_solution(Vars), Goal) - GoalInfo,
+        !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO) :-
+    substitute_vars(Vars0, Subst, Vars),
+    transform_goal(Goal0, Subst, Goal, !VarSet, !ModuleInfo, !QualInfo,
+        !SInfo, !IO),
+    goal_info_init(GoalInfo).
+
 transform_goal_2(if_then_else(Vars0, StateVars0, Cond0, Then0, Else0), Context,
         Subst, if_then_else(Vars, Cond, Then, Else) - GoalInfo,
         !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO) :-
@@ -6807,8 +6827,8 @@
         prepare_for_call(!SInfo),
         term__apply_substitution(A0, Subst, A),
         term__apply_substitution(B0, Subst, B),
-        unravel_unification(A, B, Context, explicit, [],
-            Purity, Goal, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO),
+        unravel_unification(A, B, Context, explicit, [], Purity, Goal,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO),
         finish_call(!VarSet, !SInfo)
     ).
 
@@ -7308,9 +7328,9 @@
 
             record_called_pred_or_func(PredOrFunc, SymName, InsertArity,
                 !QualInfo),
-            insert_arg_unifications(AllArgs, AllArgTerms,
-                Context, call(CallId), Goal0, Goal,
-                !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO)
+            insert_arg_unifications(AllArgs, AllArgTerms, Context,
+                call(CallId), Goal0, Goal, !VarSet, !ModuleInfo, !QualInfo,
+                !SInfo, !IO)
         ;
             invalid_goal(UpdateStr, Args0, GoalInfo,
                 Goal, !VarSet, !SInfo, !IO),
@@ -7472,7 +7492,7 @@
         % Separating the goals would make optimization of the update
         % using indexes more difficult.
         %
-        UpdateConj = some([], cannot_remove,
+        UpdateConj = scope(barrier(not_removable),
             conj([LambdaConstruct, Call]) - GoalInfo) - GoalInfo,
 
         CallId = call(generic_call(
@@ -7706,16 +7726,17 @@
     module_info::in, module_info::out, qual_info::in, qual_info::out,
     svar_info::in, svar_info::out, io::di, io::uo) is det.
 
-insert_arg_unifications(HeadVars, Args0, Context, ArgContext, !Goal, !VarSet,
-        !ModuleInfo, !QualInfo, !SInfo, !IO) :-
-    ( HeadVars = [] ->
-        true
+insert_arg_unifications(HeadVars, Args0, Context, ArgContext,
+        !Goal, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO) :-
+    (
+        HeadVars = []
     ;
+        HeadVars = [_ | _],
         !.Goal = _ - GoalInfo0,
         goal_to_conj_list(!.Goal, Goals0),
         substitute_state_var_mappings(Args0, Args, !VarSet, !SInfo, !IO),
-        insert_arg_unifications_2(HeadVars, Args, Context, ArgContext, 0,
-            Goals0, Goals, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO),
+        insert_arg_unifications_2(HeadVars, Args, Context, ArgContext,
+            0, Goals0, Goals, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO),
         goal_info_set_context(GoalInfo0, Context, GoalInfo),
         conj_list_to_goal(Goals, GoalInfo, !:Goal)
     ).
@@ -7736,19 +7757,20 @@
 insert_arg_unifications_2([], [], _, _, _, !Goals, !VarSet, !ModuleInfo,
         !QualInfo, !SInfo, !IO).
 insert_arg_unifications_2([Var | Vars], [Arg | Args], Context, ArgContext,
-        N0, !Goals, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO) :-
+        N0, !Goals, !VarSet, !ModuleInfo, !QualInfo, !SInfo,
+        !IO) :-
     N1 = N0 + 1,
     insert_arg_unification(Var, Arg, Context, ArgContext, N1,
         !VarSet, ArgUnifyConj, !ModuleInfo, !QualInfo, !SInfo, !IO),
     (
         ArgUnifyConj = [],
         % Allow the recursive call to be tail recursive.
-        insert_arg_unifications_2(Vars, Args, Context, ArgContext, N1,
-            !Goals, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO)
+        insert_arg_unifications_2(Vars, Args, Context, ArgContext,
+            N1, !Goals, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO)
     ;
         ArgUnifyConj = [_ | _],
-        insert_arg_unifications_2(Vars, Args, Context, ArgContext, N1,
-            !Goals, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO),
+        insert_arg_unifications_2(Vars, Args, Context, ArgContext,
+            N1, !Goals, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO),
         list__append(ArgUnifyConj, !.Goals, !:Goals)
     ).
 
@@ -7759,7 +7781,8 @@
     svar_info::in, svar_info::out, io::di, io::uo) is det.
 
 insert_arg_unifications_with_supplied_contexts(ArgVars, ArgTerms0, ArgContexts,
-        Context, !Goal, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO) :-
+        Context, !Goal, !VarSet, !ModuleInfo, !QualInfo, !SInfo,
+        !IO) :-
     (
         ArgVars = []
     ;
@@ -7769,15 +7792,15 @@
         substitute_state_var_mappings(ArgTerms0, ArgTerms, !VarSet, !SInfo,
             !IO),
         insert_arg_unifications_with_supplied_contexts_2(ArgVars, ArgTerms,
-            ArgContexts, Context, GoalList0, GoalList, !VarSet, !ModuleInfo,
-            !QualInfo, !SInfo, !IO),
+            ArgContexts, Context, GoalList0, GoalList, !VarSet,
+            !ModuleInfo, !QualInfo, !SInfo, !IO),
         goal_info_set_context(GoalInfo0, Context, GoalInfo),
         conj_list_to_goal(GoalList, GoalInfo, !:Goal)
     ).
 
 :- pred insert_arg_unifications_with_supplied_contexts_2(list(prog_var)::in,
-    list(prog_term)::in, assoc_list(int, arg_context)::in,
-    prog_context::in, list(hlds_goal)::in, list(hlds_goal)::out,
+    list(prog_term)::in, assoc_list(int, arg_context)::in, prog_context::in,
+    list(hlds_goal)::in, list(hlds_goal)::out,
     prog_varset::in, prog_varset::out,
     module_info::in, module_info::out, qual_info::in, qual_info::out,
     svar_info::in, svar_info::out, io::di, io::uo) is det.
@@ -7785,7 +7808,9 @@
 insert_arg_unifications_with_supplied_contexts_2(Vars, Terms, ArgContexts,
         Context, !Goals, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO) :-
     (
-        ( Vars = [], Terms = [], ArgContexts = [] )
+        Vars = [],
+        Terms = [],
+        ArgContexts = []
     ->
         true
     ;
@@ -7805,9 +7830,9 @@
 
 :- pred insert_arg_unification(prog_var::in, prog_term::in, prog_context::in,
     arg_context::in, int::in, prog_varset::in, prog_varset::out,
-    list(hlds_goal)::out,
-    module_info::in, module_info::out, qual_info::in, qual_info::out,
-    svar_info::in, svar_info::out, io::di, io::uo) is det.
+    list(hlds_goal)::out, module_info::in, module_info::out,
+    qual_info::in, qual_info::out, svar_info::in, svar_info::out,
+    io::di, io::uo) is det.
 
 insert_arg_unification(Var, Arg, Context, ArgContext, N1, !VarSet,
         ArgUnifyConj, !ModuleInfo, !QualInfo, !SInfo, !IO) :-
@@ -7818,8 +7843,8 @@
         arg_context_to_unify_context(ArgContext, N1, UnifyMainContext,
             UnifySubContext),
         unravel_unification(term__variable(Var), Arg, Context,
-            UnifyMainContext, UnifySubContext, pure, Goal, !VarSet,
-            !ModuleInfo, !QualInfo, !SInfo, !IO),
+            UnifyMainContext, UnifySubContext, pure, Goal,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO),
         goal_to_conj_list(Goal, ArgUnifyConj)
     ).
 
@@ -7833,11 +7858,12 @@
     module_info::in, module_info::out, qual_info::in, qual_info::out,
     svar_info::in, svar_info::out, io::di, io::uo) is det.
 
-append_arg_unifications(HeadVars, Args0, Context, ArgContext, !Goal, !VarSet,
-        !ModuleInfo, !QualInfo, !SInfo, !IO) :-
-    ( HeadVars = [] ->
-        true
+append_arg_unifications(HeadVars, Args0, Context, ArgContext,
+        !Goal, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO) :-
+    (
+        HeadVars = []
     ;
+        HeadVars = [_ | _],
         !.Goal = _ - GoalInfo,
         goal_to_conj_list(!.Goal, List0),
         substitute_state_var_mappings(Args0, Args, !VarSet,
@@ -7862,8 +7888,8 @@
     error("append_arg_unifications_2: length mismatch").
 append_arg_unifications_2([], [], _, _, _, !List, !VarSet, !ModuleInfo,
         !QualInfo, !SInfo, !IO).
-append_arg_unifications_2([Var|Vars], [Arg|Args], Context, ArgContext, N0,
-        !List, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO) :-
+append_arg_unifications_2([Var|Vars], [Arg|Args], Context, ArgContext,
+        N0, !List, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO) :-
     N1 = N0 + 1,
     append_arg_unification(Var, Arg, Context, ArgContext, N1, ConjList,
         !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO),
@@ -7886,8 +7912,8 @@
         arg_context_to_unify_context(ArgContext, N1, UnifyMainContext,
             UnifySubContext),
         unravel_unification(term__variable(Var), Arg, Context,
-            UnifyMainContext, UnifySubContext, pure, Goal, !VarSet,
-            !ModuleInfo, !QualInfo, !SInfo, !IO),
+            UnifyMainContext, UnifySubContext, pure, Goal,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO),
         goal_to_conj_list(Goal, ConjList)
     ).
 
@@ -7971,7 +7997,7 @@
     substitute_state_var_mapping(LHS0, LHS, !VarSet, !SInfo, !IO),
     substitute_state_var_mapping(RHS0, RHS, !VarSet, !SInfo, !IO),
     unravel_unification_2(LHS, RHS, Context, MainContext, SubContext,
-        Purity, Goal, !VarSet, !ModuleInfo, !QualInfo, !SInfo,!IO).
+        Purity, Goal, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO).
 
 :- pred unravel_unification_2(prog_term::in, prog_term::in, prog_context::in,
     unify_main_context::in, unify_sub_contexts::in, purity::in,
@@ -7982,8 +8008,8 @@
     % `X = Y' needs no unravelling.
 
 unravel_unification_2(term__variable(X), term__variable(Y), Context,
-        MainContext, SubContext, Purity, Goal, !VarSet, !ModuleInfo,
-        !QualInfo, !SInfo, !IO) :-
+        MainContext, SubContext, Purity, Goal, !VarSet,
+        !ModuleInfo, !QualInfo, !SInfo, !IO) :-
     make_atomic_unification(X, var(Y), Context, MainContext, SubContext, Goal,
         !QualInfo),
     check_expr_purity(Purity, Context, !ModuleInfo, !IO).
@@ -8175,8 +8201,8 @@
 
         ArgContext = functor(Functor, MainContext, SubContext),
         insert_arg_unifications([InputTermVar], [InputTerm],
-            FunctorContext, ArgContext, Goal0,
-            Goal, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO)
+            FunctorContext, ArgContext, Goal0, Goal,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO)
     ;
         % handle field update expressions
         F = term__atom(":="),
@@ -8198,16 +8224,16 @@
 
         TermArgContext = functor(Functor, MainContext, SubContext),
         TermArgNumber = 1,
-        FieldArgContext = functor(InnerFunctor,
-            MainContext, FieldSubContext),
+        FieldArgContext = functor(InnerFunctor, MainContext, FieldSubContext),
         FieldArgNumber = 2,
         ArgContexts = [TermArgNumber - TermArgContext,
             FieldArgNumber - FieldArgContext],
         insert_arg_unifications_with_supplied_contexts(
             [InputTermVar, FieldValueVar],
-            [InputTerm, FieldValueTerm], ArgContexts,
-            Context, Goal0, Goal, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO)
+            [InputTerm, FieldValueTerm], ArgContexts, Context,
+            Goal0, Goal, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO)
     ;
+        % handle the usual case
         parse_qualified_term(RHS, RHS, "", MaybeFunctor),
         (
             MaybeFunctor = ok(FunctorName, FunctorArgs),
@@ -8221,13 +8247,19 @@
             ConsId = make_functor_cons_id(F, Arity),
             FunctorArgs = Args
         ),
-        ( FunctorArgs = [] ->
+        (
+            FunctorArgs = [],
             make_atomic_unification(X, functor(ConsId, no, []), Context,
                 MainContext, SubContext, Goal0, !QualInfo),
             Goal0 = GoalExpr - GoalInfo0,
             add_goal_info_purity_feature(GoalInfo0, Purity, GoalInfo),
+            % We could attach the from_ground_term feature to Goal,
+            % but there would be no gain from doing so, whereas the
+            % increase would lead to a slight increase in memory and time
+            % requirements.
             Goal = GoalExpr - GoalInfo
         ;
+            FunctorArgs = [_ | _],
             make_fresh_arg_vars(FunctorArgs, HeadVars, !VarSet, !SInfo, !IO),
             make_atomic_unification(X, functor(ConsId, no, HeadVars), Context,
                 MainContext, SubContext, Goal0, !QualInfo),
@@ -8240,26 +8272,53 @@
             % around the functor unification.
             ( Purity = pure ->
                 append_arg_unifications(HeadVars, FunctorArgs, FunctorContext,
-                    ArgContext, Goal0, Goal, !VarSet, !ModuleInfo, !QualInfo,
-                    !SInfo, !IO)
+                    ArgContext, Goal0, Goal2, !VarSet,
+                    !ModuleInfo, !QualInfo, !SInfo, !IO)
             ;
-                Goal0 = GoalExpr - GoalInfo0,
-                add_goal_info_purity_feature(GoalInfo0, Purity, GoalInfo),
-                Goal1 = GoalExpr - GoalInfo,
+                Goal0 = GoalExpr0 - GoalInfo0,
+                add_goal_info_purity_feature(GoalInfo0, Purity, GoalInfo1),
+                Goal1 = GoalExpr0 - GoalInfo1,
                 insert_arg_unifications(HeadVars, FunctorArgs, FunctorContext,
-                    ArgContext, Goal1, Goal, !VarSet, !ModuleInfo, !QualInfo,
-                    !SInfo, !IO)
+                    ArgContext, Goal1, Goal2, !VarSet,
+                    !ModuleInfo, !QualInfo, !SInfo, !IO)
+            ),
+            % This "optimization" is disabled, because the extra cost of
+            % traversing the scope goals in typechecking is more than the
+            % savings from the reduction in delays/wakeups in modechecking.
+            (
+                semidet_fail,
+                ground_terms(FunctorArgs)
+            ->
+                % This insertion of the `scope' goal is undone by the code
+                % handling `scope' goals in modecheck_goal_expr in modes.m.
+
+                Goal2 = _GoalExpr2 - GoalInfo,
+                GoalExpr = scope(from_ground_term(X), Goal2),
+                Goal = GoalExpr - GoalInfo
+            ;
+                Goal = Goal2
             )
         )
     ).
 
+:- pred ground_term(term(T)::in) is semidet.
+
+ground_term(term__functor(_, Terms, _)) :-
+    ground_terms(Terms).
+
+:- pred ground_terms(list(term(T))::in) is semidet.
+
+ground_terms([]).
+ground_terms([Term | Terms]) :-
+    ground_term(Term),
+    ground_terms(Terms).
+
     % Handle `f(...) = X' in the same way as `X = f(...)'.
 
-unravel_unification_2(term__functor(F, As, FC), term__variable(Y),
-        C, MC, SC, Purity, Goal, !VarSet, !ModuleInfo, !QualInfo, !SInfo,
-        !IO) :-
-    unravel_unification(term__variable(Y), term__functor(F, As, FC),
-        C, MC, SC, Purity, Goal, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO).
+unravel_unification_2(term__functor(F, As, FC), term__variable(Y), C, MC, SC,
+        Purity, Goal, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO) :-
+    unravel_unification(term__variable(Y), term__functor(F, As, FC), C, MC, SC,
+        Purity, Goal, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !IO).
 
     % If we find a unification of the form `f1(...) = f2(...)',
     % then we replace it with `Tmp = f1(...), Tmp = f2(...)',
@@ -8439,7 +8498,7 @@
         list__sort_and_remove_dups(QuantifiedVars0, QuantifiedVars),
 
         goal_info_init(Context, GoalInfo),
-        HLDS_Goal = some(QuantifiedVars, can_remove, HLDS_Goal0) - GoalInfo,
+        HLDS_Goal = scope(exist_quant(QuantifiedVars), HLDS_Goal0) - GoalInfo,
 
         %
         % We set the lambda nonlocals here to anything that
Index: compiler/mark_static_terms.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mark_static_terms.m,v
retrieving revision 1.13
diff -u -r1.13 mark_static_terms.m
--- compiler/mark_static_terms.m	14 Jun 2004 04:16:16 -0000	1.13
+++ compiler/mark_static_terms.m	15 Feb 2005 16:31:14 -0000
@@ -52,40 +52,38 @@
 	proc_info_set_goal(Goal, !Proc).
 
 :- pred goal_mark_static_terms(hlds_goal::in, hlds_goal::out,
-		static_info::in, static_info::out) is det.
+	static_info::in, static_info::out) is det.
 
-goal_mark_static_terms(GoalExpr0 - GoalInfo, GoalExpr - GoalInfo) -->
-	goal_expr_mark_static_terms(GoalExpr0, GoalExpr).
+goal_mark_static_terms(GoalExpr0 - GoalInfo, GoalExpr - GoalInfo, !SI) :-
+	goal_expr_mark_static_terms(GoalExpr0, GoalExpr, !SI).
 
 :- pred goal_expr_mark_static_terms(hlds_goal_expr::in, hlds_goal_expr::out,
-		static_info::in, static_info::out) is det.
+	static_info::in, static_info::out) is det.
 
-goal_expr_mark_static_terms(conj(Goals0), conj(Goals), SI0, SI) :-
-	conj_mark_static_terms(Goals0, Goals, SI0, SI).
+goal_expr_mark_static_terms(conj(Goals0), conj(Goals), !SI) :-
+	conj_mark_static_terms(Goals0, Goals, !SI).
 
-goal_expr_mark_static_terms(par_conj(Goals0), par_conj(Goals),
-		SI0, SI) :-
+goal_expr_mark_static_terms(par_conj(Goals0), par_conj(Goals), !SI) :-
 	% it's OK to treat parallel conjunctions as if they were
 	% sequential here, since if we mark any variables as
 	% static, the computation of those variables will be
 	% done at compile time.
-	conj_mark_static_terms(Goals0, Goals, SI0, SI).
+	conj_mark_static_terms(Goals0, Goals, !SI).
 
-goal_expr_mark_static_terms(disj(Goals0), disj(Goals), SI0, SI0) :-
+goal_expr_mark_static_terms(disj(Goals0), disj(Goals), !SI) :-
 	% we revert to the original static_info at the end of branched goals
-	disj_mark_static_terms(Goals0, Goals, SI0).
+	disj_mark_static_terms(Goals0, Goals, !.SI).
 
-goal_expr_mark_static_terms(switch(A, B, Cases0), switch(A, B, Cases),
-		SI0, SI0) :-
+goal_expr_mark_static_terms(switch(A, B, Cases0), switch(A, B, Cases), !SI) :-
 	% we revert to the original static_info at the end of branched goals
-	cases_mark_static_terms(Cases0, Cases, SI0).
+	cases_mark_static_terms(Cases0, Cases, !.SI).
 
-goal_expr_mark_static_terms(not(Goal0), not(Goal), SI0, SI0) :-
+goal_expr_mark_static_terms(not(Goal0), not(Goal), !SI) :-
 	% we revert to the original static_info at the end of the negation
-	goal_mark_static_terms(Goal0, Goal, SI0, _SI).
+	goal_mark_static_terms(Goal0, Goal, !.SI, _SI).
 
-goal_expr_mark_static_terms(some(A, B, Goal0), some(A, B, Goal), SI0, SI) :-
-	goal_mark_static_terms(Goal0, Goal, SI0, SI).
+goal_expr_mark_static_terms(scope(A, Goal0), scope(A, Goal), !SI) :-
+	goal_mark_static_terms(Goal0, Goal, !SI).
 
 goal_expr_mark_static_terms(if_then_else(A, Cond0, Then0, Else0),
 		if_then_else(A, Cond, Then, Else), SI0, SI0) :-
@@ -98,30 +96,28 @@
 	goal_mark_static_terms(Then0, Then, SI_Cond, _SI_Then),
 	goal_mark_static_terms(Else0, Else, SI0, _SI_Else).
 
-goal_expr_mark_static_terms(Goal @ call(_, _, _, _, _, _), Goal, SI, SI).
+goal_expr_mark_static_terms(Goal @ call(_, _, _, _, _, _), Goal, !SI).
 
-goal_expr_mark_static_terms(Goal @ generic_call(_, _, _, _), Goal, SI, SI).
+goal_expr_mark_static_terms(Goal @ generic_call(_, _, _, _), Goal, !SI).
 
 goal_expr_mark_static_terms(unify(LHS, RHS, Mode, Unification0, Context),
-		unify(LHS, RHS, Mode, Unification, Context), SI0, SI) :-
-	unification_mark_static_terms(Unification0, Unification,
-		SI0, SI).
+		unify(LHS, RHS, Mode, Unification, Context), !SI) :-
+	unification_mark_static_terms(Unification0, Unification, !SI).
 
-goal_expr_mark_static_terms(Goal @ foreign_proc(_, _, _, _, _, _), Goal,
-		SI, SI).
+goal_expr_mark_static_terms(Goal @ foreign_proc(_, _, _, _, _, _), Goal, !SI).
 
-goal_expr_mark_static_terms(shorthand(_), _, _, _) :-
+goal_expr_mark_static_terms(shorthand(_), _, !SI) :-
 	% these should have been expanded out by now
 	error("fill_expr_slots: unexpected shorthand").
 
 :- pred conj_mark_static_terms(hlds_goals::in, hlds_goals::out,
-		static_info::in, static_info::out) is det.
+	static_info::in, static_info::out) is det.
 
-conj_mark_static_terms(Goals0, Goals) -->
-	list__map_foldl(goal_mark_static_terms, Goals0, Goals).
+conj_mark_static_terms(Goals0, Goals, !SI) :-
+	list__map_foldl(goal_mark_static_terms, Goals0, Goals, !SI).
 
 :- pred disj_mark_static_terms(hlds_goals::in, hlds_goals::out,
-		static_info::in) is det.
+	static_info::in) is det.
 
 disj_mark_static_terms([], [], _).
 disj_mark_static_terms([Goal0 | Goals0], [Goal | Goals], SI0) :-
@@ -130,7 +126,7 @@
 	disj_mark_static_terms(Goals0, Goals, SI0).
 
 :- pred cases_mark_static_terms(list(case)::in, list(case)::out,
-		static_info::in) is det.
+	static_info::in) is det.
 
 cases_mark_static_terms([], [], _SI0).
 cases_mark_static_terms([Case0 | Cases0], [Case | Cases], SI0) :-
@@ -141,7 +137,7 @@
 	cases_mark_static_terms(Cases0, Cases, SI0).
 
 :- pred unification_mark_static_terms(unification::in, unification::out,
-		static_info::in, static_info::out) is det.
+	static_info::in, static_info::out) is det.
 
 unification_mark_static_terms(Unification0, Unification,
 		StaticVars0, StaticVars) :-
Index: compiler/mercury_to_mercury.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mercury_to_mercury.m,v
retrieving revision 1.251
diff -u -r1.251 mercury_to_mercury.m
--- compiler/mercury_to_mercury.m	1 Feb 2005 07:11:32 -0000	1.251
+++ compiler/mercury_to_mercury.m	16 Mar 2005 06:36:51 -0000
@@ -2500,9 +2500,11 @@
 	io__write_string(")").
 
 mercury_output_goal_2(some(Vars, Goal), VarSet, Indent) -->
-	( { Vars = [] } ->
+	(
+		{ Vars = [] },
 		mercury_output_goal(Goal, VarSet, Indent)
 	;
+		{ Vars = [_ | _] },
 		io__write_string("some ["),
 		mercury_output_vars(Vars, VarSet, no),
 		io__write_string("] ("),
@@ -2514,9 +2516,11 @@
 	).
 
 mercury_output_goal_2(some_state_vars(Vars, Goal), VarSet, Indent) -->
-	( { Vars = [] } ->
+	(
+		{ Vars = [] },
 		mercury_output_goal(Goal, VarSet, Indent)
 	;
+		{ Vars = [_ | _] },
 		io__write_string("some ["),
 		mercury_output_state_vars(Vars, VarSet, no),
 		io__write_string("] ("),
@@ -2528,9 +2532,11 @@
 	).
 
 mercury_output_goal_2(all(Vars, Goal), VarSet, Indent) -->
-	( { Vars = [] } ->
+	(
+		{ Vars = [] },
 		mercury_output_goal(Goal, VarSet, Indent)
 	;
+		{ Vars = [_ | _] },
 		io__write_string("all ["),
 		mercury_output_vars(Vars, VarSet, no),
 		io__write_string("] ("),
@@ -2542,9 +2548,11 @@
 	).
 
 mercury_output_goal_2(all_state_vars(Vars, Goal), VarSet, Indent) -->
-	( { Vars = [] } ->
+	(
+		{ Vars = [] },
 		mercury_output_goal(Goal, VarSet, Indent)
 	;
+		{ Vars = [_ | _] },
 		io__write_string("all ["),
 		mercury_output_state_vars(Vars, VarSet, no),
 		io__write_string("] ("),
@@ -2554,6 +2562,42 @@
 		mercury_output_newline(Indent),
 		io__write_string(")")
 	).
+
+mercury_output_goal_2(promise_equivalent_solution(Vars, Goal), VarSet,
+		Indent) -->
+	(
+		{ Vars = [] },
+		% This should have been caught be prog_io_goal when reading in
+		% the term, but there is no point in aborting here.
+		mercury_output_goal(Goal, VarSet, Indent)
+	;
+		{ Vars = [_ | _] },
+		io__write_string("promise_equivalent_solution ["),
+		mercury_output_vars(Vars, VarSet, no),
+		io__write_string("] ("),
+		{ Indent1 = Indent + 1 },
+		mercury_output_newline(Indent1),
+		mercury_output_goal(Goal, VarSet, Indent1),
+		mercury_output_newline(Indent),
+		io__write_string(")")
+	).
+
+mercury_output_goal_2(promise_purity(Purity, Goal), VarSet, Indent) -->
+	(
+		{ Purity = pure },
+		io__write_string("promise_pure (")
+	;
+		{ Purity = (semipure) },
+		io__write_string("promise_semipure (")
+	;
+		{ Purity = (impure) },
+		io__write_string("promise_impure (")
+	),
+	{ Indent1 = Indent + 1 },
+	mercury_output_newline(Indent1),
+	mercury_output_goal(Goal, VarSet, Indent1),
+	mercury_output_newline(Indent),
+	io__write_string(")").
 
 mercury_output_goal_2(if_then_else(Vars, StateVars, A, B, C), VarSet,
 		Indent) -->
Index: compiler/ml_code_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_code_gen.m,v
retrieving revision 1.148
diff -u -r1.148 ml_code_gen.m
--- compiler/ml_code_gen.m	10 Mar 2005 02:35:58 -0000	1.148
+++ compiler/ml_code_gen.m	10 Mar 2005 06:08:34 -0000
@@ -2064,8 +2064,8 @@
 	ml_gen_switch(Var, CanFail, CasesList, CodeModel, Context,
 		Decls, Statements, !Info).
 
-ml_gen_goal_expr(some(_Vars, _CanRemove, Goal), CodeModel, Context,
-		Decls, Statements, !Info) :-
+ml_gen_goal_expr(scope(_, Goal), CodeModel, Context, Decls, Statements,
+		!Info) :-
 	ml_gen_commit(Goal, CodeModel, Context, Decls, Statements, !Info).
 
 ml_gen_goal_expr(if_then_else(_Vars, Cond, Then, Else),
Index: compiler/mode_constraint_robdd.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_constraint_robdd.m,v
retrieving revision 1.3
diff -u -r1.3 mode_constraint_robdd.m
--- compiler/mode_constraint_robdd.m	20 Dec 2004 12:46:32 -0000	1.3
+++ compiler/mode_constraint_robdd.m	16 Mar 2005 11:31:22 -0000
@@ -345,7 +345,7 @@
 	io__write_char('e').
 dump_goal_path_step(neg) -->
 	io__write_char('n').
-dump_goal_path_step(exist(_)) -->
+dump_goal_path_step(scope(_)) -->
 	io__write_char('q').
 dump_goal_path_step(first) -->
 	io__write_char('f').
Index: compiler/mode_constraints.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_constraints.m,v
retrieving revision 1.6
diff -u -r1.6 mode_constraints.m
--- compiler/mode_constraints.m	22 Feb 2005 12:32:10 -0000	1.6
+++ compiler/mode_constraints.m	23 Feb 2005 00:15:31 -0000
@@ -312,7 +312,7 @@
 	number_robdd_variables_in_goal(InstGraph, NonLocals, Occurring,
 		Goal0, Goal, !RInfo).
 number_robdd_variables_in_goal_2(InstGraph, _, _, NonLocals, Occurring,
-		some(V, CR, Goal0), some(V, CR, Goal), !RInfo) :-
+		scope(Reason, Goal0), scope(Reason, Goal), !RInfo) :-
 	number_robdd_variables_in_goal(InstGraph, NonLocals, Occurring,
 		Goal0, Goal, !RInfo).
 number_robdd_variables_in_goal_2(InstGraph, _, _, NonLocals, Occurring,
@@ -1247,8 +1247,8 @@
 	% Make sure the negation doesn't bind any nonlocal variables.
 	negation_constraints(GoalPath, NonLocals, !Constraint, !GCInfo).
 
-goal_constraints_2(GoalPath, NonLocals, Vars, CanSucceed, some(A, B, Goal0),
-		some(A, B, Goal), !Constraint, !GCInfo) :-
+goal_constraints_2(GoalPath, NonLocals, Vars, CanSucceed, scope(Reason, Goal0),
+		scope(Reason, Goal), !Constraint, !GCInfo) :-
 	goal_constraints(NonLocals, CanSucceed, Goal0, Goal, !Constraint,
 		!GCInfo),
 
Index: compiler/mode_debug.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_debug.m,v
retrieving revision 1.19
diff -u -r1.19 mode_debug.m
--- compiler/mode_debug.m	24 Feb 2005 00:35:24 -0000	1.19
+++ compiler/mode_debug.m	24 Feb 2005 10:52:29 -0000
@@ -56,17 +56,18 @@
 mode_checkpoint(Port, Msg, !ModeInfo, !IO) :-
 	mode_info_get_debug_modes(!.ModeInfo, DebugModes),
 	(
-		DebugModes = yes(Verbose - Statistics),
-		mode_checkpoint_write(Verbose, Statistics, Port, Msg,
+		DebugModes = yes(debug_flags(Verbose, Minimal, Statistics)),
+		mode_checkpoint_write(Verbose, Minimal, Statistics, Port, Msg,
 			!ModeInfo, !IO)
 	;
 		DebugModes = no
 	).
 
-:- pred mode_checkpoint_write(bool::in, bool::in, port::in, string::in,
-	mode_info::in, mode_info::out, io::di, io::uo) is det.
+:- pred mode_checkpoint_write(bool::in, bool::in, bool::in, port::in,
+	string::in, mode_info::in, mode_info::out, io::di, io::uo) is det.
 
-mode_checkpoint_write(Verbose, Statistics, Port, Msg, !ModeInfo, !IO) :-
+mode_checkpoint_write(Verbose, Minimal, Statistics, Port, Msg, !ModeInfo,
+		!IO) :-
 	mode_info_get_errors(!.ModeInfo, Errors),
 	( Port = enter ->
 		io__write_string("Enter ", !IO),
@@ -95,7 +96,7 @@
 			mode_info_get_varset(!.ModeInfo, VarSet),
 			mode_info_get_instvarset(!.ModeInfo, InstVarSet),
 			write_var_insts(NewInsts, OldInstMap, VarSet,
-				InstVarSet, Verbose, !IO)
+				InstVarSet, Verbose, Minimal, !IO)
 		;
 			io__write_string("\tUnreachable\n", !IO)
 		),
@@ -107,14 +108,19 @@
 	io__flush_output(!IO).
 
 :- pred write_var_insts(assoc_list(prog_var, inst)::in, instmap::in,
-	prog_varset::in, inst_varset::in, bool::in, io::di, io::uo) is det.
+	prog_varset::in, inst_varset::in, bool::in, bool::in,
+	io::di, io::uo) is det.
 
-write_var_insts([], _, _, _, _, !IO).
+write_var_insts([], _, _, _, _, _, !IO).
 write_var_insts([Var - Inst | VarInsts], OldInstMap, VarSet, InstVarSet,
-		Verbose, !IO) :-
+		Verbose, Minimal, !IO) :-
+	instmap__lookup_var(OldInstMap, Var, OldInst),
 	(
-		instmap__lookup_var(OldInstMap, Var, OldInst),
-		Inst = OldInst
+		(
+			identical_insts(Inst, OldInst)
+		;
+			Inst = OldInst
+		)
 	->
 		(
 			Verbose = yes,
@@ -129,11 +135,43 @@
 		io__write_string("\t", !IO),
 		mercury_output_var(Var, VarSet, no, !IO),
 		io__write_string(" ::", !IO),
-		io__write_string("\n", !IO),
-		mercury_output_structured_inst(Inst, 2, InstVarSet, !IO)
+		(
+			Minimal = yes,
+			io__write_string(" changed\n", !IO)
+		;
+			Minimal = no,
+			io__write_string("\n", !IO),
+			mercury_output_structured_inst(Inst, 2, InstVarSet,
+				!IO)
+		)
 	),
 	write_var_insts(VarInsts, OldInstMap, VarSet, InstVarSet, Verbose,
-		!IO).
+		Minimal, !IO).
+
+	% In the usual case of a C backend, this predicate allows us to
+	% conclude that two insts are identical without traversing them.
+	% Since the terms can be very large, this is a big gain; it can
+	% turn the complexity of printing a checking from quadratic in the
+	% number of variables live at the checkpoint (when the variables
+	% are e.g. all part of a single long list) to linear. The minor
+	% increase in the constant factor in cases where identical_insts fails
+	% is much easier to live with.
+
+:- pred identical_insts((inst)::in, (inst)::in) is semidet.
+
+identical_insts(_, _) :-
+	semidet_fail.
+
+:- pragma foreign_proc("C",
+	identical_insts(InstA::in, InstB::in),
+	[will_not_call_mercury, will_not_throw_exception, promise_pure],
+"
+	if (InstA == InstB) {
+		SUCCESS_INDICATOR = MR_TRUE;
+	} else {
+		SUCCESS_INDICATOR = MR_FALSE;
+	}
+").
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
Index: compiler/mode_info.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_info.m,v
retrieving revision 1.70
diff -u -r1.70 mode_info.m
--- compiler/mode_info.m	24 Feb 2005 00:35:25 -0000	1.70
+++ compiler/mode_info.m	24 Feb 2005 10:56:02 -0000
@@ -80,6 +80,16 @@
 
 :- type mode_info.
 
+:- type debug_flags
+	--->	debug_flags(
+			verbose		:: bool,
+					% The value --debug-modes-verbose
+			minimal		:: bool,
+					% The value --debug-modes-minimal
+			statistics	:: bool
+					% The value --debug-modes-statistics
+		).
+
 :- pred mode_info_init(module_info::in, pred_id::in,
 	proc_id::in, prog_context::in, set(prog_var)::in, instmap::in,
 	how_to_check_goal::in, may_change_called_proc::in,
@@ -93,7 +103,7 @@
 :- pred mode_info_get_insts(mode_info::in, inst_table::out) is det.
 :- pred mode_info_get_predid(mode_info::in, pred_id::out) is det.
 :- pred mode_info_get_procid(mode_info::in, proc_id::out) is det.
-:- pred mode_info_get_debug_modes(mode_info::in, maybe(pair(bool))::out)
+:- pred mode_info_get_debug_modes(mode_info::in, maybe(debug_flags)::out)
 	is det.
 :- pred mode_info_get_context(mode_info::in, prog_context::out) is det.
 :- pred mode_info_get_mode_context(mode_info::in, mode_context::out) is det.
@@ -280,9 +290,10 @@
 		var_types	:: vartypes,
 				% The types of the variables.
 
-		debug		:: maybe(pair(bool)),
+		debug		:: maybe(debug_flags),
 				% Is mode debugging of this procedure enabled?
 				% If yes, is verbose mode debugging enabled,
+				% is minimal mode debugging enabled,
 				% and is statistics printing enabled?
 
 		context		:: prog_context,
@@ -378,9 +389,12 @@
 	->
 		globals__lookup_bool_option(Globals, debug_modes_verbose,
 			DebugVerbose),
-		globals__lookup_bool_option(Globals, statistics,
+		globals__lookup_bool_option(Globals, debug_modes_minimal,
+			DebugMinimal),
+		globals__lookup_bool_option(Globals, debug_modes_statistics,
 			Statistics),
-		Debug = yes(DebugVerbose - Statistics)
+		Flags = debug_flags(DebugVerbose, DebugMinimal, Statistics),
+		Debug = yes(Flags)
 	;
 		Debug = no
 	),
Index: compiler/mode_ordering.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_ordering.m,v
retrieving revision 1.3
diff -u -r1.3 mode_ordering.m
--- compiler/mode_ordering.m	23 Dec 2004 06:49:17 -0000	1.3
+++ compiler/mode_ordering.m	15 Feb 2005 14:33:12 -0000
@@ -289,8 +289,8 @@
 	goal_info_copy_mode_var_sets(SubGoal ^ snd, GoalInfo0, GoalInfo).
 
 mode_ordering__goal_2(Goal0, Goal, GoalInfo0, GoalInfo, !MOI) :-
-	Goal0 = some(Vars, CanRemove, SubGoal0),
-	Goal = some(Vars, CanRemove, SubGoal),
+	Goal0 = scope(Reason, SubGoal0),
+	Goal = scope(Reason, SubGoal),
 	mode_ordering__goal(SubGoal0, SubGoal, !MOI),
 	goal_info_copy_mode_var_sets(SubGoal ^ snd, GoalInfo0, GoalInfo).
 
@@ -305,10 +305,10 @@
 	union_mode_vars_sets([Cond, Then], GoalInfo0, GoalInfo1),
 	ConsVars = GoalInfo1 ^ consuming_vars,
 	GoalInfo2 = GoalInfo1 ^ consuming_vars :=
-			ConsVars `difference` GoalInfo1 ^ producing_vars,
+		ConsVars `difference` GoalInfo1 ^ producing_vars,
 	NeedVars = GoalInfo2 ^ need_visible_vars,
 	GoalInfo3 = GoalInfo2 ^ need_visible_vars :=
-			NeedVars `difference` GoalInfo2 ^ make_visible_vars,
+		NeedVars `difference` GoalInfo2 ^ make_visible_vars,
 
 	combine_mode_vars_sets(Else ^ snd, GoalInfo3, GoalInfo).
 
Index: compiler/mode_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_util.m,v
retrieving revision 1.163
diff -u -r1.163 mode_util.m
--- compiler/mode_util.m	21 Jan 2005 03:27:42 -0000	1.163
+++ compiler/mode_util.m	15 Feb 2005 14:33:26 -0000
@@ -981,9 +981,8 @@
 		VarTypes, InstMapDeltaElse, InstMapDeltaCondThen),
 		InstMapDelta, !RI).
 
-recompute_instmap_delta_2(Atomic, some(Vars, CanRemove, Goal0), _,
-		some(Vars, CanRemove, Goal), VarTypes, InstMap, InstMapDelta,
-		!RI) :-
+recompute_instmap_delta_2(Atomic, scope(Reason, Goal0), _,
+		scope(Reason, Goal), VarTypes, InstMap, InstMapDelta, !RI) :-
 	recompute_instmap_delta_1(Atomic, Goal0, Goal, VarTypes, InstMap,
 		InstMapDelta, !RI).
 
--------------------------------------------------------------------------
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