[m-dev.] for review: add parsing/storing of assertions

Peter Ross petdr at cs.mu.OZ.AU
Thu Jul 8 20:02:01 AEST 1999


Hi,

This is for Fergus or DJ to review, whoever gets there first.

Pete.

===================================================================


Estimated hours taken: 50

Add the infrastructure for assertions into the compiler.

compiler/error_util.m:
    Output the correct pred name for assertions.

compiler/hlds_data.m:
    Add the assertion_table structure.

compiler/hlds_module.m:
    Get/set the assertion_table from the module_info.

compiler/hlds_out.m:
    Modify hlds_out__write_pred_id to identify assertions.

compiler/hlds_pred.m:
    Add the goal_type assertion.

compiler/make_hlds.m:
    Transform the assertion to a HLDS data structure that can be
    typechecked.

compiler/mercury_to_goedel.m:
compiler/module_qual.m:
    Handle the assertion structure.

compiler/mercury_to_mercury.m:
    Output assertions.

compiler/post_typecheck.m:
    Add a predicate which must be called after typechecking of
    assertions has been finished.  Also document some possible problems
    with typechecking assertions.

compiler/prog_data.m:
    Add assertion to the type item.

compiler/prog_io.m:
    Add the ability to parse assertions.

compiler/purity.m:
    After finished typechecking assertions call
    post_typecheck__finish_assertion.

compiler/typecheck.m:
    Don't output inference messages for assertions.

compiler/notes/compiler_design.html:
    Update documentation about exactly where quantification is done.

compiler/notes/glossary.html:
    Define what an assertion is.

doc/.ispell_words:
    Some more commonly spelt words.

doc/reference_manual.texi:
    Add a small section about how to declare assertions.

doc/transition_guide.texi:
    Mention the new :- assertion op.

library/ops.m:
    Declare the :- assertion op.


*** Relative DIFF ***

===================================================================
RCS file: RCS/accumulator.m,v
retrieving revision 1.10
diff -u -r1.10 accumulator.m
===================================================================
RCS file: RCS/check_assertion.m,v
retrieving revision 1.2
diff -u -r1.2 check_assertion.m
===================================================================
RCS file: RCS/hlds_data.m,v
retrieving revision 1.2
diff -u -r1.2 hlds_data.m
--- hlds_data.m	1999/07/08 00:56:46	1.2
+++ hlds_data.m	1999/07/08 08:11:28
@@ -813,24 +813,24 @@
 
 :- interface.
 
-:- import_module hlds_module.
-
 	%
 	% A table that records all the assertions in the system.
+	% An assertion is a goal that will always evaluate to true,
+	% subject to the constraints imposed by the quantifiers.
+	%
+	% ie :- assertion all [A] some [B] (B > A)
 	% 
+	% The above assertion states that for all possible values of A,
+	% there will exist at least one value, B, such that B is greater
+	% then A.
+	%
 :- type assert_id.
 :- type assertion_table.
 
 :- pred assertion_table_init(assertion_table::out) is det.
 
-	%
-	% After typechecking is finished the pred_info describing the
-	% assertion should be removed from further processing and the
-	% pred_id which describes the assertion stored in the
-	% assertion_table.
-	%
-:- pred remove_assertion_from_further_processing(pred_id::in,
-		module_info::in, module_info::out) is det.
+:- pred assertion_table_add_assertion(pred_id::in,
+		assertion_table::in, assertion_table::out) is det.
 
 :- pred assertion_table_lookup(assertion_table::in, assert_id::in,
 		pred_id::out) is det.
@@ -846,23 +846,14 @@
 assertion_table_init(assertion_table(0, AssertionMap)) :-
 	map__init(AssertionMap).
 
-remove_assertion_from_further_processing(PredId, Module0, Module) :-
-	module_info_assertion_table(Module0, AssertionTable0),
-	assertion_table_add_assertion(PredId, AssertionTable0, AssertionTable),
-	module_info_set_assertion_table(Module0, AssertionTable, Module1),
-	module_info_remove_predid(Module1, PredId, Module).
+assertion_table_add_assertion(Assertion, AssertionTable0, AssertionTable) :-
+	AssertionTable0 = assertion_table(Id, AssertionMap0),
+	map__det_insert(AssertionMap0, Id, Assertion, AssertionMap),
+	AssertionTable = assertion_table(Id + 1, AssertionMap).
 
 assertion_table_lookup(AssertionTable, Id, Assertion) :-
 	AssertionTable = assertion_table(_MaxId, AssertionMap),
 	map__lookup(AssertionMap, Id, Assertion).
-
-:- pred assertion_table_add_assertion(pred_id::in,
-		assertion_table::in, assertion_table::out) is det.
-
-assertion_table_add_assertion(Assertion, AssertionTable0, AssertionTable) :-
-	AssertionTable0 = assertion_table(Id, AssertionMap0),
-	map__det_insert(AssertionMap0, Id, Assertion, AssertionMap),
-	AssertionTable = assertion_table(Id+1, AssertionMap).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
===================================================================
RCS file: RCS/hlds_module.m,v
retrieving revision 1.2
diff -u -r1.2 hlds_module.m
===================================================================
RCS file: RCS/hlds_pred.m,v
retrieving revision 1.2
diff -u -r1.2 hlds_pred.m
--- hlds_pred.m	1999/07/08 00:56:46	1.2
+++ hlds_pred.m	1999/07/08 06:54:45
@@ -179,7 +179,7 @@
 
 :- type goal_type 	--->	pragmas		% pragma c_code(...)
 			;	clauses		
-			;	{ assertion }
+			;	(assertion)
 			;	none.
 
 	% The evaluation method that should be used for a pred.
===================================================================
RCS file: RCS/make_hlds.m,v
retrieving revision 1.4
diff -u -r1.4 make_hlds.m
--- make_hlds.m	1999/07/08 00:56:46	1.4
+++ make_hlds.m	1999/07/08 09:43:11
@@ -62,7 +62,6 @@
 :- import_module code_util, unify_proc, special_pred, type_util, mode_util.
 :- import_module mercury_to_mercury, passes_aux, clause_to_proc, inst_match.
 :- import_module fact_table, purity, goal_util, term_util, export, llds, rl.
-:- import_module check_assertion.
 
 :- import_module string, char, int, set, bintree, map, multi_map, require.
 :- import_module term, varset, getopt, assoc_list, term_io.
@@ -608,13 +607,15 @@
 add_item_clause(func_clause(VarSet, PredName, Args, Result, Body), Status,
 		Status, Context, Module0, Module, Info0, Info) -->
 	check_not_exported(Status, Context, "clause"),
+	{ IsAssertion = no },
 	module_add_func_clause(Module0, VarSet, PredName, Args, Result, Body,
-		Status, Context, no, Module, Info0, Info).
+		Status, Context, IsAssertion, Module, Info0, Info).
 add_item_clause(pred_clause(VarSet, PredName, Args, Body), Status, Status,
 		Context, Module0, Module, Info0, Info) -->
 	check_not_exported(Status, Context, "clause"),
+	{ IsAssertion = no },
 	module_add_pred_clause(Module0, VarSet, PredName, Args, Body, Status,
-		Context, no, Module, Info0, Info).
+		Context, IsAssertion, Module, Info0, Info).
 add_item_clause(type_defn(_, _, _), Status, Status, _,
 				Module, Module, Info, Info) --> [].
 add_item_clause(inst_defn(_, _, _), Status, Status, _,
@@ -692,14 +693,44 @@
 	).
 add_item_clause(assertion(Goal0, VarSet),
 		Status, Status, Context, Module0, Module, Info0, Info) -->
-	check_assertion(Goal0, VarSet, Goal, HeadVars, Module0, Module1),
+
+		%
+		% If the outermost existentially quantified variables
+		% are placed in the head of the assertion, the
+		% typechecker will avoid warning about unbound
+		% type variables as this implicity adds a universal
+		% quantification of the typevariables needed.
+		%
+	(
+		{ Goal0 = all(Vars, AllGoal) - _Context }
+	->
+		{ term__var_list_to_term_list(Vars, HeadVars) },
+		{ Goal = AllGoal }
+	;
+		{ HeadVars = [] },
+		{ Goal = Goal0 }
+	),
 
 	{ term__context_line(Context, Line) },
 	{ term__context_file(Context, File) },
 	{ string__format("assertion__%d__%s", [i(Line), s(File)], Name) },
 
