for review: rewrite of termination analysis (part 2)

Zoltan Somogyi zs at cs.mu.oz.au
Mon Dec 22 14:47:12 AEDT 1997


Tom, please review this.

Zoltan.

Index: compiler/bytecode_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/bytecode_gen.m,v
retrieving revision 1.31
diff -u -r1.31 bytecode_gen.m
--- bytecode_gen.m	1997/12/19 03:05:50	1.31
+++ bytecode_gen.m	1997/12/21 08:38:21
@@ -89,7 +89,7 @@
 
 	proc_info_goal(ProcInfo, Goal),
 	proc_info_vartypes(ProcInfo, VarTypes),
-	proc_info_variables(ProcInfo, VarSet),
+	proc_info_varset(ProcInfo, VarSet),
 	proc_info_interface_determinism(ProcInfo, Detism),
 	determinism_to_code_model(Detism, CodeModel),
 
Index: compiler/code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_gen.m,v
retrieving revision 1.41
diff -u -r1.41 code_gen.m
--- code_gen.m	1997/12/19 03:05:57	1.41
+++ code_gen.m	1997/12/21 08:38:24
@@ -180,7 +180,7 @@
 		% get the goal for this procedure
 	proc_info_goal(ProcInfo, Goal),
 		% get the information about this procedure that we need.
-	proc_info_variables(ProcInfo, VarInfo),
+	proc_info_varset(ProcInfo, VarInfo),
 	proc_info_liveness_info(ProcInfo, Liveness),
 	proc_info_stack_slots(ProcInfo, StackSlots),
 	proc_info_get_initial_instmap(ProcInfo, ModuleInfo, InitialInst),
Index: compiler/constraint.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/constraint.m,v
retrieving revision 1.36
diff -u -r1.36 constraint.m
--- constraint.m	1997/12/19 03:06:07	1.36
+++ constraint.m	1997/12/21 08:38:27
@@ -88,7 +88,7 @@
 	map__lookup(ProcTable0, ProcId, ProcInfo0),
 
 	proc_info_goal(ProcInfo0, Goal0),
-	proc_info_variables(ProcInfo0, VarSet0),
+	proc_info_varset(ProcInfo0, VarSet0),
 	varset__vars(VarSet0, VarList),
 	set__list_to_set(VarList, VarSet1),
 
@@ -104,7 +104,7 @@
 	mode_info_get_var_types(ModeInfo, VarTypes),
 	mode_info_get_module_info(ModeInfo, ModuleInfo1),
 
-	proc_info_set_variables(ProcInfo0, VarSet, ProcInfo1),
+	proc_info_set_varset(ProcInfo0, VarSet, ProcInfo1),
 	proc_info_set_vartypes(ProcInfo1, VarTypes, ProcInfo2),
 	proc_info_set_goal(ProcInfo2, Goal, ProcInfo),
 
Index: compiler/cse_detection.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/cse_detection.m,v
retrieving revision 1.49
diff -u -r1.49 cse_detection.m
--- cse_detection.m	1997/12/19 03:06:09	1.49
+++ cse_detection.m	1997/12/21 08:38:29
@@ -135,7 +135,7 @@
 
 	proc_info_goal(ProcInfo0, Goal0),
 	proc_info_get_initial_instmap(ProcInfo0, ModuleInfo0, InstMap0),
-	proc_info_variables(ProcInfo0, Varset0),
+	proc_info_varset(ProcInfo0, Varset0),
 	proc_info_vartypes(ProcInfo0, VarTypes0),
 	CseInfo0 = cse_info(Varset0, VarTypes0, ModuleInfo0),
 	detect_cse_in_goal(Goal0, InstMap0, CseInfo0, CseInfo, Redo, Goal1),
@@ -154,7 +154,7 @@
 			VarTypes1, Goal, Varset, VarTypes, _Warnings),
 
 		proc_info_set_goal(ProcInfo0, Goal, ProcInfo1),
-		proc_info_set_variables(ProcInfo1, Varset, ProcInfo2),
+		proc_info_set_varset(ProcInfo1, Varset, ProcInfo2),
 		proc_info_set_vartypes(ProcInfo2, VarTypes, ProcInfo),
 
 		map__det_update(ProcTable0, ProcId, ProcInfo, ProcTable),
Index: compiler/det_analysis.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/det_analysis.m,v
retrieving revision 1.125
diff -u -r1.125 det_analysis.m
--- det_analysis.m	1997/12/19 03:06:17	1.125
+++ det_analysis.m	1997/12/21 08:38:31
@@ -771,11 +771,11 @@
 			_TypeContext)
 	->
 		( CanFail = can_fail ->
-			proc_info_variables(ProcInfo, VarSet),
+			proc_info_varset(ProcInfo, VarSet),
 			Msgs = [cc_unify_can_fail(GoalInfo, Var, Type,
 				VarSet, GoalContext) | Msgs0]
 		; SolnContext \= first_soln ->
-			proc_info_variables(ProcInfo, VarSet),
+			proc_info_varset(ProcInfo, VarSet),
 			Msgs = [cc_unify_in_wrong_context(GoalInfo, Var,
 				Type, VarSet, GoalContext) | Msgs0]
 		;
Index: compiler/det_report.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/det_report.m,v
retrieving revision 1.45
diff -u -r1.45 det_report.m
--- det_report.m	1997/12/19 03:06:20	1.45
+++ det_report.m	1997/12/21 08:38:32
@@ -419,7 +419,7 @@
 			DetInfo),
 		prog_out__write_context(Context),
 		{ det_get_proc_info(DetInfo, ProcInfo) },
