[m-rev.] for review: two new scope types

Zoltan Somogyi zs at csse.unimelb.edu.au
Tue Dec 28 18:26:34 AEDT 2010


For review by Julien. Since we already discussed the concept of the two new
scopes in person and the implementation is straightforward, I am mostly seeking
feedback on the updates to NEWS and the manual.

This is for the release branch too, since the scopes are intended to be used by
G12 code.

I will add a mention to w3 when this is committed.

Zoltan.

Add two new kinds of scopes to the language: one that requires the goal inside
the scope to have a given determinism, and one that requires it
to be complete, i.e. to have arms for all the function symbols in the type of
the switched-on variable.

The first kind of scope adds the keywords

	require_det require_semidet
	require_multi require_nondet
	require_cc_multi require_cc_nondet
	require_erroneous require_failure

to the language. They are intended to be used like this:

	test_detism_scope(A, !IO) :-
	    (
		A > 10,
		require_det (
		    B = A * 2,
		    C = B mod 3
		),
		C = 1
	    ->
		X = C
	    ;
		X = A
	    ),
	    io.format("test_detism_scope(%d) = %d\n", [i(A), i(X)], !IO).

The second kind of scope adds the keyword require_complete_switch to
the language. They are intended to be used like this:

	do_test_switch_scope(A, X) :-
	    require_complete_switch [A] (
		(
		    A = f1,
		    fail
		;
		    A = f2,
		    ( X = 1
		    ; X = 2
		    )
		;
		    A = f3(B),
		    ( X = 3
		    ; X = B
		    ; X = B + 1
		    )
		)
	    ).

NEWS:
	Announce the new scopes.

doc/reference_manual.texi:
	Document the new scopes.

library/ops.m:
	Add the new keywords as operators.

compiler/hlds_goal.m:
	Add the new kinds of scopes to the HLDS.

compiler/prog_item.m:
	Add the new kinds of scopes to the parse tree type.

compiler/prog_io_goal.m:
	Recognize the new keywords. When we find a term with one of these
	keywords as the function symbol, generate the corresponding parse tree
	goal expression.

compiler/add_clause.m:
	Convert these goal expressions to HLDS.

compiler/simplify.m:
	Check the requirements expressed by the new scopes. If the requirement
	is met, delete the scope wrapper. If the requirement is not met,
	generate an error message and then delete the scope wrapper.

compiler/error_util.m:
	Add a new format_component, words_qoute, which is like quote, but
	yields words, not fixed, after quoting.

compiler/constraint.m:
compiler/det_analysis.m:
compiler/erl_code_gen.m:
compiler/goal_util.m:
compiler/hlds_desc.m:
compiler/hlds_out_goal.m:
compiler/interval.m:
compiler/lambda.m:
compiler/make_hlds_warn.m:
compiler/mercury_to_mercury.m:
compiler/mode_errors.m:
compiler/modecheck_goal.m:
compiler/module_imports.m:
compiler/module_qual.m:
compiler/polymorphism.m:
compiler/prog_util.m:
compiler/purity.m:
compiler/quantification.m:
compiler/saved_vars.m:
compiler/stm_expand.m:
compiler/try_expand.m:
compiler/typecheck.m:
	Conform to the changes to the parse tree and HLDS goal types.
	In one module, take advantage of the new format_component.

tests/hard_coded/require_scopes.{m,exp}:
	A new test case to test the handling of the new scopes when their
	requirements are met.

tests/hard_coded/Mmakefile:
	Add the new test.

tests/invalid/require_scopes.{m,err_exp}:
	A new test case to test the handling of the new scopes when their
	requirements are NOT met.

tests/invalid/Mmakefile:
	Add the new test.

cvs diff: Diffing .
Index: NEWS
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/NEWS,v
retrieving revision 1.554
diff -u -b -r1.554 NEWS
--- NEWS	19 Dec 2010 06:25:32 -0000	1.554
+++ NEWS	28 Dec 2010 03:33:06 -0000
@@ -10,6 +10,20 @@
 HIGHLIGHTS
 ==========
 
+Changes to the Mercury language:
+
+* We have added two new kinds of scopes to the language.
+
+  A scope introduced by one of the new keywords require_det, require_semidet,
+  require_multi, require_nondet, require_cc_multi, require_cc_nondet,
+  require_erroneous and require_failure, as the name implies, requires
+  the goal inside the scope to have the given determinism.
+  
+  A scope introduced by the keyword require_complete_switch requires the
+  goal inside the scope, if it is a switch on the variable named by the scope,
+  to be a complete switch, i.e. to have arms for all the function symbols
+  in the type of the switched-on variable.
+
 Changes to the Mercury standard library:
 
 * We have added semidet modes for hash_table.fold/4 and
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/extra
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/extra
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/libatomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops/doc
cvs diff: Diffing boehm_gc/libatomic_ops/src
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/armcc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/gcc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/hpc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/ibmc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/icc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/msftc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/sunc
cvs diff: Diffing boehm_gc/libatomic_ops/tests
cvs diff: Diffing boehm_gc/libatomic_ops-1.2
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/doc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/tests
cvs diff: Diffing boehm_gc/m4
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/add_clause.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/add_clause.m,v
retrieving revision 1.61
diff -u -b -r1.61 add_clause.m
--- compiler/add_clause.m	15 Dec 2010 06:29:27 -0000	1.61
+++ compiler/add_clause.m	27 Dec 2010 11:28:14 -0000
@@ -626,95 +626,110 @@
     svar_info::in, svar_info::out,
     list(error_spec)::in, list(error_spec)::out) is det.
 