-	module_add_pred_clause(Module1, VarSet, unqualified(Name),
-			HeadVars, Goal, Status, Context, yes, Module,
+		%
+		% The assertions are recorded as a predicate whose
+		% goal_type is set to assertion.  This allows us to
+		% leverage off all the other checks in the compiler that
+		% operate on predicates.
+		%
+		% :- assertion all [A,B,R] ( R = A + B <=> R = B + A ).
+		%
+		% becomes
+		%
+		% assertion__lineno_filename(A, B, R) :-
+		% 	( R = A + B <=> R = B + A ).
+		%
+	{ IsAssertion = yes },
+	module_add_pred_clause(Module0, VarSet, unqualified(Name),
+			HeadVars, Goal, Status, Context, IsAssertion, Module,
 			Info0, Info).
 
 add_item_clause(nothing, Status, Status, _, Module, Module, Info, Info) --> [].
@@ -2691,7 +2722,8 @@
 		in, out, di, uo) is det.
 
 module_add_pred_clause(ModuleInfo0, ClauseVarSet, PredName, Args, Body,
-			Status, Context, Assertion, ModuleInfo, Info0, Info) -->
+			Status, Context, IsAssertion, ModuleInfo,
+			Info0, Info) -->
 		% print out a progress message
 	globals__io_lookup_bool_option(very_verbose, VeryVerbose),
 	( { VeryVerbose = yes } ->
@@ -2703,7 +2735,8 @@
 		[]
 	),
 	module_add_clause(ModuleInfo0, ClauseVarSet, PredName, Args, Body,
-		Status, Context, predicate, Assertion, ModuleInfo, Info0, Info).
+		Status, Context, predicate, IsAssertion, ModuleInfo,
+		Info0, Info).
 
 :- pred module_add_func_clause(module_info, prog_varset, sym_name,
 		list(prog_term), prog_term, goal, import_status, prog_context,
@@ -2712,7 +2745,8 @@
 	in, in, in, in, out, in, out, di, uo) is det.
 
 module_add_func_clause(ModuleInfo0, ClauseVarSet, FuncName, Args0, Result, Body,
-			Status, Context, Assertion, ModuleInfo, Info0, Info) -->
+			Status, Context, IsAssertion, ModuleInfo,
+			Info0, Info) -->
 		% print out a progress message
 	globals__io_lookup_bool_option(very_verbose, VeryVerbose),
 	( { VeryVerbose = yes } ->
@@ -2725,7 +2759,8 @@
 	),
 	{ list__append(Args0, [Result], Args) },
 	module_add_clause(ModuleInfo0, ClauseVarSet, FuncName, Args, Body,
-		Status, Context, function, Assertion, ModuleInfo, Info0, Info).
+		Status, Context, function, IsAssertion, ModuleInfo,
+		Info0, Info).
 
 :- pred module_add_clause(module_info, prog_varset, sym_name, list(prog_term),
 		goal, import_status, prog_context, pred_or_func, bool,
@@ -2734,7 +2769,7 @@
 		out, in, out, di, uo) is det.
 
 module_add_clause(ModuleInfo0, ClauseVarSet, PredName, Args, Body, Status,
-			Context, PredOrFunc, Assertion, ModuleInfo,
+			Context, PredOrFunc, IsAssertion, ModuleInfo,
 			Info0, Info) -->
 		% Lookup the pred declaration in the predicate table.
 		% (If it's not there, call maybe_undefined_pred_error
@@ -2749,7 +2784,7 @@
 		{ PredId = PredId0 },
 		{ PredicateTable1 = PredicateTable0 },
 		(
-			{ Assertion = yes }
+			{ IsAssertion = yes }
 		->
 			{ prog_out__sym_name_to_string(PredName, NameString) },
 			{ string__format("%s %s %s (%s).\n",
@@ -2765,9 +2800,9 @@
 		(
 				% An assertion will not have a
 				% corresponding pred declaration.
-			{ Assertion = yes }
+			{ IsAssertion = yes }
 		;
-			{ Assertion = no },
+			{ IsAssertion = no },
 			maybe_undefined_pred_error(PredName, Arity, PredOrFunc,
 					Context, "clause")
 		),
@@ -2818,12 +2853,14 @@
 		map__keys(Procs, ModeIds)
 		},
 		clauses_info_add_clause(Clauses0, PredId, ModeIds,
-			ClauseVarSet, TVarSet0, Args, Body, Context, Goal,
-			VarSet, TVarSet, Clauses, Warnings, Info0, Info),
+			ClauseVarSet, TVarSet0, Args, Body, Context,
+			IsAssertion, Goal,
+			VarSet, TVarSet, Clauses, Warnings,
+			ModuleInfo0, ModuleInfo1, Info0, Info),
 		{
 		pred_info_set_clauses_info(PredInfo2, Clauses, PredInfo3),
 		(
-			Assertion = yes
+			IsAssertion = yes
 		->
 			pred_info_set_goal_type(PredInfo3, assertion, PredInfo4)
 		;
@@ -2849,10 +2886,10 @@
 		map__det_update(Preds0, PredId, PredInfo, Preds),
 		predicate_table_set_preds(PredicateTable1, Preds,
 			PredicateTable),
-		module_info_set_predicate_table(ModuleInfo0, PredicateTable,
+		module_info_set_predicate_table(ModuleInfo1, PredicateTable,
 			ModuleInfo)
 		},
-		( { Status \= opt_imported, Assertion = no } ->
+		( { Status \= opt_imported } ->
 			% warn about singleton variables 
 			maybe_warn_singletons(VarSet,
 				PredOrFunc - PredName/Arity, ModuleInfo, Goal),
@@ -4230,21 +4267,23 @@
 
 :- pred clauses_info_add_clause(clauses_info::in, pred_id::in, 
 		list(proc_id)::in, prog_varset::in, tvarset::in,
-		list(prog_term)::in, goal::in, prog_context::in,
+		list(prog_term)::in, goal::in, prog_context::in, bool::in,
 		hlds_goal::out, prog_varset::out, tvarset::out,
-		clauses_info::out, list(quant_warning)::out, qual_info::in,
+		clauses_info::out, list(quant_warning)::out, 
+		module_info::in, module_info::out, qual_info::in,
 		qual_info::out, io__state::di, io__state::uo) is det.
 
 clauses_info_add_clause(ClausesInfo0, PredId, ModeIds, CVarSet, TVarSet0,
-		Args, Body, Context, Goal, VarSet, TVarSet0,
-		ClausesInfo, Warnings, Info0, Info) -->
+		Args, Body, Context, IsAssertion, Goal, VarSet, TVarSet0,
+		ClausesInfo, Warnings, Module0, Module, Info0, Info) -->
 	{ ClausesInfo0 = clauses_info(VarSet0, VarTypes0, VarTypes1,
 					HeadVars, ClauseList0,
 					TI_VarMap, TCI_VarMap) },
 	{ update_qual_info(Info0, TVarSet0, VarTypes0, PredId, Info1) },
 	{ varset__merge_subst(VarSet0, CVarSet, VarSet1, Subst) },
-	transform(Subst, HeadVars, Args, Body, VarSet1, Context,
-				Goal, VarSet, Warnings, Info1, Info),
+	transform(Subst, HeadVars, Args, Body, VarSet1, Context, IsAssertion,
+				Goal, VarSet, Warnings, Module0, Module,
+				Info1, Info),
 		% XXX we should avoid append - this gives O(N*N)
 	{ list__append(ClauseList0, [clause(ModeIds, Goal, Context)],
 							ClauseList) },
@@ -4317,22 +4356,71 @@
 %-----------------------------------------------------------------------------
 
 :- pred transform(prog_substitution, list(prog_var), list(prog_term), goal,
-		prog_varset, prog_context, hlds_goal, prog_varset, 
-		list(quant_warning), qual_info, qual_info,
-		io__state, io__state).
-:- mode transform(in, in, in, in, in, in, out, out, out,
+		prog_varset, prog_context, bool, hlds_goal, prog_varset, 
+		list(quant_warning), module_info, module_info,
+		qual_info, qual_info, io__state, io__state).
+:- mode transform(in, in, in, in, in, in, in, out, out, out, in, out,
 			in, out, di, uo) is det.
 
-transform(Subst, HeadVars, Args0, Body, VarSet0, Context,
-		Goal, VarSet, Warnings, Info0, Info) -->
+transform(Subst, HeadVars, Args0, Body, VarSet0, Context, IsAssertion,
+		Goal, VarSet, Warnings, Module0, Module, Info0, Info) -->
 	transform_goal(Body, VarSet0, Subst, Goal1, VarSet1, Info0, Info1),
 	{ term__apply_substitution_to_list(Args0, Subst, Args) },
 	insert_arg_unifications(HeadVars, Args, Context, head, no,
 		Goal1, VarSet1, Goal2, VarSet2, Info1, Info),
 	{ map__init(Empty) },
+		
+		%
+		% Currently every variable in an assertion must be
+		% explicitly quantified, as it has not been determined
+		% what the correct implicit quantification should be for
+		% assertions.
+		%
+	(
+		{ IsAssertion = yes }
+	->
+			% Use Goal1, since HeadVar__* not yet
+			% introduced.
+		{ quantification__goal_vars(Goal1, Unquantified) },
+		{ set__to_sorted_list(Unquantified, ProblemVars0) },
+
+			% The Args are implicitly universally
+			% quantified.
+		{ term__term_list_to_var_list(Args, ArgVars) },
+		{ list__delete_elems(ProblemVars0, ArgVars, ProblemVars) },
+
+		{ list__length(ProblemVars, L) },
+		(
+			{ L > 0 }
+		->
+			prog_out__write_context(Context),
+			(
+				{ L = 1 }
+			->
+				io__write_string("Error: the variable `")
+			;
+				io__write_string("Error: the variables `")
+			),
+			io__write_list(ProblemVars, ",", write_var(VarSet)),
+			io__write_string("' were not explicitly quantified.\n"),
+			{ module_info_incr_errors(Module0, Module) }
+		;
+			{ Module = Module0 }
+		)
+
+	;
+		{ Module = Module0 }
+	),
 	{ implicitly_quantify_clause_body(HeadVars, Goal2, VarSet2, Empty,
 				Goal, VarSet, _, Warnings) }.
 
+	% Allow use of term_io__write_variable in io__write_list
+:- pred write_var(prog_varset::in, prog_var::in,
+		io__state::di, io__state::uo) is det.
+
+write_var(VarSet, Var) -->
+	term_io__write_variable(Var, VarSet).
+
 %-----------------------------------------------------------------------------%
 
 	% Convert goals from the prog_data `goal' structure into the
@@ -5397,7 +5485,7 @@
 
 % This is not considered an unconditional error anymore:
 % if there is no :- pred declaration, we just infer one,
-% unless the `--no-infer-types' option was specified
+% unless the `--no-infer-types' option was specified.
 
 maybe_undefined_pred_error(Name, Arity, PredOrFunc, Context, Description) -->
 	globals__io_lookup_bool_option(infer_types, InferTypes),
===================================================================
RCS file: RCS/mercury_to_goedel.m,v
retrieving revision 1.2
diff -u -r1.2 mercury_to_goedel.m
===================================================================
RCS file: RCS/mercury_to_mercury.m,v
retrieving revision 1.2
diff -u -r1.2 mercury_to_mercury.m
--- mercury_to_mercury.m	1999/07/08 00:56:46	1.2
+++ mercury_to_mercury.m	1999/07/08 07:09:58
@@ -426,9 +426,8 @@
 	io__write_string(":- assertion "),
 	{ Indent = 1 },
 	mercury_output_newline(Indent),
-	mercury_output_goal(Goal, VarSet, Indent, yes),
-	io__write_string("."),
-	io__nl.
+	mercury_output_goal(Goal, VarSet, Indent),
+	io__write_string(".\n").
 
 mercury_output_item(nothing, _) --> [].
 mercury_output_item(typeclass(Constraints, ClassName, Vars, Methods, 
@@ -1711,7 +1710,7 @@
 		[]
 	;
 		io__write_string(" :-\n\t"),
-		mercury_output_goal(Body, VarSet, 1, no)
+		mercury_output_goal(Body, VarSet, 1)
 	),
 	io__write_string(".\n").
 
@@ -1741,154 +1740,146 @@
 	;
 		mercury_output_term(Result, VarSet, no),
 		io__write_string(" :-\n\t"),
-		mercury_output_goal(Body, VarSet, 1, no)
+		mercury_output_goal(Body, VarSet, 1)
 	),
 	io__write_string(".\n").
 
-:- pred mercury_output_goal(goal, prog_varset, int, bool, io__state, io__state).
-:- mode mercury_output_goal(in, in, in, in, di, uo) is det.
+:- pred mercury_output_goal(goal, prog_varset, int, io__state, io__state).
+:- mode mercury_output_goal(in, in, in, di, uo) is det.
 
-mercury_output_goal(Goal - _Context, VarSet, Indent, InAssertion) -->
-	mercury_output_goal_2(Goal, VarSet, Indent, InAssertion).
+mercury_output_goal(Goal - _Context, VarSet, Indent) -->
+	mercury_output_goal_2(Goal, VarSet, Indent).
 
-:- pred mercury_output_goal_2(goal_expr, prog_varset, int, bool,
+:- pred mercury_output_goal_2(goal_expr, prog_varset, int,
 		io__state, io__state).
-:- mode mercury_output_goal_2(in, in, in, in, di, uo) is det.
+:- mode mercury_output_goal_2(in, in, in, di, uo) is det.
 
-mercury_output_goal_2(fail, _, _, _) -->
+mercury_output_goal_2(fail, _, _) -->
 	io__write_string("fail").
 
-mercury_output_goal_2(true, _, _, _) -->
+mercury_output_goal_2(true, _, _) -->
 	io__write_string("true").
 
-	% Implication and equivalence should have been transformed out
-	% by now, unless they are in an assertion.
-mercury_output_goal_2(implies(_G1,_G2), _VarSet, _Indent, no) -->
-	{ error("mercury_to_mercury: implies/2 in mercury_output_goal")}.
-mercury_output_goal_2(implies(G1,G2), VarSet, Indent, yes) -->
+mercury_output_goal_2(implies(G1,G2), VarSet, Indent) -->
 	{ Indent1 is Indent + 1 },
 	io__write_string("("),
 	mercury_output_newline(Indent1),
-	mercury_output_goal(G1, VarSet, Indent1, yes),
+	mercury_output_goal(G1, VarSet, Indent1),
 	mercury_output_newline(Indent),
 	io__write_string("=>"),
 	mercury_output_newline(Indent1),
-	mercury_output_goal(G2, VarSet, Indent1, yes),
+	mercury_output_goal(G2, VarSet, Indent1),
 	mercury_output_newline(Indent),
 	io__write_string(")").
 
-mercury_output_goal_2(equivalent(_G1,_G2), _VarSet, _Indent, no) -->
-	{ error("mercury_to_mercury: equivalent/2 in mercury_output_goal")}.
-mercury_output_goal_2(equivalent(G1,G2), VarSet, Indent, yes) -->
+mercury_output_goal_2(equivalent(G1,G2), VarSet, Indent) -->
 	{ Indent1 is Indent + 1 },
 	io__write_string("("),
 	mercury_output_newline(Indent1),
-	mercury_output_goal(G1, VarSet, Indent1, yes),
+	mercury_output_goal(G1, VarSet, Indent1),
 	mercury_output_newline(Indent),
 	io__write_string("<=>"),
 	mercury_output_newline(Indent1),
-	mercury_output_goal(G2, VarSet, Indent1, yes),
+	mercury_output_goal(G2, VarSet, Indent1),
 	mercury_output_newline(Indent),
 	io__write_string(")").
 
-mercury_output_goal_2(some(Vars, Goal), VarSet, Indent, InAssertion) -->
+mercury_output_goal_2(some(Vars, Goal), VarSet, Indent) -->
 	( { Vars = [] } ->
-		mercury_output_goal(Goal, VarSet, Indent, InAssertion)
+		mercury_output_goal(Goal, VarSet, Indent)
 	;
 		io__write_string("some ["),
 		mercury_output_vars(Vars, VarSet, no),
 		io__write_string("] ("),
 		{ Indent1 is Indent + 1 },
 		mercury_output_newline(Indent1),
-		mercury_output_goal(Goal, VarSet, Indent1, InAssertion),
+		mercury_output_goal(Goal, VarSet, Indent1),
 		mercury_output_newline(Indent),
 		io__write_string(")")
 	).
 
-mercury_output_goal_2(all(Vars, Goal), VarSet, Indent, InAssertion) -->
+mercury_output_goal_2(all(Vars, Goal), VarSet, Indent) -->
 	( { Vars = [] } ->
-		mercury_output_goal(Goal, VarSet, Indent, InAssertion)
+		mercury_output_goal(Goal, VarSet, Indent)
 	;
 		io__write_string("all ["),
 		mercury_output_vars(Vars, VarSet, no),
 		io__write_string("] ("),
 		{ Indent1 is Indent + 1 },
 		mercury_output_newline(Indent1),
-		mercury_output_goal(Goal, VarSet, Indent1, InAssertion),
+		mercury_output_goal(Goal, VarSet, Indent1),
 		mercury_output_newline(Indent),
 		io__write_string(")")
 	).
 
-mercury_output_goal_2(if_then_else(Vars, A, B, C), VarSet, Indent,
-		InAssertion) -->
+mercury_output_goal_2(if_then_else(Vars, A, B, C), VarSet, Indent) -->
 	io__write_string("(if"),
 	mercury_output_some(Vars, VarSet),
 	{ Indent1 is Indent + 1 },
 	mercury_output_newline(Indent1),
-	mercury_output_goal(A, VarSet, Indent1, InAssertion),
+	mercury_output_goal(A, VarSet, Indent1),
 	mercury_output_newline(Indent),
 	io__write_string("then"),
 	mercury_output_newline(Indent1),
-	mercury_output_goal(B, VarSet, Indent1, InAssertion),
+	mercury_output_goal(B, VarSet, Indent1),
 	mercury_output_newline(Indent),
 	io__write_string("else"),
 	mercury_output_newline(Indent1),
-	mercury_output_goal(C, VarSet, Indent1, InAssertion),
+	mercury_output_goal(C, VarSet, Indent1),
 	mercury_output_newline(Indent),
 	io__write_string(")").
 
-mercury_output_goal_2(if_then(Vars, A, B), VarSet, Indent, InAssertion) -->
+mercury_output_goal_2(if_then(Vars, A, B), VarSet, Indent) -->
 	io__write_string("(if"),
 	mercury_output_some(Vars, VarSet),
 	{ Indent1 is Indent + 1 },
 	mercury_output_newline(Indent1),
-	mercury_output_goal(A, VarSet, Indent1, InAssertion),
+	mercury_output_goal(A, VarSet, Indent1),
 	mercury_output_newline(Indent),
 	io__write_string("then"),
 	mercury_output_newline(Indent1),
-	mercury_output_goal(B, VarSet, Indent1, InAssertion),
+	mercury_output_goal(B, VarSet, Indent1),
 	mercury_output_newline(Indent),
 	io__write_string(")").
 
-mercury_output_goal_2(not(Goal), VarSet, Indent, InAssertion) -->
+mercury_output_goal_2(not(Goal), VarSet, Indent) -->
 	io__write_string("\\+ ("),
 	{ Indent1 is Indent + 1 },
 	mercury_output_newline(Indent1),
-	mercury_output_goal(Goal, VarSet, Indent1, InAssertion),
+	mercury_output_goal(Goal, VarSet, Indent1),
 	mercury_output_newline(Indent),
 	io__write_string(")").
 
-mercury_output_goal_2((A,B), VarSet, Indent, InAssertion) -->
-	mercury_output_goal(A, VarSet, Indent, InAssertion),
+mercury_output_goal_2((A,B), VarSet, Indent) -->
+	mercury_output_goal(A, VarSet, Indent),
 	io__write_string(","),
 	mercury_output_newline(Indent),
-	mercury_output_goal(B, VarSet, Indent, InAssertion).
+	mercury_output_goal(B, VarSet, Indent).
 
-mercury_output_goal_2((A & B), VarSet, Indent, InAssertion) -->
+mercury_output_goal_2((A & B), VarSet, Indent) -->
 	io__write_string("("),
 	{ Indent1 is Indent + 1 },
 	mercury_output_newline(Indent1),
-	mercury_output_goal(A, VarSet, Indent1, InAssertion),
-	mercury_output_par_conj(B, VarSet, Indent, InAssertion),
+	mercury_output_goal(A, VarSet, Indent1),
+	mercury_output_par_conj(B, VarSet, Indent),
 	mercury_output_newline(Indent),
 	io__write_string(")").
 
 
-mercury_output_goal_2((A;B), VarSet, Indent, InAssertion) -->
+mercury_output_goal_2((A;B), VarSet, Indent) -->
 	io__write_string("("),
 	{ Indent1 is Indent + 1 },
 	mercury_output_newline(Indent1),
-	mercury_output_goal(A, VarSet, Indent1, InAssertion),
-	mercury_output_disj(B, VarSet, Indent, InAssertion),
+	mercury_output_goal(A, VarSet, Indent1),
+	mercury_output_disj(B, VarSet, Indent),
 	mercury_output_newline(Indent),
 	io__write_string(")").
 
-mercury_output_goal_2(call(Name, Term, Purity), VarSet, Indent,
-		_InAssertion) -->
+mercury_output_goal_2(call(Name, Term, Purity), VarSet, Indent) -->
 	write_purity_prefix(Purity),
 	mercury_output_call(Name, Term, VarSet, Indent).
 
-mercury_output_goal_2(unify(A, B), VarSet, _Indent, _InAssertion) -->
+mercury_output_goal_2(unify(A, B), VarSet, _Indent) -->
 	mercury_output_term(A, VarSet, no),
 	io__write_string(" = "),
 	mercury_output_term(B, VarSet, no, next_to_graphic_token).
@@ -1914,10 +1905,10 @@
 			Term, Context0), VarSet, no, next_to_graphic_token)
 	).
 
-:- pred mercury_output_disj(goal, prog_varset, int, bool, io__state, io__state).
-:- mode mercury_output_disj(in, in, in, in, di, uo) is det.
+:- pred mercury_output_disj(goal, prog_varset, int, io__state, io__state).
+:- mode mercury_output_disj(in, in, in, di, uo) is det.
 
-mercury_output_disj(Goal, VarSet, Indent, InAssertion) -->
+mercury_output_disj(Goal, VarSet, Indent) -->
 	mercury_output_newline(Indent),
 	io__write_string(";"),
 	{ Indent1 is Indent + 1 },
@@ -1925,17 +1916,17 @@
 	(
 		{ Goal = (A;B) - _Context }
 	->
-		mercury_output_goal(A, VarSet, Indent1, InAssertion),
-		mercury_output_disj(B, VarSet, Indent, InAssertion)
+		mercury_output_goal(A, VarSet, Indent1),
+		mercury_output_disj(B, VarSet, Indent)
 	;
-		mercury_output_goal(Goal, VarSet, Indent1, InAssertion)
+		mercury_output_goal(Goal, VarSet, Indent1)
 	).
 
-:- pred mercury_output_par_conj(goal, prog_varset, int, bool,
+:- pred mercury_output_par_conj(goal, prog_varset, int,
 		io__state, io__state).
-:- mode mercury_output_par_conj(in, in, in, in, di, uo) is det.
+:- mode mercury_output_par_conj(in, in, in, di, uo) is det.
 
-mercury_output_par_conj(Goal, VarSet, Indent, InAssertion) -->
+mercury_output_par_conj(Goal, VarSet, Indent) -->
 	mercury_output_newline(Indent),
 	io__write_string("&"),
 	{ Indent1 is Indent + 1 },
@@ -1943,10 +1934,10 @@
 	(
 		{ Goal = (A & B) - _Context }
 	->
-		mercury_output_goal(A, VarSet, Indent1, InAssertion),
-		mercury_output_par_conj(B, VarSet, Indent, InAssertion)
+		mercury_output_goal(A, VarSet, Indent1),
+		mercury_output_par_conj(B, VarSet, Indent)
 	;
-		mercury_output_goal(Goal, VarSet, Indent1, InAssertion)
+		mercury_output_goal(Goal, VarSet, Indent1)
 	).
 
 :- pred mercury_output_some(list(var(T)), varset(T), io__state, io__state).
===================================================================
RCS file: RCS/module_qual.m,v
retrieving revision 1.1
diff -u -r1.1 module_qual.m
===================================================================
RCS file: RCS/post_typecheck.m,v
retrieving revision 1.1
diff -u -r1.1 post_typecheck.m
--- post_typecheck.m	1999/07/06 06:41:11	1.1
+++ post_typecheck.m	1999/07/08 07:24:34
@@ -84,11 +84,19 @@
 		pred_info, pred_info, io__state, io__state).
 :- mode post_typecheck__finish_ill_typed_pred(in, in, in, out, di, uo) is det.
 
+	% Now that the assertion has finished being typechecked,
+	% remove it from further processing and store it in the
+	% assertion_table.
+:- pred post_typecheck__finish_assertion(module_info, pred_id,
+		module_info) is det.
+:- mode post_typecheck__finish_assertion(in, in, out) is det.
+
 %-----------------------------------------------------------------------------%
+
 :- implementation.
 
 :- import_module typecheck, clause_to_proc, mode_util, inst_match.
-:- import_module mercury_to_mercury, prog_out, hlds_out, type_util.
+:- import_module mercury_to_mercury, prog_out, hlds_data, hlds_out, type_util.
 :- import_module globals, options.
 
 :- import_module map, set, assoc_list, bool, std_util, term.
@@ -366,6 +374,13 @@
 		PredInfo0, PredInfo) -->
 	post_typecheck__propagate_types_into_modes(ModuleInfo, PredId,
 		PredInfo0, PredInfo).
+
+post_typecheck__finish_assertion(Module0, PredId, Module) :-
+	module_info_assertion_table(Module0, AssertionTable0),
+	assertion_table_add_assertion(PredId, AssertionTable0, AssertionTable),
+	module_info_set_assertion_table(Module0, AssertionTable, Module1),
+	module_info_remove_predid(Module1, PredId, Module).
+	
 
 	% 
 	% Ensure that all constructors occurring in predicate mode
===================================================================
RCS file: RCS/prog_data.m,v
retrieving revision 1.1
diff -u -r1.1 prog_data.m
===================================================================
RCS file: RCS/prog_io.m,v
retrieving revision 1.1
diff -u -r1.1 prog_io.m
--- prog_io.m	1999/07/06 06:41:11	1.1
+++ prog_io.m	1999/07/08 07:02:35
@@ -183,7 +183,7 @@
 :- implementation.
 
 :- import_module prog_io_goal, prog_io_dcg, prog_io_pragma, prog_io_util.
-:- import_module prog_io_typeclass, prog_io_assertion.
+:- import_module prog_io_typeclass.
 :- import_module hlds_data, hlds_pred, prog_util, prog_out.
 :- import_module globals, options, (inst).
 :- import_module purity.
@@ -1097,6 +1097,17 @@
 attribute_description(constraints(univ, _), "type class constraint (`<=')").
 attribute_description(constraints(exist, _),
 	"existentially quantified type class constraint (`=>')").
+
+%-----------------------------------------------------------------------------%
+
+	% parse the assertion declaration. 
+:- pred parse_assertion(module_name, varset, list(term), maybe1(item)).
+:- mode parse_assertion(in, in, in, out) is semidet.
+
+parse_assertion(_ModuleName, VarSet, [AssertionTerm], Result) :-
+	varset__coerce(VarSet, ProgVarSet),
+	parse_goal(AssertionTerm, ProgVarSet, AssertGoal, AssertVarSet),
+	Result = ok(assertion(AssertGoal, AssertVarSet)).
 
 %-----------------------------------------------------------------------------%
 
===================================================================
RCS file: RCS/prog_io_assertion.m,v
retrieving revision 1.1
diff -u -r1.1 prog_io_assertion.m
===================================================================
RCS file: RCS/purity.m,v
retrieving revision 1.1
diff -u -r1.1 purity.m
--- purity.m	1999/07/06 06:41:11	1.1
+++ purity.m	1999/07/08 07:28:17
@@ -135,7 +135,7 @@
 
 :- implementation.
 
-:- import_module make_hlds, hlds_data, hlds_pred, prog_io_util.
+:- import_module make_hlds, hlds_pred, prog_io_util.
 :- import_module type_util, mode_util, code_util, prog_data, unify_proc.
 :- import_module globals, options, mercury_to_mercury, hlds_out.
 :- import_module passes_aux, typecheck, module_qual, clause_to_proc.
@@ -294,7 +294,8 @@
 	(
 		{ pred_info_get_goal_type(PredInfo0, assertion) }
 	->
-		{ module_info_remove_predid(ModuleInfo1, PredId, ModuleInfo2) }
+		{ post_typecheck__finish_assertion(ModuleInfo1,
+				PredId, ModuleInfo2) }
 	;
 		{ ModuleInfo2 = ModuleInfo1 }
 	),
===================================================================
RCS file: RCS/typecheck.m,v
retrieving revision 1.1
diff -u -r1.1 typecheck.m

*** Full DIFF vs update source ***

Index: compiler/error_util.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/error_util.m,v
retrieving revision 1.8
diff -u -r1.8 error_util.m
--- error_util.m	1999/06/16 00:38:16	1.8
+++ error_util.m	1999/07/08 06:48:56
@@ -323,16 +323,22 @@
 		PredOrFuncPart = "function",
 		OrigArity is Arity - 1
 	),
-	string__int_to_string(OrigArity, ArityPart),
-	string__append_list([
-		PredOrFuncPart,
-		" `",
-		ModuleNameString,
-		":",
-		PredName,
-		"/",
-		ArityPart,
-		"'"], Piece).
+	(
+		pred_info_get_goal_type(PredInfo, assertion)
+	->
+		Piece = "assertion"
+	;
+		string__int_to_string(OrigArity, ArityPart),
+		string__append_list([
+			PredOrFuncPart,
+			" `",
+			ModuleNameString,
+			":",
+			PredName,
+			"/",
+			ArityPart,
+			"'"], Piece)
+	).
 
 error_util__describe_one_proc_name(Module, proc(PredId, ProcId), Piece) :-
 	error_util__describe_one_pred_name(Module, PredId, PredPiece),
Index: compiler/hlds_data.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/hlds_data.m,v
retrieving revision 1.35
diff -u -r1.35 hlds_data.m
--- hlds_data.m	1999/07/08 05:08:50	1.35
+++ hlds_data.m	1999/07/08 09:48:39
@@ -805,3 +805,51 @@
 :- type superclass_table == multi_map(class_id, subclass_details).
 
 %-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- interface.
+
+	%
+	% A table that records all the assertions in the system.
+	% An assertion is a goal that will always evaluate to true,
+	% subject to the constraints imposed by the quantifiers.
+	%
+	% ie :- assertion all [A] some [B] (B > A)
+	% 
+	% The above assertion states that for all possible values of A,
+	% there will exist at least one value, B, such that B is greater
+	% then A.
+	%
+:- type assert_id.
+:- type assertion_table.
+
+:- pred assertion_table_init(assertion_table::out) is det.
+
+:- pred assertion_table_add_assertion(pred_id::in,
+		assertion_table::in, assertion_table::out) is det.
+
+:- pred assertion_table_lookup(assertion_table::in, assert_id::in,
+		pred_id::out) is det.
+
+:- implementation.
+
+:- import_module int.
+
+:- type assert_id == int.
+:- type assertion_table 
+	---> 	assertion_table(assert_id, map(assert_id, pred_id)).
+
+assertion_table_init(assertion_table(0, AssertionMap)) :-
+	map__init(AssertionMap).
+
+assertion_table_add_assertion(Assertion, AssertionTable0, AssertionTable) :-
+	AssertionTable0 = assertion_table(Id, AssertionMap0),
+	map__det_insert(AssertionMap0, Id, Assertion, AssertionMap),
+	AssertionTable = assertion_table(Id + 1, AssertionMap).
+
+assertion_table_lookup(AssertionTable, Id, Assertion) :-
+	AssertionTable = assertion_table(_MaxId, AssertionMap),
+	map__lookup(AssertionMap, Id, Assertion).
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
Index: compiler/hlds_module.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/hlds_module.m,v
retrieving revision 1.44
diff -u -r1.44 hlds_module.m
--- hlds_module.m	1999/04/30 08:23:46	1.44
+++ hlds_module.m	1999/07/08 07:24:05
@@ -198,6 +198,13 @@
 	module_info).
 :- mode module_info_set_superclasses(in, in, out) is det.
 
+:- pred module_info_assertion_table(module_info, assertion_table).
+:- mode module_info_assertion_table(in, out) is det.
+
+:- pred module_info_set_assertion_table(module_info, assertion_table,
+	module_info).
+:- mode module_info_set_assertion_table(in, in, out) is det.
+
 	% The cell count is used as a unique cell number for
 	% constants in the generated C code.
 :- pred module_info_get_cell_count(module_info, int).
@@ -555,6 +562,7 @@
 			class_table,
 			instance_table,
 			superclass_table,
+			assertion_table,
 			int		% cell count, passed into code_info
 					% and used to generate unique label
 					% numbers for constant terms in the
@@ -622,12 +630,15 @@
 	map__init(InstanceTable),
 	map__init(SuperClassTable),
 	set__init(ModuleNames),
+
+	assertion_table_init(AssertionTable),
+
 	ModuleSubInfo = module_sub(Name, Globals, [], [], no, 0, 0, [], 
 		[], [], StratPreds, UnusedArgInfo, 0, ModuleNames,
 		no_aditi_compilation, TypeSpecInfo),
 	ModuleInfo = module(ModuleSubInfo, PredicateTable, Requests,
 		UnifyPredMap, GlobalData, Types, Insts, Modes, Ctors,
-		ClassTable, SuperClassTable, InstanceTable, 0).
+		ClassTable, SuperClassTable, InstanceTable, AssertionTable, 0).
 
 %-----------------------------------------------------------------------------%
 
@@ -798,7 +809,8 @@
 % J			class_table,
 % K			instance_table,
 % L			superclass_table,
-% M			int		% cell count, passed into code_info
+% M			assertion_table
+% N			int		% cell count, passed into code_info
 %					% and used to generate unique label
 %					% numbers for constant terms in the
 %					% generated C code
@@ -809,99 +821,106 @@
 	% Various predicates which access the module_info data structure.
 
 module_info_get_sub_info(MI0, A) :-
-	MI0 = module(A, _, _, _, _, _, _, _, _, _, _, _, _).
+	MI0 = module(A, _, _, _, _, _, _, _, _, _, _, _, _, _).
 
 module_info_get_predicate_table(MI0, B) :-
-	MI0 = module(_, B, _, _, _, _, _, _, _, _, _, _, _).
+	MI0 = module(_, B, _, _, _, _, _, _, _, _, _, _, _, _).
 
 module_info_get_proc_requests(MI0, C) :-
-	MI0 = module(_, _, C, _, _, _, _, _, _, _, _, _, _).
+	MI0 = module(_, _, C, _, _, _, _, _, _, _, _, _, _, _).
 
 module_info_get_special_pred_map(MI0, D) :-
-	MI0 = module(_, _, _, D, _, _, _, _, _, _, _, _, _).
+	MI0 = module(_, _, _, D, _, _, _, _, _, _, _, _, _, _).
 
 module_info_get_global_data(MI0, E) :-
-	MI0 = module(_, _, _, _, E, _, _, _, _, _, _, _, _).
+	MI0 = module(_, _, _, _, E, _, _, _, _, _, _, _, _, _).
 
 module_info_types(MI0, F) :-
-	MI0 = module(_, _, _, _, _, F, _, _, _, _, _, _, _).
+	MI0 = module(_, _, _, _, _, F, _, _, _, _, _, _, _, _).
 
 module_info_insts(MI0, G) :-
-	MI0 = module(_, _, _, _, _, _, G, _, _, _, _, _, _).
+	MI0 = module(_, _, _, _, _, _, G, _, _, _, _, _, _, _).
 
 module_info_modes(MI0, H) :-
-	MI0 = module(_, _, _, _, _, _, _, H, _, _, _, _, _).
+	MI0 = module(_, _, _, _, _, _, _, H, _, _, _, _, _, _).
 
 module_info_ctors(MI0, I) :-
-	MI0 = module(_, _, _, _, _, _, _, _, I, _, _, _, _).
+	MI0 = module(_, _, _, _, _, _, _, _, I, _, _, _, _, _).
 
 module_info_classes(MI0, J) :-
-	MI0 = module(_, _, _, _, _, _, _, _, _, J, _, _, _).
+	MI0 = module(_, _, _, _, _, _, _, _, _, J, _, _, _, _).
 
 module_info_instances(MI0, K) :-
-	MI0 = module(_, _, _, _, _, _, _, _, _, _, K, _, _).
+	MI0 = module(_, _, _, _, _, _, _, _, _, _, K, _, _, _).
 
 module_info_superclasses(MI0, L) :-
-	MI0 = module(_, _, _, _, _, _, _, _, _, _, _, L, _).
+	MI0 = module(_, _, _, _, _, _, _, _, _, _, _, L, _, _).
+
+module_info_assertion_table(MI0, M) :-
+	MI0 = module(_, _, _, _, _, _, _, _, _, _, _, _, M, _).
 
-module_info_get_cell_count(MI0, M) :-
-	MI0 = module(_, _, _, _, _, _, _, _, _, _, _, _, M).
+module_info_get_cell_count(MI0, N) :-
+	MI0 = module(_, _, _, _, _, _, _, _, _, _, _, _, _, N).
 
 %-----------------------------------------------------------------------------%
 
 	% Various predicates which modify the module_info data structure.
 
 module_info_set_sub_info(MI0, A, MI) :-
-	MI0 = module(_, B, C, D, E, F, G, H, I, J, K, L, M),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
+	MI0 = module(_, B, C, D, E, F, G, H, I, J, K, L, M, N),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N).
 
 module_info_set_predicate_table(MI0, B, MI) :-
-	MI0 = module(A, _, C, D, E, F, G, H, I, J, K, L, M),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
+	MI0 = module(A, _, C, D, E, F, G, H, I, J, K, L, M, N),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N).
 
 module_info_set_proc_requests(MI0, C, MI) :-