-		{ proc_info_variables(ProcInfo, Varset) },
+		{ proc_info_varset(ProcInfo, Varset) },
 		{ det_info_get_module_info(DetInfo, ModuleInfo) },
 		(
 			{ det_lookup_var_type(ModuleInfo, ProcInfo, Var,
@@ -717,7 +717,7 @@
 		DetInfo) -->
 	prog_out__write_context(Context),
 	{ det_get_proc_info(DetInfo, ProcInfo) },
-	{ proc_info_variables(ProcInfo, Varset) },
+	{ proc_info_varset(ProcInfo, Varset) },
 	{ SwitchContext = switch_context(Var, ConsId) },
 	io__write_string("  Inside the case "),
 	hlds_out__write_cons_id(ConsId),
@@ -797,7 +797,7 @@
 	hlds_out__write_unify_context(First0, UnifyContext, Context, First),
 	prog_out__write_context(Context),
 	{ det_get_proc_info(DetInfo, ProcInfo) },
-	{ proc_info_variables(ProcInfo, Varset) },
+	{ proc_info_varset(ProcInfo, Varset) },
 	{ det_info_get_module_info(DetInfo, ModuleInfo) },
 	( { First = yes } ->
 		( { Last = yes } ->
Index: compiler/dnf.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dnf.m,v
retrieving revision 1.25
diff -u -r1.25 dnf.m
--- dnf.m	1997/12/19 03:06:23	1.25
+++ dnf.m	1997/12/21 08:38:34
@@ -139,7 +139,7 @@
 	pred_info_get_markers(PredInfo0, Markers),
 	pred_info_get_class_context(PredInfo0, ClassContext),
 	proc_info_goal(ProcInfo0, Goal0),
-	proc_info_variables(ProcInfo0, VarSet),
+	proc_info_varset(ProcInfo0, VarSet),
 	proc_info_vartypes(ProcInfo0, VarTypes),
 	DnfInfo = dnf_info(TVarSet, VarTypes, ClassContext, VarSet, Markers),
 
Index: compiler/excess.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/excess.m,v
retrieving revision 1.25
diff -u -r1.25 excess.m
--- excess.m	1997/12/19 03:06:31	1.25
+++ excess.m	1997/12/21 08:38:35
@@ -53,7 +53,7 @@
 	proc_info_set_goal(ProcInfo0, Goal, ProcInfo1),
 
 	% XXX We probably ought to remove these vars from the type map as well.
-	proc_info_variables(ProcInfo1, Varset0),
+	proc_info_varset(ProcInfo1, Varset0),
 	varset__delete_vars(Varset0, ElimVars, Varset),
 	proc_info_set_varset(ProcInfo1, Varset, ProcInfo).
 
Index: compiler/follow_code.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/follow_code.m,v
retrieving revision 1.44
diff -u -r1.44 follow_code.m
--- follow_code.m	1997/12/19 03:06:35	1.44
+++ follow_code.m	1997/12/21 08:38:37
@@ -43,7 +43,7 @@
 	globals__lookup_bool_option(Globals, prev_code, PrevCode),
 	Flags = FollowCode - PrevCode,
 	proc_info_goal(ProcInfo0, Goal0),
-	proc_info_variables(ProcInfo0, Varset0),
+	proc_info_varset(ProcInfo0, Varset0),
 	proc_info_vartypes(ProcInfo0, VarTypes0),
 	(
 		move_follow_code_in_goal(Goal0, Goal1, Flags, no, Res),
Index: compiler/higher_order.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/higher_order.m,v
retrieving revision 1.35
diff -u -r1.35 higher_order.m
--- higher_order.m	1997/12/19 03:06:45	1.35
+++ higher_order.m	1997/12/21 08:38:43
@@ -251,11 +251,11 @@
 	traverse_goal(Goal0, Goal1, proc(PredId, ProcId), _, _,
 					Info0, info(_, Requests1,_,_)),
 	proc_info_headvars(ProcInfo0, HeadVars),
-	proc_info_variables(ProcInfo0, Varset0),
+	proc_info_varset(ProcInfo0, Varset0),
 	implicitly_quantify_clause_body(HeadVars, Goal1, Varset0, VarTypes0,
 						Goal, Varset, VarTypes, _),
 	proc_info_set_goal(ProcInfo0, Goal, ProcInfo1),
-	proc_info_set_variables(ProcInfo1, Varset, ProcInfo2),
+	proc_info_set_varset(ProcInfo1, Varset, ProcInfo2),
 	proc_info_set_vartypes(ProcInfo2, VarTypes, ProcInfo),
 	map__det_update(Procs0, ProcId, ProcInfo, Procs1),
 	traverse_other_procs(PredId, ProcIds, ModuleInfo, Requests1,
@@ -936,13 +936,13 @@
 	set__init(Requests0),
 	traverse_goal(Goal0, Goal1, PredProcId, _, _,
 		info(PredVars0, Requests0, NewPreds, ModuleInfo0), _),
-	proc_info_variables(ProcInfo0, Varset0),
+	proc_info_varset(ProcInfo0, Varset0),
 	proc_info_headvars(ProcInfo0, HeadVars),
 	proc_info_vartypes(ProcInfo0, VarTypes0),
 	implicitly_quantify_clause_body(HeadVars, Goal1, Varset0, VarTypes0,
 					Goal, Varset, VarTypes, _),
 	proc_info_set_goal(ProcInfo0, Goal, ProcInfo1),
-	proc_info_set_variables(ProcInfo1, Varset, ProcInfo2),
+	proc_info_set_varset(ProcInfo1, Varset, ProcInfo2),
 	proc_info_set_vartypes(ProcInfo2, VarTypes, ProcInfo),
 	map__det_update(Procs0, ProcId, ProcInfo, Procs),
 	pred_info_set_procedures(PredInfo0, Procs, PredInfo),
@@ -1025,7 +1025,7 @@
 			info(PredVars0, Requests0, NewPredMap, ModuleInfo0),
 			info(_, Requests1,_,_)),
 	map__set(GoalSizes0, NewPredId, GoalSize, GoalSizes1),
-	proc_info_variables(NewProcInfo1, Varset0),
+	proc_info_varset(NewProcInfo1, Varset0),
 					
 	implicitly_quantify_clause_body(HeadVars, Goal2, Varset0, VarTypes1,
 					Goal3, Varset, VarTypes, _),
@@ -1033,7 +1033,7 @@
 	recompute_instmap_delta(no, Goal3, Goal4, InstMap0,
 		ModuleInfo0, ModuleInfo1),
 	proc_info_set_goal(NewProcInfo1, Goal4, NewProcInfo1a),
-	proc_info_set_variables(NewProcInfo1a, Varset, NewProcInfo2),
+	proc_info_set_varset(NewProcInfo1a, Varset, NewProcInfo2),
 	proc_info_set_vartypes(NewProcInfo2, VarTypes, NewProcInfo3),
 	proc_info_set_argmodes(NewProcInfo3, ArgModes, NewProcInfo4),
 	proc_info_set_headvars(NewProcInfo4, HeadVars, NewProcInfo),
@@ -1092,9 +1092,9 @@
 	;
 		error("list__split_list_failed")
 	),
-	proc_info_variables(ProcInfo0, Varset0),
+	proc_info_varset(ProcInfo0, Varset0),
 	varset__new_vars(Varset0, NumArgs, NewHeadVars0, Varset1),
-	proc_info_set_variables(ProcInfo0, Varset1, ProcInfo1),
+	proc_info_set_varset(ProcInfo0, Varset1, ProcInfo1),
 
 	% Find the type substitution and work out the types
 	% of the new variables.
Index: compiler/hlds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_out.m,v
retrieving revision 1.178
diff -u -r1.178 hlds_out.m
--- hlds_out.m	1997/12/19 03:06:54	1.178
+++ hlds_out.m	1997/12/21 08:38:46
@@ -242,12 +242,12 @@
 	{ pred_info_name(PredInfo, Name) },
 	{ pred_info_arity(PredInfo, Arity) },
 	{ pred_info_get_is_pred_or_func(PredInfo, PredOrFunc) },
-	(   { special_pred_name_arity(Kind, _, Name, Arity) } ->	
+	( { special_pred_name_arity(Kind, _, Name, Arity) } ->	
 		{ special_pred_description(Kind, Descr) },
 		io__write_string(Descr),
 		io__write_string(" for type "),
 		{ pred_info_arg_types(PredInfo, TVarSet, ArgTypes) },
-		(   { special_pred_get_type(Name, ArgTypes, Type) } ->
+		( { special_pred_get_type(Name, ArgTypes, Type) } ->
 			mercury_output_term(Type, TVarSet, no)
 		;
 			{ error("special_pred_get_type failed!") }
@@ -1931,12 +1931,13 @@
 	{ proc_info_vartypes(Proc, VarTypes) },
 	{ proc_info_declared_determinism(Proc, DeclaredDeterminism) },
 	{ proc_info_inferred_determinism(Proc, InferredDeterminism) },
-	{ proc_info_variables(Proc, VarSet) },
+	{ proc_info_varset(Proc, VarSet) },
 	{ proc_info_headvars(Proc, HeadVars) },
 	{ proc_info_argmodes(Proc, HeadModes) },
 	{ proc_info_goal(Proc, Goal) },
 	{ proc_info_context(Proc, ModeContext) },
-	{ proc_info_termination(Proc, Termination) },
+	{ proc_info_get_maybe_arg_size_info(Proc, MaybeArgSize) },
+	{ proc_info_get_maybe_termination_info(Proc, MaybeTermination) },
 	{ proc_info_typeinfo_varmap(Proc, TypeInfoMap) },
 	{ Indent1 is Indent + 1 },
 
@@ -1954,13 +1955,13 @@
 	
 	globals__io_lookup_string_option(verbose_dump_hlds, Verbose),
 	( { string__contains_char(Verbose, 't') } ->
-		io__write_string("% Inferred termination: "),
-		termination__out(Termination),
+		io__write_string("% Arg size properties: "),
+		termination__write_maybe_arg_size_info(MaybeArgSize, yes),
 		io__nl,
-		io__write_string("% Termination - used args: "),
-		termination__out_used_args(Termination),
-		io__nl,
-		term_errors__output_hlds(PredId, ProcId, ModuleInfo)
+		io__write_string("% Termination properties: "),
+		termination__write_maybe_termination_info(MaybeTermination,
+			yes),
+		io__nl
 	;
 		[]
 	),
Index: compiler/hlds_pred.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_pred.m,v
retrieving revision 1.40
diff -u -r1.40 hlds_pred.m
--- hlds_pred.m	1997/12/19 03:06:57	1.40
+++ hlds_pred.m	1997/12/21 08:58:08
@@ -528,7 +528,7 @@
 	next_mode_id(Procs0, MaybeDetism, ProcId),
 	map__det_insert(Procs0, ProcId, ProcInfo, Procs),
 	list__length(Types, Arity),
-	proc_info_variables(ProcInfo, VarSet),
+	proc_info_varset(ProcInfo, VarSet),
 	proc_info_vartypes(ProcInfo, VarTypes),
 	proc_info_headvars(ProcInfo, HeadVars),
 	unqualify_name(SymName, PredName),
@@ -694,7 +694,6 @@
 purity_to_markers(semipure, [semipure]).
 purity_to_markers(impure, [impure]).
 
-
 pred_info_get_markers(PredInfo, Markers) :-
 	PredInfo = predicate(_, _, _, _, _, _, _, _, _, _, _, _, Markers, 
 		_, _, _).
@@ -807,10 +806,10 @@
 :- pred proc_info_set(maybe(determinism), varset, map(var, type), list(var),
 	list(mode), maybe(list(is_live)), hlds_goal, term__context,
 	stack_slots, determinism, bool, list(arg_info), liveness_info,
-	map(tvar, type_info_locn), map(class_constraint, var), termination,
-	proc_info).
+	map(tvar, type_info_locn), map(class_constraint, var), 
+	maybe(arg_size_info), maybe(termination_info), proc_info).
 :- mode proc_info_set(in, in, in, in, in, in, in, in, in, in, in, in, in, in,
-	in, in, out) is det.
+	in, in, in, out) is det.
 
 :- pred proc_info_create(varset, map(var, type), list(var), list(mode),
 	determinism, hlds_goal, term__context, map(tvar, type_info_locn),
@@ -839,15 +838,12 @@
 :- pred proc_info_never_succeeds(proc_info, bool).
 :- mode proc_info_never_succeeds(in, out) is det.
 
-:- pred proc_info_variables(proc_info, varset).
-:- mode proc_info_variables(in, out) is det.
+:- pred proc_info_varset(proc_info, varset).
+:- mode proc_info_varset(in, out) is det.
 
 :- pred proc_info_set_varset(proc_info, varset, proc_info).
 :- mode proc_info_set_varset(in, in, out) is det.
 
-:- pred proc_info_set_variables(proc_info, varset, proc_info).
-:- mode proc_info_set_variables(in, in, out) is det.
-
 :- pred proc_info_vartypes(proc_info, map(var, type)).
 :- mode proc_info_vartypes(in, out) is det.
 
@@ -912,11 +908,20 @@
 :- pred proc_info_set_stack_slots(proc_info, stack_slots, proc_info).
 :- mode proc_info_set_stack_slots(in, in, out) is det.
 
-:- pred proc_info_termination(proc_info, termination).
-:- mode proc_info_termination(in, out) is det.
+:- pred proc_info_get_maybe_arg_size_info(proc_info, maybe(arg_size_info)).
+:- mode proc_info_get_maybe_arg_size_info(in, out) is det.
+
+:- pred proc_info_set_maybe_arg_size_info(proc_info, maybe(arg_size_info),
+	proc_info).
+:- mode proc_info_set_maybe_arg_size_info(in, in, out) is det.
 
-:- pred proc_info_set_termination(proc_info, termination, proc_info).
-:- mode proc_info_set_termination(in, in, out) is det.
+:- pred proc_info_get_maybe_termination_info(proc_info,
+	maybe(termination_info)).
+:- mode proc_info_get_maybe_termination_info(in, out) is det.
+
+:- pred proc_info_set_maybe_termination_info(proc_info,
+	maybe(termination_info), proc_info).
+:- mode proc_info_set_maybe_termination_info(in, in, out) is det.
 
 :- pred proc_info_set_can_process(proc_info, bool, proc_info).
 :- mode proc_info_set_can_process(in, in, out) is det.
@@ -1003,14 +1008,19 @@
 			map(class_constraint, var),
 					% typeclass_info vars for class
 					% constraints
-			termination,	% The termination properties of the
-					% procedure.  Initially 'not_set'.
-					% Final value inferred by termination.m
+			maybe(arg_size_info),
+					% Information about the relative sizes
+					% of the input and output args of the
+					% procedure. Set by termination
+					% analysis.
+			maybe(termination_info),
+					% The termination properties of the
+					% procedure. Set by termination
+					% analysis.
 			maybe(list(mode))
 					% declared modes of arguments.
 		).
 
-
 	% Some parts of the procedure aren't known yet. We initialize
 	% them to any old garbage which we will later throw away.
 
@@ -1033,39 +1043,37 @@
 	CanProcess = yes,
 	map__init(TVarsMap),
 	map__init(TCVarsMap),
-	term_util__init(Termination),
 	NewProc = procedure(
 		MaybeDet, BodyVarSet, BodyTypes, HeadVars, Modes, MaybeArgLives,
 		ClauseBody, MContext, StackSlots, InferredDet, CanProcess,
-		ArgInfo, InitialLiveness, TVarsMap, TCVarsMap, Termination,
+		ArgInfo, InitialLiveness, TVarsMap, TCVarsMap, no, no,
 		DeclaredModes
 	).
 
 proc_info_set(DeclaredDetism, BodyVarSet, BodyTypes, HeadVars, HeadModes,
-		HeadLives, Goal,
-		Context, StackSlots, InferredDetism, CanProcess,
-		ArgInfo, Liveness, TVarMap, TCVarsMap, Termination, ProcInfo) :-
+		HeadLives, Goal, Context, StackSlots, InferredDetism,
+		CanProcess, ArgInfo, Liveness, TVarMap, TCVarsMap,
+		ArgSizes, Termination, ProcInfo) :-
 	ProcInfo = procedure(
 		DeclaredDetism, BodyVarSet, BodyTypes, HeadVars, HeadModes,
 		HeadLives, Goal, Context, StackSlots, InferredDetism,
-		CanProcess, ArgInfo, Liveness, TVarMap, TCVarsMap, Termination,
-		no).
+		CanProcess, ArgInfo, Liveness, TVarMap, TCVarsMap,
+		ArgSizes, Termination, no).
 
 proc_info_create(VarSet, VarTypes, HeadVars, HeadModes, Detism, Goal,
 		Context, TVarMap, TCVarsMap, ProcInfo) :-
 	map__init(StackSlots),
 	set__init(Liveness),
-	term_util__init(Termination),
 	MaybeHeadLives = no,
 	ProcInfo = procedure(yes(Detism), VarSet, VarTypes, HeadVars, HeadModes,
 		MaybeHeadLives, Goal, Context, StackSlots, Detism, yes, [],
-		Liveness, TVarMap, TCVarsMap, Termination, no).
+		Liveness, TVarMap, TCVarsMap, no, no, no).
 
 proc_info_set_body(ProcInfo0, VarSet, VarTypes, HeadVars, Goal, ProcInfo) :-
 	ProcInfo0 = procedure(A, _, _, _, E, F, _,
-		H, I, J, K, L, M, N, O, P, Q),
+		H, I, J, K, L, M, N, O, P, Q, R),
 	ProcInfo = procedure(A, VarSet, VarTypes, HeadVars, E, F, Goal,
-		H, I, J, K, L, M, N, O, P, Q).
+		H, I, J, K, L, M, N, O, P, Q, R).
 
 proc_info_interface_determinism(ProcInfo, Determinism) :-
 	proc_info_declared_determinism(ProcInfo, MaybeDeterminism),
@@ -1113,58 +1121,6 @@
 	assoc_list__from_corresponding_lists(HeadVars, InitialInsts, InstAL),
 	instmap__from_assoc_list(InstAL, InstMap).
 
-proc_info_declared_determinism(ProcInfo, Detism) :-
-	ProcInfo = procedure(Detism, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-		_, _).
-proc_info_variables(ProcInfo, VarSet) :-
-	ProcInfo = procedure(_, VarSet, _, _, _, _, _, _, _, _, _, _, _, _, _, 
-		_, _).
-proc_info_vartypes(ProcInfo, VarTypes) :-
-	ProcInfo = procedure(_, _, VarTypes, _, _, _, _, _, _,
-		_, _, _, _, _, _, _, _).
-proc_info_headvars(ProcInfo, HeadVars) :-
-	ProcInfo = procedure(_, _, _, HeadVars, _, _, _, _, _, _,
-		_, _, _, _, _, _, _).
-proc_info_argmodes(ProcInfo, Modes) :-
-	ProcInfo = procedure(_, _, _, _, Modes, _, _, _, _, _, _, _, _, _, _, 
-		_, _).
-proc_info_maybe_arglives(ProcInfo, ArgLives) :-
-	ProcInfo = procedure(_, _, _, _, _, ArgLives, _, _, _,
-		_, _, _, _, _, _, _, _).
-proc_info_goal(ProcInfo, Goal) :-
-	ProcInfo = procedure(_, _, _, _, _, _, Goal, _, _, _, _, _, _, _, _, 
-		_, _).
-proc_info_context(ProcInfo, Context) :-
-	ProcInfo = procedure(_, _, _, _, _, _, _, Context, 
-		_, _, _, _, _, _, _, _, _).
-proc_info_stack_slots(ProcInfo, StackSlots) :-
-	ProcInfo = procedure(_, _, _, _, _, _, _, _, StackSlots,
-		_, _, _, _, _, _, _, _).
-proc_info_inferred_determinism(ProcInfo, Detism) :-
-	ProcInfo = procedure(_, _, _, _, _, _, _, _, _, Detism, _, _, _, _, _,
-		_, _).
-proc_info_can_process(ProcInfo, CanProcess) :-
- 	ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, CanProcess,
-		_, _, _, _, _, _).
-proc_info_arg_info(ProcInfo, ArgInfo) :-
-	ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, _, ArgInfo,
-		_, _, _, _, _).
-proc_info_liveness_info(ProcInfo, Liveness) :-
-	ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, _, _, Liveness,
-		_, _, _, _).
-proc_info_typeinfo_varmap(ProcInfo, TVarMap) :-
-	ProcInfo = procedure(_, _, _, _, _, _, _,
-		_, _, _, _, _, _, TVarMap, _, _, _).
-proc_info_typeclass_info_varmap(ProcInfo, TCVarMap) :-
-	ProcInfo = procedure(_, _, _, _, _, _, _,
-		_, _, _, _, _, _, _, TCVarMap, _, _).
-proc_info_termination(ProcInfo, Termination) :-
-    ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-    		Termination, _).
-proc_info_maybe_declared_argmodes(ProcInfo, MaybeArgModes) :-
-	ProcInfo = procedure(_, _, _, _, _, _, _, _,
-		_, _, _, _, _, _, _, _, MaybeArgModes).
-
 proc_info_declared_argmodes(ProcInfo, ArgModes) :-
 	proc_info_maybe_declared_argmodes(ProcInfo, MaybeArgModes),
 	( MaybeArgModes = yes(ArgModes1) ->
@@ -1173,95 +1129,169 @@
 		proc_info_argmodes(ProcInfo, ArgModes)
 	).
 