-transform_goal_2(fail_expr, _, _, hlds_goal(disj([]), GoalInfo), 0,
-        !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
-    goal_info_init(GoalInfo),
-    svar_prepare_for_next_conjunct(set.init, !VarSet, !SInfo).
-transform_goal_2(true_expr, _, _, hlds_goal(conj(plain_conj, []), GoalInfo), 0,
+transform_goal_2(Expr, Context, Renaming, Goal, !:NumAdded,
         !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+    (
+        (
+            Expr = fail_expr,
+            GoalExpr = disj([])
+        ;
+            Expr = true_expr,
+            GoalExpr = conj(plain_conj, [])
+        ),
+        !:NumAdded = 0,
     goal_info_init(GoalInfo),
-    svar_prepare_for_next_conjunct(set.init, !VarSet, !SInfo).
-transform_goal_2(all_expr(Vars0, Goal0), Context, Renaming, Goal, NumAdded,
-        !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+        Goal = hlds_goal(GoalExpr, GoalInfo),
+        svar_prepare_for_next_conjunct(set.init, !VarSet, !SInfo)
+    ;
     % Convert `all [Vars] Goal' into `not some [Vars] not Goal'.
-    TransformedGoal = not_expr(some_expr(Vars0, not_expr(Goal0) - Context)
-        - Context),
-    transform_goal_2(TransformedGoal, Context, Renaming, Goal, NumAdded,
-        !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs).
-transform_goal_2(all_state_vars_expr(StateVars, Goal0), Context, Renaming,
-        Goal, NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
-    transform_goal_2(
-        not_expr(some_state_vars_expr(StateVars,
-            not_expr(Goal0) - Context) - Context),
-        Context, Renaming, Goal, NumAdded, !VarSet, !ModuleInfo, !QualInfo,
-        !SInfo, !Specs).
-transform_goal_2(some_expr(Vars0, Goal0), _, Renaming,
-        hlds_goal(scope(exist_quant(Vars), Goal), GoalInfo), NumAdded,
-        !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+        (
+            Expr = all_expr(Vars0, Goal0),
+            TransformedExpr = not_expr(some_expr(Vars0,
+                not_expr(Goal0) - Context) - Context)
+        ;
+            Expr = all_state_vars_expr(StateVars, Goal0),
+            TransformedExpr = not_expr(some_state_vars_expr(StateVars,
+                not_expr(Goal0) - Context) - Context)
+        ),
+        transform_goal_2(TransformedExpr, Context, Renaming, Goal, !:NumAdded,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs)
+    ;
+        Expr = some_expr(Vars0, SubExpr),
     rename_var_list(need_not_rename, Renaming, Vars0, Vars),
-    transform_goal(Goal0, Renaming, Goal, NumAdded, !VarSet, !ModuleInfo,
-        !QualInfo, !SInfo, !Specs),
-    goal_info_init(GoalInfo).
-transform_goal_2(some_state_vars_expr(StateVars0, Goal0), _, Renaming,
-        hlds_goal(scope(exist_quant(Vars), Goal), GoalInfo), NumAdded,
-        !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+        transform_goal(SubExpr, Renaming, SubGoal, !:NumAdded,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
+        GoalExpr = scope(exist_quant(Vars), SubGoal),
+        goal_info_init(GoalInfo),
+        Goal = hlds_goal(GoalExpr, GoalInfo)
+    ;
+        Expr = some_state_vars_expr(StateVars0, SubExpr0),
     BeforeSInfo = !.SInfo,
     rename_var_list(need_not_rename, Renaming, StateVars0, StateVars),
     prepare_for_local_state_vars(StateVars, !VarSet, !SInfo),
-    transform_goal(Goal0, Renaming, Goal, NumAdded, !VarSet, !ModuleInfo,
-        !QualInfo, !SInfo, !Specs),
+        transform_goal(SubExpr0, Renaming, SubGoal, !:NumAdded,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
     finish_local_state_vars(StateVars, Vars, BeforeSInfo, !SInfo),
-    goal_info_init(GoalInfo).
-transform_goal_2(promise_purity_expr(Purity, Goal0), _, Renaming,
-        hlds_goal(
-            scope(promise_purity(Purity), Goal),
-            GoalInfo),
-        NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
-    transform_goal(Goal0, Renaming, Goal, NumAdded, !VarSet, !ModuleInfo,
-        !QualInfo, !SInfo, !Specs),
-    goal_info_init(GoalInfo).
-transform_goal_2(
-        promise_equivalent_solutions_expr(Vars0, DotSVars0, ColonSVars0,
-            Goal0),
-        Context, Renaming,
-        hlds_goal(
-            scope(promise_solutions(Vars, equivalent_solutions), Goal),
-            GoalInfo),
-        NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+        GoalExpr = scope(exist_quant(Vars), SubGoal),
+        goal_info_init(GoalInfo),
+        Goal = hlds_goal(GoalExpr, GoalInfo)
+    ;
+        Expr = promise_purity_expr(Purity, SubExpr0),
+        transform_goal(SubExpr0, Renaming, SubGoal, !:NumAdded,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
+        GoalExpr = scope(promise_purity(Purity), SubGoal),
+        goal_info_init(GoalInfo),
+        Goal = hlds_goal(GoalExpr, GoalInfo)
+    ;
+        Expr = promise_equivalent_solutions_expr(Vars0, DotSVars0, ColonSVars0,
+            SubExpr0),
     transform_promise_eqv_goal(Vars0, DotSVars0, ColonSVars0,
-        Context, Renaming, Vars, Goal0, Goal, GoalInfo, NumAdded,
-        !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs).
-transform_goal_2(
-        promise_equivalent_solution_sets_expr(Vars0, DotSVars0, ColonSVars0,
-            Goal0),
-        Context, Renaming,
-        hlds_goal(
-            scope(promise_solutions(Vars, equivalent_solution_sets), Goal),
-            GoalInfo),
-        NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+            Context, Renaming, Vars, SubExpr0, SubGoal, GoalInfo, !:NumAdded,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
+        GoalExpr = scope(promise_solutions(Vars, equivalent_solutions),
+            SubGoal),
+        Goal = hlds_goal(GoalExpr, GoalInfo)
+    ;
+        Expr = promise_equivalent_solution_sets_expr(Vars0,
+            DotSVars0, ColonSVars0, SubExpr0),
     transform_promise_eqv_goal(Vars0, DotSVars0, ColonSVars0,
-        Context, Renaming, Vars, Goal0, Goal, GoalInfo, NumAdded,
-        !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs).
-transform_goal_2(
-        promise_equivalent_solution_arbitrary_expr(Vars0,
-            DotSVars0, ColonSVars0, Goal0),
-        Context, Renaming,
-        hlds_goal(
-            scope(promise_solutions(Vars, equivalent_solution_sets_arbitrary),
-                Goal),
-            GoalInfo),
-        NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+            Context, Renaming, Vars, SubExpr0, SubGoal, GoalInfo, !:NumAdded,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
+        GoalExpr = scope(promise_solutions(Vars, equivalent_solution_sets),
+            SubGoal),
+        Goal = hlds_goal(GoalExpr, GoalInfo)
+    ;
+        Expr = require_detism_expr(Detism, SubExpr),
+        transform_goal(SubExpr, Renaming, SubGoal, !:NumAdded,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
+        GoalExpr = scope(require_detism(Detism), SubGoal),
+        goal_info_init(GoalInfo),
+        Goal = hlds_goal(GoalExpr, GoalInfo)
+    ;
+        Expr = require_complete_switch_expr(Var0, SubExpr),
+        rename_var(need_not_rename, Renaming, Var0, Var),
+        transform_goal(SubExpr, Renaming, SubGoal, !:NumAdded,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
+        GoalExpr = scope(require_complete_switch(Var), SubGoal),
+        goal_info_init(GoalInfo),
+        Goal = hlds_goal(GoalExpr, GoalInfo)
+    ;
+        Expr = promise_equivalent_solution_arbitrary_expr(Vars0,
+            DotSVars0, ColonSVars0, SubExpr0),
     transform_promise_eqv_goal(Vars0, DotSVars0, ColonSVars0,
-        Context, Renaming, Vars, Goal0, Goal, GoalInfo, NumAdded,
-        !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs).
-transform_goal_2(atomic_expr(Outer0, Inner0, MaybeOutputVars0,
-        MainGoal, OrElseGoals), Context, Renaming, HLDSGoal,
-        !:NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+            Context, Renaming, Vars, SubExpr0, SubGoal, GoalInfo, !:NumAdded,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
+        GoalExpr = scope(promise_solutions(Vars,
+            equivalent_solution_sets_arbitrary), SubGoal),
+        Goal = hlds_goal(GoalExpr, GoalInfo)
+    ;
+        Expr = atomic_expr(Outer0, Inner0, MaybeOutputVars0,
+            MainExpr, OrElseExprs),
     (
         Outer0 = atomic_state_var(OuterStateVar0),
-        rename_var(need_not_rename, Renaming, OuterStateVar0, OuterStateVar),
-        svar_start_outer_atomic_scope(Context, OuterStateVar, OuterDI, OuterUO,
-            OuterScopeInfo, !VarSet, !SInfo, !Specs),
+            rename_var(need_not_rename, Renaming,
+                OuterStateVar0, OuterStateVar),
+            svar_start_outer_atomic_scope(Context, OuterStateVar,
+                OuterDI, OuterUO, OuterScopeInfo, !VarSet, !SInfo, !Specs),
         MaybeOuterScopeInfo = yes(OuterScopeInfo),
         Outer = atomic_interface_vars(OuterDI, OuterUO)
     ;
@@ -726,22 +741,22 @@
     ),
     (
         Inner0 = atomic_state_var(InnerStateVar0),
-        rename_var(need_not_rename, Renaming, InnerStateVar0, InnerStateVar),
-        svar_start_inner_atomic_scope(Context, InnerStateVar, InnerScopeInfo,
-            !VarSet, !SInfo, !Specs),
+            rename_var(need_not_rename, Renaming,
+                InnerStateVar0, InnerStateVar),
+            svar_start_inner_atomic_scope(Context, InnerStateVar,
+                InnerScopeInfo, !VarSet, !SInfo, !Specs),
         MaybeInnerScopeInfo = yes(InnerScopeInfo)
     ;
         Inner0 = atomic_var_pair(_InnerDI0, _InnerUO0),
         MaybeInnerScopeInfo = no
     ),
     BeforeDisjSInfo = !.SInfo,
-    transform_goal(MainGoal, Renaming, HLDSMainGoal0,
-        !:NumAdded, !VarSet, !ModuleInfo, !QualInfo, BeforeDisjSInfo, SInfo1,
-        !Specs),
+        transform_goal(MainExpr, Renaming, HLDSMainGoal0, !:NumAdded,
+            !VarSet, !ModuleInfo, !QualInfo, BeforeDisjSInfo, SInfo1, !Specs),
     MainDisjInfo = {HLDSMainGoal0, SInfo1},
-    transform_orelse_goals(OrElseGoals, Renaming, OrElseDisjInfos,
-        0, OrElseNumAdded, !VarSet, !ModuleInfo, !QualInfo, BeforeDisjSInfo,
-        !Specs),
+        transform_orelse_goals(OrElseExprs, Renaming, OrElseDisjInfos,
+            0, OrElseNumAdded, !VarSet, !ModuleInfo, !QualInfo,
+            BeforeDisjSInfo, !Specs),
     AllDisjInfos = [MainDisjInfo | OrElseDisjInfos],
     svar_finish_disjunction(Context, !.VarSet, AllDisjInfos, HLDSGoals,
         !:SInfo),
@@ -749,7 +764,7 @@
         HLDSGoals = [HLDSMainGoal | HLDSOrElseGoals]
     ;
         HLDSGoals = [],
-        unexpected(this_file, "transform_goal_2: atomic HLDSGoals = []")
+            unexpected($module, $pred, "atomic HLDSGoals = []")
     ),
     (
         Inner0 = atomic_state_var(_),
@@ -760,7 +775,7 @@
             Inner = atomic_interface_vars(InnerDI, InnerUO)
         ;
             MaybeInnerScopeInfo = no,
-            unexpected(this_file, "transform_goal_2: MaybeFinishStateVar = no")
+                unexpected($module, $pred, "MaybeFinishStateVar = no")
         )
     ;
         Inner0 = atomic_var_pair(InnerDI0, InnerUO0),
@@ -773,7 +788,8 @@
         MaybeOutputVars = no
     ;
         MaybeOutputVars0 = yes(OutputVars0),
-        rename_var_list(need_not_rename, Renaming, OutputVars0, OutputVars),
+            rename_var_list(need_not_rename, Renaming,
+                OutputVars0, OutputVars),
         MaybeOutputVars = yes(OutputVars)
     ),
     (
@@ -787,79 +803,81 @@
         MaybeOutputVars, HLDSMainGoal, HLDSOrElseGoals, []),
     GoalExpr = shorthand(ShortHand),
     goal_info_init(Context, GoalInfo),
-    HLDSGoal = hlds_goal(GoalExpr, GoalInfo),
+        Goal = hlds_goal(GoalExpr, GoalInfo),
     trace [compiletime(flag("atomic_scope_syntax")), io(!IO)] (
         io.write_string("atomic:\n", !IO),
         module_info_get_globals(!.ModuleInfo, Globals),
         OutInfo = init_hlds_out_info(Globals),
-        write_goal(OutInfo, HLDSGoal, !.ModuleInfo, !.VarSet, yes, 0, "\n",
+            write_goal(OutInfo, Goal, !.ModuleInfo, !.VarSet, yes, 0, "\n",
             !IO),
         io.nl(!IO)
-    ).
-transform_goal_2(
-        trace_expr(MaybeCompileTime, MaybeRunTime, MaybeIO, Mutables, Goal0),
-        Context, Renaming, hlds_goal(scope(Reason, Goal), GoalInfo), NumAdded,
-        !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+        )
+    ;
+        Expr = trace_expr(MaybeCompileTime, MaybeRunTime, MaybeIO,
+            Mutables, SubExpr0),
     list.map4(extract_trace_mutable_var(Context, !.VarSet), Mutables,
-        MutableHLDSs, MutableStateVars, MutableGetGoals, MutableSetGoals),
+            MutableHLDSs, MutableStateVars, MutableGetExprs, MutableSetExprs),
     (
         MaybeIO = yes(IOStateVar),
         varset.lookup_name(!.VarSet, IOStateVar, IOStateVarName),
         MaybeIOHLDS = yes(IOStateVarName),
-        extract_trace_io_var(Context, IOStateVar, IOGetGoal, IOSetGoal),
+            extract_trace_io_var(Context, IOStateVar, IOGetExpr, IOSetExpr),
         StateVars0 = [IOStateVar | MutableStateVars],
-        GetGoals = [IOGetGoal | MutableGetGoals],
-        SetGoals = [IOSetGoal | MutableSetGoals]
+            GetExprs = [IOGetExpr | MutableGetExprs],
+            SetExprs = [IOSetExpr | MutableSetExprs]
     ;
         MaybeIO = no,
         MaybeIOHLDS = no,
         StateVars0 = MutableStateVars,
-        GetGoals = MutableGetGoals,
-        SetGoals = MutableSetGoals
+            GetExprs = MutableGetExprs,
+            SetExprs = MutableSetExprs
     ),
-    Goal1 = goal_list_to_conj(Context, GetGoals ++ [Goal0] ++ SetGoals),
+        SubExpr1 =
+            goal_list_to_conj(Context, GetExprs ++ [SubExpr0] ++ SetExprs),
     BeforeSInfo = !.SInfo,
     rename_var_list(need_not_rename, Renaming, StateVars0, StateVars),
     prepare_for_local_state_vars(StateVars, !VarSet, !SInfo),
-    transform_goal(Goal1, Renaming, Goal, NumAdded1, !VarSet, !ModuleInfo,
-        !QualInfo, !SInfo, !Specs),
-    NumAdded = list.length(GetGoals) + NumAdded1 + list.length(SetGoals),
+        transform_goal(SubExpr1, Renaming, SubGoal, !:NumAdded,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
+        !:NumAdded =
+            list.length(GetExprs) + !.NumAdded + list.length(SetExprs),
     finish_local_state_vars(StateVars, Vars, BeforeSInfo, !SInfo),
     Reason = trace_goal(MaybeCompileTime, MaybeRunTime, MaybeIOHLDS,
         MutableHLDSs, Vars),
-    goal_info_init(GoalInfo).
-transform_goal_2(
-        try_expr(MaybeIO0, Goal0, Then0, MaybeElse0, Catches0, MaybeCatchAny0),
-        Context, Renaming, TryGoal, NumAdded,
-        !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+        GoalExpr = scope(Reason, SubGoal),
+        goal_info_init(GoalInfo),
+        Goal = hlds_goal(GoalExpr, GoalInfo)
+    ;
+        Expr = try_expr(MaybeIO0, SubExpr0, Then0, MaybeElse0,
+            Catches0, MaybeCatchAny0),
     (
         MaybeIO0 = yes(IOStateVar0),
         (
             MaybeElse0 = no,
             rename_var(need_not_rename, Renaming, IOStateVar0, IOStateVar),
-            transform_try_expr_with_io(IOStateVar0, IOStateVar, Goal0, Then0,
-                Catches0, MaybeCatchAny0, Context, Renaming, TryGoal,
-                NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs)
+                transform_try_expr_with_io(IOStateVar0, IOStateVar, SubExpr0,
+                    Then0, Catches0, MaybeCatchAny0, Context, Renaming, Goal,
+                    !:NumAdded, !VarSet, !ModuleInfo, !QualInfo,
+                    !SInfo, !Specs)
         ;
             MaybeElse0 = yes(_),
             Pieces = [words("Error: a `try' goal with an `io' parameter"),
                 words("cannot have an else part."), nl],
             Msg = simple_msg(Context, [always(Pieces)]),
-            Spec = error_spec(severity_error, phase_parse_tree_to_hlds, [Msg]),
+                Spec = error_spec(severity_error,
+                    phase_parse_tree_to_hlds, [Msg]),
             !:Specs = [Spec | !.Specs],
-            TryGoal = true_goal,
-            NumAdded = 0
+                Goal = true_goal,
+                !:NumAdded = 0
         )
     ;
         MaybeIO0 = no,
-        transform_try_expr_without_io(Goal0, Then0, MaybeElse0, Catches0,
-            MaybeCatchAny0, Context, Renaming, TryGoal, NumAdded,
+            transform_try_expr_without_io(SubExpr0, Then0, MaybeElse0,
+                Catches0, MaybeCatchAny0, Context, Renaming, Goal, !:NumAdded,
             !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs)
-    ).
-transform_goal_2(if_then_else_expr(Vars0, StateVars0, Cond0, Then0, Else0),
-        Context, Renaming,
-        hlds_goal(if_then_else(Vars, Cond, Then, Else), GoalInfo),
-        NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+        )
+    ;
+        Expr = if_then_else_expr(Vars0, StateVars0, Cond0, Then0, Else0),
     BeforeSInfo = !.SInfo,
     rename_var_list(need_not_rename, Renaming, Vars0, Vars),
     rename_var_list(need_not_rename, Renaming, StateVars0, StateVars),
@@ -870,74 +888,79 @@
         BeforeSInfo, !.SInfo, AfterCondSInfo, !:SInfo),
     transform_goal(Then0, Renaming, Then1, ThenAdded, !VarSet, !ModuleInfo,
         !QualInfo, !SInfo, !Specs),
-    svar_finish_if_then_else_goal_then_goal(StateVars, BeforeSInfo, !SInfo),
+        svar_finish_if_then_else_goal_then_goal(StateVars, BeforeSInfo,
+            !SInfo),
     AfterThenSInfo = !.SInfo,
     transform_goal(Else0, Renaming, Else1, ElseAdded, !VarSet, !ModuleInfo,
         !QualInfo, BeforeSInfo, !:SInfo, !Specs),
-    NumAdded = CondAdded + ThenAdded + ElseAdded,
+        !:NumAdded = CondAdded + ThenAdded + ElseAdded,
     goal_info_init(Context, GoalInfo),
     svar_finish_if_then_else(Context, Then1, Then, Else1, Else,
-        BeforeSInfo, AfterCondSInfo, AfterThenSInfo, !SInfo, !VarSet).
-transform_goal_2(not_expr(SubGoal0), _, Renaming,
-        hlds_goal(negation(SubGoal), GoalInfo),
-        NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+            BeforeSInfo, AfterCondSInfo, AfterThenSInfo, !SInfo, !VarSet),
+        GoalExpr = if_then_else(Vars, Cond, Then, Else),
+        Goal = hlds_goal(GoalExpr, GoalInfo)
+    ;
+        Expr = not_expr(SubExpr0),
     BeforeSInfo = !.SInfo,
-    transform_goal(SubGoal0, Renaming, SubGoal, NumAdded, !VarSet, !ModuleInfo,
-        !QualInfo, !SInfo, !Specs),
+        transform_goal(SubExpr0, Renaming, SubGoal, !:NumAdded,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
+        svar_finish_negation(BeforeSInfo, !SInfo),
+        GoalExpr = negation(SubGoal),
     goal_info_init(GoalInfo),
-    svar_finish_negation(BeforeSInfo, !SInfo).
-transform_goal_2(conj_expr(A0, B0), _, Renaming, Goal, NumAdded, !VarSet,
-        !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
-    get_rev_conj(A0, Renaming, [], R0, 0, NumAddedA,
+        Goal = hlds_goal(GoalExpr, GoalInfo)
+    ;
+        Expr = conj_expr(A0, B0),
+        get_rev_conj(A0, Renaming, [], R0, 0, !:NumAdded,
         !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
-    get_rev_conj(B0, Renaming, R0, R,  NumAddedA, NumAdded,
+        get_rev_conj(B0, Renaming, R0, R,  !NumAdded,
         !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
     L = list.reverse(R),
     goal_info_init(GoalInfo),
-    conj_list_to_goal(L, GoalInfo, Goal).
-transform_goal_2(par_conj_expr(A0, B0), _, Renaming, Goal, NumAdded, !VarSet,
-        !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
-    get_rev_par_conj(A0, Renaming, [], R0, 0, NumAddedA,
+        conj_list_to_goal(L, GoalInfo, Goal)
+    ;
+        Expr = par_conj_expr(A0, B0),
+        get_rev_par_conj(A0, Renaming, [], R0, 0, !:NumAdded,
         !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
-    get_rev_par_conj(B0, Renaming, R0, R,  NumAddedA, NumAdded,
+        get_rev_par_conj(B0, Renaming, R0, R,  !NumAdded,
         !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
     L = list.reverse(R),
     goal_info_init(GoalInfo),
-    par_conj_list_to_goal(L, GoalInfo, Goal).
-transform_goal_2(disj_expr(A0, B0), Context, Renaming, Goal, NumAdded, !VarSet,
-        !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
-    get_disj(B0, Renaming, [], L0, 0, NumAddedB,
+        par_conj_list_to_goal(L, GoalInfo, Goal)
+    ;
+        Expr = disj_expr(A0, B0),
+        get_disj(B0, Renaming, [], L0, 0, !:NumAdded,
         !VarSet, !ModuleInfo, !QualInfo, !.SInfo, !Specs),
-    get_disj(A0, Renaming, L0, L1, NumAddedB, NumAdded,
+        get_disj(A0, Renaming, L0, L1, !NumAdded,
         !VarSet, !ModuleInfo, !QualInfo, !.SInfo, !Specs),
     svar_finish_disjunction(Context, !.VarSet, L1, L, !:SInfo),
     goal_info_init(Context, GoalInfo),
-    disj_list_to_goal(L, GoalInfo, Goal).
-transform_goal_2(implies_expr(P, Q), Context, Renaming, Goal, NumAdded,
-        !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+        disj_list_to_goal(L, GoalInfo, Goal)
+    ;
+        Expr = implies_expr(P, Q),
         % `P => Q' is defined as `not (P, not Q)'
-    TransformedGoal = not_expr(conj_expr(P, not_expr(Q) - Context) - Context),
-    transform_goal_2(TransformedGoal, Context, Renaming, Goal, NumAdded,
-        !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs).
-transform_goal_2(equivalent_expr(P0, Q0), _, Renaming, Goal, NumAdded, !VarSet,
-        !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+        TransformedExpr = not_expr(conj_expr(P, not_expr(Q) - Context)
+            - Context),
+        transform_goal_2(TransformedExpr, Context, Renaming, Goal, !:NumAdded,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs)
+    ;
+        Expr = equivalent_expr(P0, Q0),
     % `P <=> Q' is defined as `(P => Q), (Q => P)',
-    % but that transformation must not be done until
-    % after quantification analysis, lest the duplication of
-    % the goals concerned affect the implicit quantification
-    % of the variables inside them.
+        % but that transformation must not be done until after quantification,
+        % lest the duplication of the goals concerned affect the implicit
+        % quantification of the variables inside them.
 
     BeforeSInfo = !.SInfo,
+        transform_goal(P0, Renaming, P, NumAddedP,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
+        transform_goal(Q0, Renaming, Q, NumAddedQ,
+            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
+        svar_finish_equivalence(BeforeSInfo, !SInfo),
+        !:NumAdded = NumAddedP + NumAddedQ,
+        GoalExpr = shorthand(bi_implication(P, Q)),
     goal_info_init(GoalInfo),
-    transform_goal(P0, Renaming, P, NumAddedP, !VarSet, !ModuleInfo, !QualInfo,
-        !SInfo, !Specs),
-    transform_goal(Q0, Renaming, Q, NumAddedQ, !VarSet, !ModuleInfo, !QualInfo,
-        !SInfo, !Specs),
-    NumAdded = NumAddedP + NumAddedQ,
-    Goal = hlds_goal(shorthand(bi_implication(P, Q)), GoalInfo),
-    svar_finish_equivalence(BeforeSInfo, !SInfo).
-transform_goal_2(event_expr(EventName, Args0), Context, Renaming, Goal,
-        NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+        Goal = hlds_goal(GoalExpr, GoalInfo)
+    ;
+        Expr = event_expr(EventName, Args0),
     Args1 = expand_bang_state_var_args(Args0),
     svar_prepare_for_call(!SInfo),
     rename_vars_in_term_list(need_not_rename, Renaming, Args1, Args),
@@ -950,11 +973,11 @@
     Goal0 = hlds_goal(GoalExpr0, GoalInfo),
     CallId = generic_call_id(gcid_event_call(EventName)),
     insert_arg_unifications(HeadVars, Args, Context, ac_call(CallId),
-        Goal0, Goal, NumAdded, !VarSet, !ModuleInfo, !QualInfo,
+            Goal0, Goal, !:NumAdded, !VarSet, !ModuleInfo, !QualInfo,
         !SInfo, !Specs),
-    svar_finish_call(!VarSet, !SInfo).
-transform_goal_2(call_expr(Name, Args0, Purity), Context, Renaming, Goal,
-        NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+        svar_finish_call(!VarSet, !SInfo)
+    ;
+        Expr = call_expr(Name, Args0, Purity),
     Args1 = expand_bang_state_var_args(Args0),
     (
         Name = unqualified("\\="),
@@ -962,29 +985,31 @@
     ->
         svar_prepare_for_call(!SInfo),
         % `LHS \= RHS' is defined as `not (LHS = RHS)'
-        transform_goal_2(not_expr(unify_expr(LHS, RHS, Purity) - Context),
-            Context, Renaming, Goal, NumAdded, !VarSet, !ModuleInfo, !QualInfo,
-            !SInfo, !Specs),
+            TransformedExpr = not_expr(unify_expr(LHS, RHS, Purity) - Context),
+            transform_goal_2(TransformedExpr, Context, Renaming, Goal,
+                !:NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
         svar_finish_call(!VarSet, !SInfo)
     ;
         % check for a state var record assignment:
         % !Var ^ field := Value
         Name = unqualified(":="),
         Args1 = [LHS0, RHS0],
-        LHS0 = functor(atom("^"), [StateVar0, Remainder], FieldListContext),
+            LHS0 = functor(atom("^"), [StateVar0, Remainder],
+                FieldListContext),
         StateVar0 = functor(atom("!"), Args @ [variable(_, _)],
             StateVarContext)
     ->
         svar_prepare_for_call(!SInfo),
-        % !Var ^ field := Value is defined as !:Var = !.Var ^ field := Value.
+            % !Var ^ field := Value is defined as
+            % !:Var = !.Var ^ field := Value.
         LHS = functor(atom("!:"), Args, StateVarContext),
         StateVar = functor(atom("!."), Args, StateVarContext),
         FieldList = functor(atom("^"), [StateVar, Remainder],
                 FieldListContext),
         RHS = functor(atom(":="), [FieldList, RHS0], Context),
-        transform_goal_2(unify_expr(LHS, RHS, Purity),
-            Context, Renaming, Goal, NumAdded, !VarSet, !ModuleInfo, !QualInfo,
-            !SInfo, !Specs),
+            TransformedExpr = unify_expr(LHS, RHS, Purity),
+            transform_goal_2(TransformedExpr, Context, Renaming, Goal,
+                !:NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
         svar_finish_call(!VarSet, !SInfo)
     ;
         % check for a DCG field access goal:
@@ -997,8 +1022,8 @@
     ->
         svar_prepare_for_call(!SInfo),
         rename_vars_in_term_list(need_not_rename, Renaming, Args1, Args2),
-        transform_dcg_record_syntax(Operator, Args2, Context, Goal, NumAdded,
-            !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
+            transform_dcg_record_syntax(Operator, Args2, Context, Goal,
+                !:NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
         svar_finish_call(!VarSet, !SInfo)
     ;
         svar_prepare_for_call(!SInfo),
@@ -1017,7 +1042,8 @@
             Modes = [],
             Det = detism_erroneous,
 
-            GenericCall = higher_order(PredVar, Purity, pf_predicate, Arity),
+                GenericCall = higher_order(PredVar, Purity, pf_predicate,
+                    Arity),
             Call = generic_call(GenericCall, RealHeadVars, Modes, Det),
 
             hlds_goal.generic_call_id(GenericCall, CallId)
@@ -1029,7 +1055,8 @@
             MaybeUnifyContext = no,
             Call = plain_call(PredId, ModeId, HeadVars, not_builtin,
                 MaybeUnifyContext, Name),
-            CallId = plain_call_id(simple_call_id(pf_predicate, Name, Arity))
+                CallId =
+                    plain_call_id(simple_call_id(pf_predicate, Name, Arity))
         ),
         goal_info_init(Context, GoalInfo0),
         goal_info_set_purity(Purity, GoalInfo0, GoalInfo),
@@ -1037,12 +1064,12 @@
 
         record_called_pred_or_func(pf_predicate, Name, Arity, !QualInfo),
         insert_arg_unifications(HeadVars, Args, Context, ac_call(CallId),
-            Goal0, Goal, NumAdded, !VarSet, !ModuleInfo, !QualInfo,
+                Goal0, Goal, !:NumAdded, !VarSet, !ModuleInfo, !QualInfo,
             !SInfo, !Specs),
         svar_finish_call(!VarSet, !SInfo)
-    ).
-transform_goal_2(unify_expr(A0, B0, Purity), Context, Renaming, Goal,
-        NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs) :-
+        )
+    ;
+        Expr = unify_expr(A0, B0, Purity),
     rename_vars_in_term(need_not_rename, Renaming, A0, A),
     rename_vars_in_term(need_not_rename, Renaming, B0, B),
     % It is an error for the left or right hand side of a
@@ -1050,16 +1077,17 @@
     ( A = functor(atom("!"), [variable(StateVarA, _)], _) ->
         report_svar_unify_error(Context, !.VarSet, StateVarA, !Specs),
         Goal = true_goal,
-        NumAdded = 0
+            !:NumAdded = 0
     ; B = functor(atom("!"), [variable(StateVarB, _)], _) ->
         report_svar_unify_error(Context, !.VarSet, StateVarB, !Specs),
         Goal = true_goal,
-        NumAdded = 0
+            !:NumAdded = 0
     ;
         svar_prepare_for_call(!SInfo),
         unravel_unification(A, B, Context, umc_explicit, [], Purity, Goal,
-            NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
+                !:NumAdded, !VarSet, !ModuleInfo, !QualInfo, !SInfo, !Specs),
         svar_finish_call(!VarSet, !SInfo)
+        )
     ).
 
 :- pred extract_trace_mutable_var(prog_context::in, prog_varset::in,
Index: compiler/constraint.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/constraint.m,v
retrieving revision 1.95
diff -u -b -r1.95 constraint.m
--- compiler/constraint.m	15 Dec 2010 06:29:31 -0000	1.95
+++ compiler/constraint.m	27 Dec 2010 07:48:31 -0000
@@ -183,6 +183,12 @@
             FinalGoals = [hlds_goal(scope(Reason, SubGoal), GoalInfo) |
                 ConstraintGoals]
         ;
+            ( Reason = require_detism(_)
+            ; Reason = require_complete_switch(_)
+            ),
+            % These scopes should have been deleted by now.
+            unexpected($module, $pred, "unexpected scope")
+        ;
             Reason = from_ground_term(_, from_ground_term_construct),
             % There is no point in either propagating constraints into these
             % scopes or propagating local constraints within these scopes.
Index: compiler/det_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/det_analysis.m,v
retrieving revision 1.225
diff -u -b -r1.225 det_analysis.m
--- compiler/det_analysis.m	15 Dec 2010 06:29:33 -0000	1.225
+++ compiler/det_analysis.m	27 Dec 2010 08:21:47 -0000
@@ -1692,6 +1692,8 @@
     ;
         ( Reason = exist_quant(_)
         ; Reason = promise_purity(_)
+        ; Reason = require_detism(_)
+        ; Reason = require_complete_switch(_)
         ; Reason = commit(_)
         ; Reason = barrier(_)
         ),
Index: compiler/erl_code_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/erl_code_gen.m,v
retrieving revision 1.36
diff -u -b -r1.36 erl_code_gen.m
--- compiler/erl_code_gen.m	15 Dec 2010 06:29:34 -0000	1.36
+++ compiler/erl_code_gen.m	27 Dec 2010 04:57:33 -0000
@@ -616,61 +616,63 @@
     instmap::in, prog_context::in, maybe(elds_expr)::in,
     elds_expr::out, erl_gen_info::in, erl_gen_info::out) is det.
 
-erl_gen_goal_expr(switch(Var, CanFail, CasesList), CodeModel, _Detism,
-        InstMap, Context, MaybeSuccessExpr, Statement, !Info) :-
+erl_gen_goal_expr(GoalExpr, CodeModel, Detism, InstMap, Context,
+        MaybeSuccessExpr, Statement, !Info) :-
+    (
+        GoalExpr = switch(Var, CanFail, CasesList),
     erl_gen_switch(Var, CanFail, CasesList, CodeModel, InstMap,
-        Context, MaybeSuccessExpr, Statement, !Info).
-
-erl_gen_goal_expr(scope(ScopeReason, Goal), CodeModel, Detism, InstMap,
-        Context, MaybeSuccessExpr, Statement, !Info) :-
+            Context, MaybeSuccessExpr, Statement, !Info)
+    ;
+        GoalExpr = scope(Reason, SubGoal),
     (
-        ( ScopeReason = promise_solutions(_, _)
-        ; ScopeReason = commit(_)
+            ( Reason = promise_solutions(_, _)
+            ; Reason = commit(_)
         ),
-        erl_gen_commit(Goal, CodeModel, Detism, InstMap, Context,
+            erl_gen_commit(SubGoal, CodeModel, Detism, InstMap, Context,
             MaybeSuccessExpr, Statement, !Info)
     ;
-        ( ScopeReason = exist_quant(_)
-        ; ScopeReason = promise_purity(_)
-        ; ScopeReason = barrier(_)
-        ; ScopeReason = from_ground_term(_, _)
-        ; ScopeReason = trace_goal(_, _, _, _, _)
+            Reason = require_detism(_),
+            unexpected($module, $pred, "require_detism")
+        ;
+            Reason = require_complete_switch(_),
+            unexpected($module, $pred, "require_complete_switch")
+        ;
+            ( Reason = exist_quant(_)
+            ; Reason = promise_purity(_)
+            ; Reason = barrier(_)
+            ; Reason = from_ground_term(_, _)
+            ; Reason = trace_goal(_, _, _, _, _)
             % Trace goals with run-time conditions are transformed into
-            % if-then-else goals where the condition is a special foreign_proc
-            % call and the then branch is the actual trace goal (i.e. this
-            % goal).  Thus there is nothing special we have to do here.
-        ),
-        Goal = hlds_goal(GoalExpr, GoalInfo),
-        GoalDetism = goal_info_get_determinism(GoalInfo),
-        erl_gen_goal_expr(GoalExpr, CodeModel, GoalDetism, InstMap, Context,
-            MaybeSuccessExpr, Statement, !Info)
-    ).
-
-erl_gen_goal_expr(if_then_else(_Vars, Cond, Then, Else), CodeModel, _Detism,
-        InstMap, Context, MaybeSuccessExpr, Statement, !Info) :-
+                % if-then-else goals where the condition is a special
+                % foreign_proc call and the then branch is the actual
+                % trace goal (i.e. this goal). Thus there is nothing special
+                % we have to do here.
+            ),
+            SubGoal = hlds_goal(SubGoalExpr, SubGoalInfo),
+            SubGoalDetism = goal_info_get_determinism(SubGoalInfo),
+            erl_gen_goal_expr(SubGoalExpr, CodeModel, SubGoalDetism,
+                InstMap, Context, MaybeSuccessExpr, Statement, !Info)
+        )
+    ;
+        GoalExpr = if_then_else(_Vars, Cond, Then, Else),
     erl_gen_ite(CodeModel, InstMap, Cond, Then, Else, Context,
-        MaybeSuccessExpr, Statement, !Info).
-
-erl_gen_goal_expr(negation(Goal), CodeModel, _Detism, InstMap, Context,
-        MaybeSuccessExpr, Statement, !Info) :-
-    erl_gen_negation(Goal, CodeModel, InstMap, Context, MaybeSuccessExpr,
-        Statement, !Info).
-
-erl_gen_goal_expr(conj(_ConjType, Goals), CodeModel, Detism, InstMap, Context,
-        MaybeSuccessExpr, Statement, !Info) :-
+            MaybeSuccessExpr, Statement, !Info)
+    ;
+        GoalExpr = negation(SubGoal),
+        erl_gen_negation(SubGoal, CodeModel, InstMap, Context, MaybeSuccessExpr,
+            Statement, !Info)
+    ;
+        GoalExpr = conj(_ConjType, Goals),
     % XXX Currently we treat parallel conjunction the same as
     % sequential conjunction -- parallelism is not yet implemented.
-    erl_gen_conj(Goals, CodeModel, Detism, InstMap, Context, MaybeSuccessExpr,
-        Statement, !Info).
-
-erl_gen_goal_expr(disj(Goals), CodeModel, _Detism, InstMap, Context,
-        MaybeSuccessExpr, Statement, !Info) :-
+        erl_gen_conj(Goals, CodeModel, Detism, InstMap, Context,
+            MaybeSuccessExpr, Statement, !Info)
+    ;
+        GoalExpr = disj(Goals),
     erl_gen_disj(Goals, CodeModel, InstMap, Context, MaybeSuccessExpr,
-        Statement, !Info).
-
-erl_gen_goal_expr(generic_call(GenericCall, Vars, Modes, CallDetism),
-        CodeModel, _Detism, _InstMap, Context, MaybeSuccessExpr, Statement,
-        !Info) :-
+            Statement, !Info)
+    ;
+        GoalExpr = generic_call(GenericCall, Vars, Modes, CallDetism),
     determinism_to_code_model(CallDetism, CallCodeModel),
     expect(unify(CodeModel, CallCodeModel), this_file,
         "erl_gen_generic_call: code model mismatch"),
@@ -688,11 +690,9 @@
     ;
         GenericCall = cast(_),
         erl_gen_cast(Context, Vars, MaybeSuccessExpr, Statement, !Info)
-    ).
-
-erl_gen_goal_expr(plain_call(PredId, ProcId, ArgVars, BuiltinState, _, _),
-        CodeModel, _Detism, _InstMap, Context, MaybeSuccessExpr, Statement,
-        !Info) :-
+        )
+    ;
+        GoalExpr = plain_call(PredId, ProcId, ArgVars, BuiltinState, _, _),
     (
         BuiltinState = not_builtin,
         erl_variable_types(!.Info, ArgVars, ActualArgTypes),
@@ -705,28 +705,25 @@
     ;
         BuiltinState = out_of_line_builtin,
         unexpected(this_file, "erl_gen_goal_expr: out_of_line_builtin")
-    ).
-
-erl_gen_goal_expr(unify(_LHS, _RHS, _Mode, Unification, _UnifyContext),
-        CodeModel, _Detism, _InstMap, Context, MaybeSuccessExpr, Statement,
-        !Info) :-
+        )
+    ;
+        GoalExpr = unify(_LHS, _RHS, _Mode, Unification, _UnifyContext),
     erl_gen_unification(Unification, CodeModel, Context, MaybeSuccessExpr,
-        Statement, !Info).
-
-erl_gen_goal_expr(
-        call_foreign_proc(_Attributes, _PredId, _ProcId, Args, _ExtraArgs,
-            MaybeTraceRuntimeCond, PragmaImpl), CodeModel, _Detism, _InstMap,
-        OuterContext, MaybeSuccessExpr, Statement, !Info) :-
+            Statement, !Info)
+    ;
+        GoalExpr = call_foreign_proc(_Attributes, _PredId, _ProcId,
+            Args, _ExtraArgs, MaybeTraceRuntimeCond, PragmaImpl),
     erl_gen_foreign_code_call(Args, MaybeTraceRuntimeCond, PragmaImpl,
-        CodeModel, OuterContext, MaybeSuccessExpr, Statement, !Info).
-
-erl_gen_goal_expr(shorthand(_), _, _, _, _, _, _, !Info) :-
+            CodeModel, Context, MaybeSuccessExpr, Statement, !Info)
+    ;
+        GoalExpr = shorthand(_),
     % These should have been expanded out by now.
-    unexpected(this_file, "erl_gen_goal_expr: unexpected shorthand").
+        unexpected(this_file, "erl_gen_goal_expr: unexpected shorthand")
+    ).
 
 %-----------------------------------------------------------------------------%
 %
-% Code for switches
+% Code for switches.
 %
 
 :- func duplicate_expr_limit = int.
@@ -938,7 +935,9 @@
     ELDSCase = elds_case(elds_atom_raw(String), Statement).
 
 %-----------------------------------------------------------------------------%
+%
 % This code is shared by disjunctions and switches.
+%
 
 :- pred union_bound_nonlocals_in_goals(erl_gen_info::in, instmap::in,
     hlds_goals::in, set(prog_var)::out) is det.
@@ -1010,7 +1009,7 @@
 
 %-----------------------------------------------------------------------------%
 %
-% Code for if-then-else
+% Code for if-then-elses.
 %
 
 :- pred erl_gen_ite(code_model::in, instmap::in,
@@ -1165,7 +1164,7 @@
 
 %-----------------------------------------------------------------------------%
 %
-% Code for negation
+% Code for negation.
 %
 
 :- pred erl_gen_negation(hlds_goal::in, code_model::in, instmap::in,
@@ -1232,7 +1231,7 @@
 
 %-----------------------------------------------------------------------------%
 %
-% Code for conjunctions
+% Code for conjunctions.
 %
 
 :- pred erl_gen_conj(hlds_goals::in, code_model::in, determinism::in,
@@ -1368,7 +1367,7 @@
 
 %-----------------------------------------------------------------------------%
 %
-% Code for disjunctions
+% Code for disjunctions.
 %
 
 :- pred erl_gen_disj(hlds_goals::in, code_model::in, instmap::in,
@@ -1554,7 +1553,7 @@
 
 %-----------------------------------------------------------------------------%
 %
-% Code for generating foreign exported procedures
+% Code for generating foreign exported procedures.
 %
 
 :- pred erl_gen_foreign_exports(list(elds_defn)::in,
@@ -1571,9 +1570,7 @@
 erl_gen_foreign_export_defn(ProcDefns, PragmaExport, ForeignExportDefn) :-
     PragmaExport = pragma_exported_proc(_Lang, PredId, ProcId, Name, _Context),
     PredProcId = proc(PredId, ProcId),
-    ( 
-        search_elds_defn(ProcDefns, PredProcId, TargetProc)
-    ->
+    ( search_elds_defn(ProcDefns, PredProcId, TargetProc) ->
         TargetProc = elds_defn(_TargetPPId, _TargetVarSet, TargetBody,
             _EnvVarNames),
         Arity = elds_body_arity(TargetBody),
Index: compiler/error_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/error_util.m,v
retrieving revision 1.75
diff -u -b -r1.75 error_util.m
--- compiler/error_util.m	23 Aug 2010 07:38:28 -0000	1.75
+++ compiler/error_util.m	28 Dec 2010 07:08:36 -0000
@@ -270,72 +270,69 @@
 %-----------------------------------------------------------------------------%
 
 :- type format_component
-    --->    fixed(string)   % This string should appear in the output
-                            % in one piece, as it is.
+    --->    fixed(string)
+            % This string should appear in the output in one piece, as it is.
 
-    ;       quote(string)   % Surround the string with `' quotes, then treat
-                            % as fixed.
+    ;       quote(string)
+            % Surround the string with `' quotes, then treat as fixed.
 
-    ;       int_fixed(int)  % Convert the integer to a string, then treat
-                            % as fixed.
+    ;       int_fixed(int)
+            % Convert the integer to a string, then treat as fixed.
 
-    ;       nth_fixed(int)  % Convert the integer to a string, such as
-                            % "first", "second", "third", "4th", "5th" and
-                            % then treat as fixed.
-                            %
+    ;       nth_fixed(int)
+            % Convert the integer to a string, such as "first", "second",
+            % "third", "4th", "5th" and then treat as fixed.
 
     ;       lower_case_next_if_not_first
-                            % If this is the first component, ignore it.
-                            % If this is not the first component, lower case
-                            % the initial letter of the next component.
-                            % There is no effect if the next component
-                            % starts does not exist or does not start with
-                            % an upper case letter.
-
-    ;       prefix(string)  % This string should appear in the output
-                            % in one piece, as it is, inserted directly
-                            % before the next format_component, without
+            % If this is the first component, ignore it. If this is not
+            % the first component, lower case the initial letter of the
+            % next component. There is no effect if the next component
+            % does not exist or does not start with an upper case letter.
+
+    ;       prefix(string)
+            % This string should appear in the output in one piece, as it is,
+            % inserted directly before the next format_component, without
                             % any intervening space.
 
-    ;       suffix(string)  % This string should appear in the output
-                            % in one piece, as it is, appended directly
-                            % after the previous format_component, without
+    ;       suffix(string)
+            % This string should appear in the output in one piece, as it is,
+            % appended directly after the previous format_component, without
                             % any intervening space.
 
-    ;       words(string)   % This string contains words separated by
-                            % white space. The words should appear in
-                            % the output in the given order, but the
-                            % white space may be rearranged and line
-                            % breaks may be inserted.
+    ;       words(string)
+            % This string contains words separated by white space. The words
+            % should appear in the output in the given order, but the white
+            % space may be rearranged and line breaks may be inserted.
+
+    ;       words_quote(string)
+            % Surround the string with `' quotes, then treat as words.
 
     ;       sym_name(sym_name)
-                            % The output should contain the string form of
-                            % the sym_name, surrounded by `' quotes.
+            % The output should contain the string form of the sym_name,
+            % surrounded by `' quotes.
 
     ;       sym_name_and_arity(sym_name_and_arity)
-                            % The output should contain the string form of
-                            % the sym_name, followed by '/' and the arity,
-                            % all surrounded by `' quotes.
+            % The output should contain the string form of the sym_name,
+            % followed by '/' and the arity, all surrounded by `' quotes.
 
     ;       top_ctor_of_type(mer_type)
                             % The top level type constructor of the given type,
-                            % which must have one (i.e. must not be a
-                            % variable).
+            % which must have one (i.e. must not be a variable).
 
     ;       p_or_f(pred_or_func)
-                            % Output the string "predicate" or "function"
-                            % as appropriate.
+            % Output the string "predicate" or "function" as appropriate.
 
     ;       simple_call(simple_call_id)
                             % Output the identity of the given call.
 
-    ;       nl              % Insert a line break if there has been text
-                            % output since the last line break.
+    ;       nl
+            % Insert a line break if there has been text output since
+            % the last line break.
 
     ;       nl_indent_delta(int)
-                            % Act as nl, but also add the given integer
-                            % (which should be a small positive or negative
-                            % integer) to the current indent level.
+            % Act as nl, but also add the given integer (which should be a
+            % small positive or negative integer) to the current indent level.
+
     ;       blank_line.
                             % Create a blank line.
 
@@ -1021,6 +1018,12 @@
 error_pieces_to_string_2(FirstInMsg, [Component | Components]) = Str :-
     TailStr = error_pieces_to_string_2(not_first_in_msg, Components),
     (
+        Component = words(Words),
+        Str = join_string_and_tail(Words, Components, TailStr)
+    ;
+        Component = words_quote(Words),
+        Str = join_string_and_tail(add_quotes(Words), Components, TailStr)
+    ;
         Component = fixed(Word),
         Str = join_string_and_tail(Word, Components, TailStr)
     ;
@@ -1048,9 +1051,6 @@
         Component = suffix(Suffix),
         Str = join_string_and_tail(Suffix, Components, TailStr)
     ;
-        Component = words(Words),
-        Str = join_string_and_tail(Words, Components, TailStr)
-    ;
         Component = sym_name(SymName),
         Word = sym_name_to_word(SymName),
         Str = join_string_and_tail(Word, Components, TailStr)
@@ -1148,6 +1148,12 @@
 convert_components_to_paragraphs_acc(FirstInMsg, [Component | Components],
         RevWords0, !Paras) :-
     (
+        Component = words(WordsStr),
+        break_into_words(WordsStr, RevWords0, RevWords1)
+    ;
+        Component = words_quote(WordsStr),
+        break_into_words(add_quotes(WordsStr), RevWords0, RevWords1)
+    ;
         Component = fixed(Word),
         RevWords1 = [plain_word(Word) | RevWords0]
     ;
@@ -1175,9 +1181,6 @@
         Component = suffix(Word),
         RevWords1 = [suffix_word(Word) | RevWords0]
     ;
-        Component = words(WordsStr),
-        break_into_words(WordsStr, RevWords0, RevWords1)
-    ;
         Component = sym_name(SymName),
         RevWords1 = [plain_word(sym_name_to_word(SymName)) | RevWords0]
     ;
Index: compiler/goal_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/goal_util.m,v
retrieving revision 1.176
diff -u -b -r1.176 goal_util.m
--- compiler/goal_util.m	20 Dec 2010 07:47:30 -0000	1.176
+++ compiler/goal_util.m	27 Dec 2010 04:57:33 -0000
@@ -591,19 +591,21 @@
             Reason = exist_quant(Vars),
             svset.insert_list(Vars, !Set)
         ;
-            Reason = promise_purity(_)
-        ;
             Reason = promise_solutions(Vars, _),
             svset.insert_list(Vars, !Set)
         ;
-            Reason = barrier(_)
-        ;
-            Reason = commit(_)
-        ;
             Reason = from_ground_term(Var, _),
             set.insert(!.Set, Var, !:Set)
         ;
-            Reason = trace_goal(_, _, _, _, _)
+            Reason = require_complete_switch(Var),
+            set.insert(!.Set, Var, !:Set)
+        ;
+            ( Reason = promise_purity(_)
+            ; Reason = require_detism(_)
+            ; Reason = commit(_)
+            ; Reason = barrier(_)
+            ; Reason = trace_goal(_, _, _, _, _)
+            )
         ),
         goal_vars_2(SubGoal, !Set)
     ;
Index: compiler/hlds_desc.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_desc.m,v
retrieving revision 1.5
diff -u -b -r1.5 hlds_desc.m
--- compiler/hlds_desc.m	4 Nov 2009 03:44:47 -0000	1.5
+++ compiler/hlds_desc.m	27 Dec 2010 04:57:33 -0000
@@ -140,6 +140,12 @@
             Reason = promise_purity(_),
             Desc = "scope promise purity"
         ;
+            Reason = require_detism(_),
+            Desc = "scope require detism"
+        ;
+            Reason = require_complete_switch(_),
+            Desc = "scope require complete switch"
+        ;
             Reason = commit(_),
             Desc = "scope commit"
         ;
Index: compiler/hlds_goal.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_goal.m,v
retrieving revision 1.218
diff -u -b -r1.218 hlds_goal.m
--- compiler/hlds_goal.m	20 Dec 2010 07:47:31 -0000	1.218
+++ compiler/hlds_goal.m	28 Dec 2010 03:25:16 -0000
@@ -467,6 +467,19 @@
             % pragma, except that it applies to arbitrary goals and not
             % just whole procedure bodies.
 
+    ;       require_detism(determinism)
+            % Require the wrapped subgoal to have the specified determinism.
+            % If it does not, report an error.
+            % This scope reason should not exist after the first invocation
+            % of simplification.
+
+    ;       require_complete_switch(prog_var)
+            % If the wrapped subgoal is a switch on the given variable,
+            % require it have arms for every function symbol in the type
+            % of that variable. If it does not, report an error.
+            % This scope reason should not exist after the first invocation
+            % of simplification.
+
     ;       commit(force_pruning)
             % This scope exists to delimit a piece of code
             % with at_most_many components but with no outputs,
@@ -2497,6 +2510,13 @@
             rename_var_list(Must, Subn, Vars0, Vars),
             Reason = promise_solutions(Vars, Kind)
         ;
+            Reason0 = require_complete_switch(Var0),
+            rename_var(Must, Subn, Var0, Var),
+            Reason = require_complete_switch(Var)
+        ;
+            Reason0 = require_detism(_),
+            Reason = Reason0
+        ;
             Reason0 = barrier(_),
             Reason = Reason0
         ;
Index: compiler/hlds_out_goal.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_out_goal.m,v
retrieving revision 1.3
diff -u -b -r1.3 hlds_out_goal.m
--- compiler/hlds_out_goal.m	20 Dec 2010 07:47:31 -0000	1.3
+++ compiler/hlds_out_goal.m	27 Dec 2010 07:38:29 -0000
@@ -1836,6 +1836,39 @@
         mercury_output_vars(VarSet, AppendVarNums, Vars, !IO),
         io.write_string("] (\n", !IO)
     ;
+        Reason = require_complete_switch(Var),
+        io.write_string("require_complete_switch [", !IO),
+        mercury_output_var(VarSet, AppendVarNums, Var, !IO),
+        io.write_string("] (\n", !IO)
+    ;
+        Reason = require_detism(Detism),
+        (
+            Detism = detism_det,
+            io.write_string("require_det", !IO)
+        ;
+            Detism = detism_semi,
+            io.write_string("require_semidet", !IO)
+        ;
+            Detism = detism_non,
+            io.write_string("require_nondet", !IO)
+        ;
+            Detism = detism_multi,
+            io.write_string("require_multi", !IO)
+        ;
+            Detism = detism_cc_multi,
+            io.write_string("require_cc_multi", !IO)
+        ;
+            Detism = detism_cc_non,
+            io.write_string("require_cc_nondet", !IO)
+        ;
+            Detism = detism_failure,
+            io.write_string("require_failure", !IO)
+        ;
+            Detism = detism_erroneous,
+            io.write_string("require_erroneous", !IO)
+        ),
+        io.write_string(" (\n", !IO)
+    ;
         Reason = barrier(removable),
         io.write_string("(\n", !IO),
         write_indent(Indent, !IO),
Index: compiler/interval.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/interval.m,v
retrieving revision 1.44
diff -u -b -r1.44 interval.m
--- compiler/interval.m	20 Dec 2010 07:47:32 -0000	1.44
+++ compiler/interval.m	27 Dec 2010 04:57:34 -0000
@@ -959,6 +959,8 @@
         ;
             ( Reason0 = promise_purity(_)
             ; Reason0 = promise_solutions(_, _)
+            ; Reason0 = require_detism(_)
+            ; Reason0 = require_complete_switch(_)
             ; Reason0 = commit(_)
             ; Reason0 = barrier(_)
             ; Reason0 = trace_goal(_, _, _, _, _)
Index: compiler/lambda.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/lambda.m,v
retrieving revision 1.146
diff -u -b -r1.146 lambda.m
--- compiler/lambda.m	15 Dec 2010 06:29:40 -0000	1.146
+++ compiler/lambda.m	27 Dec 2010 07:50:02 -0000
@@ -740,19 +740,24 @@
             Reason = exist_quant(Vars),
             mark_vars_as_used(Vars, !VarUses)
         ;
-            Reason = promise_purity(_)
-        ;
             Reason = promise_solutions(Vars, _),
             mark_vars_as_used(Vars, !VarUses)
         ;
-            Reason = barrier(_)
-        ;
-            Reason = commit(_)
-        ;
             Reason = from_ground_term(Var, _),
             mark_var_as_used(Var, !VarUses)
         ;
-            Reason = trace_goal(_, _, _, _, _)
+            ( Reason = promise_purity(_)
+            ; Reason = barrier(_)
+            ; Reason = commit(_)
+            ; Reason = trace_goal(_, _, _, _, _)
+            )
+            % Do nothing.
+        ;
+            ( Reason = require_detism(_)
+            ; Reason = require_complete_switch(_)
+            ),
+            % These scopes should have been deleted by now.
+            unexpected($module, $pred, "unexpected scope")
         ),
         find_used_vars_in_goal(SubGoal, !VarUses)
     ;
Index: compiler/make_hlds_warn.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make_hlds_warn.m,v
retrieving revision 1.37
diff -u -b -r1.37 make_hlds_warn.m
--- compiler/make_hlds_warn.m	10 Sep 2010 05:14:58 -0000	1.37
+++ compiler/make_hlds_warn.m	27 Dec 2010 07:41:11 -0000
@@ -164,6 +164,8 @@
                 ModuleInfo, !Specs)
         ;
             ( Reason = promise_purity(_)
+            ; Reason = require_detism(_)
+            ; Reason = require_complete_switch(_)
             ; Reason = commit(_)
             ; Reason = barrier(_)
             ; Reason = trace_goal(_, _, _, _, _)
Index: compiler/mercury_to_mercury.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mercury_to_mercury.m,v
retrieving revision 1.344
diff -u -b -r1.344 mercury_to_mercury.m
--- compiler/mercury_to_mercury.m	15 Dec 2010 06:29:45 -0000	1.344
+++ compiler/mercury_to_mercury.m	27 Dec 2010 11:40:10 -0000
@@ -2832,13 +2832,15 @@
 :- pred mercury_output_goal_2(goal_expr::in, prog_varset::in, int::in,
     io::di, io::uo) is det.
 
-mercury_output_goal_2(fail_expr, _, _, !IO) :-
-    io.write_string("fail", !IO).
-
-mercury_output_goal_2(true_expr, _, _, !IO) :-
-    io.write_string("true", !IO).
-
-mercury_output_goal_2(implies_expr(G1,G2), VarSet, Indent, !IO) :-
+mercury_output_goal_2(Expr, VarSet, Indent, !IO) :-
+    (
+        Expr = fail_expr,
+        io.write_string("fail", !IO)
+    ;
+        Expr = true_expr,
+        io.write_string("true", !IO)
+    ;
+        Expr = implies_expr(G1, G2),
     Indent1 = Indent + 1,
     io.write_string("(", !IO),
     mercury_output_newline(Indent1, !IO),
@@ -2848,9 +2850,9 @@
     mercury_output_newline(Indent1, !IO),
     mercury_output_goal(G2, VarSet, Indent1, !IO),
     mercury_output_newline(Indent, !IO),
-    io.write_string(")", !IO).
-
-mercury_output_goal_2(equivalent_expr(G1,G2), VarSet, Indent, !IO) :-
+        io.write_string(")", !IO)
+    ;
+        Expr = equivalent_expr(G1, G2),
     Indent1 = Indent + 1,
     io.write_string("(", !IO),
     mercury_output_newline(Indent1, !IO),
@@ -2860,9 +2862,9 @@
     mercury_output_newline(Indent1, !IO),
     mercury_output_goal(G2, VarSet, Indent1, !IO),
     mercury_output_newline(Indent, !IO),
-    io.write_string(")", !IO).
-
-mercury_output_goal_2(some_expr(Vars, Goal), VarSet, Indent, !IO) :-
+        io.write_string(")", !IO)
+    ;
+        Expr = some_expr(Vars, Goal),
     (
         Vars = [],
         mercury_output_goal(Goal, VarSet, Indent, !IO)
@@ -2876,9 +2878,9 @@
         mercury_output_goal(Goal, VarSet, Indent1, !IO),
         mercury_output_newline(Indent, !IO),
         io.write_string(")", !IO)
-    ).
-
-mercury_output_goal_2(some_state_vars_expr(Vars, Goal), VarSet, Indent, !IO) :-
+        )
+    ;
+        Expr = some_state_vars_expr(Vars, Goal),
     (
         Vars = [],
         mercury_output_goal(Goal, VarSet, Indent, !IO)
@@ -2892,9 +2894,9 @@
         mercury_output_goal(Goal, VarSet, Indent1, !IO),
         mercury_output_newline(Indent, !IO),
         io.write_string(")", !IO)
-    ).
-
-mercury_output_goal_2(all_expr(Vars, Goal), VarSet, Indent, !IO) :-
+        )
+    ;
+        Expr = all_expr(Vars, Goal),
     (
         Vars = [],
         mercury_output_goal(Goal, VarSet, Indent, !IO)
@@ -2908,9 +2910,9 @@
         mercury_output_goal(Goal, VarSet, Indent1, !IO),
         mercury_output_newline(Indent, !IO),
         io.write_string(")", !IO)
-    ).
-
-mercury_output_goal_2(all_state_vars_expr(Vars, Goal), VarSet, Indent, !IO) :-
+        )
+    ;
+        Expr = all_state_vars_expr(Vars, Goal),
     (
         Vars = [],
         mercury_output_goal(Goal, VarSet, Indent, !IO)
@@ -2924,30 +2926,24 @@
         mercury_output_goal(Goal, VarSet, Indent1, !IO),
         mercury_output_newline(Indent, !IO),
         io.write_string(")", !IO)
-    ).
-
-mercury_output_goal_2(
-        promise_equivalent_solutions_expr(Vars, DotSVars, ColonSVars, Goal),
-        VarSet, Indent, !IO) :-
+        )
+    ;
+        Expr = promise_equivalent_solutions_expr(Vars,
+            DotSVars, ColonSVars, Goal),
     mercury_output_promise_eqv_solutions_goal(Vars, DotSVars, ColonSVars,
-        Goal, VarSet, Indent, "promise_equivalent_solutions", !IO).
-
-mercury_output_goal_2(
-        promise_equivalent_solution_sets_expr(Vars, DotSVars, ColonSVars,
-            Goal),
-        VarSet, Indent, !IO) :-
+            Goal, VarSet, Indent, "promise_equivalent_solutions", !IO)
+    ;
+        Expr = promise_equivalent_solution_sets_expr(Vars,
+            DotSVars, ColonSVars, Goal),
     mercury_output_promise_eqv_solutions_goal(Vars, DotSVars, ColonSVars,
-        Goal, VarSet, Indent, "promise_equivalent_solution_sets", !IO).
-
-mercury_output_goal_2(
-        promise_equivalent_solution_arbitrary_expr(Vars, DotSVars, ColonSVars,
-            Goal),
-        VarSet, Indent, !IO) :-
+            Goal, VarSet, Indent, "promise_equivalent_solution_sets", !IO)
+    ;   
+        Expr = promise_equivalent_solution_arbitrary_expr(Vars,
+            DotSVars, ColonSVars, Goal),
     mercury_output_promise_eqv_solutions_goal(Vars, DotSVars, ColonSVars,
-        Goal, VarSet, Indent, "arbitrary", !IO).
-
-mercury_output_goal_2(promise_purity_expr(Purity, Goal), VarSet,
-        Indent, !IO) :-
+            Goal, VarSet, Indent, "arbitrary", !IO)
+    ;
+        Expr = promise_purity_expr(Purity, Goal),
     (
         Purity = purity_pure,
         io.write_string("promise_pure (", !IO)
@@ -2962,10 +2958,52 @@
     mercury_output_newline(Indent1, !IO),
     mercury_output_goal(Goal, VarSet, Indent1, !IO),
     mercury_output_newline(Indent, !IO),
-    io.write_string(")", !IO).
-
-mercury_output_goal_2(atomic_expr(Outer, Inner, _, MainExpr,
-        OrElseExprs), VarSet, Indent, !IO) :-
+        io.write_string(")", !IO)
+    ;
+        Expr = require_detism_expr(Detism, Goal),
+        (
+            Detism = detism_det,
+            io.write_string("require_det", !IO)
+        ;
+            Detism = detism_semi,
+            io.write_string("require_semidet", !IO)
+        ;
+            Detism = detism_multi,
+            io.write_string("require_multi", !IO)
+        ;
+            Detism = detism_non,
+            io.write_string("require_nondet", !IO)
+        ;
+            Detism = detism_cc_multi,
+            io.write_string("require_cc_multi", !IO)
+        ;
+            Detism = detism_cc_non,
+            io.write_string("require_cc_nondet", !IO)
+        ;
+            Detism = detism_erroneous,
+            io.write_string("require_erroneous", !IO)
+        ;
+            Detism = detism_failure,
+            io.write_string("require_failure", !IO)
+        ),
+        io.write_string(" (", !IO),
+        Indent1 = Indent + 1,
+        mercury_output_newline(Indent1, !IO),
+        mercury_output_goal(Goal, VarSet, Indent1, !IO),
+        mercury_output_newline(Indent, !IO),
+        io.write_string(")", !IO)
+    ;
+        Expr = require_complete_switch_expr(Var, Goal),
+        io.write_string("require_complete_switch [", !IO),
+        mercury_output_var(VarSet, no, Var, !IO),
+        io.write_string("] (", !IO),
+        Indent1 = Indent + 1,
+        mercury_output_newline(Indent1, !IO),
+        mercury_output_goal(Goal, VarSet, Indent1, !IO),
+        mercury_output_newline(Indent, !IO),
+        io.write_string(")", !IO)
+    ;
+        Expr = atomic_expr(Outer, Inner, _, MainExpr, OrElseExprs),
     io.write_string("atomic [outer(", !IO),
     (
         Outer = atomic_state_var(OVar),
@@ -2995,9 +3033,8 @@
     mercury_output_orelse_goals([MainExpr | OrElseExprs], VarSet, Indent1,
         !IO),
     mercury_output_newline(Indent, !IO),
-    io.write_string(")", !IO).
-
-mercury_output_goal_2(Expr, VarSet, Indent, !IO) :-
+        io.write_string(")", !IO)
+    ;
     Expr = trace_expr(MaybeCompileTime, MaybeRunTime, MaybeIO, MutableVars,
         Goal),
     mercury_output_newline(Indent, !IO),
@@ -3038,10 +3075,10 @@
     mercury_output_newline(Indent + 1, !IO),
     mercury_output_goal(Goal, VarSet, Indent + 1, !IO),
     mercury_output_newline(Indent, !IO),
-    io.write_string(")", !IO).
-
-mercury_output_goal_2(Expr, VarSet, Indent, !IO) :-
-    Expr = try_expr(MaybeIO, Goal, Then, MaybeElse, Catches, MaybeCatchAny),
+        io.write_string(")", !IO)
+    ;
+        Expr = try_expr(MaybeIO, Goal, Then, MaybeElse, Catches,
+            MaybeCatchAny),
     io.write_string("(try [", !IO),
     (
         MaybeIO = yes(IOStateVar),
@@ -3082,10 +3119,9 @@
         MaybeCatchAny = no
     ),
     mercury_output_newline(Indent, !IO),
-    io.write_string(")", !IO).
-
-mercury_output_goal_2(if_then_else_expr(Vars, StateVars, Cond, Then, Else),
-        VarSet, Indent, !IO) :-
+        io.write_string(")", !IO)
+    ;
+        Expr = if_then_else_expr(Vars, StateVars, Cond, Then, Else),
     io.write_string("(if", !IO),
     mercury_output_some(Vars, StateVars, VarSet, !IO),
     Indent1 = Indent + 1,
@@ -3100,53 +3136,54 @@
     mercury_output_newline(Indent1, !IO),
     mercury_output_goal(Else, VarSet, Indent1, !IO),
     mercury_output_newline(Indent, !IO),
-    io.write_string(")", !IO).
-
-mercury_output_goal_2(not_expr(Goal), VarSet, Indent, !IO) :-
+        io.write_string(")", !IO)
+    ;
+        Expr = not_expr(Goal),
     io.write_string("\\+ (", !IO),
     Indent1 = Indent + 1,
     mercury_output_newline(Indent1, !IO),
     mercury_output_goal(Goal, VarSet, Indent1, !IO),
     mercury_output_newline(Indent, !IO),
-    io.write_string(")", !IO).
-
-mercury_output_goal_2(conj_expr(A, B), VarSet, Indent, !IO) :-
+        io.write_string(")", !IO)
+    ;
+        Expr = conj_expr(A, B),
     mercury_output_goal(A, VarSet, Indent, !IO),
     io.write_string(",", !IO),
     mercury_output_newline(Indent, !IO),
-    mercury_output_goal(B, VarSet, Indent, !IO).
-
-mercury_output_goal_2(par_conj_expr(A, B), VarSet, Indent, !IO) :-
+        mercury_output_goal(B, VarSet, Indent, !IO)
+    ;
+        Expr = par_conj_expr(A, B),
     io.write_string("(", !IO),
     Indent1 = Indent + 1,
     mercury_output_newline(Indent1, !IO),
     mercury_output_goal(A, VarSet, Indent1, !IO),
     mercury_output_par_conj(B, VarSet, Indent, !IO),
     mercury_output_newline(Indent, !IO),
-    io.write_string(")", !IO).
-
-mercury_output_goal_2(disj_expr(A, B), VarSet, Indent, !IO) :-
+        io.write_string(")", !IO)
+    ;
+        Expr = disj_expr(A, B),
     io.write_string("(", !IO),
     Indent1 = Indent + 1,
     mercury_output_newline(Indent1, !IO),
     mercury_output_goal(A, VarSet, Indent1, !IO),
     mercury_output_disj(B, VarSet, Indent, !IO),
     mercury_output_newline(Indent, !IO),
-    io.write_string(")", !IO).
-
-mercury_output_goal_2(event_expr(Name, Terms), VarSet, Indent, !IO) :-
+        io.write_string(")", !IO)
+    ;
+        Expr = event_expr(Name, Terms),
     io.write_string("event ", !IO),
-    mercury_output_call(unqualified(Name), Terms, VarSet, Indent, !IO).
-
-mercury_output_goal_2(call_expr(Name, Terms, Purity), VarSet, Indent, !IO) :-
+        mercury_output_call(unqualified(Name), Terms, VarSet, Indent, !IO)
+    ;
+        Expr = call_expr(Name, Terms, Purity),
     write_purity_prefix(Purity, !IO),
-    mercury_output_call(Name, Terms, VarSet, Indent, !IO).
-
-mercury_output_goal_2(unify_expr(A, B, Purity), VarSet, _Indent, !IO) :-
+        mercury_output_call(Name, Terms, VarSet, Indent, !IO)
+    ;   
+        Expr = unify_expr(A, B, Purity),
     write_purity_prefix(Purity, !IO),
     mercury_output_term(VarSet, no, A, !IO),
     io.write_string(" = ", !IO),
-    mercury_output_term_nq(VarSet, no, next_to_graphic_token, B, !IO).
+        mercury_output_term_nq(VarSet, no, next_to_graphic_token, B, !IO)
+    ).
 
 :- pred mercury_output_promise_eqv_solutions_goal(prog_vars::in,
     prog_vars::in, prog_vars::in, goal::in, prog_varset::in, int::in,
Index: compiler/mode_errors.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_errors.m,v
retrieving revision 1.132
diff -u -b -r1.132 mode_errors.m
--- compiler/mode_errors.m	15 Dec 2010 06:29:50 -0000	1.132
+++ compiler/mode_errors.m	28 Dec 2010 01:52:13 -0000
@@ -560,8 +560,7 @@
 merge_error_to_pieces(ModeInfo, MergeError) = Pieces :-
     MergeError = merge_error(Var, Insts),
     mode_info_get_varset(ModeInfo, VarSet),
-    Pieces = [words(add_quotes(mercury_var_to_string(VarSet, no, Var))),
-        fixed("::"),
+    Pieces = [quote(mercury_var_to_string(VarSet, no, Var)), fixed("::"),
         words(inst_list_to_string(ModeInfo, Insts)), suffix("."), nl].
 
 :- func merge_context_to_string(merge_context) = string.
@@ -604,12 +603,11 @@
             " inside more than one parallel conjunct."
     ),
     MainPieces = [words("scope error:"), words(ReasonStr), nl,
-        words("Variable"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, Var))),
+        words("Variable"), quote(mercury_var_to_string(VarSet, no, Var)),
         words("has instantiatedness"),
-        words(add_quotes(inst_to_string(ModeInfo, VarInst))), suffix(","), nl,
+        words_quote(inst_to_string(ModeInfo, VarInst)), suffix(","), nl,
         words("expected instantiatedness was"),
-        words(add_quotes(inst_to_string(ModeInfo, Inst))), suffix("."), nl],
+        words_quote(inst_to_string(ModeInfo, Inst)), suffix("."), nl],
     (
         Reason = var_lock_negation,
         VerbosePieces =
@@ -660,9 +658,9 @@
     mode_info_get_context(ModeInfo, Context),
     mode_info_get_varset(ModeInfo, VarSet),
     Pieces = [words("mode error: variable"),
-        fixed(add_quotes(mercury_var_to_string(VarSet, no, Var))),
+        quote(mercury_var_to_string(VarSet, no, Var)),
         words("has instantiatedness"),
-        words(add_quotes(inst_to_string(ModeInfo, VarInst))),
+        words_quote(inst_to_string(ModeInfo, VarInst)),
         suffix(","), nl,
         words("expected instantiatedness for non-local variables"),
         words("of lambda goals is `ground'."), nl],
@@ -681,7 +679,7 @@
     mode_info_get_context(!.ModeInfo, Context),
     mode_info_get_varset(!.ModeInfo, VarSet),
     MainPieces = [words("mode error: arguments"),
-        words(add_quotes(mercury_vars_to_string(VarSet, no, Vars))),
+        quote(mercury_vars_to_string(VarSet, no, Vars)),
         words("have the following insts:"), nl_indent_delta(1)] ++
         inst_list_to_sep_lines(!.ModeInfo, Insts) ++
         [words("which does not match any of the valid modes for")],
@@ -753,7 +751,7 @@
             "report_mode_error_no_matching_mode: invalid context")
     ),
     Pieces = [words("mode error: arguments"),
-        fixed(add_quotes(mercury_vars_to_string(VarSet, no, Vars))),
+        quote(mercury_vars_to_string(VarSet, no, Vars)),
         words("have the following insts:"), nl_indent_delta(1)] ++
         inst_list_to_sep_lines(ModeInfo, Insts) ++
         [words("which does not match any of the modes for"),
@@ -779,10 +777,9 @@
             int_to_string(Arity - 1) ++ ")."
     ),
     Pieces = [words("mode error: variable"),
-        fixed(add_quotes(mercury_var_to_string(VarSet, no, Var))),
+        quote(mercury_var_to_string(VarSet, no, Var)),
         words("has instantiatedness"),
-        words(add_quotes(inst_to_string(ModeInfo, VarInst))),
-        suffix(","), nl,
+        words_quote(inst_to_string(ModeInfo, VarInst)), suffix(","), nl,
         words(Expecting), nl],
     Spec = error_spec(severity_error, phase_mode_check(report_in_any_mode),
         [simple_msg(Context, [always(Preamble ++ Pieces)])]).
@@ -796,9 +793,9 @@
     mode_info_get_varset(ModeInfo, VarSet),
     MainPieces = [words("in polymorphically-typed unification:"), nl,
         words("mode error: variable"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, Var))),
+        quote(mercury_var_to_string(VarSet, no, Var)),
         words("has instantiatedness"),
-        words(add_quotes(inst_to_string(ModeInfo, VarInst))), suffix(","), nl,
+        words_quote(inst_to_string(ModeInfo, VarInst)), suffix(","), nl,
         words("expected instantiatedness was `ground' or `any'."), nl],
     VerbosePieces = [words("When unifying two variables whose type"),
         words("will not be known until runtime, the variables must both"),
@@ -817,7 +814,7 @@
     mode_info_get_varset(ModeInfo, VarSet),
     Pieces = [words("unique-mode error: the called procedure"),
         words("would clobber its argument, but variable"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, Var))),
+        quote(mercury_var_to_string(VarSet, no, Var)),
         words("is still live."), nl],
     Spec = error_spec(severity_error, phase_mode_check(report_in_any_mode),
         [simple_msg(Context, [always(Preamble ++ Pieces)])]).
@@ -830,11 +827,11 @@
     mode_info_get_context(ModeInfo, Context),
     mode_info_get_varset(ModeInfo, VarSet),
     Pieces = [words("mode error: variable"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, Var))),
+        quote(mercury_var_to_string(VarSet, no, Var)),
         words("has instantiatedness"),
-        words(add_quotes(inst_to_string(ModeInfo, VarInst))), suffix(","), nl,
+        words_quote(inst_to_string(ModeInfo, VarInst)), suffix(","), nl,
         words("expected instantiatedness was"),
-        words(add_quotes(inst_to_string(ModeInfo, Inst))), suffix("."), nl],
+        words_quote(inst_to_string(ModeInfo, Inst)), suffix("."), nl],
     Spec = error_spec(severity_error, phase_mode_check(report_in_any_mode),
         [simple_msg(Context, [always(Preamble ++ Pieces)])]).
 
@@ -849,13 +846,11 @@
     mode_info_get_varset(ModeInfo, VarSet),
     Pieces = [words("sorry, implied modes not implemented."), nl,
         words("Variable"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, Var))),
+        quote(mercury_var_to_string(VarSet, no, Var)),
         words("has instantiatedness"),
-        words(add_quotes(inst_to_string(ModeInfo, VarInst))),
-        suffix(","), nl,
+        words_quote(inst_to_string(ModeInfo, VarInst)), suffix(","), nl,
         words("expected instantiatedness was"),
-        words(add_quotes(inst_to_string(ModeInfo, Inst))),
-        suffix("."), nl],
+        words_quote(inst_to_string(ModeInfo, Inst)), suffix("."), nl],
     Severity = severity_conditional(errorcheck_only, no, severity_error, no),
     Spec = error_spec(Severity, phase_mode_check(report_in_any_mode),
         [simple_msg(Context,
@@ -895,12 +890,11 @@
     ),
     varset.init(TypeVarSet),
     MainPieces = [words("In unification of"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, X))),
-        words("with"), words(add_quotes(RHSStr)), suffix(":"), nl,
+        quote(mercury_var_to_string(VarSet, no, X)),
+        words("with"), quote(RHSStr), suffix(":"), nl,
         words("mode error: attempt at higher-order unification."), nl,
         words("Cannot unify two terms of type"),
-        words(add_quotes(mercury_type_to_string(TypeVarSet, no, Type))),
-        suffix("."), nl],
+        quote(mercury_type_to_string(TypeVarSet, no, Type)), suffix("."), nl],
     VerbosePieces = [words("Your code is trying to test whether two "),
         words(prog_out.pred_or_func_to_full_str(PredOrFunc) ++ "s"),
         words("are equal, by unifying them."),
@@ -926,18 +920,16 @@
     mode_info_get_context(ModeInfo, Context),
     mode_info_get_varset(ModeInfo, VarSet),
     Pieces = [words("mode error in unification of"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, X))),
-        words("and"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, Y))),
-        suffix("."), nl,
+        quote(mercury_var_to_string(VarSet, no, X)), words("and"),
+        quote(mercury_var_to_string(VarSet, no, Y)), suffix("."), nl,
         words("Variable"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, X))),
+        quote(mercury_var_to_string(VarSet, no, X)),
         words("has instantiatedness"),
-        words(add_quotes(inst_to_string(ModeInfo, InstX))), suffix(","), nl,
+        words_quote(inst_to_string(ModeInfo, InstX)), suffix(","), nl,
         words("variable"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, Y))),
+        quote(mercury_var_to_string(VarSet, no, Y)),
         words("has instantiatedness"),
-        words(add_quotes(inst_to_string(ModeInfo, InstY))), suffix("."), nl],
+        words_quote(inst_to_string(ModeInfo, InstY)), suffix("."), nl],
     Spec = error_spec(severity_error, phase_mode_check(report_in_any_mode),
         [simple_msg(Context, [always(Preamble ++ Pieces)])]).
 
@@ -951,14 +943,14 @@
     mode_info_get_context(ModeInfo, Context),
     mode_info_get_varset(ModeInfo, VarSet),
     Pieces = [words("mode error in unification of"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, X))),
+        quote(mercury_var_to_string(VarSet, no, X)),
         words("and lambda expression."), nl,
         words("Variable"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, X))),
+        quote(mercury_var_to_string(VarSet, no, X)),
         words("has instantiatedness"),
-        words(add_quotes(inst_to_string(ModeInfo, InstX))), suffix(","), nl,
+        words_quote(inst_to_string(ModeInfo, InstX)), suffix(","), nl,
         words("lambda expression has instantiatedness"),
-        words(add_quotes(inst_to_string(ModeInfo, InstY))), suffix("."), nl],
+        words_quote(inst_to_string(ModeInfo, InstY)), suffix("."), nl],
     Spec = error_spec(severity_error, phase_mode_check(report_in_any_mode),
         [simple_msg(Context, [always(Preamble ++ Pieces)])]).
 
@@ -980,7 +972,7 @@
     Arity = pred_info_orig_arity(PredInfo),
     adjust_func_arity(PredOrFunc, FuncArity, Arity),
     Pieces = [words("mode error in unification of"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, X))),
+        quote(mercury_var_to_string(VarSet, no, X)),
         words("and higher-order term based on multi-moded"),
         p_or_f(PredOrFunc), sym_name_and_arity(QualifiedName / FuncArity),
         suffix("."), nl],
@@ -1004,7 +996,7 @@
     Arity = pred_info_orig_arity(PredInfo),
     adjust_func_arity(PredOrFunc, FuncArity, Arity),
     Pieces = [words("In unification of"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, X))),
+        quote(mercury_var_to_string(VarSet, no, X)),
         words("and higher-order term."),
         words("Could not determine the mode of"),
         p_or_f(PredOrFunc), sym_name_and_arity(QualifiedName / FuncArity),
@@ -1023,18 +1015,16 @@
     mode_info_get_context(ModeInfo, Context),
     mode_info_get_varset(ModeInfo, VarSet),
     mode_info_get_module_info(ModeInfo, ModuleInfo),
+    FunctorConsIdStr =
+        functor_cons_id_to_string(ConsId, Args, VarSet, ModuleInfo, no),
     Pieces1 = [words("mode error in unification of"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, X))),
-        words("and"),
-        words(add_quotes(functor_cons_id_to_string(ConsId, Args,
-            VarSet, ModuleInfo, no))), suffix("."), nl,
-        words("Variable"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, X))),
+        quote(mercury_var_to_string(VarSet, no, X)),
+        words("and"), words_quote(FunctorConsIdStr), suffix("."), nl,
+        words("Variable"), quote(mercury_var_to_string(VarSet, no, X)),
         words("has instantiatedness"),
-        words(add_quotes(inst_to_string(ModeInfo, InstX))), suffix(","), nl,
+        words_quote(inst_to_string(ModeInfo, InstX)), suffix(","), nl,
         words("term"),
-        words(add_quotes(functor_cons_id_to_string(ConsId, Args,
-            VarSet, ModuleInfo, no)))],
+        words_quote(FunctorConsIdStr)],
     ConsIdStr = mercury_cons_id_to_string(ConsId, does_not_need_brackets),
     (
         Args = [_ | _],
@@ -1060,16 +1050,15 @@
     mode_info_get_context(ModeInfo, Context),
     mode_info_get_varset(ModeInfo, VarSet),
     Pieces = [words("warning: unification of"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, X))),
-        words("and"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, Y))),
+        quote(mercury_var_to_string(VarSet, no, X)),
+        words("and"), quote(mercury_var_to_string(VarSet, no, Y)),
         words("cannot succeed"), nl,
-        words(add_quotes(mercury_var_to_string(VarSet, no, X))),
+        quote(mercury_var_to_string(VarSet, no, X)),
         words("has instantiatedness"),
-        words(add_quotes(inst_to_string(ModeInfo, InstX))), suffix(","), nl,
-        words(add_quotes(mercury_var_to_string(VarSet, no, Y))),
+        words_quote(inst_to_string(ModeInfo, InstX)), suffix(","), nl,
+        quote(mercury_var_to_string(VarSet, no, Y)),
         words("has instantiatedness"),
-        words(add_quotes(inst_to_string(ModeInfo, InstY))), suffix("."), nl],
+        words_quote(inst_to_string(ModeInfo, InstY)), suffix("."), nl],
     Spec = error_spec(severity_warning,
         phase_mode_check(report_only_if_in_all_modes),
         [simple_msg(Context, [always(Preamble ++ Pieces)])]).
@@ -1082,13 +1071,12 @@
     mode_info_get_context(ModeInfo, Context),
     mode_info_get_varset(ModeInfo, VarSet),
     Pieces = [words("warning: unification of"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, X))),
-        words("and"),
+        quote(mercury_var_to_string(VarSet, no, X)), words("and"),
         words(mercury_cons_id_to_string(ConsId, does_not_need_brackets)),
         words("cannot succeed"), nl,
-        words(add_quotes(mercury_var_to_string(VarSet, no, X))),
+        quote(mercury_var_to_string(VarSet, no, X)),
         words("has instantiatedness"),
-        words(add_quotes(inst_to_string(ModeInfo, InstX))), suffix("."), nl],
+        words_quote(inst_to_string(ModeInfo, InstX)), suffix("."), nl],
     Spec = error_spec(severity_warning,
         phase_mode_check(report_only_if_in_all_modes),
         [simple_msg(Context, [always(Preamble ++ Pieces)])]).