-	MI0 = module(A, B, _, D, E, F, G, H, I, J, K, L, M),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
+	MI0 = module(A, B, _, D, E, F, G, H, I, J, K, L, M, N),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N).
 
 module_info_set_special_pred_map(MI0, D, MI) :-
-	MI0 = module(A, B, C, _, E, F, G, H, I, J, K, L, M),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
+	MI0 = module(A, B, C, _, E, F, G, H, I, J, K, L, M, N),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N).
 
 module_info_set_global_data(MI0, E, MI) :-
-	MI0 = module(A, B, C, D, _, F, G, H, I, J, K, L, M),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
+	MI0 = module(A, B, C, D, _, F, G, H, I, J, K, L, M, N),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N).
 
 module_info_set_types(MI0, F, MI) :-
-	MI0 = module(A, B, C, D, E, _, G, H, I, J, K, L, M),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
+	MI0 = module(A, B, C, D, E, _, G, H, I, J, K, L, M, N),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N).
 
 module_info_set_insts(MI0, G, MI) :-
-	MI0 = module(A, B, C, D, E, F, _, H, I, J, K, L, M),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
+	MI0 = module(A, B, C, D, E, F, _, H, I, J, K, L, M, N),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N).
 
 module_info_set_modes(MI0, H, MI) :-