-% :- type proc_info	--->	procedure(
-% 				A	maybe(determinism),% _declared_ detism
-% 				B	varset,		% variable names
-% 				C	map(var, type),	% variable types
-% 				D	list(var),	% head vars
-% 				E	list(mode), 	% modes of args
-% 				F	list(is_live), 	% liveness of args
-% 				G	hlds_goal,	% Body
-% 				H	term__context,	% The context of
-% 							% the :- mode decl,
-% 							% not the clause.
-% 				I	stack_slots,	% stack allocations
-% 				J	determinism,	% _inferred_ detism
-% 				K	bool,		% can_process
-% 				L	list(arg_info),	% information about
-% 							% the arguments
-% 							% derived from the
-% 							% modes etc
-% 				M	liveness_info	% the initial liveness
-%				N	map(tvar, type_info_locn)  
-%							% typeinfo vars to
-%							% locations.
-%				O	map(class_constraint, var)  
-%							% constraints to
-%							% vars.
-%				P	termination	% Termination analys
-%				Q	maybe(list(mode)) % declared modes
-%							% of args
-% 				).
-
-proc_info_set_varset(ProcInfo0, VarSet, ProcInfo) :-
-	ProcInfo0 = procedure(A,_,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q),
-	ProcInfo = procedure(A,VarSet,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
-
-proc_info_set_variables(ProcInfo0, Vars, ProcInfo) :-
-	ProcInfo0 = procedure(A,_,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q),
-	ProcInfo = procedure(A,Vars,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
-
-proc_info_set_vartypes(ProcInfo0, Vars, ProcInfo) :-
-	ProcInfo0 = procedure(A,B,_,D,E,F,G,H,I,J,K,L,M,N,O,P,Q),
-	ProcInfo = procedure(A,B,Vars,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
-
-proc_info_set_headvars(ProcInfo0, HeadVars, ProcInfo) :-
-	ProcInfo0 = procedure(A,B,C,_,E,F,G,H,I,J,K,L,M,N,O,P,Q),
-	ProcInfo = procedure(A,B,C,HeadVars,E,F,G,H,I,J,K,L,M,N,O,P,Q).
-
-proc_info_set_argmodes(ProcInfo0, ArgModes, ProcInfo) :-
-	ProcInfo0 = procedure(A,B,C,D,_,F,G,H,I,J,K,L,M,N,O,P,Q),
-	ProcInfo = procedure(A,B,C,D,ArgModes,F,G,H,I,J,K,L,M,N,O,P,Q).
-
-proc_info_set_maybe_arglives(ProcInfo0, ArgLives, ProcInfo) :-
-	ProcInfo0 = procedure(A,B,C,D,E,_,G,H,I,J,K,L,M,N,O,P,Q),
-	ProcInfo = procedure(A,B,C,D,E,ArgLives,G,H,I,J,K,L,M,N,O,P,Q).
-
-proc_info_set_inferred_determinism(ProcInfo0, Detism, ProcInfo) :-
-	ProcInfo0 = procedure(A,B,C,D,E,F,G,H,I,_,K,L,M,N,O,P,Q),
-	ProcInfo = procedure(A,B,C,D,E,F,G,H,I,Detism,K,L,M,N,O,P,Q).
-
-proc_info_set_can_process(ProcInfo0, CanProcess, ProcInfo) :-
- 	ProcInfo0 = procedure(A,B,C,D,E,F,G,H,I,J,_,L,M,N,O,P,Q),
- 	ProcInfo = procedure(A,B,C,D,E,F,G,H,I,J,CanProcess,L,M,N,O,P,Q).
-
-proc_info_set_goal(ProcInfo0, Goal, ProcInfo) :-
-	ProcInfo0 = procedure(A,B,C,D,E,F,_,H,I,J,K,L,M,N,O,P,Q),
-	ProcInfo = procedure(A,B,C,D,E,F,Goal,H,I,J,K,L,M,N,O,P,Q).
-
-proc_info_set_stack_slots(ProcInfo0, StackSlots, ProcInfo) :-
-	ProcInfo0 = procedure(A,B,C,D,E,F,G,H,_,J,K,L,M,N,O,P,Q),
-	ProcInfo = procedure(A,B,C,D,E,F,G,H,StackSlots,J,K,L,M,N,O,P,Q).
-
-proc_info_set_arg_info(ProcInfo0, ArgInfo, ProcInfo) :-
-	ProcInfo0 = procedure(A,B,C,D,E,F,G,H,I,J,K,_,M,N,O,P,Q),
-	ProcInfo = procedure(A,B,C,D,E,F,G,H,I,J,K,ArgInfo,M,N,O,P,Q).
-
-proc_info_set_liveness_info(ProcInfo0, Liveness, ProcInfo) :-
-	ProcInfo0 = procedure(A,B,C,D,E,F,G,H,I,J,K,L,_,N,O,P,Q),
-	ProcInfo = procedure(A,B,C,D,E,F,G,H,I,J,K,L,Liveness,N,O,P,Q).
-
-proc_info_set_typeinfo_varmap(ProcInfo0, TVarMap, ProcInfo) :-
-	ProcInfo0 = procedure(A,B,C,D,E,F,G,H,I,J,K,L,M,_,O,P,Q),
-	ProcInfo = procedure(A,B,C,D,E,F,G,H,I,J,K,L,M,TVarMap,O,P,Q).
-
-proc_info_set_typeclass_info_varmap(ProcInfo0, TCVarMap, ProcInfo) :-
-	ProcInfo0 = procedure(A,B,C,D,E,F,G,H,I,J,K,L,M,N,_,P,Q),
-	ProcInfo = procedure(A,B,C,D,E,F,G,H,I,J,K,L,M,N,TCVarMap,P,Q).
-
-proc_info_set_termination(ProcInfo0, Terminat, ProcInfo) :-
-    ProcInfo0 = procedure(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,_,Q),
-    ProcInfo = procedure(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,Terminat,Q).
+proc_info_declared_determinism(ProcInfo, A) :-
+    ProcInfo = procedure(A, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _).
+
+proc_info_varset(ProcInfo, B) :-
+    ProcInfo = procedure(_, B, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _).
+
+proc_info_vartypes(ProcInfo, C) :-
+    ProcInfo = procedure(_, _, C, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _).
+
+proc_info_headvars(ProcInfo, D) :-
+    ProcInfo = procedure(_, _, _, D, _, _, _, _, _, _, _, _, _, _, _, _, _, _).
+
+proc_info_argmodes(ProcInfo, E) :-
+    ProcInfo = procedure(_, _, _, _, E, _, _, _, _, _, _, _, _, _, _, _, _, _).
+
+proc_info_maybe_arglives(ProcInfo, F) :-
+    ProcInfo = procedure(_, _, _, _, _, F, _, _, _, _, _, _, _, _, _, _, _, _).
+
+proc_info_goal(ProcInfo, G) :-
+    ProcInfo = procedure(_, _, _, _, _, _, G, _, _, _, _, _, _, _, _, _, _, _).
+
+proc_info_context(ProcInfo, H) :-
+    ProcInfo = procedure(_, _, _, _, _, _, _, H, _, _, _, _, _, _, _, _, _, _).
+
+proc_info_stack_slots(ProcInfo, I) :-
+    ProcInfo = procedure(_, _, _, _, _, _, _, _, I, _, _, _, _, _, _, _, _, _).
+
+proc_info_inferred_determinism(ProcInfo, J) :-
+    ProcInfo = procedure(_, _, _, _, _, _, _, _, _, J, _, _, _, _, _, _, _, _).
+
+proc_info_can_process(ProcInfo, K) :-
+    ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, K, _, _, _, _, _, _, _).
+
+proc_info_arg_info(ProcInfo, L) :- 
+    ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, _, L, _, _, _, _, _, _).
+
+proc_info_liveness_info(ProcInfo, M) :-
+    ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, _, _, M, _, _, _, _, _).
+
+proc_info_typeinfo_varmap(ProcInfo, N) :-
+    ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, _, _, _, N, _, _, _, _).
+
+proc_info_typeclass_info_varmap(ProcInfo, O) :-
+    ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, _, _, _, _, O, _, _, _).
+
+proc_info_get_maybe_arg_size_info(ProcInfo, P) :-
+    ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, P, _, _).
+
+proc_info_get_maybe_termination_info(ProcInfo, Q) :-
+    ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, Q, _).
+
+proc_info_maybe_declared_argmodes(ProcInfo, R) :-
+    ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, R).
+
+% :- type proc_info
+% 	--->	procedure(
+% A			maybe(determinism),
+% 					% _declared_ determinism
+% 					% or `no' if there was no detism decl
+% B			varset,		% variable names
+% C 			map(var, type),	% variable types
+% D			list(var),	% head vars
+% E			list(mode), 	% modes of args
+% F			maybe(list(is_live)),
+% 					% liveness (in the mode analysis sense)
+% 					% of the arguments
+% G			hlds_goal,	% Body
+% H			term__context,	% The context of the `:- mode' decl
+% 					% (or the context of the first clause,
+% 					% if there was no mode declaration).
+% I			stack_slots,	% stack allocations
+% J			determinism,	% _inferred_ determinism
+% K			bool,		% no if we must not process this
+% 					% procedure yet (used to delay
+% 					% mode checking etc. for complicated
+% 					% modes of unification procs until
+% 					% the end of the unique_modes pass.)
+% L			list(arg_info),	% calling convention of each arg:
+% 					% information computed by arg_info.m
+% 					% (based on the modes etc.)
+% 					% and used by code generation
+% 					% to determine how each argument
+% 					% should be passed.
+% M			liveness_info,	% the initial liveness,
+% 					% for code generation
+% N			map(tvar, type_info_locn),	
+% 					% typeinfo vars for
+% 					% type parameters
+% O			map(class_constraint, var),
+% 					% typeclass_info vars for class
+% 					% constraints
+% P			maybe(arg_size_info),
+% 					% Information about the relative sizes
+% 					% of the input and output args of the
+% 					% procedure. Set by termination
+% 					% analysis.
+% Q			maybe(termination_info),
+% 					% The termination properties of the
+% 					% procedure. Set by termination
+% 					% analysis.
+% R			maybe(list(mode))
+% 					% declared modes of arguments.
+% 		).
+
+proc_info_set_varset(ProcInfo0, B, ProcInfo) :-
+    ProcInfo0 = procedure(A, _, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R),
+    ProcInfo  = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R).
+
+proc_info_set_vartypes(ProcInfo0, C, ProcInfo) :-
+    ProcInfo0 = procedure(A, B, _, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R),
+    ProcInfo  = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R).
+
+proc_info_set_headvars(ProcInfo0, D, ProcInfo) :-
+    ProcInfo0 = procedure(A, B, C, _, E, F, G, H, I, J, K, L, M, N, O, P, Q, R),
+    ProcInfo  = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R).
+
+proc_info_set_argmodes(ProcInfo0, E, ProcInfo) :-
+    ProcInfo0 = procedure(A, B, C, D, _, F, G, H, I, J, K, L, M, N, O, P, Q, R),
+    ProcInfo  = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R).
+
+proc_info_set_maybe_arglives(ProcInfo0, F, ProcInfo) :-
+    ProcInfo0 = procedure(A, B, C, D, E, _, G, H, I, J, K, L, M, N, O, P, Q, R),
+    ProcInfo  = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R).
+
+proc_info_set_goal(ProcInfo0, G, ProcInfo) :-
+    ProcInfo0 = procedure(A, B, C, D, E, F, _, H, I, J, K, L, M, N, O, P, Q, R),
+    ProcInfo  = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R).
+
+proc_info_set_stack_slots(ProcInfo0, I, ProcInfo) :-
+    ProcInfo0 = procedure(A, B, C, D, E, F, G, H, _, J, K, L, M, N, O, P, Q, R),
+    ProcInfo  = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R).
+
+proc_info_set_inferred_determinism(ProcInfo0, J, ProcInfo) :-
+    ProcInfo0 = procedure(A, B, C, D, E, F, G, H, I, _, K, L, M, N, O, P, Q, R),
+    ProcInfo  = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R).
+
+proc_info_set_can_process(ProcInfo0, K, ProcInfo) :-
+    ProcInfo0 = procedure(A, B, C, D, E, F, G, H, I, J, _, L, M, N, O, P, Q, R),
+    ProcInfo  = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R).
+
+proc_info_set_arg_info(ProcInfo0, L, ProcInfo) :-
+    ProcInfo0 = procedure(A, B, C, D, E, F, G, H, I, J, K, _, M, N, O, P, Q, R),
+    ProcInfo  = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R).
+
+proc_info_set_liveness_info(ProcInfo0, M, ProcInfo) :-
+    ProcInfo0 = procedure(A, B, C, D, E, F, G, H, I, J, K, L, _, N, O, P, Q, R),
+    ProcInfo  = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R).
+
+proc_info_set_typeinfo_varmap(ProcInfo0, N, ProcInfo) :-
+    ProcInfo0 = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, _, O, P, Q, R),
+    ProcInfo  = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R).
+
+proc_info_set_typeclass_info_varmap(ProcInfo0, O, ProcInfo) :-
+    ProcInfo0 = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, _, P, Q, R),
+    ProcInfo  = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R).
+
+proc_info_set_maybe_arg_size_info(ProcInfo0, P, ProcInfo) :-
+    ProcInfo0 = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, _, Q, R),
+    ProcInfo  = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R).
+
+proc_info_set_maybe_termination_info(ProcInfo0, Q, ProcInfo) :-
+    ProcInfo0 = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, _, R),
+    ProcInfo  = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R).
 
 proc_info_get_typeinfo_vars_setwise(ProcInfo, Vars, TypeInfoVars) :-
 	set__to_sorted_list(Vars, VarList),