@@ -1115,8 +1103,8 @@
 
     ModeSubDeclStr = mercury_mode_subdecl_to_string(PredOrFunc, InstVarSet,
         Name, Modes, MaybeDet, Context),
-    Pieces1 = [words("In clause for"),
-        words(add_quotes(ModeSubDeclStr)), suffix(":"), nl],
+    Pieces1 = [words("In clause for"), words_quote(ModeSubDeclStr),
+        suffix(":"), nl],
     mode_info_get_mode_context(ModeInfo, ModeContext),
     Pieces2 = mode_context_to_pieces(ModeContext, PredMarkers),
     Pieces = Pieces1 ++ Pieces2.
@@ -1165,12 +1153,10 @@
     Pieces = [words("mode error: argument"), fixed(int_to_string(ArgNum)),
         words(Problem), nl,
         words("Final instantiatedness of"),
-        words(add_quotes(mercury_var_to_string(VarSet, no, Var))),
-        words("was"), words(add_quotes(inst_to_string(ModeInfo, VarInst))),
-        suffix(","), nl,
+        quote(mercury_var_to_string(VarSet, no, Var)), words("was"),
+        words_quote(inst_to_string(ModeInfo, VarInst)), suffix(","), nl,
         words("expected final instantiatedness was"),
-        words(add_quotes(inst_to_string(ModeInfo, Inst))),
-        suffix("."), nl],
+        words_quote(inst_to_string(ModeInfo, Inst)), suffix("."), nl],
     Spec = error_spec(severity_error, phase_mode_check(report_in_any_mode),
         [simple_msg(Context, [always(Preamble ++ Pieces)])]).
 