-	MI0 = module(A, B, C, D, E, F, G, _, I, J, K, L, M),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
+	MI0 = module(A, B, C, D, E, F, G, _, I, J, K, L, M, N),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N).
 
 module_info_set_ctors(MI0, I, MI) :-
-	MI0 = module(A, B, C, D, E, F, G, H, _, J, K, L, M),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
+	MI0 = module(A, B, C, D, E, F, G, H, _, J, K, L, M, N),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N).
 
 module_info_set_classes(MI0, J, MI) :-
-	MI0 = module(A, B, C, D, E, F, G, H, I, _, K, L, M),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
+	MI0 = module(A, B, C, D, E, F, G, H, I, _, K, L, M, N),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N).
 
 module_info_set_instances(MI0, K, MI) :-
-	MI0 = module(A, B, C, D, E, F, G, H, I, J, _, L, M),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
+	MI0 = module(A, B, C, D, E, F, G, H, I, J, _, L, M, N),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N).
 
 module_info_set_superclasses(MI0, L, MI) :-
-	MI0 = module(A, B, C, D, E, F, G, H, I, J, K, _, M),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
+	MI0 = module(A, B, C, D, E, F, G, H, I, J, K, _, M, N),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N).
 
-module_info_set_cell_count(MI0, M, MI) :-
-	MI0 = module(A, B, C, D, E, F, G, H, I, J, K, L, _),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
+module_info_set_assertion_table(MI0, M, MI) :-
+	MI0 = module(A, B, C, D, E, F, G, H, I, J, K, L, _, N),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N).
+
+module_info_set_cell_count(MI0, N, MI) :-
+	MI0 = module(A, B, C, D, E, F, G, H, I, J, K, L, M, _),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/hlds_out.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/hlds_out.m,v
retrieving revision 1.221
diff -u -r1.221 hlds_out.m
--- hlds_out.m	1999/06/30 17:12:24	1.221
+++ hlds_out.m	1999/07/08 06:45:33
@@ -271,7 +271,7 @@
 	io__write_string("<tabling_pointer>").
 
 	% The code of this predicate duplicates the functionality of