@@ -1272,6 +1302,7 @@
 	% variables that store typeinfos for these variables. 
 :- pred proc_info_get_typeinfo_vars_2(proc_info, list(var), list(var)).
 :- mode proc_info_get_typeinfo_vars_2(in, in, out) is det.
+
 proc_info_get_typeinfo_vars_2(_, [], []).
 proc_info_get_typeinfo_vars_2(ProcInfo, [Var | Vars1], TypeInfoVars) :-
 	proc_info_vartypes(ProcInfo, VarTypeMap),
@@ -1313,26 +1344,26 @@
 proc_info_ensure_unique_names(ProcInfo0, ProcInfo) :-
 	proc_info_vartypes(ProcInfo0, VarTypes),
 	map__keys(VarTypes, AllVars),
-	proc_info_variables(ProcInfo0, VarSet0),
+	proc_info_varset(ProcInfo0, VarSet0),
 	varset__ensure_unique_names(AllVars, "p", VarSet0, VarSet),
-	proc_info_set_variables(ProcInfo0, VarSet, ProcInfo).
+	proc_info_set_varset(ProcInfo0, VarSet, ProcInfo).
 
 proc_info_create_var_from_type(ProcInfo0, Type, NewVar, ProcInfo) :-
-	proc_info_variables(ProcInfo0, VarSet0),
+	proc_info_varset(ProcInfo0, VarSet0),
 	proc_info_vartypes(ProcInfo0, VarTypes0),
 	varset__new_var(VarSet0, NewVar, VarSet),
 	map__det_insert(VarTypes0, NewVar, Type, VarTypes),
-	proc_info_set_variables(ProcInfo0, VarSet, ProcInfo1),
+	proc_info_set_varset(ProcInfo0, VarSet, ProcInfo1),
 	proc_info_set_vartypes(ProcInfo1, VarTypes, ProcInfo).
 
 proc_info_create_vars_from_types(ProcInfo0, Types, NewVars, ProcInfo) :-
 	list__length(Types, NumVars),
-	proc_info_variables(ProcInfo0, VarSet0),
+	proc_info_varset(ProcInfo0, VarSet0),
 	proc_info_vartypes(ProcInfo0, VarTypes0),
 	varset__new_vars(VarSet0, NumVars, NewVars, VarSet),
 	map__det_insert_from_corresponding_lists(VarTypes0, 
 		NewVars, Types, VarTypes),
-	proc_info_set_variables(ProcInfo0, VarSet, ProcInfo1),
+	proc_info_set_varset(ProcInfo0, VarSet, ProcInfo1),
 	proc_info_set_vartypes(ProcInfo1, VarTypes, ProcInfo).
 
 %-----------------------------------------------------------------------------%
Index: compiler/inlining.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/inlining.m,v
retrieving revision 1.70
diff -u -r1.70 inlining.m
--- inlining.m	1997/12/19 03:06:59	1.70
+++ inlining.m	1997/12/21 08:38:49
@@ -338,7 +338,7 @@
 	pred_info_typevarset(PredInfo0, TypeVarSet0),
 
 	proc_info_goal(ProcInfo0, Goal0),
-	proc_info_variables(ProcInfo0, VarSet0),
+	proc_info_varset(ProcInfo0, VarSet0),
 	proc_info_vartypes(ProcInfo0, VarTypes0),
 	proc_info_typeinfo_varmap(ProcInfo0, TypeInfoVarMap0),
 
@@ -354,7 +354,7 @@
 
 	pred_info_set_typevarset(PredInfo0, TypeVarSet, PredInfo1),
 
-	proc_info_set_variables(ProcInfo0, VarSet, ProcInfo1),
+	proc_info_set_varset(ProcInfo0, VarSet, ProcInfo1),
 	proc_info_set_vartypes(ProcInfo1, VarTypes, ProcInfo2),
 	proc_info_set_typeinfo_varmap(ProcInfo2, TypeInfoVarMap, ProcInfo3),
 	proc_info_set_goal(ProcInfo3, Goal, ProcInfo),
@@ -427,7 +427,7 @@
 			% Callee has
 		module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
 			PredInfo, ProcInfo),
-        	proc_info_variables(ProcInfo, CalleeVarset),
+        	proc_info_varset(ProcInfo, CalleeVarset),
 		varset__vars(CalleeVarset, CalleeListOfVars),
 		list__length(CalleeListOfVars, CalleeThisMany),
 		TotalVars is ThisMany + CalleeThisMany,
Index: compiler/lambda.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/lambda.m,v
retrieving revision 1.34
diff -u -r1.34 lambda.m
--- lambda.m	1997/12/19 03:07:04	1.34
+++ lambda.m	1997/12/21 08:40:11
@@ -133,7 +133,7 @@
 	pred_info_get_is_pred_or_func(PredInfo0, PredOrFunc),
 	pred_info_typevarset(PredInfo0, TypeVarSet0),
 	pred_info_get_class_context(PredInfo0, Constraints0),
-	proc_info_variables(ProcInfo0, VarSet0),
+	proc_info_varset(ProcInfo0, VarSet0),
 	proc_info_vartypes(ProcInfo0, VarTypes0),
 	proc_info_goal(ProcInfo0, Goal0),
 	proc_info_typeinfo_varmap(ProcInfo0, TVarMap0),
@@ -148,7 +148,7 @@
 
 	% set the new values of the fields in proc_info and pred_info
 	proc_info_set_goal(ProcInfo0, Goal, ProcInfo1),
-	proc_info_set_variables(ProcInfo1, VarSet, ProcInfo2),
+	proc_info_set_varset(ProcInfo1, VarSet, ProcInfo2),
 	proc_info_set_vartypes(ProcInfo2, VarTypes, ProcInfo3),
 	proc_info_set_typeinfo_varmap(ProcInfo3, TVarMap, ProcInfo4),
 	proc_info_set_typeclass_info_varmap(ProcInfo4, TCVarMap, ProcInfo),
Index: compiler/liveness.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/liveness.m,v
retrieving revision 1.85
diff -u -r1.85 liveness.m
--- liveness.m	1997/12/19 03:07:13	1.85
+++ liveness.m	1997/12/21 08:38:54
@@ -153,7 +153,7 @@
 detect_liveness_proc(ProcInfo0, ModuleInfo, ProcInfo) :-
 	requantify_proc(ProcInfo0, ProcInfo1),
 	proc_info_goal(ProcInfo1, Goal0),
-	proc_info_variables(ProcInfo1, Varset),
+	proc_info_varset(ProcInfo1, Varset),
 	proc_info_vartypes(ProcInfo1, VarTypes),
 	live_info_init(ModuleInfo, ProcInfo1, VarTypes, Varset, LiveInfo),
 
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.247
diff -u -r1.247 make_hlds.m
--- make_hlds.m	1997/12/19 03:07:22	1.247
+++ make_hlds.m	1997/12/21 08:38:58
@@ -403,7 +403,7 @@
 				promised_pure, [], Module)
 	;
 		{ Pragma = termination_info(PredOrFunc, SymName, ModeList, 
-			Termination) },
+			MaybeArgSizeInfo, MaybeTerminationInfo) },
 		{ module_info_get_predicate_table(Module0, Preds) },
 		{ list__length(ModeList, Arity) },
 		(
@@ -425,8 +425,11 @@
 					ModeList, Module0, ProcId) }
 			->
 				{ map__lookup(ProcTable0, ProcId, ProcInfo0) },
-				{ proc_info_set_termination(ProcInfo0, 
-					Termination, ProcInfo) },
+				{ proc_info_set_maybe_arg_size_info(ProcInfo0, 
+					MaybeArgSizeInfo, ProcInfo1) },
+				{ proc_info_set_maybe_termination_info(
+					ProcInfo1, 
+					MaybeTerminationInfo, ProcInfo) },
 				{ map__det_update(ProcTable0, ProcId, ProcInfo,
 					ProcTable) },
 				{ pred_info_set_procedures(PredInfo0, 
Index: compiler/mercury_to_c.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_to_c.m,v
retrieving revision 1.30
diff -u -r1.30 mercury_to_c.m
--- mercury_to_c.m	1997/12/19 03:07:27	1.30
+++ mercury_to_c.m	1997/12/21 08:38:59
@@ -233,7 +233,7 @@
 
 c_gen_proc(Indent, ModuleInfo, PredId, ProcId, Pred, Proc) -->
 	{ proc_info_interface_determinism(Proc, InterfaceDeterminism) },
-	{ proc_info_variables(Proc, VarSet) },
+	{ proc_info_varset(Proc, VarSet) },
 	{ proc_info_headvars(Proc, HeadVars) },
 	{ pred_info_name(Pred, PredName) },
 	{ proc_info_vartypes(Proc, VarTypes) },
@@ -350,7 +350,7 @@
 		PredInfo, ProcInfo) },
 
 	{ proc_info_interface_code_model(ProcInfo, CodeModel) },
-	{ proc_info_variables(ProcInfo, VarSet) },
+	{ proc_info_varset(ProcInfo, VarSet) },
 	{ proc_info_headvars(ProcInfo, HeadVars) },
 	{ pred_info_arg_types(PredInfo, _HeadTypeVarSet, HeadTypes) },
 	{ proc_info_argmodes(ProcInfo, HeadModes) },
Index: compiler/mercury_to_mercury.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_to_mercury.m,v
retrieving revision 1.123
diff -u -r1.123 mercury_to_mercury.m
--- mercury_to_mercury.m	1997/12/19 03:07:32	1.123
+++ mercury_to_mercury.m	1997/12/21 08:39:01
@@ -324,9 +324,10 @@
 					   "promise_pure")
 	;
 		{ Pragma = termination_info(PredOrFunc, PredName, 
-			ModeList, Termination) },
-		termination__output_pragma_termination_info(PredOrFunc,
-			PredName, ModeList, Termination, Context)
+			ModeList, MaybeArgSizeInfo, MaybeTerminationInfo) },
+		termination__write_pragma_termination_info(PredOrFunc,
+			PredName, ModeList, Context,
+			MaybeArgSizeInfo, MaybeTerminationInfo)
 	;
 		{ Pragma = terminates(Pred, Arity) },
 		mercury_output_pragma_decl(Pred, Arity, predicate, "terminates")