@@ -1411,9 +1397,9 @@
         describe_one_pred_name(ModuleInfo, should_module_qualify, PredId)
         ++ [suffix(":"), nl, words("error: duplicate mode declaration."), nl],
     VerbosePieces = [words("Modes"),
-        fixed(add_quotes(mode_decl_to_string(OldProcId, PredInfo))),
+        words_quote(mode_decl_to_string(OldProcId, PredInfo)),
         words("and"),
-        fixed(add_quotes(mode_decl_to_string(NewProcId, PredInfo))),
+        words_quote(mode_decl_to_string(NewProcId, PredInfo)),
         words("are indistinguishable.")],
     OldPieces = [words("Here is the conflicting mode declaration.")],
     Spec = error_spec(severity_error, phase_mode_check(report_in_any_mode),
Index: compiler/modecheck_goal.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/modecheck_goal.m,v
retrieving revision 1.3
diff -u -b -r1.3 modecheck_goal.m
--- compiler/modecheck_goal.m	15 Dec 2010 06:29:51 -0000	1.3
+++ compiler/modecheck_goal.m	27 Dec 2010 04:57:34 -0000
@@ -522,6 +522,8 @@
             ; Reason = exist_quant(_)
             ; Reason = promise_solutions(_, _)
             ; Reason = promise_purity(_)
+            ; Reason = require_detism(_)
+            ; Reason = require_complete_switch(_)
             ; Reason = commit(_)
             ; Reason = barrier(_)
             ; Reason = trace_goal(_, _, _, _, _)
@@ -594,6 +596,8 @@
             ; Reason = exist_quant(_)
             ; Reason = promise_solutions(_, _)
             ; Reason = promise_purity(_)
+            ; Reason = require_detism(_)
+            ; Reason = require_complete_switch(_)
             ; Reason = commit(_)
             ; Reason = barrier(_)
             ; Reason = trace_goal(_, _, _, _, _)
@@ -791,6 +795,8 @@
     ;
         ( Reason = exist_quant(_)
         ; Reason = promise_solutions(_, _)
+        ; Reason = require_detism(_)
+        ; Reason = require_complete_switch(_)
         ; Reason = commit(_)
         ; Reason = barrier(_)
         ),
Index: compiler/module_imports.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/module_imports.m,v
retrieving revision 1.8
diff -u -b -r1.8 module_imports.m
--- compiler/module_imports.m	15 Dec 2010 06:29:52 -0000	1.8
+++ compiler/module_imports.m	27 Dec 2010 10:23:47 -0000
@@ -671,6 +671,8 @@
         ; GoalExpr = promise_equivalent_solution_sets_expr(_, _, _, SubGoal)
         ; GoalExpr = promise_equivalent_solution_arbitrary_expr(_, _, _,
             SubGoal)
+        ; GoalExpr = require_detism_expr(_, SubGoal)
+        ; GoalExpr = require_complete_switch_expr(_, SubGoal)
         ; GoalExpr = trace_expr(_, _, _, _, SubGoal)
         ),
         goal_contains_stm_atomic_or_try(SubGoal, ContainsAtomic, ContainsTry)