-	% term_errors__describe_one_pred_name. Changes here should be made
+	% error_util__describe_one_pred_name. Changes here should be made
 	% there as well.
 
 hlds_out__write_pred_id(ModuleInfo, PredId) -->
@@ -298,6 +298,10 @@
 			check_typeclass__introduced_pred_name_prefix) } 
 	->
 		io__write_string("type class method implementation")
+	;
+		{ pred_info_get_goal_type(PredInfo, assertion) }
+	->
+		io__write_string("assertion")
 	;
 		hlds_out__write_pred_or_func(PredOrFunc),
 		io__write_string(" `"),
Index: compiler/hlds_pred.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/hlds_pred.m,v
retrieving revision 1.60
diff -u -r1.60 hlds_pred.m
--- hlds_pred.m	1999/07/08 05:08:51	1.60
+++ hlds_pred.m	1999/07/08 09:48:43
@@ -179,6 +179,7 @@
 
 :- type goal_type 	--->	pragmas		% pragma c_code(...)
 			;	clauses		
+			;	(assertion)
 			;	none.
 
 	% Note: `liveness' and `liveness_info' record liveness in the sense
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/make_hlds.m,v
retrieving revision 1.297
diff -u -r1.297 make_hlds.m
--- make_hlds.m	1999/07/08 05:08:53	1.297
+++ make_hlds.m	1999/07/08 09:48:59
@@ -220,6 +220,8 @@
 
 add_item_decl_pass_1(pragma(_), _, Status, Module, Status, Module) --> [].
 
+add_item_decl_pass_1(assertion(_, _), _, Status, Module, Status, Module) --> [].
+
 add_item_decl_pass_1(module_defn(_VarSet, ModuleDefn), Context,
 		Status0, Module0, Status, Module) -->
 	( { module_defn_update_import_status(ModuleDefn, Status1) } ->
@@ -514,6 +516,7 @@
 		{ error("make_hlds.m: can't find func declaration") }
 	).
 
+add_item_decl_pass_2(assertion(_, _), _, Status, Module, Status, Module) --> [].
 add_item_decl_pass_2(func_clause(_, _, _, _, _), _, Status, Module, Status,
 		Module) --> [].
 add_item_decl_pass_2(pred_clause(_, _, _, _), _, Status, Module, Status, Module)
@@ -605,13 +608,15 @@
 add_item_clause(func_clause(VarSet, PredName, Args, Result, Body), Status,
 		Status, Context, Module0, Module, Info0, Info) -->
 	check_not_exported(Status, Context, "clause"),
+	{ IsAssertion = no },
 	module_add_func_clause(Module0, VarSet, PredName, Args, Result, Body,
-		Status, Context, Module, Info0, Info).
+		Status, Context, IsAssertion, Module, Info0, Info).
 add_item_clause(pred_clause(VarSet, PredName, Args, Body), Status, Status,
 		Context, Module0, Module, Info0, Info) -->
 	check_not_exported(Status, Context, "clause"),