Index: compiler/mode_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mode_info.m,v
retrieving revision 1.40
diff -u -r1.40 mode_info.m
--- mode_info.m	1997/10/14 09:18:44	1.40
+++ mode_info.m	1997/11/15 02:28:00
@@ -336,7 +336,7 @@
 	map__lookup(Preds, PredId, PredInfo),
 	pred_info_procedures(PredInfo, Procs),
 	map__lookup(Procs, ProcId, ProcInfo),
-	proc_info_variables(ProcInfo, VarSet),
+	proc_info_varset(ProcInfo, VarSet),
 	proc_info_vartypes(ProcInfo, VarTypes),
 
 	LiveVarsList = [LiveVars],
Index: compiler/modes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modes.m,v
retrieving revision 1.211
diff -u -r1.211 modes.m
--- modes.m	1997/12/19 03:07:39	1.211
+++ modes.m	1997/12/21 08:39:03
@@ -684,7 +684,7 @@
 	mode_info_get_varset(ModeInfo, VarSet),
 	mode_info_get_var_types(ModeInfo, VarTypes),
 	proc_info_set_goal(ProcInfo0, Body, ProcInfo1),
-	proc_info_set_variables(ProcInfo1, VarSet, ProcInfo2),
+	proc_info_set_varset(ProcInfo1, VarSet, ProcInfo2),
 	proc_info_set_vartypes(ProcInfo2, VarTypes, ProcInfo3),
 	proc_info_set_argmodes(ProcInfo3, ArgModes, ProcInfo).
 
Index: compiler/module_qual.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/module_qual.m,v
retrieving revision 1.26
diff -u -r1.26 module_qual.m
--- module_qual.m	1997/12/19 03:07:41	1.26
+++ module_qual.m	1997/12/21 08:39:04
@@ -656,8 +656,8 @@
 	fact_table(SymName, Arity, FileName), Info, Info) --> [].
 qualify_pragma(promise_pure(SymName, Arity), promise_pure(SymName, Arity),
 		Info, Info) --> [].
-qualify_pragma(termination_info(PredOrFunc, SymName, ModeList0, Termination), 
-		termination_info(PredOrFunc, SymName, ModeList, Termination), 
+qualify_pragma(termination_info(PredOrFunc, SymName, ModeList0, Args, Term), 
+		termination_info(PredOrFunc, SymName, ModeList, Args, Term), 
 		Info0, Info) --> 
 	qualify_mode_list(ModeList0, ModeList, Info0, Info).
 qualify_pragma(terminates(A, B), terminates(A, B), Info, Info) --> [].
Index: compiler/modules.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.44
diff -u -r1.44 modules.m
--- modules.m	1997/12/19 03:07:43	1.44
+++ modules.m	1997/12/21 08:39:05
@@ -257,7 +257,7 @@
 		{ Pragma \= terminates(_, _) },
 		{ Pragma \= does_not_terminate(_, _) },
 		{ Pragma \= check_termination(_, _) },
-		{ Pragma \= termination_info(_, _, _, _) }
+		{ Pragma \= termination_info(_, _, _, _, _) }
 	->
 		prog_out__write_context(Context),
 		report_warning("Warning: pragma in module interface.\n"),
Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.213
diff -u -r1.213 options.m
--- options.m	1997/12/10 07:15:49	1.213
+++ options.m	1997/12/21 08:39:08
@@ -204,6 +204,8 @@
 		;	verbose_check_termination
 		;	termination_single_args
 		;	termination_norm
+		;	termination_error_limit
+		;	termination_path_limit
 	%	- HLDS->LLDS
 		;	smart_indexing
 		;	  dense_switch_req_density
@@ -438,8 +440,10 @@
 	check_termination	-	bool(no),
 	verbose_check_termination -	bool(no),
 	termination		-	bool(no),
-	termination_single_args	-	bool(no),
+	termination_single_args	-	int(0),
 	termination_norm	-	string("total"),
+	termination_error_limit	-	int(3),
+	termination_path_limit	-	int(256),
 	split_c_files		-	bool(no)
 ]).
 option_defaults_2(optimization_option, [
@@ -767,6 +771,10 @@
 long_option("term-single-arg", 		termination_single_args).
 long_option("termination-norm",		termination_norm).
 long_option("term-norm",		termination_norm).
+long_option("termination-error-limit",	termination_error_limit).
+long_option("term-err-limit",		termination_error_limit).
+long_option("termination-path-limit",	termination_path_limit).
+long_option("term-path-limit",		termination_path_limit).
 
 % HLDS->LLDS optimizations
 long_option("smart-indexing",		smart_indexing).
@@ -1531,6 +1539,10 @@
 	io__write_string("\t--verb-chk-term, --verb-check-term, --verbose-check-termination\n"),
 	io__write_string("\t\tEnable termination analysis, and emit warnings for all\n"),
 	io__write_string("\t\tpredicates or functions that cannot be proved to terminate.\n"),
+	io__write_string("\t--term-single-arg <n>, --termination-single-argument-analysis <n>\n"),
+	io__write_string("\t\tWhen performing termination analysis, try analyzing\n"),
+	io__write_string("\t\trecursion on single arguments in strongly connected\n"),
+	io__write_string("\t\tcomponents of the call graph that have up to n procedures.\n"),
 	io__write_string("\t--termination-norm {simple, total, num-data-elems}\n"),
 	io__write_string("\t\tThe norm defines how termination analysis measures the size\n"),
 	io__write_string("\t\tof a memory cell. The simple norm says that size is always one.\n"),
@@ -1538,6 +1550,12 @@
 	io__write_string("\t\tThe num-data-elems norm says that it is the number of words in\n"),
 	io__write_string("\t\tthe cell that contain something other than pointers to cells of\n"),
 	io__write_string("\t\tthe same type.\n"),
+	io__write_string("\t--termination-error-limit <n>, --term-err-limit <n>\n"),
+	io__write_string("\t\tPrint at most n reasons for any single termination error\n"),
+	io__write_string("\t\t(default: 3).\n"),
+	io__write_string("\t--termination-path-limit <n>, --term-path-limit <n>\n"),
+	io__write_string("\t\tPerform termination analysis only on predicates\n"),
+	io__write_string("\t\twith at most n paths (default: 256).\n"),
 	io__write_string("\t--split-c-files\n"),
 	io__write_string("\t\tGenerate each C function in its own C file,\n"),
 	io__write_string("\t\tso that the linker will optimize away unused code.\n"),
Index: compiler/polymorphism.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/polymorphism.m,v
retrieving revision 1.119
diff -u -r1.119 polymorphism.m
--- polymorphism.m	1997/12/19 03:07:51	1.119
+++ polymorphism.m	1997/12/21 09:09:04
@@ -460,7 +460,7 @@
 	pred_info_get_constraint_proofs(PredInfo0, Proofs),
 	pred_info_name(PredInfo0, PredName),
 	proc_info_headvars(ProcInfo0, HeadVars0),
-	proc_info_variables(ProcInfo0, VarSet0),
+	proc_info_varset(ProcInfo0, VarSet0),
 	proc_info_vartypes(ProcInfo0, VarTypes0),
 	proc_info_goal(ProcInfo0, Goal0),
 	proc_info_argmodes(ProcInfo0, ArgModes0),
Index: compiler/prog_data.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_data.m,v
retrieving revision 1.28
diff -u -r1.28 prog_data.m
--- prog_data.m	1997/12/19 03:07:53	1.28
+++ prog_data.m	1997/12/21 08:39:11
@@ -146,7 +146,7 @@
 			% Predname, Arity
 
 	;	termination_info(pred_or_func, sym_name, list(mode),
-			termination)
+			maybe(arg_size_info), maybe(termination_info))
 			% the list(mode) is the declared argmodes of the
 			% procedure, unless there are no declared argmodes,
 			% in which case the inferred argmodes are used.
Index: compiler/prog_io_pragma.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_io_pragma.m,v
retrieving revision 1.9
diff -u -r1.9 prog_io_pragma.m
--- prog_io_pragma.m	1997/12/09 04:01:29	1.9
+++ prog_io_pragma.m	1997/12/10 01:08:47
@@ -334,9 +334,8 @@
     (
 	PragmaTerms = [
 	    PredAndModesTerm0,
-	    ConstTerm,
-	    TerminatesTerm,
-	    MaybeUsedArgsTerm
+	    ArgSizeTerm,
+	    TerminationTerm
 	],
 	( 
 	    PredAndModesTerm0 = term__functor(Const, Terms0, _) 
@@ -367,44 +366,35 @@
 	    ),
 	    convert_mode_list(ModeListTerm, ModeList),
 	    (			
-		ConstTerm = term__functor(term__atom("not_set"), [], _),
-		TerminationConst = not_set
+		ArgSizeTerm = term__functor(term__atom("not_set"), [], _),
+		MaybeArgSizeInfo = no
 	    ;
-		ConstTerm = term__functor( 
-		    term__atom("infinite"), [], ConstContext),
-		TerminationConst = inf(ConstContext - imported_pred)
+		ArgSizeTerm = term__functor(term__atom("infinite"), [],
+			ArgSizeContext),
+		MaybeArgSizeInfo = yes(infinite(
+			[ArgSizeContext - imported_pred]))
 	    ;
-		ConstTerm = term__functor(term__atom("set"), [IntTerm], _),
+		ArgSizeTerm = term__functor(term__atom("finite"),
+			[IntTerm, UsedArgsTerm], _),
 		IntTerm = term__functor(term__integer(Int), [], _),
-		TerminationConst = set(Int)
+		convert_bool_list(UsedArgsTerm, UsedArgs),
+		MaybeArgSizeInfo = yes(finite(Int, UsedArgs))
 	    ),
 	    (
-		TerminatesTerm = term__functor(term__atom("not_set"), [], _),
-		Terminates = not_set,
-		MaybeError = no
-	    ;
-		TerminatesTerm = term__functor(
-		    term__atom("dont_know"), [], TermContext),
-		Terminates = dont_know,
-		MaybeError = yes(TermContext - imported_pred)
-	    ;
-		TerminatesTerm = term__functor(term__atom("yes"), [], _),
-		Terminates = yes,
-		MaybeError = no
-	    ),
-	    (
-		MaybeUsedArgsTerm = term__functor(
-		    term__atom("yes"), [BoolListTerm], _),
-		convert_bool_list(BoolListTerm, BoolList),
-		MaybeUsedArgs = yes(BoolList)
+		TerminationTerm = term__functor(term__atom("not_set"), [], _),
+		MaybeTerminationInfo = no
 	    ;
-		MaybeUsedArgsTerm = term__functor(term__atom("no"), [], _),
-		MaybeUsedArgs = no
+		TerminationTerm = term__functor(term__atom("can_loop"),
+			[], TermContext),
+		MaybeTerminationInfo = yes(can_loop(
+			[TermContext - imported_pred]))
+	    ;
+		TerminationTerm = term__functor(term__atom("cannot_loop"),
+			[], _),
+		MaybeTerminationInfo = yes(cannot_loop)
 	    ),
-	    Termination = term(TerminationConst, Terminates,
-	    	MaybeUsedArgs, MaybeError),
 	    Result0 = ok(pragma(termination_info(PredOrFunc, PredName, 
-	    	ModeList, Termination)))
+	    	ModeList, MaybeArgSizeInfo, MaybeTerminationInfo)))
 	;
 	    Result0 = error("unexpected variable in pragma termination_info",
 						ErrorTerm)
@@ -415,7 +405,6 @@
 	Result = error("syntax error in `pragma termination_info'", ErrorTerm)
     ).
 			
-
 parse_pragma_type(ModuleName, "terminates", PragmaTerms,
 				ErrorTerm, _VarSet, Result) :-
 	parse_simple_pragma(ModuleName, "terminates",
Index: compiler/quantification.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/quantification.m,v
retrieving revision 1.54
diff -u -r1.54 quantification.m
--- quantification.m	1997/12/19 03:08:06	1.54
+++ quantification.m	1997/12/21 08:39:14
@@ -122,13 +122,13 @@
 			OutsideVars, Goal, Varset, VarTypes, Warnings).
 
 requantify_proc(ProcInfo0, ProcInfo) :-
-	proc_info_variables(ProcInfo0, Varset0),
+	proc_info_varset(ProcInfo0, Varset0),
 	proc_info_vartypes(ProcInfo0, VarTypes0),
 	proc_info_headvars(ProcInfo0, HeadVars),
 	proc_info_goal(ProcInfo0, Goal0),
 	implicitly_quantify_clause_body(HeadVars, Goal0, Varset0, VarTypes0,
 		Goal, Varset, VarTypes, _),
-	proc_info_set_variables(ProcInfo0, Varset, ProcInfo1),
+	proc_info_set_varset(ProcInfo0, Varset, ProcInfo1),
 	proc_info_set_vartypes(ProcInfo1, VarTypes, ProcInfo2),
 	proc_info_set_goal(ProcInfo2, Goal, ProcInfo).
 