Index: compiler/module_qual.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/module_qual.m,v
retrieving revision 1.179
diff -u -b -r1.179 module_qual.m
--- compiler/module_qual.m	15 Dec 2010 06:29:52 -0000	1.179
+++ compiler/module_qual.m	27 Dec 2010 10:38:13 -0000
@@ -559,50 +559,48 @@
     % the maybe_and predicate to be associative.
     % NB. accumulator introduction doesn't work on this case yet.
     %
-process_assert(conj_expr(GA, GB) - _, Symbols, Success) :-
-    process_assert(GA, SymbolsA, SuccessA),
-    process_assert(GB, SymbolsB, SuccessB),
-    list.append(SymbolsA, SymbolsB, Symbols),
-    bool.and(SuccessA, SuccessB, Success).
-process_assert(true_expr - _, [], yes).
-process_assert(par_conj_expr(GA, GB) - _, Symbols, Success) :-
-    process_assert(GA, SymbolsA, SuccessA),
-    process_assert(GB, SymbolsB, SuccessB),
-    list.append(SymbolsA, SymbolsB, Symbols),
-    bool.and(SuccessA, SuccessB, Success).
-process_assert(disj_expr(GA, GB) - _, Symbols, Success) :-
+process_assert(Goal, Symbols, Success) :-
+    Goal = GoalExpr - _Context,
+    (
+        ( GoalExpr = conj_expr(GA, GB)
+        ; GoalExpr = par_conj_expr(GA, GB)
+        ; GoalExpr = disj_expr(GA, GB)
+        ; GoalExpr = implies_expr(GA, GB)
+        ; GoalExpr = equivalent_expr(GA, GB)
+        ),
     process_assert(GA, SymbolsA, SuccessA),
     process_assert(GB, SymbolsB, SuccessB),
-    list.append(SymbolsA, SymbolsB, Symbols),
-    bool.and(SuccessA, SuccessB, Success).
-process_assert(fail_expr - _, [], yes).
-process_assert(some_expr(_, G) - _, Symbols, Success) :-
-    process_assert(G, Symbols, Success).
-process_assert(some_state_vars_expr(_, G) - _, Symbols, Success) :-
-    process_assert(G, Symbols, Success).
-process_assert(all_expr(_, G) - _, Symbols, Success) :-
-    process_assert(G, Symbols, Success).
-process_assert(all_state_vars_expr(_, G) - _, Symbols, Success) :-
-    process_assert(G, Symbols, Success).
-process_assert(promise_purity_expr(_P, G) - _, Symbols, Success) :-
-    process_assert(G, Symbols, Success).
-process_assert(promise_equivalent_solutions_expr(_V, _D, _C, G) - _,
-        Symbols, Success) :-
-    process_assert(G, Symbols, Success).
-process_assert(promise_equivalent_solution_sets_expr(_V, _D, _C, G) - _,
-        Symbols, Success) :-
-    process_assert(G, Symbols, Success).
-process_assert(promise_equivalent_solution_arbitrary_expr(_V, _D, _C, G) - _,
-        Symbols, Success) :-
-    process_assert(G, Symbols, Success).
-process_assert(trace_expr(_C, _R, _I, _M, G) - _, Symbols, Success) :-
-    process_assert(G, Symbols, Success).
-process_assert(try_expr(_, Goal, Then, MaybeElse, Catches, MaybeCatchAny) - _,
-        Symbols, Success) :-
-    process_assert(Goal, SymbolsGoal, SuccessGoal),
+        Symbols = SymbolsA ++ SymbolsB,
+        bool.and(SuccessA, SuccessB, Success)
+    ;
+        ( GoalExpr = true_expr
+        ; GoalExpr = fail_expr
+        ),
+        Symbols = [],
+        Success = yes
+    ;
+        ( GoalExpr = not_expr(G)
+        ; GoalExpr = some_expr(_, G)
+        ; GoalExpr = some_state_vars_expr(_, G)
+        ; GoalExpr = all_expr(_, G)
+        ; GoalExpr = all_state_vars_expr(_, G)
+        ; GoalExpr = promise_purity_expr(_, G)
+        ; GoalExpr = promise_equivalent_solutions_expr(_, _, _, G)
+        ; GoalExpr = promise_equivalent_solution_sets_expr(_, _, _, G)
+        ; GoalExpr = promise_equivalent_solution_arbitrary_expr(_, _, _, G)
+        ; GoalExpr = require_detism_expr(_, G)
+        ; GoalExpr = require_complete_switch_expr(_, G)
+        ; GoalExpr = trace_expr(_, _, _, _, G)
+        ),
+        process_assert(G, Symbols, Success)
+    ;
+        GoalExpr = try_expr(_, SubGoal, Then, MaybeElse, Catches,
+            MaybeCatchAny),
+        process_assert(SubGoal, SymbolsGoal, SuccessGoal),
     process_assert(Then, SymbolsThen, SuccessThen),
     maybe_process_assert(MaybeElse, SymbolsElse, SuccessElse),
-    list.map2(process_assert_catch, Catches, SymbolsCatches, SuccessCatches),
+        list.map2(process_assert_catch, Catches,
+            SymbolsCatches, SuccessCatches),
     (
         MaybeCatchAny = yes(catch_any_expr(_, CatchAnyGoal)),
         process_assert(CatchAnyGoal, SymbolsCatchAny, SuccessCatchAny)
@@ -611,39 +609,29 @@
         SymbolsCatchAny = [],
         SuccessCatchAny = no
     ),
-    SymbolsLists = [SymbolsGoal, SymbolsThen, SymbolsElse, SymbolsCatchAny |
-        SymbolsCatches],
+        SymbolsLists = [SymbolsGoal, SymbolsThen, SymbolsElse, SymbolsCatchAny
+            | SymbolsCatches],
     list.condense(SymbolsLists, Symbols),
-    SuccessLists = [SuccessGoal, SuccessThen, SuccessElse, SuccessCatchAny |
-        SuccessCatches],
-    bool.and_list(SuccessLists, Success).
-process_assert(atomic_expr(_, _, _, MainGoal, OrElseGoals) - _, Symbols,
-        Success) :-
+        SuccessLists = [SuccessGoal, SuccessThen, SuccessElse, SuccessCatchAny
+            | SuccessCatches],
+        bool.and_list(SuccessLists, Success)
+    ;
+        GoalExpr = atomic_expr(_, _, _, MainGoal, OrElseGoals),
     process_assert(MainGoal, SymbolsMainGoal, SuccessMainGoal),
-    process_assert_list(OrElseGoals, SymbolsOrElseGoals, SuccessOrElseGoals),
-    list.append(SymbolsMainGoal, SymbolsOrElseGoals, Symbols),
-    bool.and(SuccessMainGoal, SuccessOrElseGoals, Success).
-process_assert(implies_expr(GA, GB) - _, Symbols, Success) :-
-    process_assert(GA, SymbolsA, SuccessA),
-    process_assert(GB, SymbolsB, SuccessB),
-    list.append(SymbolsA, SymbolsB, Symbols),
-    bool.and(SuccessA, SuccessB, Success).
-process_assert(equivalent_expr(GA, GB) - _, Symbols, Success) :-
-    process_assert(GA, SymbolsA, SuccessA),
-    process_assert(GB, SymbolsB, SuccessB),
-    list.append(SymbolsA, SymbolsB, Symbols),
-    bool.and(SuccessA, SuccessB, Success).
-process_assert(not_expr(G) - _, Symbols, Success) :-
-    process_assert(G, Symbols, Success).
-process_assert(if_then_else_expr(_, _, GA, GB, GC) - _, Symbols, Success) :-
+        process_assert_list(OrElseGoals,
+            SymbolsOrElseGoals, SuccessOrElseGoals),
+        Symbols = SymbolsMainGoal ++ SymbolsOrElseGoals,
+        bool.and(SuccessMainGoal, SuccessOrElseGoals, Success)
+    ;
+        GoalExpr = if_then_else_expr(_, _, GA, GB, GC),
     process_assert(GA, SymbolsA, SuccessA),
     process_assert(GB, SymbolsB, SuccessB),
     process_assert(GC, SymbolsC, SuccessC),
-    list.append(SymbolsA, SymbolsB, Symbols0),
-    list.append(Symbols0, SymbolsC, Symbols),
+        Symbols = SymbolsA ++ SymbolsB ++ SymbolsC,
     bool.and(SuccessA, SuccessB, Success0),
-    bool.and(Success0, SuccessC, Success).
-process_assert(event_expr(_Name, Args0) - _, Symbols, Success) :-
+        bool.and(Success0, SuccessC, Success)
+    ;
+        GoalExpr = event_expr(_Name, Args0),
     list.map(term.coerce, Args0, Args),
     ( term_qualified_symbols_list(Args, SymbolsPrime) ->
         Symbols = SymbolsPrime,
@@ -651,8 +639,9 @@
     ;
         Symbols = [],
         Success = no
-    ).
-process_assert(call_expr(SymName, Args0, _Purity) - _, Symbols, Success) :-
+        )
+    ;
+        GoalExpr = call_expr(SymName, Args0, _Purity),
     (
         SymName = qualified(_, _),
         list.map(term.coerce, Args0, Args),
@@ -667,8 +656,9 @@
         SymName = unqualified(_),
         Symbols = [],
         Success = no
-    ).
-process_assert(unify_expr(LHS0, RHS0, _Purity) - _, Symbols, Success) :-
+        )
+    ;
+        GoalExpr = unify_expr(LHS0, RHS0, _Purity),
     term.coerce(LHS0, LHS),
     term.coerce(RHS0, RHS),
     (
@@ -680,6 +670,7 @@
     ;
         Symbols = [],
         Success = no
+        )
     ).
 
 :- pred maybe_process_assert(maybe(goal)::in, list(sym_name)::out, bool::out)
Index: compiler/polymorphism.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/polymorphism.m,v
retrieving revision 1.354
diff -u -b -r1.354 polymorphism.m
--- compiler/polymorphism.m	20 Dec 2010 07:47:35 -0000	1.354
+++ compiler/polymorphism.m	27 Dec 2010 04:57:34 -0000
@@ -1160,6 +1160,8 @@
             ;
                 ( Reason0 = promise_solutions(_, _)
                 ; Reason0 = promise_purity(_)
+                ; Reason0 = require_detism(_)
+                ; Reason0 = require_complete_switch(_)
                 ; Reason0 = commit(_)
                 ; Reason0 = barrier(_)
                 ),
Index: compiler/prog_io_goal.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_io_goal.m,v
retrieving revision 1.62
diff -u -b -r1.62 prog_io_goal.m
--- compiler/prog_io_goal.m	4 Aug 2010 02:44:10 -0000	1.62
+++ compiler/prog_io_goal.m	27 Dec 2010 14:30:06 -0000
@@ -157,14 +157,24 @@
     % For consistency we also disallow if-then without the else.
 
     % XXX We should update ContextPieces as we recurse down.
-parse_goal_2("true", [], Context, _CP, ok1(true_expr - Context), !VarSet).
-parse_goal_2("fail", [], Context, _CP, ok1(fail_expr - Context), !VarSet).
-parse_goal_2("=", [ATerm0, BTerm0], Context, _CP, MaybeGoal, !VarSet) :-
+parse_goal_2(Functor, Args, Context, ContextPieces, MaybeGoal, !VarSet) :-
+    (
+        Functor = "true",
+        Args = [],
+        MaybeGoal = ok1(true_expr - Context)
+    ;
+        Functor = "fail",
+        Args = [],
+        MaybeGoal = ok1(fail_expr - Context)
+    ;
+        Functor = "=",
+        Args = [ATerm0, BTerm0],
     term.coerce(ATerm0, ATerm),
     term.coerce(BTerm0, BTerm),
-    MaybeGoal = ok1(unify_expr(ATerm, BTerm, purity_pure) - Context).
-parse_goal_2(",", [ATerm, BTerm], Context, ContextPieces, MaybeGoal,
-        !VarSet) :-
+        MaybeGoal = ok1(unify_expr(ATerm, BTerm, purity_pure) - Context)
+    ;
+        Functor = ",",
+        Args = [ATerm, BTerm],
     parse_goal(ATerm, ContextPieces, MaybeAGoal, !VarSet),
     parse_goal(BTerm, ContextPieces, MaybeBGoal, !VarSet),
     (
@@ -176,9 +186,10 @@
         ASpecs = get_any_errors1(MaybeAGoal),
         BSpecs = get_any_errors1(MaybeBGoal),
         MaybeGoal = error1(ASpecs ++ BSpecs)
-    ).
-parse_goal_2("&", [ATerm, BTerm], Context, ContextPieces, MaybeGoal,
-        !VarSet) :-
+        )
+    ;
+        Functor = "&",
+        Args = [ATerm, BTerm],
     parse_goal(ATerm, ContextPieces, MaybeAGoal, !VarSet),
     parse_goal(BTerm, ContextPieces, MaybeBGoal, !VarSet),
     (
@@ -190,9 +201,10 @@
         ASpecs = get_any_errors1(MaybeAGoal),
         BSpecs = get_any_errors1(MaybeBGoal),
         MaybeGoal = error1(ASpecs ++ BSpecs)
-    ).
-parse_goal_2(";", [ATerm, BTerm], Context, ContextPieces, MaybeGoal,
-        !VarSet) :-
+        )
+    ;
+        Functor = ";",
+        Args = [ATerm, BTerm],
     ( ATerm = term.functor(term.atom("->"), [XTerm, YTerm], _Context) ->
         parse_some_vars_goal(XTerm, ContextPieces, MaybeXGoal, !VarSet),
         parse_goal(YTerm, ContextPieces, MaybeYGoal, !VarSet),
@@ -224,9 +236,10 @@
             BSpecs = get_any_errors1(MaybeBGoal),
             MaybeGoal = error1(ASpecs ++ BSpecs)
         )