+	{ IsAssertion = no },
 	module_add_pred_clause(Module0, VarSet, PredName, Args, Body, Status,
-		Context, Module, Info0, Info).
+		Context, IsAssertion, Module, Info0, Info).
 add_item_clause(type_defn(_, _, _), Status, Status, _,
 				Module, Module, Info, Info) --> [].
 add_item_clause(inst_defn(_, _, _), Status, Status, _,
@@ -687,6 +692,48 @@
 		{ Module = Module0 },
 		{ Info = Info0 }	
 	).
+add_item_clause(assertion(Goal0, VarSet),
+		Status, Status, Context, Module0, Module, Info0, Info) -->
+
+		%
+		% If the outermost existentially quantified variables
+		% are placed in the head of the assertion, the
+		% typechecker will avoid warning about unbound
+		% type variables as this implicity adds a universal
+		% quantification of the typevariables needed.
+		%
+	(
+		{ Goal0 = all(Vars, AllGoal) - _Context }
+	->
+		{ term__var_list_to_term_list(Vars, HeadVars) },
+		{ Goal = AllGoal }
+	;
+		{ HeadVars = [] },
+		{ Goal = Goal0 }
+	),
+
+	{ term__context_line(Context, Line) },
+	{ term__context_file(Context, File) },
+	{ string__format("assertion__%d__%s", [i(Line), s(File)], Name) },
+
+		%
+		% The assertions are recorded as a predicate whose
+		% goal_type is set to assertion.  This allows us to
+		% leverage off all the other checks in the compiler that
+		% operate on predicates.
+		%
+		% :- assertion all [A,B,R] ( R = A + B <=> R = B + A ).
+		%
+		% becomes
+		%
+		% assertion__lineno_filename(A, B, R) :-
+		% 	( R = A + B <=> R = B + A ).
+		%
+	{ IsAssertion = yes },
+	module_add_pred_clause(Module0, VarSet, unqualified(Name),
+			HeadVars, Goal, Status, Context, IsAssertion, Module,
+			Info0, Info).
+
 add_item_clause(nothing, Status, Status, _, Module, Module, Info, Info) --> [].
 add_item_clause(typeclass(_, _, _, _, _),
 	Status, Status, _, Module, Module, Info, Info) --> [].
@@ -2679,12 +2726,13 @@
 
 :- pred module_add_pred_clause(module_info, prog_varset, sym_name,
 		list(prog_term), goal, import_status, prog_context,
-		module_info, qual_info, qual_info, io__state, io__state).
-:- mode module_add_pred_clause(in, in, in, in, in, in, in, out,
+		bool, module_info, qual_info, qual_info, io__state, io__state).
+:- mode module_add_pred_clause(in, in, in, in, in, in, in, in, out,
 		in, out, di, uo) is det.
 
 module_add_pred_clause(ModuleInfo0, ClauseVarSet, PredName, Args, Body,
-			Status, Context, ModuleInfo, Info0, Info) -->
+			Status, Context, IsAssertion, ModuleInfo,
+			Info0, Info) -->
 		% print out a progress message
 	globals__io_lookup_bool_option(very_verbose, VeryVerbose),
 	( { VeryVerbose = yes } ->
@@ -2696,16 +2744,18 @@
 		[]
 	),
 	module_add_clause(ModuleInfo0, ClauseVarSet, PredName, Args, Body,
-		Status, Context, predicate, ModuleInfo, Info0, Info).
+		Status, Context, predicate, IsAssertion, ModuleInfo,
+		Info0, Info).
 
 :- pred module_add_func_clause(module_info, prog_varset, sym_name,
 		list(prog_term), prog_term, goal, import_status, prog_context,
-		module_info, qual_info, qual_info, io__state, io__state).
+		bool, module_info, qual_info, qual_info, io__state, io__state).
 :- mode module_add_func_clause(in, in, in, in, in,
-	in, in, in, out, in, out, di, uo) is det.
+	in, in, in, in, out, in, out, di, uo) is det.
 
 module_add_func_clause(ModuleInfo0, ClauseVarSet, FuncName, Args0, Result, Body,
-			Status, Context, ModuleInfo, Info0, Info) -->
+			Status, Context, IsAssertion, ModuleInfo,
+			Info0, Info) -->
 		% print out a progress message
 	globals__io_lookup_bool_option(very_verbose, VeryVerbose),
 	( { VeryVerbose = yes } ->
@@ -2718,16 +2768,18 @@
 	),
 	{ list__append(Args0, [Result], Args) },
 	module_add_clause(ModuleInfo0, ClauseVarSet, FuncName, Args, Body,
-		Status, Context, function, ModuleInfo, Info0, Info).
+		Status, Context, function, IsAssertion, ModuleInfo,
+		Info0, Info).
 
 :- pred module_add_clause(module_info, prog_varset, sym_name, list(prog_term),
-		goal, import_status, prog_context, pred_or_func,
+		goal, import_status, prog_context, pred_or_func, bool,
 		module_info, qual_info, qual_info, io__state, io__state).
-:- mode module_add_clause(in, in, in, in, in, in, in, in,
+:- mode module_add_clause(in, in, in, in, in, in, in, in, in,
 		out, in, out, di, uo) is det.
 
 module_add_clause(ModuleInfo0, ClauseVarSet, PredName, Args, Body, Status,
-			Context, PredOrFunc, ModuleInfo, Info0, Info) -->
+			Context, PredOrFunc, IsAssertion, ModuleInfo,
+			Info0, Info) -->
 		% Lookup the pred declaration in the predicate table.
 		% (If it's not there, call maybe_undefined_pred_error
 		% and insert an implicit declaration for the predicate.)
@@ -2739,11 +2791,30 @@
 				PredOrFunc, PredName, Arity, [PredId0]) }
 	->
 		{ PredId = PredId0 },
-		{ PredicateTable1 = PredicateTable0 }
+		{ PredicateTable1 = PredicateTable0 },
+		(
+			{ IsAssertion = yes }
+		->
+			{ prog_out__sym_name_to_string(PredName, NameString) },
+			{ string__format("%s %s %s (%s).\n",
+				[s("Attempted to introduce a predicate"),
+				s("for an assertion with an identical"),
+				s("name to an existing predicate"),
+				s(NameString)], String) },
+			{ error(String) }
+		;
+			[]
+		)
 	;
-
-		maybe_undefined_pred_error(PredName, Arity, PredOrFunc,
-			Context, "clause"),
+		(
+				% An assertion will not have a
+				% corresponding pred declaration.
+			{ IsAssertion = yes }
+		;
+			{ IsAssertion = no },
+			maybe_undefined_pred_error(PredName, Arity, PredOrFunc,
+					Context, "clause")
+		),
 		{ preds_add_implicit(ModuleInfo0, PredicateTable0,
 				ModuleName, PredName, Arity, Status, Context,
 				PredOrFunc,
@@ -2791,11 +2862,19 @@
 		map__keys(Procs, ModeIds)
 		},
 		clauses_info_add_clause(Clauses0, PredId, ModeIds,
-			ClauseVarSet, TVarSet0, Args, Body, Context, Goal,
-			VarSet, TVarSet, Clauses, Warnings, Info0, Info),
+			ClauseVarSet, TVarSet0, Args, Body, Context,
+			IsAssertion, Goal,
+			VarSet, TVarSet, Clauses, Warnings,
+			ModuleInfo0, ModuleInfo1, Info0, Info),
 		{
 		pred_info_set_clauses_info(PredInfo2, Clauses, PredInfo3),
-		pred_info_set_goal_type(PredInfo3, clauses, PredInfo4),
+		(
+			IsAssertion = yes
+		->
+			pred_info_set_goal_type(PredInfo3, assertion, PredInfo4)
+		;
+			pred_info_set_goal_type(PredInfo3, clauses, PredInfo4)
+		),
 		pred_info_set_typevarset(PredInfo4, TVarSet, PredInfo5),
 		pred_info_arg_types(PredInfo5, _ArgTVarSet,
 				ExistQVars, ArgTypes),
@@ -2816,7 +2895,7 @@
 		map__det_update(Preds0, PredId, PredInfo, Preds),
 		predicate_table_set_preds(PredicateTable1, Preds,
 			PredicateTable),
-		module_info_set_predicate_table(ModuleInfo0, PredicateTable,
+		module_info_set_predicate_table(ModuleInfo1, PredicateTable,
 			ModuleInfo)
 		},
 		( { Status \= opt_imported } ->
@@ -4197,21 +4276,23 @@
 
 :- pred clauses_info_add_clause(clauses_info::in, pred_id::in, 
 		list(proc_id)::in, prog_varset::in, tvarset::in,
-		list(prog_term)::in, goal::in, prog_context::in,
+		list(prog_term)::in, goal::in, prog_context::in, bool::in,
 		hlds_goal::out, prog_varset::out, tvarset::out,
-		clauses_info::out, list(quant_warning)::out, qual_info::in,
+		clauses_info::out, list(quant_warning)::out, 
+		module_info::in, module_info::out, qual_info::in,
 		qual_info::out, io__state::di, io__state::uo) is det.
 
 clauses_info_add_clause(ClausesInfo0, PredId, ModeIds, CVarSet, TVarSet0,
-		Args, Body, Context, Goal, VarSet, TVarSet0,
-		ClausesInfo, Warnings, Info0, Info) -->
+		Args, Body, Context, IsAssertion, Goal, VarSet, TVarSet0,
+		ClausesInfo, Warnings, Module0, Module, Info0, Info) -->
 	{ ClausesInfo0 = clauses_info(VarSet0, VarTypes0, VarTypes1,
 					HeadVars, ClauseList0,
 					TI_VarMap, TCI_VarMap) },
 	{ update_qual_info(Info0, TVarSet0, VarTypes0, PredId, Info1) },
 	{ varset__merge_subst(VarSet0, CVarSet, VarSet1, Subst) },
-	transform(Subst, HeadVars, Args, Body, VarSet1, Context,
-				Goal, VarSet, Warnings, Info1, Info),
+	transform(Subst, HeadVars, Args, Body, VarSet1, Context, IsAssertion,
+				Goal, VarSet, Warnings, Module0, Module,
+				Info1, Info),
 		% XXX we should avoid append - this gives O(N*N)
 	{ list__append(ClauseList0, [clause(ModeIds, Goal, Context)],
 							ClauseList) },
@@ -4284,21 +4365,70 @@
 %-----------------------------------------------------------------------------
 
 :- pred transform(prog_substitution, list(prog_var), list(prog_term), goal,
-		prog_varset, prog_context, hlds_goal, prog_varset, 
-		list(quant_warning), qual_info, qual_info,
-		io__state, io__state).
-:- mode transform(in, in, in, in, in, in, out, out, out,
+		prog_varset, prog_context, bool, hlds_goal, prog_varset, 
+		list(quant_warning), module_info, module_info,
+		qual_info, qual_info, io__state, io__state).
+:- mode transform(in, in, in, in, in, in, in, out, out, out, in, out,
 			in, out, di, uo) is det.
 
-transform(Subst, HeadVars, Args0, Body, VarSet0, Context,
-		Goal, VarSet, Warnings, Info0, Info) -->
+transform(Subst, HeadVars, Args0, Body, VarSet0, Context, IsAssertion,
+		Goal, VarSet, Warnings, Module0, Module, Info0, Info) -->
 	transform_goal(Body, VarSet0, Subst, Goal1, VarSet1, Info0, Info1),
 	{ term__apply_substitution_to_list(Args0, Subst, Args) },
 	insert_arg_unifications(HeadVars, Args, Context, head, no,
 		Goal1, VarSet1, Goal2, VarSet2, Info1, Info),
 	{ map__init(Empty) },
+		
+		%
+		% Currently every variable in an assertion must be
+		% explicitly quantified, as it has not been determined
+		% what the correct implicit quantification should be for
+		% assertions.
+		%
+	(
+		{ IsAssertion = yes }
+	->
+			% Use Goal1, since HeadVar__* not yet
+			% introduced.
+		{ quantification__goal_vars(Goal1, Unquantified) },
+		{ set__to_sorted_list(Unquantified, ProblemVars0) },
+
+			% The Args are implicitly universally
+			% quantified.
+		{ term__term_list_to_var_list(Args, ArgVars) },
+		{ list__delete_elems(ProblemVars0, ArgVars, ProblemVars) },
+
+		{ list__length(ProblemVars, L) },
+		(
+			{ L > 0 }
+		->
+			prog_out__write_context(Context),
+			(
+				{ L = 1 }
+			->
+				io__write_string("Error: the variable `")
+			;
+				io__write_string("Error: the variables `")
+			),
+			io__write_list(ProblemVars, ",", write_var(VarSet)),
+			io__write_string("' were not explicitly quantified.\n"),
+			{ module_info_incr_errors(Module0, Module) }
+		;
+			{ Module = Module0 }
+		)
+
+	;
+		{ Module = Module0 }
+	),
 	{ implicitly_quantify_clause_body(HeadVars, Goal2, VarSet2, Empty,
 				Goal, VarSet, _, Warnings) }.
+
+	% Allow use of term_io__write_variable in io__write_list
+:- pred write_var(prog_varset::in, prog_var::in,
+		io__state::di, io__state::uo) is det.
+
+write_var(VarSet, Var) -->
+	term_io__write_variable(Var, VarSet).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/mercury_to_goedel.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/mercury_to_goedel.m,v
retrieving revision 1.66
diff -u -r1.66 mercury_to_goedel.m
--- mercury_to_goedel.m	1998/11/20 04:08:20	1.66
+++ mercury_to_goedel.m	1999/07/08 00:30:59
@@ -200,7 +200,12 @@
 goedel_output_item(pragma(_Pragma), _Context) -->
 	io__stderr_stream(Stderr),
 	io__write_string(Stderr, 
-			"warning: C header declarations not allowed. Ignoring\n").
+			"warning: pragma declarations not allowed. Ignoring\n").
+
+goedel_output_item(assertion(_, _), _Context) -->
+	io__stderr_stream(Stderr),
+	io__write_string(Stderr, 
+			"warning: assertion declarations not allowed. Ignoring\n").
 
 goedel_output_item(nothing, _) --> [].
 goedel_output_item(typeclass(_, _, _, _, _), _) -->