Index: compiler/saved_vars.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/saved_vars.m,v
retrieving revision 1.12
diff -u -r1.12 saved_vars.m
--- saved_vars.m	1997/12/19 03:08:08	1.12
+++ saved_vars.m	1997/12/21 08:39:16
@@ -47,7 +47,7 @@
 	write_proc_progress_message("% Minimizing saved vars in ",
 		PredId, ProcId, ModuleInfo0),
 	{ proc_info_goal(ProcInfo0, Goal0) },
-	{ proc_info_variables(ProcInfo0, Varset0) },
+	{ proc_info_varset(ProcInfo0, Varset0) },
 	{ proc_info_vartypes(ProcInfo0, VarTypes0) },
 	{ init_slot_info(Varset0, VarTypes0, SlotInfo0) },
 
@@ -68,7 +68,7 @@
 	% hlds_out__write_goal(Goal, ModuleInfo, Varset, 0, ""),
 
 	{ proc_info_set_goal(ProcInfo0, Goal, ProcInfo1) },
-	{ proc_info_set_variables(ProcInfo1, Varset, ProcInfo2) },
+	{ proc_info_set_varset(ProcInfo1, Varset, ProcInfo2) },
 	{ proc_info_set_vartypes(ProcInfo2, VarTypes, ProcInfo) }.
 
 %-----------------------------------------------------------------------------%
Index: compiler/simplify.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/simplify.m,v
retrieving revision 1.49
diff -u -r1.49 simplify.m
--- simplify.m	1997/12/19 03:08:10	1.49
+++ simplify.m	1997/12/21 08:39:17
@@ -75,7 +75,7 @@
 	globals__io_get_globals(Globals, State0, State1),
 	det_info_init(ModuleInfo0, PredId, ProcId, Globals, DetInfo0),
 	proc_info_get_initial_instmap(Proc0, ModuleInfo0, InstMap0),
-	proc_info_variables(Proc0, VarSet0),
+	proc_info_varset(Proc0, VarSet0),
 	proc_info_vartypes(Proc0, VarTypes0),
 	simplify_info_init(DetInfo0, Simplify, InstMap0,
 		VarSet0, VarTypes0, Info0),
@@ -92,7 +92,7 @@
 		simplify__proc_2(Proc0, Proc1, Info1, Info2, State2, State3),
 		simplify_info_get_msgs(Info2, Msgs1),
 		simplify_info_get_det_info(Info2, DetInfo1),