-    ).
-parse_goal_2("else", [IfTerm, CTerm], Context, ContextPieces, MaybeGoal,
-        !VarSet) :-
+        )
+    ;
+        Functor = "else",
+        Args = [IfTerm, CTerm],
     (
         IfTerm = term.functor(term.atom("if"),
             [term.functor(term.atom("then"), [ATerm, BTerm], _)], _)
@@ -251,23 +264,26 @@
     ;
         % `else' can also be part of a `try' goal.
         parse_else_then_try_term(
-            term.functor(term.atom("else"), [IfTerm, CTerm], Context), [], no,
-            Context, ContextPieces, MaybeGoal, !VarSet)
-    ).
-parse_goal_2("then", [TryTerm, ThenTerm], Context, ContextPieces,
-        MaybeGoal, !VarSet) :-
+                term.functor(term.atom("else"), [IfTerm, CTerm], Context),
+                [], no, Context, ContextPieces, MaybeGoal, !VarSet)
+        )
+    ;
+        Functor = "then",
+        Args = [TryTerm, ThenTerm],
     parse_then_try_term(
-        term.functor(atom("then"), [TryTerm, ThenTerm], Context), no, [], no,
-        Context, ContextPieces, MaybeGoal, !VarSet).
-parse_goal_2("catch", [ElseThenTryTerm, CatchTerm], Context, ContextPieces,
-        MaybeGoal, !VarSet) :-
+            term.functor(atom("then"), [TryTerm, ThenTerm], Context),
+            no, [], no, Context, ContextPieces, MaybeGoal, !VarSet)
+    ;
+        Functor = "catch",
+        Args = [ElseThenTryTerm, CatchTerm],
     parse_catch_then_try_term(
-        term.functor(atom("catch"), [ElseThenTryTerm, CatchTerm], Context), no,
-        Context, ContextPieces, MaybeGoal, !VarSet).
-parse_goal_2("catch_any", [TermA, ArrowTerm], Context, ContextPieces,
-        MaybeGoal, !VarSet) :-
-    parse_catch_any_term(ArrowTerm, Context, ContextPieces, MaybeCatchAnyExpr,
-        !VarSet),
+            term.functor(atom("catch"), [ElseThenTryTerm, CatchTerm], Context),
+            no, Context, ContextPieces, MaybeGoal, !VarSet)
+    ;
+        Functor = "catch_any",
+        Args = [TermA, ArrowTerm],
+        parse_catch_any_term(ArrowTerm, Context, ContextPieces,
+            MaybeCatchAnyExpr, !VarSet),
     (
         MaybeCatchAnyExpr = ok1(CatchAnyExpr),
         ( TermA = term.functor(atom("catch"), _, _) ->
@@ -280,17 +296,12 @@
     ;
         MaybeCatchAnyExpr = error1(Specs),
         MaybeGoal = error1(Specs)
-    ).
-parse_goal_2("not", [ATerm], Context, ContextPieces, MaybeGoal, !VarSet) :-
-    parse_goal(ATerm, ContextPieces, MaybeAGoal, !VarSet),
-    (
-        MaybeAGoal = ok1(AGoal),
-        MaybeGoal = ok1(not_expr(AGoal) - Context)
+        )
     ;
-        MaybeAGoal = error1(_),
-        MaybeGoal = MaybeAGoal
-    ).
-parse_goal_2("\\+", [ATerm], Context, ContextPieces, MaybeGoal, !VarSet) :-
+        ( Functor = "not"
+        ; Functor = "\\+"
+        ),
+        Args = [ATerm],
     parse_goal(ATerm, ContextPieces, MaybeAGoal, !VarSet),
     (
         MaybeAGoal = ok1(AGoal),
@@ -298,9 +309,10 @@
     ;
         MaybeAGoal = error1(_),
         MaybeGoal = MaybeAGoal
-    ).
-parse_goal_2("all", [QVarsTerm, SubTerm], Context, ContextPieces, MaybeGoal,
-        !VarSet) :-
+        )
+    ;
+        Functor = "all",
+        Args = [QVarsTerm, SubTerm],
     % Extract any state variables in the quantifier.
     varset.coerce(!.VarSet, GenericVarSet),
     parse_quantifier_vars(QVarsTerm, GenericVarSet, ContextPieces,
@@ -328,7 +340,8 @@
             GoalExpr = all_expr(Vars, SubGoal)
         ;
             Vars = [_ | _], StateVars = [_ | _],
-            GoalExpr = all_expr(Vars, all_state_vars_expr(StateVars, SubGoal)
+                GoalExpr = all_expr(Vars,
+                    all_state_vars_expr(StateVars, SubGoal)
                 - SubContext)
         ),
         Goal = GoalExpr - Context,
@@ -337,9 +350,10 @@
         VarsSpecs = get_any_errors2(MaybeStateVarsAndVars),
         SubGoalSpecs = get_any_errors1(MaybeSubGoal),
         MaybeGoal = error1(VarsSpecs ++ SubGoalSpecs)
-    ).
-parse_goal_2("<=", [ATerm, BTerm], Context, ContextPieces, MaybeGoal,
-        !VarSet) :-
+        )
+    ;
+        Functor = "<=",
+        Args = [ATerm, BTerm],
     parse_goal(ATerm, ContextPieces, MaybeAGoal, !VarSet),
     parse_goal(BTerm, ContextPieces, MaybeBGoal, !VarSet),
     (
@@ -351,9 +365,10 @@
         ASpecs = get_any_errors1(MaybeAGoal),
         BSpecs = get_any_errors1(MaybeBGoal),
         MaybeGoal = error1(ASpecs ++ BSpecs)
-    ).
-parse_goal_2("=>", [ATerm, BTerm], Context, ContextPieces, MaybeGoal,
-        !VarSet) :-
+        )
+    ;
+        Functor = "=>",
+        Args = [ATerm, BTerm],
     parse_goal(ATerm, ContextPieces, MaybeAGoal, !VarSet),
     parse_goal(BTerm, ContextPieces, MaybeBGoal, !VarSet),
     (
@@ -365,9 +380,10 @@
         ASpecs = get_any_errors1(MaybeAGoal),
         BSpecs = get_any_errors1(MaybeBGoal),
         MaybeGoal = error1(ASpecs ++ BSpecs)
-    ).
-parse_goal_2("<=>", [ATerm, BTerm], Context, ContextPieces, MaybeGoal,
-        !VarSet) :-
+        )
+    ;
+        Functor = "<=>",
+        Args = [ATerm, BTerm],
     parse_goal(ATerm, ContextPieces, MaybeAGoal, !VarSet),
     parse_goal(BTerm, ContextPieces, MaybeBGoal, !VarSet),
     (
@@ -379,9 +395,10 @@
         ASpecs = get_any_errors1(MaybeAGoal),
         BSpecs = get_any_errors1(MaybeBGoal),
         MaybeGoal = error1(ASpecs ++ BSpecs)
-    ).
-parse_goal_2("some", [QVarsTerm, SubTerm], Context, ContextPieces, MaybeGoal,
-        !VarSet) :-
+        )
+    ;
+        Functor = "some",
+        Args = [QVarsTerm, SubTerm],
     % Extract any state variables in the quantifier.
     UpdatedContextPieces = ContextPieces ++ [lower_case_next_if_not_first,
         words("In first argument of"), quote("some"), suffix(":")],
@@ -411,7 +428,8 @@
         ;
             Vars = [_ | _],
             StateVars = [_ | _],
-            GoalExpr = some_expr(Vars, some_state_vars_expr(StateVars, SubGoal)
+                GoalExpr = some_expr(Vars,
+                    some_state_vars_expr(StateVars, SubGoal)
                 - SubContext)
         ),
         Goal = GoalExpr - Context,
@@ -420,9 +438,10 @@
         VarsSpecs = get_any_errors2(MaybeStateVarsAndVars),
         SubGoalSpecs = get_any_errors1(MaybeSubGoal),
         MaybeGoal = error1(VarsSpecs ++ SubGoalSpecs)
-    ).
-parse_goal_2("trace", [ParamsTerm, SubTerm], Context, ContextPieces, MaybeGoal,
-        !VarSet) :-
+        )
+    ;
+        Functor = "trace",
+        Args = [ParamsTerm, SubTerm],
     varset.coerce(!.VarSet, GenericVarSet),
     parse_trace_params(GenericVarSet, Context, ParamsTerm, MaybeParams),
     parse_goal(SubTerm, ContextPieces, MaybeSubGoal, !VarSet),
@@ -444,9 +463,10 @@
         ParamsSpecs = get_any_errors1(MaybeParams),
         SubGoalSpecs = get_any_errors1(MaybeSubGoal),
         MaybeGoal = error1(ParamsSpecs ++ SubGoalSpecs)
-    ).
-parse_goal_2("atomic", [ParamsTerm, SubTerm], Context, _CP, MaybeGoal,
-        !VarSet) :-
+        )
+    ;
+        Functor = "atomic",
+        Args = [ParamsTerm, SubTerm],
     varset.coerce(!.VarSet, GenericVarSet),
     parse_atomic_params(Context, ParamsTerm, GenericVarSet, MaybeParams),
     parse_atomic_subexpr(SubTerm, MaybeSubGoals, !VarSet),
@@ -468,9 +488,12 @@
         ParamsSpecs = get_any_errors1(MaybeParams),
         SubGoalSpecs = get_any_errors2(MaybeSubGoals),
         MaybeGoal = error1(ParamsSpecs ++ SubGoalSpecs)
-    ).
-parse_goal_2("promise_equivalent_solutions", [VarsTerm, SubTerm], Context,
-        ContextPieces, MaybeGoal, !VarSet) :-
+        )
+    ;
+        ( Functor = "promise_equivalent_solutions"
+        ; Functor = "promise_equivalent_solution_sets"
+        ),
+        Args = [VarsTerm, SubTerm],
     varset.coerce(!.VarSet, GenericVarSet),
     parse_vars_and_state_vars(VarsTerm, GenericVarSet, ContextPieces,
         MaybeVars),
@@ -482,35 +505,23 @@
         list.map(term.coerce_var, Vars0, Vars),
         list.map(term.coerce_var, DotSVars0, DotSVars),
         list.map(term.coerce_var, ColonSVars0, ColonSVars),
+            (
+                Functor = "promise_equivalent_solutions",
         MaybeGoal = ok1(promise_equivalent_solutions_expr(Vars,
             DotSVars, ColonSVars, SubGoal) - Context)
     ;
-        VarsSpecs = get_any_errors3(MaybeVars),
-        SubGoalSpecs = get_any_errors1(MaybeSubGoal),
-        MaybeGoal = error1(VarsSpecs ++ SubGoalSpecs)
-    ).
-parse_goal_2("promise_equivalent_solution_sets", [VarsTerm, SubTerm], Context,
-        ContextPieces, MaybeGoal, !VarSet) :-
-    varset.coerce(!.VarSet, GenericVarSet),
-    parse_vars_and_state_vars(VarsTerm, GenericVarSet, ContextPieces,
-        MaybeVars),
-    parse_goal(SubTerm, ContextPieces, MaybeSubGoal, !VarSet),
-    (
-        MaybeVars = ok3(Vars0, DotSVars0, ColonSVars0),
-        MaybeSubGoal = ok1(SubGoal)
-    ->
-        list.map(term.coerce_var, Vars0, Vars),
-        list.map(term.coerce_var, DotSVars0, DotSVars),
-        list.map(term.coerce_var, ColonSVars0, ColonSVars),
+                Functor = "promise_equivalent_solution_sets",
         MaybeGoal = ok1(promise_equivalent_solution_sets_expr(Vars,
             DotSVars, ColonSVars, SubGoal) - Context)
+            )
     ;
         VarsSpecs = get_any_errors3(MaybeVars),
         SubGoalSpecs = get_any_errors1(MaybeSubGoal),
         MaybeGoal = error1(VarsSpecs ++ SubGoalSpecs)
-    ).
-parse_goal_2("arbitrary", [VarsTerm, SubTerm], Context,
-        ContextPieces, MaybeGoal, !VarSet) :-
+        )
+    ;
+        Functor = "arbitrary",
+        Args = [VarsTerm, SubTerm],
     varset.coerce(!.VarSet, GenericVarSet),
     parse_vars_and_state_vars(VarsTerm, GenericVarSet, ContextPieces,
         MaybeVars),
@@ -528,58 +539,151 @@
         VarsSpecs = get_any_errors3(MaybeVars),
         SubGoalSpecs = get_any_errors1(MaybeSubGoal),
         MaybeGoal = error1(VarsSpecs ++ SubGoalSpecs)
-    ).
-parse_goal_2("promise_pure", [SubTerm], Context, ContextPieces, MaybeGoal,
-        !VarSet) :-
+        )
+    ;
+        (
+            Functor = "promise_pure",
+            Purity = purity_pure
+        ;
+            Functor = "promise_semipure",
+            Purity = purity_semipure
+        ;
+            Functor = "promise_impure",
+            Purity = purity_impure
+        ),
+        Args = [SubTerm],
     parse_goal(SubTerm, ContextPieces, MaybeSubGoal, !VarSet),
     (
         MaybeSubGoal = ok1(SubGoal),
-        Goal = promise_purity_expr(purity_pure, SubGoal) - Context,
+            Goal = promise_purity_expr(Purity, SubGoal) - Context,
         MaybeGoal = ok1(Goal)
     ;
         MaybeSubGoal = error1(Specs),
         MaybeGoal = error1(Specs)
-    ).
-parse_goal_2("promise_semipure", [SubTerm], Context, ContextPieces, MaybeGoal,
-        !VarSet) :-
+        )
+    ;
+        (
+            Functor = "require_det",
+            Detism = detism_det
+        ;
+            Functor = "require_semi",
+            Detism = detism_semi
+        ;
+            Functor = "require_multi",
+            Detism = detism_multi
+        ;
+            Functor = "require_nondet",
+            Detism = detism_non
+        ;
+            Functor = "require_cc_multi",
+            Detism = detism_cc_multi
+        ;
+            Functor = "require_cc_nondet",
+            Detism = detism_cc_non
+        ;
+            Functor = "require_erroneous",
+            Detism = detism_erroneous
+        ;
+            Functor = "require_failure",
+            Detism = detism_failure
+        ),
+        Args = [SubTerm],
     parse_goal(SubTerm, ContextPieces, MaybeSubGoal, !VarSet),
     (
         MaybeSubGoal = ok1(SubGoal),
-        Goal = promise_purity_expr(purity_semipure, SubGoal) - Context,
+            Goal = require_detism_expr(Detism, SubGoal) - Context,
         MaybeGoal = ok1(Goal)
     ;
         MaybeSubGoal = error1(Specs),
         MaybeGoal = error1(Specs)
-    ).
-parse_goal_2("promise_impure", [SubTerm], Context, ContextPieces, MaybeGoal,
-        !VarSet) :-
+        )
+    ;
+        Functor = "require_complete_switch",
+        Args = [VarsTerm, SubTerm],
+        varset.coerce(!.VarSet, GenericVarSet),
+        parse_vars(VarsTerm, GenericVarSet, ContextPieces, MaybeVars),
+        parse_goal(SubTerm, ContextPieces, MaybeSubGoal, !VarSet),
+        (
+            MaybeVars = ok1(Vars0),
+            MaybeSubGoal = ok1(SubGoal)
+        ->
+            (
+                Vars0 = [],
+                SubGoal = _ - SubContext,
+                RCSPieces = ContextPieces ++
+                    [words("Error: the first argument of"),
+                    words("require_complete_switch"),
+                    words("must contain a variable."), nl],
+                RCSSpec = error_spec(severity_error, phase_term_to_parse_tree,
+                    [simple_msg(SubContext, [always(RCSPieces)])]),
+                MaybeGoal = error1([RCSSpec])
+            ;
+                Vars0 = [Var0],
+                term.coerce_var(Var0, Var),
+                MaybeGoal = ok1(require_complete_switch_expr(Var, SubGoal)
+                    - Context)
+            ;
+                Vars0 = [_, _ | _],
+                SubGoal = _ - SubContext,
+                RCSPieces = ContextPieces ++
+                    [words("Error: the first argument of"),
+                    words("require_complete_switch"),
+                    words("cannot contain more than one variable."), nl],
+                RCSSpec = error_spec(severity_error, phase_term_to_parse_tree,
+                    [simple_msg(SubContext, [always(RCSPieces)])]),
+                MaybeGoal = error1([RCSSpec])
+            )
+        ;
+            VarsSpecs = get_any_errors1(MaybeVars),
+            SubGoalSpecs = get_any_errors1(MaybeSubGoal),
+            MaybeGoal = error1(VarsSpecs ++ SubGoalSpecs)
+        )
+    ;
+        (
+            Functor = "impure",
+            Purity = purity_impure
+        ;
+            Functor = "semipure",
+            Purity = purity_semipure
+        ),
+        Args = [SubTerm],
     parse_goal(SubTerm, ContextPieces, MaybeSubGoal, !VarSet),
     (
         MaybeSubGoal = ok1(SubGoal),
-        Goal = promise_purity_expr(purity_impure, SubGoal) - Context,
-        MaybeGoal = ok1(Goal)
+            SubGoal = SubGoalExpr - _SubContext,
+            ( SubGoalExpr = call_expr(Pred, CallArgs, purity_pure) ->
+                MaybeGoal = ok1(call_expr(Pred, CallArgs, Purity) - Context)
+            ; SubGoalExpr = unify_expr(ProgTerm1, ProgTerm2, purity_pure) ->
+                MaybeGoal = ok1(unify_expr(ProgTerm1, ProgTerm2, Purity)
+                    - Context)
     ;
-        MaybeSubGoal = error1(Specs),
-        MaybeGoal = error1(Specs)
-    ).
-parse_goal_2("impure", [SubTerm], Context, ContextPieces,
-        MaybeGoal, !VarSet) :-
-    parse_goal_with_purity(SubTerm, purity_impure, Context, ContextPieces,
-        MaybeGoal, !VarSet).
-parse_goal_2("semipure", [SubTerm], Context, ContextPieces,
-        MaybeGoal, !VarSet) :-
-    parse_goal_with_purity(SubTerm, purity_semipure, Context, ContextPieces,
-        MaybeGoal, !VarSet).
-parse_goal_2("event", [SubTerm], Context, ContextPieces, MaybeGoal, !VarSet) :-
+                % Inappropriate placement of an impurity marker, so we treat
+                % it like a predicate call. typecheck.m prints out something
+                % descriptive for these errors.
+                %
+                % XXX we could return MaybeGoal = error1 here.
+                purity_name(Purity, PurityString),
+                term.coerce(SubTerm, CoercedSubTerm),
+                GoalExpr = call_expr(unqualified(PurityString),
+                    [CoercedSubTerm], purity_pure),
+                MaybeGoal = ok1(GoalExpr - Context)
+            )
+        ;
+            MaybeSubGoal = error1(_),
+            MaybeGoal = MaybeSubGoal
+        )
+    ;
+        Functor = "event",
+        Args = [SubTerm],
     parse_goal(SubTerm, ContextPieces, MaybeSubGoal, !VarSet),
     (
         MaybeSubGoal = ok1(SubGoal),
-        ( SubGoal = call_expr(SymName, Args, Purity) - SubContext ->
+            ( SubGoal = call_expr(SymName, CallArgs, Purity) - SubContext ->
             (
                 SymName = unqualified(EventName),
                 Purity = purity_pure
             ->
-                Goal = event_expr(EventName, Args) - Context,
+                    Goal = event_expr(EventName, CallArgs) - Context,
                 MaybeGoal = ok1(Goal)
             ;
                 some [!Specs] (
@@ -590,11 +694,12 @@
                         SymName = qualified(_, _),
                         QualPieces = ContextPieces ++
                             [lower_case_next_if_not_first,
-                            words("Error: event name must not be qualified."),
-                            nl],
+                                words("Error: event name"),
+                                words("must not be qualified."), nl],
                         QualSpec = error_spec(severity_error,
                             phase_term_to_parse_tree,
-                            [simple_msg(SubContext, [always(QualPieces)])]),
+                                [simple_msg(SubContext,
+                                    [always(QualPieces)])]),
                         !:Specs = [QualSpec | !.Specs]
                     ),
                     (
@@ -609,7 +714,8 @@
                             words("impure or semipure."), nl],
                         PuritySpec = error_spec(severity_error,
                             phase_term_to_parse_tree,
-                            [simple_msg(SubContext, [always(PurityPieces)])]),
+                                [simple_msg(SubContext,
+                                    [always(PurityPieces)])]),
                         !:Specs = [PuritySpec | !.Specs]
                     ),
                     MaybeGoal = error1(!.Specs)
@@ -626,44 +732,16 @@
     ;
         MaybeSubGoal = error1(Specs),
         MaybeGoal = error1(Specs)
-    ).
-parse_goal_2("is", [ATerm0, BTerm0], Context, _CP, MaybeGoal, !VarSet) :-
+        )
+    ;
+        Functor = "is",
+        Args = [ATerm0, BTerm0],
     % The following is a temporary hack to handle `is' in the parser -
     % we ought to handle it in the code generation - but then `is/2' itself
     % is a bit of a hack.
     term.coerce(ATerm0, ATerm),
     term.coerce(BTerm0, BTerm),
-    MaybeGoal = ok1(unify_expr(ATerm, BTerm, purity_pure) - Context).
-
-:- pred parse_goal_with_purity(term::in, purity::in, context::in,
-    list(format_component)::in, maybe1(goal)::out,
-    prog_varset::in, prog_varset::out) is det.
-
-parse_goal_with_purity(Term, Purity, Context, ContextPieces, MaybeGoal,
-        !VarSet) :-
-    parse_goal(Term, ContextPieces, MaybeSubGoal, !VarSet),
-    (
-        MaybeSubGoal = ok1(SubGoal),
-        SubGoal = SubGoalExpr - _SubContext,
-        ( SubGoalExpr = call_expr(Pred, Args, purity_pure) ->
-            MaybeGoal = ok1(call_expr(Pred, Args, Purity) - Context)
-        ; SubGoalExpr = unify_expr(ProgTerm1, ProgTerm2, purity_pure) ->
-            MaybeGoal = ok1(unify_expr(ProgTerm1, ProgTerm2, Purity) - Context)
-        ;
-            % Inappropriate placement of an impurity marker, so we treat
-            % it like a predicate call. typecheck.m prints out something
-            % descriptive for these errors.
-            %
-            % XXX we could return MaybeGoal = error1 here.
-            purity_name(Purity, PurityString),
-            term.coerce(Term, CoercedTerm),
-            GoalExpr = call_expr(unqualified(PurityString), [CoercedTerm],
-                purity_pure),
-            MaybeGoal = ok1(GoalExpr - Context)
-        )
-    ;
-        MaybeSubGoal = error1(_),
-        MaybeGoal = MaybeSubGoal
+        MaybeGoal = ok1(unify_expr(ATerm, BTerm, purity_pure) - Context)
     ).
 
 %-----------------------------------------------------------------------------%