Index: compiler/mercury_to_mercury.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/mercury_to_mercury.m,v
retrieving revision 1.158
diff -u -r1.158 mercury_to_mercury.m
--- mercury_to_mercury.m	1999/07/08 05:08:54	1.158
+++ mercury_to_mercury.m	1999/07/08 09:49:04
@@ -427,6 +427,13 @@
 			"check_termination")
 	).
 
+mercury_output_item(assertion(Goal, VarSet), _) -->
+	io__write_string(":- assertion "),
+	{ Indent = 1 },
+	mercury_output_newline(Indent),
+	mercury_output_goal(Goal, VarSet, Indent),
+	io__write_string(".\n").
+
 mercury_output_item(nothing, _) --> [].
 mercury_output_item(typeclass(Constraints, ClassName, Vars, Methods, 
 		VarSet), _) --> 
@@ -1758,13 +1765,29 @@
 mercury_output_goal_2(true, _, _) -->
 	io__write_string("true").
 
-	% Implication and equivalence should have been transformed out
-	% by now
-mercury_output_goal_2(implies(_G1,_G2), _VarSet, _Indent) -->
-	{ error("mercury_to_mercury: implies/2 in mercury_output_goal")}.
+mercury_output_goal_2(implies(G1,G2), VarSet, Indent) -->
+	{ Indent1 is Indent + 1 },
+	io__write_string("("),
+	mercury_output_newline(Indent1),
+	mercury_output_goal(G1, VarSet, Indent1),
+	mercury_output_newline(Indent),
+	io__write_string("=>"),
+	mercury_output_newline(Indent1),
+	mercury_output_goal(G2, VarSet, Indent1),
+	mercury_output_newline(Indent),
+	io__write_string(")").
 
-mercury_output_goal_2(equivalent(_G1,_G2), _VarSet, _Indent) -->
-	{ error("mercury_to_mercury: equivalent/2 in mercury_output_goal")}.
+mercury_output_goal_2(equivalent(G1,G2), VarSet, Indent) -->
+	{ Indent1 is Indent + 1 },
+	io__write_string("("),
+	mercury_output_newline(Indent1),
+	mercury_output_goal(G1, VarSet, Indent1),
+	mercury_output_newline(Indent),
+	io__write_string("<=>"),
+	mercury_output_newline(Indent1),
+	mercury_output_goal(G2, VarSet, Indent1),
+	mercury_output_newline(Indent),
+	io__write_string(")").
 
 mercury_output_goal_2(some(Vars, Goal), VarSet, Indent) -->
 	( { Vars = [] } ->
@@ -1904,7 +1927,8 @@
 		mercury_output_goal(Goal, VarSet, Indent1)
 	).
 
-:- pred mercury_output_par_conj(goal, prog_varset, int, io__state, io__state).
+:- pred mercury_output_par_conj(goal, prog_varset, int,
+		io__state, io__state).
 :- mode mercury_output_par_conj(in, in, in, di, uo) is det.
 
 mercury_output_par_conj(Goal, VarSet, Indent) -->
@@ -2805,6 +2829,7 @@
 mercury_unary_prefix_op("?-").
 mercury_unary_prefix_op("\\").
 mercury_unary_prefix_op("\\+").
+mercury_unary_prefix_op("assertion").
 mercury_unary_prefix_op("delete").
 mercury_unary_prefix_op("dynamic").
 mercury_unary_prefix_op("end_module").
Index: compiler/module_qual.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/module_qual.m,v
retrieving revision 1.44
diff -u -r1.44 module_qual.m
--- module_qual.m	1999/04/23 01:02:52	1.44
+++ module_qual.m	1999/06/30 07:01:35
@@ -144,6 +144,7 @@
 collect_mq_info_2(pred_mode(_,_,_,_,_), Info, Info).
 collect_mq_info_2(func_mode(_,_,_,_,_,_), Info, Info).
 collect_mq_info_2(pragma(_), Info, Info).
+collect_mq_info_2(assertion(_, _), Info, Info).
 collect_mq_info_2(nothing, Info, Info).
 collect_mq_info_2(typeclass(_, Name, Vars, _, _), Info0, Info) :-
 	add_typeclass_defn(Name, Vars, Info0, Info).
@@ -329,6 +330,8 @@
 						Info0, Info, yes) -->
 	{ mq_info_set_error_context(Info0, (pragma) - Context, Info1) },
 	qualify_pragma(Pragma0, Pragma, Info1, Info).