-		proc_info_variables(Proc1, VarSet1),
+		proc_info_varset(Proc1, VarSet1),
 		proc_info_vartypes(Proc1, VarTypes1),
 		simplify_info_init(DetInfo1,
 			simplify(no, no, Once, no, no, Excess, no, Prop),
@@ -134,7 +134,7 @@
 	simplify_info_get_varset(Info1, VarSet),
 	simplify_info_get_var_types(Info1, VarTypes),
 	proc_info_set_goal(Proc0, Goal, Proc1),
-	proc_info_set_variables(Proc1, VarSet, Proc2),
+	proc_info_set_varset(Proc1, VarSet, Proc2),
 	proc_info_set_vartypes(Proc2, VarTypes, Proc3),
 	( simplify_info_requantify(Info1) ->
 		requantify_proc(Proc3, Proc4),
Index: compiler_design.html
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/notes/compiler_design.html,v
retrieving revision 1.10
diff -u -u -r1.10 compiler_design.html
--- compiler_design.html	1997/12/19 03:10:03	1.10
+++ compiler_design.html	1997/12/22 03:31:22
@@ -32,12 +32,12 @@
 stages:
 
 <ol>
-<li> parsing (source files -> HLDS)
-<li> semantic analysis and error checking (HLDS -> annotated HLDS)
-<li> high-level transformations (annotated HLDS -> annotated HLDS)
-<li> code generation (annotated HLDS -> LLDS)
-<li> low-level optimizations (LLDS -> LLDS)
-<li> output C code (LLDS -> C)
+<li> parsing (source files -&gt HLDS)
+<li> semantic analysis and error checking (HLDS -&gt annotated HLDS)
+<li> high-level transformations (annotated HLDS -&gt annotated HLDS)
+<li> code generation (annotated HLDS -&gt LLDS)
+<li> low-level optimizations (LLDS -&gt LLDS)
+<li> output C code (LLDS -&gt C)
 </ol>
 
 <p>
@@ -367,6 +367,30 @@
 
 <p>
 
+The next pass is termination analysis. The various modules involved are:
+
+<ul>
+<li>
+termination.m is the control module. It sets the argument size and
+termination properties of builtin and compiler generated procedures,
+invokes term_pass1.m and term_pass2.m
+and writes .trans_opt files and error messages as appropriate.
+<li>
+term_pass1.m analyzes the argument size properties of user-defined procedures,
+<li>
+term_pass2.m analyzes the termination properties of user-defined procedures.
+<li>
+term_traversal.m contains code common to the two passes.
+<li>
+term_errors.m defines the various kinds of termination errors
+and prints the messages appropriate for each.
+<li>
+term_util.m defines the main types used in termination analysis
+and contains utility predicates.
+</ul>
+
+<p>
+
 Most of the remaining HLDS-to-HLDS transformations are optimizations:
 
 <ul>
@@ -375,10 +399,8 @@
 
 <li> inlining (i.e. unfolding) of simple procedures (inlining.m)
 
-<li> constraint propagation (constraint.m) <br>
-	<p>
-
-	Not yet working.
+<li> pushing constraints as far left as possible (constraint.m);
+  this does not yet work.
 
 <li> issue warnings about unused arguments from predicates, and create
   specialized versions without them (unused_args.m); type_infos are
@@ -392,11 +414,12 @@
 <li> elimination of useless assignments, assignments that merely introduce
   another name for an already existing variable (excess.m).
 
-<li> reducing the number of variables that have to be saved across procedure calls
-  (saved_vars.m). We do this by putting the code that generates the value of
-  a variable just before the use of that variable, duplicating the variable
-  and the code that produces it if necessary, provided the cost of doing so
-  is smaller than the cost of saving and restoring the variable would be.
+<li> reducing the number of variables that have to be saved across
+  procedure calls (saved_vars.m). We do this by putting the code that
+  generates the value of a variable just before the use of that variable,
+  duplicating the variable and the code that produces it if necessary,
+  provided the cost of doing so is smaller than the cost of saving and
+  restoring the variable would be.
 
 </ul>
 
@@ -642,7 +665,7 @@
   creates base_type_functors structures that give information on 
   the functors of a given type. The base_type_layout and base_type_functors
   structures of each declared type constructor are added to the LLDS.
-<ul>
+
 <li> base_typeclass_info.m generates the base_typeclass_info structures that 
   list the methods of a class for each instance declaration. These are added to
   the LLDS.
@@ -698,10 +721,8 @@
 		<dd>
 		These modules contain stuff for handling the special
 		compiler-generated predicates which are generated for
-		each type: unify/2, compare/3, index/1 (used in the
-		implementation of compare/3), and also type_to_term/2
-		and term_to_type/2 (but those last two are disabled
-		at the moment).
+		each type: unify/2, compare/3, and index/1 (used in the
+		implementation of compare/3).
 
 	<dt> dependency_graph.m:
 		<dd>
@@ -722,6 +743,10 @@
 	<dt> opt_debug.m:
 		<dd>
 		Utility routines for debugging the LLDS-to-LLDS optimizations.
+
+	<dt> error_util.m:
+		<dd>
+		Utility routines for printing nicely formatted error messages.
 	</dl>
 
 

Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.108
diff -u -r1.108 user_guide.texi
--- user_guide.texi	1997/12/05 15:49:06	1.108
+++ user_guide.texi	1997/12/10 01:10:33
@@ -132,12 +132,12 @@
 these are generated automatically by the compiler,
 using the @samp{--make-interface} (or @samp{--make-int})
 and @samp{--make-short-interface} (or @samp{--make-short-int}) options.
-Files ending in @file{.opt} are 
+Files ending in @file{.opt} are
 interface files used in inter-module optimization,
-and are created using the @samp{--make-optimization-interface} 
+and are created using the @samp{--make-optimization-interface}
 (or @samp{--make-opt-int}) option.
- at c Files ending in @file{.trans_opt} are interface files used in 
- at c transitive inter-module optimization, and are created using the 
+ at c Files ending in @file{.trans_opt} are interface files used in
+ at c transitive inter-module optimization, and are created using the
 @c @samp{--make-transitive-optimization-interface} option.
 
 Since the interface of a module changes less often than its implementation,
@@ -225,7 +225,7 @@
 @c @example
 @c mmc -make-trans-opt @var{module1}.m @var{module2}.m ...
 @c @end example
- at c 
+ at c
 Given that you have made all the interface files,
 one way to create an executable for a multi-module program
 is to compile all the modules at the same time
@@ -684,7 +684,7 @@
 NU-Prolog has logical alternatives
 to the non-logical Prolog operations,
 and since Mercury supports both syntaxes,
-you can use NU-Prolog's logical alternatives to avoid this problem. 
+you can use NU-Prolog's logical alternatives to avoid this problem.
 However, during the development of the Mercury compiler
 we had to abandon their use for efficiency reasons.
 
@@ -807,15 +807,15 @@
 Removes all the automatically generated files.
 In addition to the files removed by @var{main-module}.clean, this
 removes the @samp{.date}, @samp{.int}, @samp{.int2}, @samp{.int3},
- at samp{.opt}, @samp{.optdate}, @samp{.date3}, 
- at c @samp{.trans_opt}, @samp{.trans_optdate}, 
+ at samp{.opt}, @samp{.optdate}, @samp{.date3},
+ at c @samp{.trans_opt}, @samp{.trans_optdate},
 @samp{.d}, and @samp{.dep} belonging to one of the modules of the program,
 and also the various possible executables for the program ---
- at samp{@var{main-module}}, 
- at samp{@var{main-module}.nu}, 
- at samp{@var{main-module}.nu.save}, 
- at samp{@var{main-module}.nu.debug}, 
- at samp{@var{main-module}.nu.debug.save}, 
+ at samp{@var{main-module}},
+ at samp{@var{main-module}.nu},
+ at samp{@var{main-module}.nu.save},
+ at samp{@var{main-module}.nu.debug},
+ at samp{@var{main-module}.nu.debug.save},
 @samp{@var{main-module}.sicstus}, and
 @samp{@var{main-module}.sicstus.debug}.
 
@@ -863,7 +863,7 @@
 @end table
 
 Other variables also exist - see
- at file{@var{prefix}/lib/mercury/mmake/Mmake.vars} for a complete list. 
+ at file{@var{prefix}/lib/mercury/mmake/Mmake.vars} for a complete list.
 
 If you wish to temporarily change the flags passed to an executable,
 rather than setting the various @samp{FLAGS} variables directly, one can
@@ -886,7 +886,7 @@
 @chapter Libraries
 
 Often you will want to use a particular set of Mercury modules
-in more than one program. The Mercury implementation 
+in more than one program. The Mercury implementation
 includes support for developing libraries, i.e. sets of Mercury modules
 intended for reuse.  It allows separate compilation of libraries
 and, on many platforms, it supports shared object libraries.
@@ -934,7 +934,7 @@
 Static libraries are created using the standard tools @samp{ar}
 and @samp{ranlib}.
 Shared libraries are created using the @samp{--make-shared-lib}
-option to @samp{ml}. 
+option to @samp{ml}.
 The automatically-generated Make rules for @samp{libmypackage}
 will look something like this:
 
@@ -1029,9 +1029,9 @@
 The @samp{-I} options in @samp{MCFLAGS} tell @samp{mmc} where to find
 the interface files.  The @samp{-R} options in @samp{MLFLAGS} tell
 the loader where to find shared libraries, and the @samp{-L}
-options tell the linker where to find libraries. 
+options tell the linker where to find libraries.
 (Note that the @samp{-R} options must precede the @samp{-L} options.)
-The @samp{-l} options tell the linker which libraries to link with. 
+The @samp{-l} options tell the linker which libraries to link with.
 The extras arguments to @samp{c2init} specified in the @samp{C2INITLFLAGS}
 variable tell @samp{c2init} where to find the @samp{.init} files for the
 libraries, so that it can generate appropriate initialization code.
@@ -1144,8 +1144,8 @@
 @node Displaying the profile
 @section Displaying the profile
 
-To display the profile, just type @samp{mprof}.  This will read the 
- at file{Prof.*} files and display the flat profile in a nice human-readable 
+To display the profile, just type @samp{mprof}.  This will read the
+ at file{Prof.*} files and display the flat profile in a nice human-readable
 format.  If you also want to see the call graph profile, which takes a lot
 longer to generate, type @samp{mprof -c}.
 
@@ -1157,7 +1157,7 @@
 @node Analysis of results
 @section Analysis of results
 
-The profile output consists of three major sections.  These are 
+The profile output consists of three major sections.  These are
 named the call graph profile, the flat profile and the alphabetic listing.
 
 The call graph profile presents the local call graph of each
@@ -1199,26 +1199,26 @@
                                   called/total       children
 
                                                      <spontaneous>
-[1]    100.0    0.00        0.75       0         call_engine_label [1] 
+[1]    100.0    0.00        0.75       0         call_engine_label [1]
                 0.00        0.75       1/1           do_interpreter [3]
 
 -----------------------------------------------
 
                 0.00        0.75       1/1           do_interpreter [3]
-[2]    100.0    0.00        0.75       1         io__run/0(0) [2] 
+[2]    100.0    0.00        0.75       1         io__run/0(0) [2]
                 0.00        0.00       1/1           io__init_state/2(0) [11]
                 0.00        0.74       1/1           main/2(0) [4]
 
 -----------------------------------------------
 
                 0.00        0.75       1/1           call_engine_label [1]
-[3]    100.0    0.00        0.75       1         do_interpreter [3] 
+[3]    100.0    0.00        0.75       1         do_interpreter [3]
                 0.00        0.75       1/1           io__run/0(0) [2]
 
 -----------------------------------------------
 
                 0.00        0.74       1/1           io__run/0(0) [2]
-[4]     99.9    0.00        0.74       1         main/2(0) [4] 
+[4]     99.9    0.00        0.74       1         main/2(0) [4]
                 0.00        0.74       1/1           sort/2(0) [5]
                 0.00        0.00       1/1           print_list/3(0) [16]
                 0.00        0.00       1/10          io__write_string/3(0) [18]
@@ -1226,7 +1226,7 @@
 -----------------------------------------------
 
                 0.00        0.74       1/1           main/2(0) [4]
-[5]     99.9    0.00        0.74       1         sort/2(0) [5] 
+[5]     99.9    0.00        0.74       1         sort/2(0) [5]
                 0.05        0.65       1/1           list__perm/2(0) [6]
                 0.00        0.09   40320/40320       sorted/1(0) [10]
 
@@ -1234,35 +1234,35 @@
 
                                        8             list__perm/2(0) [6]
                 0.05        0.65       1/1           sort/2(0) [5]
-[6]     86.6    0.05        0.65       1+8      list__perm/2(0) [6] 
+[6]     86.6    0.05        0.65       1+8      list__perm/2(0) [6]
                 0.00        0.60    5914/5914        list__insert/3(2) [7]
                                        8             list__perm/2(0) [6]
 
 -----------------------------------------------
 
                 0.00        0.60    5914/5914        list__perm/2(0) [6]
-[7]     80.0    0.00        0.60    5914         list__insert/3(2) [7] 
+[7]     80.0    0.00        0.60    5914         list__insert/3(2) [7]
                 0.60        0.60    5914/5914        list__delete/3(3) [8]
 
 -----------------------------------------------
 
                                    40319             list__delete/3(3) [8]
                 0.60        0.60    5914/5914        list__insert/3(2) [7]
-[8]     80.0    0.60        0.60    5914+40319  list__delete/3(3) [8] 
+[8]     80.0    0.60        0.60    5914+40319  list__delete/3(3) [8]
                                    40319             list__delete/3(3) [8]
 
 -----------------------------------------------
 
                 0.00        0.00       3/69283       tree234__set/4(0) [15]
                 0.09        0.09   69280/69283       sorted/1(0) [10]
-[9]     13.3    0.10        0.10   69283         compare/3(0) [9] 
+[9]     13.3    0.10        0.10   69283         compare/3(0) [9]
                 0.00        0.00       3/3           __Compare___io__stream/0(0) [20]
                 0.00        0.00   69280/69280       builtin_compare_int/3(0) [27]
 
 -----------------------------------------------
 
                 0.00        0.09   40320/40320       sort/2(0) [5]
-[10]    13.3    0.00        0.09   40320         sorted/1(0) [10] 
+[10]    13.3    0.00        0.09   40320         sorted/1(0) [10]
                 0.09        0.09   69280/69283       compare/3(0) [9]
 
 -----------------------------------------------
@@ -1275,29 +1275,29 @@
 @samp{main/2} is the entry point to the user's program.)
 
 Each entry of the call graph profile consists of three sections, the parent
-procedures, the current procedure and the children procedures.  
+procedures, the current procedure and the children procedures.
 
 Reading across from the left, for the current procedure the fields are:
 
 @itemize @bullet
 @item
-The unique index number for the current procedure. 
+The unique index number for the current procedure.
 (The index numbers are used only to make it easier to find
 a particular entry in the call graph.)
 
 @item
 The percentage of total execution time spent in the current procedure
-and all its descendents. 
+and all its descendents.
 As noted above, this is only a statistical approximation.
 
 @item
-The ``self'' time: the time spent executing code that is 
-part of current procedure.  
+The ``self'' time: the time spent executing code that is
+part of current procedure.
 As noted above, this is only a statistical approximation.
 
 @item
 The descendent time: the time spent in the
-current procedure and all its descendents.  
+current procedure and all its descendents.
 As noted above, this is only a statistical approximation.
 
 @item
@@ -1308,7 +1308,7 @@
 These numbers are exact, not approximate.
 
 @item
-The name of the procedure followed by its index number. 
+The name of the procedure followed by its index number.
 @end itemize
 
 The predicate or function names are not just followed by their arity but
@@ -1319,7 +1319,7 @@
 
 Now for the parent and child procedures the self and descendent time have
 slightly different meanings.  For the parent procedures the self and descendent
-time represent the proportion of the current procedure's self and descendent 
+time represent the proportion of the current procedure's self and descendent
 time due to that parent.  These times are obtained using the assumption that
 each call contributes equally to the total time of the current procedure.
 
@@ -1366,16 +1366,16 @@
 
 @menu
 * Invocation overview::
-* Verbosity options::           
-* Warning options::   
-* Output options::   
-* Auxiliary output options::   
+* Verbosity options::
+* Warning options::
+* Output options::
+* Auxiliary output options::
 * Language semantics options::
 * Compilation model options::
-* Code generation options::   
-* Optimization options::   
-* Link options::   
-* Miscellaneous options::   
+* Code generation options::
+* Optimization options::
+* Link options::
+* Miscellaneous options::
 @end menu
 
 @node Invocation overview
@@ -1456,7 +1456,7 @@
 
 @sp 1
 @item --warn-non-stratification
-Warn about possible non-stratification of the predicates/functions in the 
+Warn about possible non-stratification of the predicates/functions in the
 module.
 Non-stratification occurs when a predicate/function can call itself
 negatively through some path along its call graph.
@@ -1539,7 +1539,7 @@
 and all of its dependencies to @file{@var{module}.dep}.
 
 @item --generate-module-order
-Output the strongly connected components of the module 
+Output the strongly connected components of the module
 dependency graph in top-down order to @file{@var{module}.order}.
 Implies @samp{--generate-dependencies}.
 
@@ -1566,10 +1566,10 @@
 @c @item --make-transitive-optimization-interface
 @c @itemx --make-trans-opt
 @c Write the @file{@var{module}.trans_opt} file.  This file is used to store
- at c information used for inter-module optimization. The information is read 
- at c in when the compiler is invoked with the @samp{--transitive-optimization} 
- at c option.  The file is called ``transitive'' because a 
- at c @file{@var{module}.trans_opt} file may depend on other 
+ at c information used for inter-module optimization. The information is read
+ at c in when the compiler is invoked with the @samp{--transitive-optimization}
+ at c option.  The file is called ``transitive'' because a
+ at c @file{@var{module}.trans_opt} file may depend on other
 @c @file{@var{module}.trans_opt} files.
 @c
 @sp 1
@@ -1584,7 +1584,7 @@
 @itemx --pretty-print
 @itemx --convert-to-mercury
 Convert to Mercury. Output to file @file{@var{module}.ugly}.
-This option acts as a Mercury ugly-printer. 
+This option acts as a Mercury ugly-printer.
 (It would be a pretty-printer, except that comments are stripped
 and nested if-then-elses are indented too much --- so the result
 is rather ugly.)
@@ -1917,7 +1917,7 @@
 Similar to @samp{--profiling}, except that this option only gathers
 timing information, not call counts.  For the results to be useful,
 call counts for an identical run of your program need to be gathered
-using @samp{--profiling} or @samp{--profile-calls}. 
+using @samp{--profiling} or @samp{--profile-calls}.
 XXX this doesn't work, because the code addresses change.
 The only advantage of using @samp{--profile-time} and @samp{--profile-calls}
 to gather timing information and call counts in seperate runs,
@@ -1932,7 +1932,7 @@
 @item @code{--debug} (grades: any grade containing @samp{.debug})
 Enable debugging.
 Pass the @samp{-g} flag to the C compiler, instead of @samp{-DSPEED},
-to enable debugging of the generated C code. 
+to enable debugging of the generated C code.
 This option also implies @samp{--no-c-optimize}.
 Debugging support is currently extremely primitive -
 this option is probably not useful to anyone except the Mercury implementors.
@@ -1958,7 +1958,7 @@
 (This option is not intended for general use.)
 Don't output base_type_layout structures or references to them.
 This option will generate smaller executables, but will not allow the
-use of code that uses the layout information (e.g. @samp{functor}, 
+use of code that uses the layout information (e.g. @samp{functor},
 @samp{arg}). Using such code will result in undefined behaviour at
 runtime. The C code also needs to be compiled with
 @samp{-DNO_TYPE_LAYOUT}.
@@ -2012,7 +2012,7 @@
 
 @sp 1
 @item --fact-table-max-array-size @var{size}
-Specify the maximum number of elements in a single 
+Specify the maximum number of elements in a single
 @samp{pragma fact_table} data array (default: 1024).
 The data for fact tables is placed into multiple C arrays, each with a
 maximum size given by this option.  The reason for doing this is that
@@ -2116,7 +2116,7 @@
 @c different to the @file{@var{module}.opt} as @file{@var{module}.trans_opt}
 @c files may depend on other @file{@var{module}.trans_opt} files.
 @c @file{@var{module}.opt} files may only depend on the
- at c @file{@var{module}.m} file.  
+ at c @file{@var{module}.m} file.
 @c
 @sp 1
 @item --enable-termination
@@ -2133,19 +2133,45 @@
 @itemx --check-term
 @itemx --chk-term
 Enable termination analysis, and emit warnings for some predicates or
-functions that cannot be proved to terminate.  In many cases the
-compiler is unable to prove termination the problem is either a lack of
-information about the termination properties of other predicates, or
-because the program used language constructs (such as higher order
-calls) which could not be analysed.  In these cases the compiler does
+functions that cannot be proved to terminate.  In many cases in which the
+compiler is unable to prove termination, the problem is either a lack of
+information about the termination properties of other predicates, or the
+fact that the program used language constructs (such as higher order
+calls) which cannot be analysed.  In these cases the compiler does
 not emit a warning of non-termination, as it is likely to be spurious.
 
 @sp 1
 @item --verbose-check-termination
 @itemx --verb-check-term
 @itemx --verb-chk-term
-Enable termination analysis, and emit warnings for all predicates or 
-functions that cannot be proved to terminate.  
+Enable termination analysis, and emit warnings for all predicates or
+functions that cannot be proved to terminate.
+
+ at sp 1
+ at item --termination-single-argument-analysis @var{limit}
+ at itemx --term-single-arg @var{limit}
+When performing termination analysis, try analyzing
+recursion on single arguments in strongly connected
+components of the call graph that have up to @var{limit} procedures.
+
+ at sp 1
+ at item --termination-norm @var{norm}
+The norm defines how termination analysis measures the size
+of a memory cell. The @samp{simple} norm says that size is always one.
+The @samp{total} norm says that it is the number of words in the cell.
+The @samp{num-data-elems} norm says that it is the number of words in
+the cell that contain something other than pointers to cells of
+the same type.
+
+ at sp 1
+ at item --termination-error-limit @var{limit}
+ at itemx --term-err-limit @var{limit}
+Print at most @var{n} reasons for any single termination error.
+
+ at sp 1
+ at item --termination-path-limit @var{limit}
+ at itemx --term-path-limit @var{limit}
+Perform termination analysis only on predicates with at most @var{n} paths.
 
 @sp 1
 @item --split-c-files
@@ -2195,7 +2221,7 @@
 
 @item --intermod-inline-simple-threshold @var{threshold}
 Similar to --inline-simple-threshold, except used to determine which
-predicates should be included in @samp{.opt} files. Note that changing this 
+predicates should be included in @samp{.opt} files. Note that changing this
 between writing the @samp{.opt} file and compiling to C may cause link errors,
 and too high a value may result in reduced performance.
 
@@ -2454,7 +2480,7 @@
 @table @code
 @item -I @var{dir}
 @itemx --search-directory @var{dir}
-Append @var{dir} to the list of directories to be searched for 
+Append @var{dir} to the list of directories to be searched for
 imported modules.
 
 @item --intermod-directory @var{dir}
@@ -2524,7 +2550,7 @@
 A list of options for the Mercury runtime that gets
 linked into every Mercury program.
 Options are available to set the size of the different memory
-areas, and to enable various debugging traces. 
+areas, and to enable various debugging traces.
 Set @samp{MERCURY_OPTIONS} to @samp{-h} for help.
 
 @sp 1
@@ -2617,7 +2643,7 @@
 it is possible to do so.  Here's what you need to do.
 
 @itemize @bullet
- at item You must specify the name of the new compiler. 
+ at item You must specify the name of the new compiler.
 You can do this either by setting the @samp{MERCURY_C_COMPILER}
 environment variable, by adding
 @samp{MGNUC=MERCURY_C_COMPILER=@dots{} mgnuc} to your @samp{Mmake} file,
@@ -2629,7 +2655,7 @@
 @samp{-std} option to @samp{cc}).
 
 @item
-You must use the grade @samp{none} or @samp{none.gc}. 
+You must use the grade @samp{none} or @samp{none.gc}.
 You can specify the grade in one of three ways: by setting the
 @samp{MERCURY_DEFAULT_GRADE} environment variable, by adding a line
 @samp{GRADE=@dots{}} to your @samp{Mmake} file, or by using the
Index: library/bag.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/bag.m,v
retrieving revision 1.12
diff -u -r1.12 bag.m
--- bag.m	1997/10/04 06:16:50	1.12
+++ bag.m	1997/12/02 04:10:46
@@ -16,7 +16,7 @@
 
 :- interface.
 
-:- import_module list.
+:- import_module list, assoc_list.
 
 :- type bag(T).
 
@@ -36,13 +36,20 @@
 :- pred bag__from_list(list(T), bag(T)).
 :- mode bag__from_list(in, out) is det.
 
-	 % Given a bag, produce a sorted list containing all the values in
-	 % the bag.  Each value will appear in the list the same number of
-	 % times that it appears in the bag.
+	% Given a bag, produce a sorted list containing all the values in
+	% the bag.  Each value will appear in the list the same number of
+	% times that it appears in the bag.
 :- pred bag__to_list(bag(T), list(T)).
 :- mode bag__to_list(in, out) is det.
 
-	% Given a bag, produce a sorted list with no duplicates 
+	% Given a bag, produce a sorted list containing all the values in
+	% the bag.  Each value will appear in the list once, with the
+	% associated value giving the number of times that it appears
+	% in the bag.
+:- pred bag__to_assoc_list(bag(T), assoc_list(T, int)).
+:- mode bag__to_assoc_list(in, out) is det.
+
+	% Given a bag, produce a sorted list with no duplicates
 	% containing all the values in the bag.
 :- pred bag__to_list_without_duplicates(bag(T), list(T)).
 :- mode bag__to_list_without_duplicates(in, out) is det.
@@ -80,7 +87,7 @@
 	% each element in SubBag is removed from Bag0 to produce Bag.
 	% If an element exists in SubBag, but not in Bag, then that
 	% element is not removed.
-	% e.g. bag__subtract({1, 1, 2, 2, 3 }, {1, 1, 2, 3, 3, 3}, {2}). 
+	% e.g. bag__subtract({1, 1, 2, 2, 3 }, {1, 1, 2, 3, 3, 3}, {2}).
 :- pred bag__subtract(bag(T), bag(T), bag(T)).
 :- mode bag__subtract(in, in, out) is det.
 
@@ -103,6 +110,16 @@
 :- pred bag__intersect(bag(T), bag(T)).
 :- mode bag__intersect(in, in) is semidet.
 
+	% The third bag is the smallest bag that has both the first two bags
+	% as subbags. If an element X is present N times in one of the first
+	% two bags, X will be present at least N times in the third bag.
+	% E.g. {1, 1, 2} upper_bound {2, 2, 3} = {1, 1, 2, 2, 3}
+	% If the two input bags are known to be unequal in size, then
+	% making the first bag the larger bag will usually be more
+	% efficient.
+:- pred bag__least_upper_bound(bag(T), bag(T), bag(T)).
+:- mode bag__least_upper_bound(in, in, out) is det.
+
 	% Fails if the first bag is not a subbag of the second.
 	% bag__is_subbag(A, B). implies that every element in the bag A
 	% is also in the bag B.  If an element is in bag A multiple times, it
@@ -120,7 +137,7 @@
 :- pred bag__remove_smallest(bag(T), T, bag(T)).
 :- mode bag__remove_smallest(in, out, out) is semidet.
 
-	% Compares the two bags, and returns whether the first bag is a 
+	% Compares the two bags, and returns whether the first bag is a
 	% subset (<), is equal (=), or is a superset (>) of the second.
 	% bag__subset_compare(<, {apple, orange}, {apple, apple, orange}).
 	% bag__subset_compare(=, {apple, orange}, {apple, orange}).
@@ -131,9 +148,10 @@
 
 %---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
+
 :- implementation.
 
-:- import_module map, int, require, assoc_list, std_util.
+:- import_module map, int, require, std_util.
 
 :- type bag(T)		==	map(T, int).
 
@@ -167,15 +185,13 @@
 	bag__init(Bag0),
 	bag__insert_list(Bag0, List, Bag).
 
-bag__to_list_without_duplicates(Bag, List) :-
-	map__keys(Bag, List).
-
 bag__to_list(Bag, List) :-
 	map__to_assoc_list(Bag, AssocList),
 	bag__to_list_2(AssocList, List).
 
 :- pred bag__to_list_2(assoc_list(T, int), list(T)).
 :- mode bag__to_list_2(in, out) is det.
+
 bag__to_list_2([], []).
 bag__to_list_2([X - Int | Xs ], Out) :-
 	( Int =< 0 ->
@@ -185,7 +201,12 @@
 		bag__to_list_2([X - NewInt | Xs], Out0),
 		Out = [X | Out0]
 	).
-		
+
+bag__to_assoc_list(Bag, AssocList) :-
+	map__to_assoc_list(Bag, AssocList).
+
+bag__to_list_without_duplicates(Bag, List) :-
+	map__keys(Bag, List).
 
 %---------------------------------------------------------------------------%
 
@@ -245,11 +266,10 @@
 		Bag = Bag0
 	).
 
-	
 bag__union(A, B, Out) :-
 	( map__remove_smallest(B, Key, BVal, B0) ->
 		( map__search(A, Key, AVal) ->
-			NewVal = AVal + BVal,
+			NewVal is AVal + BVal,
 			map__det_update(A, Key, NewVal, A0)
 		;
 			map__det_insert(A, Key, BVal, A0)
@@ -258,8 +278,6 @@
 	;
 		Out = A
 	).
-			
-		
 
 bag__intersect(A, B, Out) :-
 	bag__init(Out0),
@@ -267,6 +285,7 @@
 
 :- pred bag__intersect_2(bag(T), bag(T), bag(T), bag(T)).
 :- mode bag__intersect_2(in, in, in, out) is det.
+
 bag__intersect_2(A, B, Out0, Out) :-
 	( map__remove_smallest(A, Key, AVal,A0) ->
 		( map__search(B, Key, BVal) ->
@@ -288,6 +307,19 @@
 		bag__intersect(A0, B)
 	).
 
+bag__least_upper_bound(A, B, Out) :-
+	( map__remove_smallest(B, Key, BVal, B0) ->
+		( map__search(A, Key, AVal) ->
+			int__max(AVal, BVal, NewVal),
+			map__det_update(A, Key, NewVal, A0)
+		;
+			map__det_insert(A, Key, BVal, A0)
+		),
+		bag__least_upper_bound(A0, B0, Out)
+	;
+		Out = A
+	).
+
 %---------------------------------------------------------------------------%
 
 bag__is_subbag(SubBag, BigBag) :-
@@ -310,7 +342,7 @@
 		Bag = Bag1
 	).
 
-	% compares the two bags, and returns whether the first bag is a 
+	% compares the two bags, and returns whether the first bag is a
 	% subset (<), is equal (=), or is a superset (>) of the second
 	% bag__subset_compare(<, {apple, orange}, {apple, apple, orange}).
 	% bag__subset_compare(=, {apple, orange}, {apple, orange}).
@@ -322,7 +354,7 @@
 	( map__remove_smallest(A, Key, AVal, A0) ->
 		( map__remove(B, Key, BVal, B0) ->
 			compare(ValRes, AVal, BVal),
-			( 
+			(
 				ValRes = (>),
 				bag__is_subbag(B0, A0),
 				Res = (>)
Index: library/list.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/list.m,v
retrieving revision 1.78
diff -u -r1.78 list.m
--- list.m	1997/09/02 23:05:45	1.78
+++ list.m	1997/11/17 00:31:15
@@ -154,6 +154,13 @@
 :- pred list__take(int, list(T), list(T)).
 :- mode list__take(in, in, out) is semidet.
 
+	% list__take_upto(Len, List, Start):
+	%	`Start' is the first `Len' elements of `List'.
+	%	If `List' has fewer elements than that, return the entire list.
+	%
+:- pred list__take_upto(int, list(T), list(T)).
+:- mode list__take_upto(in, in, out) is det.
+
 	% list__drop(Len, List, End):
 	%	`End' is the remainder of `List' after removing the
 	%	first `Len' elements.
@@ -797,9 +804,26 @@
 		N > 0
 	->
 		N1 is N - 1,
-		As = [A|As1],
-		Bs = [A|Bs1],
+		As = [A | As1],
+		Bs = [A | Bs1],
 		list__take(N1, As1, Bs1)
+	;
+		Bs = []
+	).
+
+list__take_upto(N, As, Bs) :-
+	(
+		N > 0
+	->
+		N1 is N - 1,
+		(
+			As = [A | As1],
+			Bs = [A | Bs1],
+			list__take_upto(N1, As1, Bs1)
+		;
+			As = [],
+			Bs = []
+		)
 	;
 		Bs = []
 	).
Index: library/set.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/set.m,v
retrieving revision 1.47
diff -u -r1.47 set.m
--- set.m	1997/11/02 08:50:39	1.47
+++ set.m	1997/11/15 07:39:57
@@ -182,6 +182,11 @@
 :- pred set__difference(set(T), set(T), set(T)).
 :- mode set__difference(in, in, out) is det.
 
+	% `set__count(Set, Count)' is true iff `Set' has `Count' elements.
+
+:- pred set__count(set(T), int).
+:- mode set__count(in, out) is det.
+
 %--------------------------------------------------------------------------%
 
 :- implementation.
@@ -258,6 +263,9 @@
 
 set__difference(SetA, SetB, Set) :-
 	set_ordlist__difference(SetA, SetB, Set).
+
+set__count(Set, Count) :-
+	set_ordlist__count(Set, Count).
 
 %--------------------------------------------------------------------------%
 %--------------------------------------------------------------------------%
Index: library/set_ordlist.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/set_ordlist.m,v
retrieving revision 1.5
diff -u -r1.5 set_ordlist.m
--- set_ordlist.m	1997/07/27 15:07:11	1.5
+++ set_ordlist.m	1997/11/15 07:34:27
@@ -162,7 +162,7 @@
 :- mode set_ordlist__intersect(in, in, in) is semidet.
 
 	% `set_ordlist__power_intersect(A, B)' is true iff `B' is the
-	% intersection of all the sets in `A'
+	% intersection of all the sets in `A'.
 
 :- pred set_ordlist__power_intersect(set_ordlist(set_ordlist(T)),
 							set_ordlist(T)).
@@ -170,12 +170,18 @@
 
 	% `set_ordlist__difference(SetA, SetB, Set)' is true iff `Set' is the
 	% set containing all the elements of `SetA' except those that
-	% occur in `SetB'
+	% occur in `SetB'.
 
 :- pred set_ordlist__difference(set_ordlist(T), set_ordlist(T),
 							set_ordlist(T)).
 :- mode set_ordlist__difference(in, in, out) is det.
 
+	% `set_ordlist__count(Set, Count)' is true iff `Set' has
+	% `Count' elements.
+
+:- pred set_ordlist__count(set_ordlist(T), int).
+:- mode set_ordlist__count(in, out) is det.
+
 %--------------------------------------------------------------------------%
 
 :- implementation.
@@ -336,5 +342,10 @@
 		R = (>),
 		set_ordlist__difference([X|Xs], Ys, Set)
 	).
+
+%--------------------------------------------------------------------------%
+
+set_ordlist__count(Set, Count) :-
+	list__length(Set, Count).
 
 %--------------------------------------------------------------------------%



More information about the developers mailing list