Index: compiler/prog_item.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_item.m,v
retrieving revision 1.40
diff -u -b -r1.40 prog_item.m
--- compiler/prog_item.m	10 Sep 2010 05:14:59 -0000	1.40
+++ compiler/prog_item.m	27 Dec 2010 10:23:11 -0000
@@ -789,6 +789,14 @@
                 prog_vars,  % ColonStateVars
                 goal
             )
+    ;       require_detism_expr(
+                determinism,
+                goal
+            )
+    ;       require_complete_switch_expr(
+                prog_var,
+                goal
+            )
     ;       trace_expr(
                 texpr_compiletime   :: maybe(trace_expr(trace_compiletime)),
                 texpr_runtime       :: maybe(trace_expr(trace_runtime)),
Index: compiler/prog_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_util.m,v
retrieving revision 1.110
diff -u -b -r1.110 prog_util.m
--- compiler/prog_util.m	15 Dec 2010 06:29:58 -0000	1.110
+++ compiler/prog_util.m	27 Dec 2010 11:57:07 -0000
@@ -265,79 +265,93 @@
 :- pred rename_in_goal_expr(prog_var::in, prog_var::in,
     goal_expr::in, goal_expr::out) is det.
 
-rename_in_goal_expr(OldVar, NewVar,
-        conj_expr(GoalA0, GoalB0),
-        conj_expr(GoalA, GoalB)) :-
+rename_in_goal_expr(OldVar, NewVar, Expr0, Expr) :-
+    (
+        ( Expr0 = true_expr
+        ; Expr0 = fail_expr
+        ),
+        Expr = Expr0
+    ;
+        Expr0 = conj_expr(GoalA0, GoalB0),
     rename_in_goal(OldVar, NewVar, GoalA0, GoalA),
-    rename_in_goal(OldVar, NewVar, GoalB0, GoalB).
-rename_in_goal_expr(OldVar, NewVar,
-        par_conj_expr(GoalA0, GoalB0),
-        par_conj_expr(GoalA, GoalB)) :-
+        rename_in_goal(OldVar, NewVar, GoalB0, GoalB),
+        Expr = conj_expr(GoalA, GoalB)
+    ;
+        Expr0 = par_conj_expr(GoalA0, GoalB0),
     rename_in_goal(OldVar, NewVar, GoalA0, GoalA),
-    rename_in_goal(OldVar, NewVar, GoalB0, GoalB).
-rename_in_goal_expr(_OldVar, _NewVar, true_expr, true_expr).
-rename_in_goal_expr(OldVar, NewVar,
-        disj_expr(GoalA0, GoalB0),
-        disj_expr(GoalA, GoalB)) :-
+        rename_in_goal(OldVar, NewVar, GoalB0, GoalB),
+        Expr = par_conj_expr(GoalA, GoalB)
+    ;
+        Expr0 = disj_expr(GoalA0, GoalB0),
     rename_in_goal(OldVar, NewVar, GoalA0, GoalA),
-    rename_in_goal(OldVar, NewVar, GoalB0, GoalB).
-rename_in_goal_expr(_Var, _NewVar, fail_expr, fail_expr).
-rename_in_goal_expr(OldVar, NewVar, not_expr(Goal0), not_expr(Goal)) :-
-    rename_in_goal(OldVar, NewVar, Goal0, Goal).
-rename_in_goal_expr(OldVar, NewVar,
-        some_expr(Vars0, Goal0),
-        some_expr(Vars, Goal)) :-
+        rename_in_goal(OldVar, NewVar, GoalB0, GoalB),
+        Expr = disj_expr(GoalA, GoalB)
+    ;
+        Expr0 = not_expr(Goal0),
+        rename_in_goal(OldVar, NewVar, Goal0, Goal),
+        Expr = not_expr(Goal)
+    ;
+        Expr0 = some_expr(Vars0, Goal0),
     rename_in_vars(OldVar, NewVar, Vars0, Vars),
-    rename_in_goal(OldVar, NewVar, Goal0, Goal).
-rename_in_goal_expr(OldVar, NewVar,
-        some_state_vars_expr(Vars0, Goal0),
-        some_state_vars_expr(Vars, Goal)) :-
+        rename_in_goal(OldVar, NewVar, Goal0, Goal),
+        Expr = some_expr(Vars, Goal)
+    ;
+        Expr0 = some_state_vars_expr(Vars0, Goal0),
     rename_in_vars(OldVar, NewVar, Vars0, Vars),
-    rename_in_goal(OldVar, NewVar, Goal0, Goal).
-rename_in_goal_expr(OldVar, NewVar,
-        all_expr(Vars0, Goal0),
-        all_expr(Vars, Goal)) :-
+        rename_in_goal(OldVar, NewVar, Goal0, Goal),
+        Expr = some_state_vars_expr(Vars, Goal)
+    ;
+        Expr0 = all_expr(Vars0, Goal0),
     rename_in_vars(OldVar, NewVar, Vars0, Vars),
-    rename_in_goal(OldVar, NewVar, Goal0, Goal).
-rename_in_goal_expr(OldVar, NewVar,
-        all_state_vars_expr(Vars0, Goal0),
-        all_state_vars_expr(Vars, Goal)) :-
+        rename_in_goal(OldVar, NewVar, Goal0, Goal),
+        Expr = all_expr(Vars, Goal)
+    ;
+        Expr0 = all_state_vars_expr(Vars0, Goal0),
     rename_in_vars(OldVar, NewVar, Vars0, Vars),
-    rename_in_goal(OldVar, NewVar, Goal0, Goal).
-rename_in_goal_expr(OldVar, NewVar,
-        promise_purity_expr(Purity, Goal0),
-        promise_purity_expr(Purity, Goal)) :-
-    rename_in_goal(OldVar, NewVar, Goal0, Goal).
-rename_in_goal_expr(OldVar, NewVar,
-        promise_equivalent_solutions_expr(Vars0, DotSVars0, ColonSVars0,
-            Goal0),
-        promise_equivalent_solutions_expr(Vars, DotSVars, ColonSVars,
-            Goal)) :-
+        rename_in_goal(OldVar, NewVar, Goal0, Goal),
+        Expr = all_state_vars_expr(Vars, Goal)
+    ;
+        Expr0 = promise_purity_expr(Purity, Goal0),
+        rename_in_goal(OldVar, NewVar, Goal0, Goal),
+        Expr = promise_purity_expr(Purity, Goal)
+    ;
+        Expr0 = promise_equivalent_solutions_expr(Vars0,
+            DotSVars0, ColonSVars0, Goal0),
     rename_in_vars(OldVar, NewVar, Vars0, Vars),
     rename_in_vars(OldVar, NewVar, DotSVars0, DotSVars),
     rename_in_vars(OldVar, NewVar, ColonSVars0, ColonSVars),
-    rename_in_goal(OldVar, NewVar, Goal0, Goal).
-rename_in_goal_expr(OldVar, NewVar,
-        promise_equivalent_solution_sets_expr(Vars0, DotSVars0, ColonSVars0,
-            Goal0),
-        promise_equivalent_solution_sets_expr(Vars, DotSVars, ColonSVars,
-            Goal)) :-
+        rename_in_goal(OldVar, NewVar, Goal0, Goal),
+        Expr = promise_equivalent_solutions_expr(Vars,
+            DotSVars, ColonSVars, Goal)
+    ;
+        Expr0 = promise_equivalent_solution_sets_expr(Vars0,
+            DotSVars0, ColonSVars0, Goal0),
     rename_in_vars(OldVar, NewVar, Vars0, Vars),
     rename_in_vars(OldVar, NewVar, DotSVars0, DotSVars),
     rename_in_vars(OldVar, NewVar, ColonSVars0, ColonSVars),
-    rename_in_goal(OldVar, NewVar, Goal0, Goal).
-rename_in_goal_expr(OldVar, NewVar,
-        promise_equivalent_solution_arbitrary_expr(Vars0,
+        rename_in_goal(OldVar, NewVar, Goal0, Goal),
+        Expr = promise_equivalent_solution_sets_expr(Vars,
+            DotSVars, ColonSVars, Goal)
+    ;
+        Expr0 = promise_equivalent_solution_arbitrary_expr(Vars0,
             DotSVars0, ColonSVars0, Goal0),
-        promise_equivalent_solution_arbitrary_expr(Vars,
-            DotSVars, ColonSVars, Goal)) :-
     rename_in_vars(OldVar, NewVar, Vars0, Vars),
     rename_in_vars(OldVar, NewVar, DotSVars0, DotSVars),
     rename_in_vars(OldVar, NewVar, ColonSVars0, ColonSVars),
-    rename_in_goal(OldVar, NewVar, Goal0, Goal).
-rename_in_goal_expr(OldVar, NewVar,
-        trace_expr(CompileTime, RunTime, MaybeIO0, Mutables0, Goal0),
-        trace_expr(CompileTime, RunTime, MaybeIO, Mutables, Goal)) :-
+        rename_in_goal(OldVar, NewVar, Goal0, Goal),
+        Expr = promise_equivalent_solution_arbitrary_expr(Vars,
+            DotSVars, ColonSVars, Goal)
+    ;
+        Expr0 = require_detism_expr(Detism, Goal0),
+        rename_in_goal(OldVar, NewVar, Goal0, Goal),
+        Expr = require_detism_expr(Detism, Goal)
+    ;
+        Expr0 = require_complete_switch_expr(Var0, Goal0),
+        rename_in_var(OldVar, NewVar, Var0, Var),
+        rename_in_goal(OldVar, NewVar, Goal0, Goal),
+        Expr = require_complete_switch_expr(Var, Goal)
+    ;
+        Expr0 = trace_expr(CompileTime, RunTime, MaybeIO0, Mutables0, Goal0),
     (
         MaybeIO0 = no,
         MaybeIO = no
@@ -348,10 +362,11 @@
     ),
     list.map(rename_in_trace_mutable_var(OldVar, NewVar),
         Mutables0, Mutables),
-    rename_in_goal(OldVar, NewVar, Goal0, Goal).
-rename_in_goal_expr(OldVar, NewVar,
-        atomic_expr(InVars0, OutVars0, MaybeVars0, MainExpr0, OrElseExpr0),
-        atomic_expr(InVars, OutVars, MaybeVars, MainExpr, OrElseExpr)) :-
+        rename_in_goal(OldVar, NewVar, Goal0, Goal),
+        Expr = trace_expr(CompileTime, RunTime, MaybeIO, Mutables, Goal)
+    ;
+        Expr0 = atomic_expr(InVars0, OutVars0, MaybeVars0, MainExpr0,
+            OrElseExpr0),
     rename_in_atomic_varlist(OldVar, NewVar, InVars0, InVars),
     rename_in_atomic_varlist(OldVar, NewVar, OutVars0, OutVars),
     (
@@ -364,11 +379,11 @@
         MaybeVars = yes(TransVars)
     ),
     rename_in_goal(OldVar, NewVar, MainExpr0, MainExpr),
-    list.map(rename_in_goal(OldVar, NewVar), OrElseExpr0, OrElseExpr).
-rename_in_goal_expr(OldVar, NewVar,
-        try_expr(MaybeIO0, SubGoal0, Then0, MaybeElse0, Catches0,
+        list.map(rename_in_goal(OldVar, NewVar), OrElseExpr0, OrElseExpr),
+        Expr = atomic_expr(InVars, OutVars, MaybeVars, MainExpr, OrElseExpr)
+    ;
+        Expr0 = try_expr(MaybeIO0, SubGoal0, Then0, MaybeElse0, Catches0,
             MaybeCatchAny0),
-        try_expr(MaybeIO, SubGoal, Then, MaybeElse, Catches, MaybeCatchAny)) :-
     rename_in_maybe_var(OldVar, NewVar, MaybeIO0, MaybeIO),
     rename_in_goal(OldVar, NewVar, SubGoal0, SubGoal),
     rename_in_goal(OldVar, NewVar, Then0, Then),
@@ -389,38 +404,45 @@
     ;
         MaybeCatchAny0 = no,
         MaybeCatchAny = no
-    ).
-rename_in_goal_expr(OldVar, NewVar,
-        implies_expr(GoalA0, GoalB0),
-        implies_expr(GoalA, GoalB)) :-
+        ),
+        Expr = try_expr(MaybeIO, SubGoal, Then, MaybeElse, Catches,
+            MaybeCatchAny)
+    ;
+        Expr0 = implies_expr(GoalA0, GoalB0),
     rename_in_goal(OldVar, NewVar, GoalA0, GoalA),
-    rename_in_goal(OldVar, NewVar, GoalB0, GoalB).
-rename_in_goal_expr(OldVar, NewVar,
-        equivalent_expr(GoalA0, GoalB0),
-        equivalent_expr(GoalA, GoalB)) :-
+        rename_in_goal(OldVar, NewVar, GoalB0, GoalB),
+        Expr = implies_expr(GoalA, GoalB)
+    ;
+        Expr0 = equivalent_expr(GoalA0, GoalB0),
     rename_in_goal(OldVar, NewVar, GoalA0, GoalA),
-    rename_in_goal(OldVar, NewVar, GoalB0, GoalB).
-rename_in_goal_expr(OldVar, NewVar,
-        if_then_else_expr(Vars0, StateVars0, Cond0, Then0, Else0),
-        if_then_else_expr(Vars, StateVars, Cond, Then, Else)) :-
+        rename_in_goal(OldVar, NewVar, GoalB0, GoalB),
+        Expr = equivalent_expr(GoalA, GoalB)
+    ;
+        Expr0 = if_then_else_expr(Vars0, StateVars0, Cond0, Then0, Else0),
     rename_in_vars(OldVar, NewVar, Vars0, Vars),
     rename_in_vars(OldVar, NewVar, StateVars0, StateVars),
     rename_in_goal(OldVar, NewVar, Cond0, Cond),
     rename_in_goal(OldVar, NewVar, Then0, Then),
-    rename_in_goal(OldVar, NewVar, Else0, Else).
-rename_in_goal_expr(OldVar, NewVar,
-        event_expr(Name, Terms0),
-        event_expr(Name, Terms)) :-
-    term.substitute_list(Terms0, OldVar, variable(NewVar, context_init), Terms).
-rename_in_goal_expr(OldVar, NewVar,
-        call_expr(SymName, Terms0, Purity),
-        call_expr(SymName, Terms, Purity)) :-
-    term.substitute_list(Terms0, OldVar, variable(NewVar, context_init), Terms).
-rename_in_goal_expr(OldVar, NewVar,
-        unify_expr(TermA0, TermB0, Purity),
-        unify_expr(TermA, TermB, Purity)) :-
-    term.substitute(TermA0, OldVar, term.variable(NewVar, context_init), TermA),
-    term.substitute(TermB0, OldVar, term.variable(NewVar, context_init), TermB).
+        rename_in_goal(OldVar, NewVar, Else0, Else),
+        Expr = if_then_else_expr(Vars, StateVars, Cond, Then, Else)
+    ;
+        Expr0 = event_expr(Name, Terms0),
+        term.substitute_list(Terms0, OldVar, variable(NewVar, context_init),
+            Terms),
+        Expr = event_expr(Name, Terms)
+    ;
+        Expr0 = call_expr(SymName, Terms0, Purity),
+        term.substitute_list(Terms0, OldVar, variable(NewVar, context_init),
+            Terms),
+        Expr = call_expr(SymName, Terms, Purity)
+    ;
+        Expr0 = unify_expr(TermA0, TermB0, Purity),
+        term.substitute(TermA0, OldVar, term.variable(NewVar, context_init),
+            TermA),
+        term.substitute(TermB0, OldVar, term.variable(NewVar, context_init),
+            TermB),
+        Expr = unify_expr(TermA, TermB, Purity)
+    ).
 
 :- pred rename_in_atomic_varlist(prog_var::in, prog_var::in,
     atomic_component_state::in, atomic_component_state::out) is det.
Index: compiler/purity.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/purity.m,v
retrieving revision 1.139
diff -u -b -r1.139 purity.m
--- compiler/purity.m	15 Dec 2010 06:29:58 -0000	1.139
+++ compiler/purity.m	27 Dec 2010 04:57:34 -0000
@@ -657,6 +657,8 @@
             % that, e.g. by avoiding repeatedly taking the varset and vartypes
             % out of !Info and just as repeatedly putting it back again.
             ( Reason = promise_solutions(_, _)
+            ; Reason = require_detism(_)
+            ; Reason = require_complete_switch(_)
             ; Reason = commit(_)
             ; Reason = barrier(_)
             ; Reason = from_ground_term(_, _)
Index: compiler/quantification.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/quantification.m,v
retrieving revision 1.140
diff -u -b -r1.140 quantification.m
--- compiler/quantification.m	15 Dec 2010 06:29:59 -0000	1.140
+++ compiler/quantification.m	28 Dec 2010 03:24:32 -0000
@@ -713,6 +713,8 @@
     ;
         ( Reason0 = promise_purity(_)
         ; Reason0 = promise_solutions(_, _)
+        ; Reason0 = require_detism(_)
+        ; Reason0 = require_complete_switch(_)
         ; Reason0 = commit(_)
         ; Reason0 = barrier(_)
         ; Reason0 = from_ground_term(_, from_ground_term_deconstruct)
@@ -725,9 +727,9 @@
             NonLocalsToRecompute, !Info)
     ;
         Reason0 = trace_goal(_, _, _, _, Vars0),
-        implicitly_quantify_goal_quant_info_scope_rename_vars(
-            Reason0, Reason, SubGoal0, SubGoal1, Vars0, Vars, GoalInfo0,
-            NonLocalsToRecompute, !Info),
+        implicitly_quantify_goal_quant_info_scope_rename_vars(Reason0, Reason,
+            SubGoal0, SubGoal1, Vars0, Vars, GoalInfo0, NonLocalsToRecompute,
+            !Info),
         goal_expr_vars_bitset(NonLocalsToRecompute, GoalExpr0,
             PossiblyNonLocalGoalVars0),
         implicitly_quantify_goal_quant_info(SubGoal1, SubGoal,
@@ -781,14 +783,15 @@
             Reason = trace_goal(Comp, Run, IO, Mut, TraceVars)
         ;
             ( Reason0 = promise_purity(_)
+            ; Reason0 = promise_solutions(_, _)
+            ; Reason0 = require_detism(_)
+            ; Reason0 = require_complete_switch(_)
             ; Reason0 = commit(_)
             ; Reason0 = barrier(_)
             ; Reason0 = from_ground_term(_, _)
-            ; Reason0 = promise_solutions(_, _)
             ),
             % We shouldn't invoke this predicate for these kinds of scopes.
-            unexpected(this_file,
-                "implicitly_quantify_goal_quant_info_scope_rename_vars")
+            unexpected($module, $pred, "unexpected scope")
         )
     ),
     update_seen_vars(QVars, !Info),
@@ -1878,6 +1881,7 @@
         LambdaSet0 = !.LambdaSet,
         (
             ( Reason = promise_purity(_)
+            ; Reason = require_detism(_)
             ; Reason = commit(_)
             ; Reason = barrier(_)
             ; Reason = trace_goal(_, _, _, _, _)
@@ -1896,6 +1900,11 @@
                 !:Set, !:LambdaSet),
             insert_list(!.Set, Vars, !:Set)
         ;
+            Reason = require_complete_switch(Var),
+            goal_vars_both_maybe_lambda(NonLocalsToRecompute, SubGoal,
+                !:Set, !:LambdaSet),
+            insert(!.Set, Var, !:Set)
+        ;
             Reason = from_ground_term(TermVar, Kind),
             (
                 Kind = from_ground_term_construct,
@@ -2040,6 +2049,7 @@
         LambdaSet0 = !.LambdaSet,
         (
             ( Reason = promise_purity(_)
+            ; Reason = require_detism(_)
             ; Reason = commit(_)
             ; Reason = barrier(_)
             ; Reason = trace_goal(_, _, _, _, _)
@@ -2058,6 +2068,11 @@
                 !:Set, !:LambdaSet),
             insert_list(!.Set, Vars, !:Set)
         ;
+            Reason = require_complete_switch(Var),
+            goal_vars_both_maybe_lambda_and_bi_impl(SubGoal,
+                !:Set, !:LambdaSet),
+            insert(!.Set, Var, !:Set)
+        ;
             Reason = from_ground_term(_TermVar, _Kind),
             goal_vars_both_maybe_lambda_and_bi_impl(SubGoal,
                 !:Set, !:LambdaSet)
@@ -2186,6 +2201,7 @@
         Set0 = !.Set,
         (
             ( Reason = promise_purity(_)
+            ; Reason = require_detism(_)
             ; Reason = commit(_)
             ; Reason = barrier(_)
             ; Reason = trace_goal(_, _, _, _, _)
@@ -2200,6 +2216,10 @@
             goal_vars_both_no_lambda(NonLocalsToRecompute, SubGoal, !:Set),
             insert_list(!.Set, Vars, !:Set)
         ;
+            Reason = require_complete_switch(Var),
+            goal_vars_both_no_lambda(NonLocalsToRecompute, SubGoal, !:Set),
+            insert(!.Set, Var, !:Set)
+        ;
             Reason = from_ground_term(_TermVar, _),
             goal_vars_both_no_lambda(NonLocalsToRecompute, SubGoal, !:Set)
             % _TermVar should have been put into the relevant sets when we
Index: compiler/saved_vars.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/saved_vars.m,v
retrieving revision 1.86
diff -u -b -r1.86 saved_vars.m
--- compiler/saved_vars.m	15 Dec 2010 06:30:01 -0000	1.86
+++ compiler/saved_vars.m	27 Dec 2010 07:46:10 -0000
@@ -317,6 +317,12 @@
                 ; Reason = trace_goal(_, _, _, _, _)
                 ),
                 CanPush = no
+            ;
+                ( Reason = require_detism(_)
+                ; Reason = require_complete_switch(_)
+                ),
+                % These scopes should have been deleted by now.
+                unexpected($module, $pred, "unexpected scope")
             )
         ;
             GoalExpr = switch(SwitchVar, _, _),
Index: compiler/simplify.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/simplify.m,v
retrieving revision 1.253
diff -u -b -r1.253 simplify.m
--- compiler/simplify.m	15 Dec 2010 06:30:01 -0000	1.253
+++ compiler/simplify.m	28 Dec 2010 03:23:52 -0000
@@ -146,8 +146,10 @@
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.
 :- import_module parse_tree.builtin_lib_types.
+:- import_module parse_tree.mercury_to_mercury.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_mode.
+:- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_type.
 :- import_module parse_tree.prog_type_subst.
 :- import_module parse_tree.prog_util.
@@ -1907,9 +1909,11 @@
         )
     ;
         simplify_info_get_common_info(!.Info, Common),
+        % Note that we need to keep SubGoal0 for require_complete_switch
+        % scopes.
         simplify_goal(SubGoal0, SubGoal, !Info),
         nested_scopes(Reason0, SubGoal, GoalInfo0, Goal1),
-        Goal1 = hlds_goal(GoalExpr1, _GoalInfo1),
+        Goal1 = hlds_goal(GoalExpr1, GoalInfo1),
         ( GoalExpr1 = scope(FinalReason, FinalSubGoal) ->
             (
                 ( FinalReason = promise_purity(_)
@@ -1936,6 +1940,58 @@
                 % of the goal.
                 simplify_info_set_common_info(Common, !Info)
             ;
+                FinalReason = require_detism(RequiredDetism),
+                FinalSubGoal = hlds_goal(_, FinalSubGoalInfo),
+                ActualDetism = goal_info_get_determinism(FinalSubGoalInfo),
+                ( ActualDetism = RequiredDetism ->
+                    true
+                ;
+                    RequiredDetismStr = determinism_to_string(RequiredDetism),
+                    ActualDetismStr = determinism_to_string(ActualDetism),
+                    DetismPieces = [words("Error: required determinism is"),
+                        quote(RequiredDetismStr), suffix(","),
+                        words("but actual determinism is"),
+                        quote(ActualDetismStr), suffix("."), nl],
+                    Context = goal_info_get_context(GoalInfo1),
+                    DetismMsg = simple_msg(Context, [always(DetismPieces)]),
+                    DetismSpec = error_spec(severity_error,
+                        phase_simplify(report_in_any_mode), [DetismMsg]),
+                    simplify_info_add_error_spec(DetismSpec, !Info)
+                ),
+                Goal = FinalSubGoal
+            ;
+                FinalReason = require_complete_switch(RequiredVar),
+                % We must test the version of the subgoal that has not yet been
+                % simplified, since simplification can convert a complete
+                % switch into an incomplete switch by deleting an arm
+                % consisting of nothing but `fail'.
+                SubGoal0 = hlds_goal(SubGoalExpr0, _),
+                (
+                    SubGoalExpr0 = switch(SwitchVar, CanFail, _Cases),
+                    SwitchVar = RequiredVar
+                ->
+                    (
+                        CanFail = cannot_fail
+                    ;
+                        CanFail = can_fail,
+                        simplify_info_get_varset(!.Info, VarSet),
+                        VarStr = mercury_var_to_string(VarSet, no, SwitchVar),
+                        SwitchPieces = [words("Error: the switch on"),
+                            quote(VarStr), 
+                            words("is required to be complete,"),
+                            words("but it is not."), nl],
+                        Context = goal_info_get_context(GoalInfo1),
+                        SwitchMsg = simple_msg(Context,
+                            [always(SwitchPieces)]),
+                        SwitchSpec = error_spec(severity_error,
+                            phase_simplify(report_in_any_mode), [SwitchMsg]),
+                        simplify_info_add_error_spec(SwitchSpec, !Info)
+                    )
+                ;
+                    true
+                ),
+                Goal = FinalSubGoal
+            ;
                 FinalReason = trace_goal(MaybeCompiletimeExpr,
                     MaybeRuntimeExpr, _, _, _),
                 ( simplify_do_after_front_end(!.Info) ->
@@ -1960,8 +2016,7 @@
         Goal0, Goal, !Info) :-
     (
         MaybeCompiletimeExpr = yes(CompiletimeExpr),
-        KeepGoal = evaluate_compile_time_condition(CompiletimeExpr,
-            !.Info)
+        KeepGoal = evaluate_compile_time_condition(CompiletimeExpr, !.Info)
     ;
         MaybeCompiletimeExpr = no,
         % A missing compile time condition means that the
@@ -3611,6 +3666,8 @@
             ( Reason = exist_quant(_)
             ; Reason = promise_solutions(_, _)
             ; Reason = promise_purity(_)
+            ; Reason = require_detism(_)
+            ; Reason = require_complete_switch(_)
             ; Reason = commit(_)
             ; Reason = barrier(_)
             ; Reason = from_ground_term(_, from_ground_term_deconstruct)
Index: compiler/stm_expand.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/stm_expand.m,v
retrieving revision 1.13
diff -u -b -r1.13 stm_expand.m
--- compiler/stm_expand.m	15 Dec 2010 06:30:03 -0000	1.13
+++ compiler/stm_expand.m	27 Dec 2010 07:52:19 -0000
@@ -348,6 +348,12 @@
             stm_process_goal(Instmap, InnerGoal0, InnerGoal, !Info),
             GoalExpr = scope(Reason, InnerGoal),
             Goal = hlds_goal(GoalExpr, GoalInfo0)
+        ;
+            ( Reason = require_detism(_)
+            ; Reason = require_complete_switch(_)
+            ),
+            % These scopes should have been deleted by now.
+            unexpected($module, $pred, "unexpected scope")
         )
     ;
         GoalExpr0 = if_then_else(Vars, Cond0, Then0, Else0),
Index: compiler/try_expand.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/try_expand.m,v
retrieving revision 1.12
diff -u -b -r1.12 try_expand.m
--- compiler/try_expand.m	15 Dec 2010 06:30:07 -0000	1.12
+++ compiler/try_expand.m	27 Dec 2010 04:57:34 -0000
@@ -382,6 +382,8 @@
             ( Reason = exist_quant(_)
             ; Reason = promise_solutions(_, _)
             ; Reason = promise_purity(_)
+            ; Reason = require_detism(_)
+            ; Reason = require_complete_switch(_)
             ; Reason = commit(_)
             ; Reason = barrier(_)
             ; Reason = from_ground_term(_, from_ground_term_deconstruct)
Index: compiler/typecheck.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/typecheck.m,v
retrieving revision 1.450
diff -u -b -r1.450 typecheck.m
--- compiler/typecheck.m	20 Dec 2010 07:47:39 -0000	1.450
+++ compiler/typecheck.m	27 Dec 2010 04:57:33 -0000
@@ -1280,18 +1280,17 @@
             Reason = exist_quant(Vars),
             ensure_vars_have_a_type(Vars, !Info)
         ;
-            Reason = promise_purity(_)
-        ;
             Reason = promise_solutions(Vars, _),
             ensure_vars_have_a_type(Vars, !Info)
         ;
-            Reason = commit(_)
-        ;
-            Reason = barrier(_)
-        ;
-            Reason = from_ground_term(_, _)
-        ;
-            Reason = trace_goal(_, _, _, _, _)
+            ( Reason = promise_purity(_)
+            ; Reason = require_detism(_)
+            ; Reason = require_complete_switch(_)
+            ; Reason = commit(_)
+            ; Reason = barrier(_)
+            ; Reason = from_ground_term(_, _)
+            ; Reason = trace_goal(_, _, _, _, _)
+            )
         ),
         GoalExpr = scope(Reason, SubGoal)
     ;
cvs diff: Diffing compiler/notes
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.453
diff -u -b -r1.453 reference_manual.texi
--- doc/reference_manual.texi	20 Dec 2010 05:47:23 -0000	1.453
+++ doc/reference_manual.texi	28 Dec 2010 03:48:35 -0000
@@ -510,6 +510,15 @@
 promise_impure                  fx                950
 promise_pure                    fx                950
 promise_semipure                fx                950
+require_complete_switch         fxy               950
+require_det                     fx                950
+require_semidet                 fx                950
+require_multi                   fx                950
+require_nondet                  fx                950
+require_cc_multi                fx                950
+require_cc_nondet               fx                950
+require_erroneous               fx                950
+require_failure                 fx                950
 some                            fxy               950
 ,                               xfy               1000
 &                               xfy               1025
@@ -870,6 +879,43 @@
 are not allowed to occur outside
 @code{promise_equivalent_solution_sets @var{Vars} @var{Goal}} goals.
 
+ at item @code{require_det @var{Goal}}
+A determinism check, typically used to enhance the robustness of code.
+ at var{Goal} must be a valid goal.
+If @var{Goal} is det, then
+ at item @code{require_det @var{Goal}} is equivalent to just @var{Goal}.
+If @var{Goal} is not det,
+then the compiler is required to generate an error message.
+
+The @code{require_det} keyword
+may be replaced with
+ at code{require_semidet},
+ at code{require_multi},
+ at code{require_nondet},
+ at code{require_cc_multi},
+ at code{require_cc_nondet},
+ at code{require_erroneous} or
+ at code{require_failure},
+each of which requires @var{Goal} to have the named determinism.
+
+ at item @code{require_complete_switch [@var{Var}] @var{Goal}}
+A switch completeness check, typically used to enhance the robustness of code.
+If @var{Goal} is a complete switch on @var{Var},
+i.e. a switch that has an arm
+for all the function symbols in the type of @var{Var},
+then @code{require_complete_switch [@var{Var}] @var{Goal}}
+is equivalent to @var{Goal}.
+If @var{Goal} is a switch on @var{Var} but it is not a complete switch,
+i.e. it has no arm
+for at least one of the function symbols in the type of @var{Var},
+then the compiler is required to generate an error message.
+If @var{Goal} is not a switch on @var{Var},
+then @code{require_complete_switch [@var{Var}] @var{Goal}}
+is equivalent to @var{Goal}.
+This is intended to allow these scopes to be used
+even if @var{Var} is input to the scope
+only in some but not all modes of the containing predicate.
+
 @item @code{trace @var{Params} @var{Goal}}
 A trace goal, typically used for debugging or logging.
 @var{Goal} must be a valid goal;
cvs diff: Diffing extras
cvs diff: Diffing extras/base64
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/fixed
cvs diff: Diffing extras/gator
cvs diff: Diffing extras/gator/generations
cvs diff: Diffing extras/gator/generations/1
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_allegro
cvs diff: Diffing extras/graphics/mercury_allegro/examples
cvs diff: Diffing extras/graphics/mercury_allegro/samples
cvs diff: Diffing extras/graphics/mercury_allegro/samples/demo
cvs diff: Diffing extras/graphics/mercury_allegro/samples/mandel
cvs diff: Diffing extras/graphics/mercury_allegro/samples/pendulum2
cvs diff: Diffing extras/graphics/mercury_allegro/samples/speed
cvs diff: Diffing extras/graphics/mercury_cairo
cvs diff: Diffing extras/graphics/mercury_cairo/samples
cvs diff: Diffing extras/graphics/mercury_cairo/samples/data
cvs diff: Diffing extras/graphics/mercury_cairo/tutorial
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/log4m
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/monte
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/mopenssl
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/net
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/posix/samples
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/solver_types
cvs diff: Diffing extras/solver_types/library
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/windows_installer_generator
cvs diff: Diffing extras/windows_installer_generator/sample
cvs diff: Diffing extras/windows_installer_generator/sample/images
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
Index: library/ops.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/ops.m,v
retrieving revision 1.72
diff -u -b -r1.72 ops.m
--- library/ops.m	10 Mar 2009 05:00:28 -0000	1.72
+++ library/ops.m	27 Dec 2010 13:40:46 -0000
@@ -435,6 +435,7 @@
         ( Op = "arbitrary"
         ; Op = "promise_equivalent_solutions"
         ; Op = "promise_equivalent_solution_sets"
+        ; Op = "require_complete_switch"
         ; Op = "trace"
         ; Op = "atomic"
         ; Op = "try"
@@ -452,6 +453,14 @@
         ( Op = "promise_pure"
         ; Op = "promise_semipure"
         ; Op = "promise_impure"
+        ; Op = "require_det"
+        ; Op = "require_semidet"
+        ; Op = "require_multi"
+        ; Op = "require_nondet"
+        ; Op = "require_cc_multi"
+        ; Op = "require_cc_nondet"
+        ; Op = "require_erroneous"
+        ; Op = "require_failure"
         ),
         Info = op_info(prefix(x), 950),
         OtherInfos = []
cvs diff: Diffing mdbcomp
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/standalone_c
cvs diff: Diffing samples/concurrency
cvs diff: Diffing samples/concurrency/dining_philosophers
cvs diff: Diffing samples/concurrency/midimon
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/java_interface
cvs diff: Diffing samples/java_interface/java_calls_mercury
cvs diff: Diffing samples/java_interface/mercury_calls_java
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/solver_types
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing slice
cvs diff: Diffing ssdb
cvs diff: Diffing tests
cvs diff: Diffing tests/analysis
cvs diff: Diffing tests/analysis/ctgc
cvs diff: Diffing tests/analysis/excp
cvs diff: Diffing tests/analysis/ext
cvs diff: Diffing tests/analysis/sharing
cvs diff: Diffing tests/analysis/table
cvs diff: Diffing tests/analysis/trail
cvs diff: Diffing tests/analysis/unused_args
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.395
diff -u -b -r1.395 Mmakefile
--- tests/hard_coded/Mmakefile	7 Dec 2010 03:09:13 -0000	1.395
+++ tests/hard_coded/Mmakefile	28 Dec 2010 02:57:24 -0000
@@ -212,6 +212,7 @@
 	relation_test \
 	remove_file \
 	reorder_di \
+	require_scopes \
 	rev_arith \
 	reverse_arith \
 	rtc_bug \
Index: tests/hard_coded/require_scopes.exp
===================================================================
RCS file: tests/hard_coded/require_scopes.exp
diff -N tests/hard_coded/require_scopes.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/require_scopes.exp	28 Dec 2010 02:57:39 -0000
@@ -0,0 +1,7 @@
+test_detism_scope(1) = 1
+test_detism_scope(11) = 1
+test_detism_scope(21) = 21
+test_switch_scope(f1) = []
+test_switch_scope(f2) = [1, 2]
+test_switch_scope(f3(10)) = [3, 10, 11]
+test_switch_scope(f3(20)) = [3, 20, 21]
Index: tests/hard_coded/require_scopes.m
===================================================================
RCS file: tests/hard_coded/require_scopes.m
diff -N tests/hard_coded/require_scopes.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/require_scopes.m	27 Dec 2010 14:12:43 -0000
@@ -0,0 +1,78 @@
+% vim: ft=mercury ts=4 sw=4 et
+
+:- module require_scopes.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module int.
+:- import_module list.
+:- import_module string.
+:- import_module solutions.
+
+:- type t
+    --->    f1
+    ;       f2
+    ;       f3(int).
+
+main(!IO) :-
+    test_detism_scope(1, !IO),
+    test_detism_scope(11, !IO),
+    test_detism_scope(21, !IO),
+    test_switch_scope(f1, !IO),
+    test_switch_scope(f2, !IO),
+    test_switch_scope(f3(10), !IO),
+    test_switch_scope(f3(20), !IO).
+
+:- pred test_detism_scope(int::in, io::di, io::uo) is det.
+
+test_detism_scope(A, !IO) :-
+    (
+        A > 10,
+        require_det (
+            B = A * 2,
+            C = B mod 3
+        ),
+        C = 1
+    ->
+        X = C
+    ;
+        X = A
+    ),
+    io.format("test_detism_scope(%d) = %d\n", [i(A), i(X)], !IO).
+
+:- pred test_switch_scope(t::in, io::di, io::uo) is det.
+
+test_switch_scope(A, !IO) :-
+    solutions(do_test_switch_scope(A), Solns),
+    io.write_string("test_switch_scope(", !IO),
+    io.write(A, !IO),
+    io.write_string(") = ", !IO),
+    io.write(Solns, !IO),
+    io.nl(!IO).
+
+:- pred do_test_switch_scope(t::in, int::out) is nondet.
+
+do_test_switch_scope(A, X) :-
+    require_complete_switch [A] (
+        (
+            A = f1,
+            fail
+        ;
+            A = f2,
+            ( X = 1
+            ; X = 2
+            )
+        ;
+            A = f3(B),
+            ( X = 3
+            ; X = B
+            ; X = B + 1
+            )
+        )
+    ).
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.243
diff -u -b -r1.243 Mmakefile
--- tests/invalid/Mmakefile	30 Sep 2010 07:23:35 -0000	1.243
+++ tests/invalid/Mmakefile	28 Dec 2010 03:02:07 -0000
@@ -179,6 +179,7 @@
 	quant_constraint_2 \
 	range_restrict \
 	record_syntax_errors \
+	require_scopes \
 	some \
 	specified \
 	spurious_mode_error \
Index: tests/invalid/duplicate_modes.err_exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/invalid/duplicate_modes.err_exp,v
retrieving revision 1.11
diff -u -b -r1.11 duplicate_modes.err_exp
--- tests/invalid/duplicate_modes.err_exp	1 Oct 2006 04:24:11 -0000	1.11
+++ tests/invalid/duplicate_modes.err_exp	28 Dec 2010 05:02:10 -0000
@@ -8,16 +8,14 @@
 duplicate_modes.m:008: In mode declarations for predicate
 duplicate_modes.m:008:   `duplicate_modes.q'/2:
 duplicate_modes.m:008:   error: duplicate mode declaration.
-duplicate_modes.m:008:   Modes `q(in, out) is det' and
-duplicate_modes.m:008:   `q((ground >> ground), (free >> ground)) is det' are
-duplicate_modes.m:008:   indistinguishable.
+duplicate_modes.m:008:   Modes `q(in, out) is det' and `q((ground >> ground),
+duplicate_modes.m:008:   (free >> ground)) is det' are indistinguishable.
 duplicate_modes.m:009:   Here is the conflicting mode declaration.
 duplicate_modes.m:008: In mode declarations for predicate
 duplicate_modes.m:008:   `duplicate_modes.q'/2:
 duplicate_modes.m:008:   error: duplicate mode declaration.
-duplicate_modes.m:008:   Modes `q(in, out) is det' and
-duplicate_modes.m:008:   `q((ground >> ground), (free >> ground)) is det' are
-duplicate_modes.m:008:   indistinguishable.
+duplicate_modes.m:008:   Modes `q(in, out) is det' and `q((ground >> ground),
+duplicate_modes.m:008:   (free >> ground)) is det' are indistinguishable.
 duplicate_modes.m:010:   Here is the conflicting mode declaration.
 duplicate_modes.m:014: In mode declarations for predicate
 duplicate_modes.m:014:   `duplicate_modes.r'/2:
Index: tests/invalid/require_scopes.err_exp
===================================================================
RCS file: tests/invalid/require_scopes.err_exp
diff -N tests/invalid/require_scopes.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/require_scopes.err_exp	28 Dec 2010 05:03:30 -0000
@@ -0,0 +1,6 @@
+require_scopes.m:036: Error: required determinism is `det', but actual
+require_scopes.m:036:   determinism is `semidet'.
+require_scopes.m:040: Error: required determinism is `nondet', but actual
+require_scopes.m:040:   determinism is `semidet'.
+require_scopes.m:064: Error: the switch on `A' is required to be complete, but
+require_scopes.m:064:   it is not.
Index: tests/invalid/require_scopes.m
===================================================================
RCS file: tests/invalid/require_scopes.m
diff -N tests/invalid/require_scopes.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/require_scopes.m	28 Dec 2010 03:53:26 -0000
@@ -0,0 +1,77 @@
+% vim: ft=mercury ts=4 sw=4 et
+
+:- module require_scopes.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module int.
+:- import_module list.
+:- import_module string.
+:- import_module solutions.
+
+:- type t
+    --->    f1
+    ;       f2
+    ;       f3(int).
+
+main(!IO) :-
+    test_detism_scope(1, !IO),
+    test_detism_scope(11, !IO),
+    test_detism_scope(21, !IO),
+    test_switch_scope(f1, !IO),
+    test_switch_scope(f2, !IO),
+    test_switch_scope(f3(10), !IO),
+    test_switch_scope(f3(20), !IO).
+
+:- pred test_detism_scope(int::in, io::di, io::uo) is det.
+
+test_detism_scope(A, !IO) :-
+    (
+        require_det (
+            A > 10
+        ),
+        B = A * 2,
+        require_nondet (
+            C = B mod 3,
+            C = 1
+        )
+    ->
+        X = C
+    ;
+        X = A
+    ),
+    io.format("test_detism_scope(%d) = %d\n", [i(A), i(X)], !IO).
+
+:- pred test_switch_scope(t::in, io::di, io::uo) is det.
+
+test_switch_scope(A, !IO) :-
+    solutions(do_test_switch_scope(A), Solns),
+    io.write_string("test_switch_scope(", !IO),
+    io.write(A, !IO),
+    io.write_string(") = ", !IO),
+    io.write(Solns, !IO),
+    io.nl(!IO).
+
+:- pred do_test_switch_scope(t::in, int::out) is nondet.
+
+do_test_switch_scope(A, X) :-
+    require_complete_switch [A] (
+        (
+            A = f2,
+            ( X = 1
+            ; X = 2
+            )
+        ;
+            A = f3(B),
+            ( X = 3
+            ; X = B
+            ; X = B + 1
+            )
+        )
+    ).
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/par_conj
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/stm
cvs diff: Diffing tests/stm/orig
cvs diff: Diffing tests/stm/orig/stm-compiler
cvs diff: Diffing tests/stm/orig/stm-compiler/test1
cvs diff: Diffing tests/stm/orig/stm-compiler/test10
cvs diff: Diffing tests/stm/orig/stm-compiler/test2
cvs diff: Diffing tests/stm/orig/stm-compiler/test3
cvs diff: Diffing tests/stm/orig/stm-compiler/test4
cvs diff: Diffing tests/stm/orig/stm-compiler/test5
cvs diff: Diffing tests/stm/orig/stm-compiler/test6
cvs diff: Diffing tests/stm/orig/stm-compiler/test7
cvs diff: Diffing tests/stm/orig/stm-compiler/test8
cvs diff: Diffing tests/stm/orig/stm-compiler/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/stmqueue
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test10
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test11
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test9
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/trailing
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list