+module_qualify_item(assertion(G, V) - Context, assertion(G, V) - Context,
+						Info, Info, yes) --> [].
 module_qualify_item(nothing - Context, nothing - Context,
 						Info, Info, yes) --> [].
 module_qualify_item(typeclass(Constraints0, Name, Vars, Interface0, VarSet) -
Index: compiler/post_typecheck.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/post_typecheck.m,v
retrieving revision 1.7
diff -u -r1.7 post_typecheck.m
--- post_typecheck.m	1999/06/30 17:12:37	1.7
+++ post_typecheck.m	1999/07/08 07:24:34
@@ -50,6 +50,9 @@
 	% constraints, and if ReportErrors = yes, print appropriate
 	% warning/error messages.
 	% Also bind any unbound type variables to the type `void'.
+	% Note that when checking assertions we take the conservative
+	% approach of warning about unbound type variables.  There may
+	% be cases for which this doesn't make sense.
 	%
 :- pred post_typecheck__check_type_bindings(pred_id, pred_info, module_info,
 		bool, pred_info, int, io__state, io__state).
@@ -81,11 +84,19 @@
 		pred_info, pred_info, io__state, io__state).
 :- mode post_typecheck__finish_ill_typed_pred(in, in, in, out, di, uo) is det.
 
+	% Now that the assertion has finished being typechecked,
+	% remove it from further processing and store it in the
+	% assertion_table.
+:- pred post_typecheck__finish_assertion(module_info, pred_id,
+		module_info) is det.
+:- mode post_typecheck__finish_assertion(in, in, out) is det.
+
 %-----------------------------------------------------------------------------%
+
 :- implementation.
 
 :- import_module typecheck, clause_to_proc, mode_util, inst_match.
-:- import_module mercury_to_mercury, prog_out, hlds_out, type_util.
+:- import_module mercury_to_mercury, prog_out, hlds_data, hlds_out, type_util.
 :- import_module globals, options.
 
 :- import_module map, set, assoc_list, bool, std_util, term.
@@ -363,6 +374,13 @@
 		PredInfo0, PredInfo) -->
 	post_typecheck__propagate_types_into_modes(ModuleInfo, PredId,
 		PredInfo0, PredInfo).
+
+post_typecheck__finish_assertion(Module0, PredId, Module) :-
+	module_info_assertion_table(Module0, AssertionTable0),
+	assertion_table_add_assertion(PredId, AssertionTable0, AssertionTable),
+	module_info_set_assertion_table(Module0, AssertionTable, Module1),
+	module_info_remove_predid(Module1, PredId, Module).
+	
 
 	% 
 	% Ensure that all constructors occurring in predicate mode
Index: compiler/prog_data.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/prog_data.m,v
retrieving revision 1.46
diff -u -r1.46 prog_data.m
--- prog_data.m	1999/07/08 05:08:55	1.46
+++ prog_data.m	1999/07/08 09:49:08
@@ -83,6 +83,8 @@
 
 	;	pragma(pragma_type)
 
+	;	assertion(goal, prog_varset)
+
 	;	typeclass(list(class_constraint), class_name, list(tvar),
 			class_interface, tvarset)
 		%	Constraints, ClassName, ClassParams, 
Index: compiler/prog_io.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/prog_io.m,v
retrieving revision 1.181
diff -u -r1.181 prog_io.m
--- prog_io.m	1999/03/15 08:47:49	1.181
+++ prog_io.m	1999/07/08 07:02:35
@@ -1043,6 +1043,10 @@
 	parse_pragma(ModuleName, VarSet, Pragma, Result0),
 	check_no_attributes(Result0, Attributes, Result).
 
+process_decl(ModuleName, VarSet, "assertion", Assertion, Attributes, Result):-
+	parse_assertion(ModuleName, VarSet, Assertion, Result0),
+	check_no_attributes(Result0, Attributes, Result).
+
 process_decl(ModuleName, VarSet, "typeclass", Args, Attributes, Result):-
 	parse_typeclass(ModuleName, VarSet, Args, Result0),
 	check_no_attributes(Result0, Attributes, Result).
@@ -1093,6 +1097,17 @@
 attribute_description(constraints(univ, _), "type class constraint (`<=')").
 attribute_description(constraints(exist, _),
 	"existentially quantified type class constraint (`=>')").
+
+%-----------------------------------------------------------------------------%
+
+	% parse the assertion declaration. 
+:- pred parse_assertion(module_name, varset, list(term), maybe1(item)).
+:- mode parse_assertion(in, in, in, out) is semidet.
+
+parse_assertion(_ModuleName, VarSet, [AssertionTerm], Result) :-
+	varset__coerce(VarSet, ProgVarSet),
+	parse_goal(AssertionTerm, ProgVarSet, AssertGoal, AssertVarSet),
+	Result = ok(assertion(AssertGoal, AssertVarSet)).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/purity.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/purity.m,v
retrieving revision 1.15
diff -u -r1.15 purity.m
--- purity.m	1999/07/08 05:08:57	1.15
+++ purity.m	1999/07/08 09:49:11
@@ -135,7 +135,7 @@
 
 :- implementation.
 
-:- import_module make_hlds, hlds_data, hlds_pred, prog_io_util.
+:- import_module make_hlds, hlds_pred, prog_io_util.
 :- import_module type_util, mode_util, code_util, prog_data, unify_proc.
 :- import_module globals, options, mercury_to_mercury, hlds_out.
 :- import_module passes_aux, typecheck, module_qual, clause_to_proc.
@@ -290,7 +290,16 @@
 	{ predicate_table_set_preds(PredTable0, Preds, PredTable) },
 	{ module_info_set_predicate_table(ModuleInfo0, PredTable,
 					  ModuleInfo1) },
-	check_preds_purity_2(PredIds, FoundTypeError, ModuleInfo1, ModuleInfo,
+
+	(
+		{ pred_info_get_goal_type(PredInfo0, assertion) }
+	->
+		{ post_typecheck__finish_assertion(ModuleInfo1,
+				PredId, ModuleInfo2) }
+	;
+		{ ModuleInfo2 = ModuleInfo1 }
+	),
+	check_preds_purity_2(PredIds, FoundTypeError, ModuleInfo2, ModuleInfo,
 				  NumErrors1, NumErrors).
 
 	% Purity-check the code for single predicate, reporting any errors.
Index: compiler/typecheck.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/typecheck.m,v
retrieving revision 1.260
diff -u -r1.260 typecheck.m
--- typecheck.m	1999/07/08 08:15:18	1.260
+++ typecheck.m	1999/07/08 09:49:15
@@ -3885,7 +3885,8 @@
 %-----------------------------------------------------------------------------%
 
 	% write out the inferred `pred' or `func' declarations
-	% for a list of predicates.
+	% for a list of predicates.  Don't write out the inferred types
+	% for assertions.
 
 :- pred write_inference_messages(list(pred_id), module_info,
 				io__state, io__state).
@@ -3898,7 +3899,8 @@
 	(
 		{ check_marker(Markers, infer_type) },
 		{ module_info_predids(ModuleInfo, ValidPredIds) },
-		{ list__member(PredId, ValidPredIds) }
+		{ list__member(PredId, ValidPredIds) },
+		{ \+ pred_info_get_goal_type(PredInfo, assertion) }
 	->
 		write_inference_message(PredInfo)
 	;
Index: compiler/notes/compiler_design.html
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/notes/compiler_design.html,v
retrieving revision 1.26
diff -u -r1.26 compiler_design.html
--- compiler_design.html	1999/06/30 17:13:13	1.26
+++ compiler_design.html	1999/07/08 06:21:24
@@ -202,7 +202,8 @@
 
 	<dd>
 	quantification.m handles implicit quantification and computes
-	the set of non-local variables for each sub-goal
+	the set of non-local variables for each sub-goal.
+    This is done in transform in make_hlds.m
 
 <dt> checking typeclass instances (check_typeclass.m)
 	<dd>
Index: compiler/notes/glossary.html
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/notes/glossary.html,v
retrieving revision 1.2
diff -u -r1.2 glossary.html
--- glossary.html	1997/12/19 03:10:05	1.2
+++ glossary.html	1999/07/08 05:41:37
@@ -15,6 +15,11 @@
 
 <dl>
 
+<dt> assertion
+	<dd>
+    A declaration that specifies a law that holds for the
+    predicates/functions in the declaration.
+
 <dt> class context 
 	<dd>
 	The typeclass constraints on a predicate or function.
Index: doc/.ispell_words
===================================================================
RCS file: /home/staff/zs/imp/mercury/doc/.ispell_words,v
retrieving revision 1.1
diff -u -r1.1 .ispell_words
--- .ispell_words	1999/07/08 04:58:07	1.1
+++ .ispell_words	1999/07/08 08:45:40
@@ -65,6 +65,7 @@
 debuggable
 decl
 decls
+deconstruct
 deconstruction
 demangler
 Demoen
@@ -110,6 +111,7 @@
 fixpoint
 foldl
 foo
+fooable
 fpic
 fr
 fulljumps
@@ -211,6 +213,8 @@
 mindepth
 minimize
 MKINIT
+mkshowable
+mkuniv
 MLFLAGS
 MLLIBS
 MLOBJS
@@ -319,6 +323,7 @@
 rla
 rlo
 rm
+RTTI
 Sagonas
 samp
 Schachte
@@ -332,6 +337,7 @@
 settitle
 sh
 shar
+showable
 sicstus
 skel
 SLDNF
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/staff/zs/imp/mercury/doc/reference_manual.texi,v
retrieving revision 1.142
diff -u -r1.142 reference_manual.texi
--- reference_manual.texi	1999/07/08 08:48:05	1.142
+++ reference_manual.texi	1999/07/08 08:49:42
@@ -49,6 +49,7 @@
 @author Peter Schachte
 @author Simon Taylor
 @author Chris Speirs
+ at author Peter Ross
 @page
 @vskip 0pt plus 1filll
 Copyright @copyright{} 1995-1999 The University of Melbourne.
@@ -82,6 +83,8 @@
                       safely use destructive update to modify that value
 * Determinism::       Determinism declarations let you specify that a predicate
                       should never fail or should never succeed more than once
+* Assertions::        Assertion declarations allow you to declare laws
+                      that hold.
 * Equality preds::    User-defined types can have user-defined equality
                       predicates.
 * Higher-order::      Mercury supports higher-order predicates and functions,
@@ -349,6 +352,7 @@
 :- typeclass
 :- instance
 :- pragma
+:- assertion
 :- module
 :- interface
 :- implementation
@@ -2098,6 +2102,46 @@
 And there are a variety of other applications.
 
 @c XXX fix semantics for I/O + committed choice + mode inference 
+
+ at node Assertions
+ at chapter Assertions
+
+Mercury supports the declaration of laws that hold for predicates and
+functions.  
+These laws are only checked for type-correctness,
+it is the responsibility of the programmer to ensure overall correctness.
+The behaviour of programs with incorrect laws is undefined.
+
+A new law is introduced with the @samp{:- assertion} declaration.
+
+Here are some examples of @samp{:- assertion} declarations.
+The following example declares the function @samp{+} to be commutative.
+
+ at example
+:- assertion
+    all [A,B,R] (
+        R = A + B
+    <=>
+        R = B + A
+    ).
+ at end example
+
+Note that each variable in the declaration was explicitly quantified.
+The current Mercury compiler requires that each assertion begins with
+an @samp{all} quantification, and that every variable is explicitly
+quantified.
+
+Here is a more complicated declaration. It declares that @samp{append} is
+associative.
+
+ at example
+:- assertion
+    all [A,B,C,ABC] (
+        (some [AB] (append(A, B, AB), append(AB, C, ABC)))
+    <=>
+        (some [BC] (append(B, C, BC), append(A, BC, ABC)))
+    ).
+ at end example
 
 @node Equality preds
 @chapter User-defined equality predicates
Index: doc/transition_guide.texi
===================================================================
RCS file: /home/staff/zs/imp/mercury/doc/transition_guide.texi,v
retrieving revision 1.27
diff -u -r1.27 transition_guide.texi
--- transition_guide.texi	1999/03/24 13:09:02	1.27
+++ transition_guide.texi	1999/07/08 05:48:19
@@ -146,6 +146,7 @@
 ~               fy              900
 all             fxy             950
 and             xfy             720
+assertion       fx              1199
 div             yfx             400
 else            xfy             1170
 end_module      fx              1199
Index: library/ops.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/ops.m,v
retrieving revision 1.23
diff -u -r1.23 ops.m
--- ops.m	1998/03/03 17:26:02	1.23
+++ ops.m	1999/06/30 07:41:26
@@ -167,6 +167,7 @@
 ops__op_table("^", after, xfy, 200).		% standard ISO Prolog
 ops__op_table("all", before, fxy, 950).		% Mercury/NU-Prolog extension
 ops__op_table("and", after, xfy, 720).		% NU-Prolog extension
+ops__op_table("assertion", before, fx, 1199).	% Mercury extension
 ops__op_table("div", after, yfx, 400).		% standard ISO Prolog
 ops__op_table("else", after, xfy, 1170).	% Mercury/NU-Prolog extension
 ops__op_table("end_module", before, fx, 1199).	% Mercury extension

--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list