[m-rev.] diff: add promise_pure and promise_semipure attributes

Tyson Dowd trd at cs.mu.OZ.AU
Tue Jan 15 15:05:15 AEDT 2002


Hi,


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


Estimated hours taken: 8
Branches: main

Soon foreign_proc will be impure by default unless given a promise_pure
or promise_semipure attribute.  The syntax has been accepted for some
time, we now add the necessary declarations.

browser/dl.m:
compiler/timestamp.m:
library/*.m:
tests/hard_coded/unused_float_box_test.m:
	Add promise_pure and promise_semipure declarations for foreign_procs.


Index: browser/dl.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/dl.m,v
retrieving revision 1.13
diff -u -r1.13 dl.m
--- browser/dl.m	6 Jul 2001 14:39:28 -0000	1.13
+++ browser/dl.m	15 Jan 2002 03:59:17 -0000
@@ -200,7 +200,7 @@
 :- func make_closure_layout = c_pointer.
 
 :- pragma foreign_proc("C", make_closure_layout = (ClosureLayout::out),
-	[will_not_call_mercury, thread_safe],
+	[will_not_call_mercury, promise_pure, thread_safe],
 "{
 	MR_Closure_Id			*closure_id;
 	MR_Closure_Dyn_Link_Layout	*closure_layout;
Index: compiler/timestamp.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/timestamp.m,v
retrieving revision 1.2
diff -u -r1.2 timestamp.m
--- compiler/timestamp.m	2 Jul 2001 01:59:36 -0000	1.2
+++ compiler/timestamp.m	15 Jan 2002 03:59:17 -0000
@@ -68,7 +68,7 @@
 :- pragma foreign_proc("C",
 	gmtime_to_timestamp(Yr::in, Mnt::in, MD::in, Hrs::in, Min::in, Sec::in,
 		YD::in, WD::in, N::in) = (Result::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	int size;
 	struct tm t;
@@ -92,7 +92,7 @@
 :- pragma foreign_proc("MC++",
 	gmtime_to_timestamp(_Yr::in, _Mnt::in, _MD::in, _Hrs::in, _Min::in,
 		_Sec::in, _YD::in, _WD::in, _N::in) = (_Result::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
Index: library/array.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/array.m,v
retrieving revision 1.100
diff -u -r1.100 array.m
--- library/array.m	20 Sep 2001 13:56:04 -0000	1.100
+++ library/array.m	15 Jan 2002 03:59:17 -0000
@@ -708,7 +708,7 @@
 :- pragma inline(bounds_checks/0).
 
 :- pragma foreign_proc("C", bounds_checks,
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 #ifdef ML_OMIT_ARRAY_BOUNDS_CHECKS
 	SUCCESS_INDICATOR = FALSE;
 #else
@@ -717,7 +717,7 @@
 ").		
 
 :- pragma foreign_proc("MC++", bounds_checks,
-		[thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 #if ML_OMIT_ARRAY_BOUNDS_CHECKS
 	SUCCESS_INDICATOR = FALSE;
 #else
@@ -764,21 +764,21 @@
 
 :- pragma foreign_proc("C", 
 		array__init_2(Size::in, Item::in, Array::array_uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	MR_maybe_record_allocation(Size + 1, MR_PROC_LABEL, ""array:array/1"");
 	Array = (MR_Word) ML_make_array(Size, Item);
 ").
 
 :- pragma foreign_proc("C",
 		array__make_empty_array(Array::array_uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	MR_maybe_record_allocation(1, MR_PROC_LABEL, ""array:array/1"");
 	Array = (MR_Word) ML_make_array(0, 0);
 ").
 
 :- pragma foreign_proc("C#", 
 		array__init_2(Size::in, Item::in, Array::array_uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Array = System.Array.CreateInstance(Item.GetType(), Size);
 	for (int i = 0; i < Size; i++) {
 		Array.SetValue(Item, i);
@@ -787,7 +787,7 @@
 
 :- pragma foreign_proc("C#",
 		array__make_empty_array(_Array::array_uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
         mercury.runtime.Errors.SORRY(""foreign code for this predicate"");
 ").
 
@@ -796,48 +796,48 @@
 
 :- pragma foreign_proc("C",
 		array__min(Array::array_ui, Min::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	/* Array not used */
 	Min = 0;
 ").
 :- pragma foreign_proc("C", 
 		array__min(Array::in, Min::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	/* Array not used */
 	Min = 0;
 ").
 
 :- pragma foreign_proc("C#",
 		array__min(Array::array_ui, Min::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	/* Array not used */
 	Min = 0;
 ").
 :- pragma foreign_proc("C#", 
 		array__min(Array::in, Min::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	/* Array not used */
 	Min = 0;
 ").
 
 :- pragma foreign_proc("C", 
 		array__max(Array::array_ui, Max::out), 
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Max = ((MR_ArrayType *)Array)->size - 1;
 ").
 :- pragma foreign_proc("C",
 		array__max(Array::in, Max::out), 
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Max = ((MR_ArrayType *)Array)->size - 1;
 ").
 :- pragma foreign_proc("C#", 
 		array__max(Array::array_ui, Max::out), 
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Max = Array.Length - 1;
 ").
 :- pragma foreign_proc("C#",
 		array__max(Array::in, Max::out), 
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Max = Array.Length - 1;
 ").
 
@@ -850,23 +850,23 @@
 
 :- pragma foreign_proc("C",
 		array__size(Array::array_ui, Max::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Max = ((MR_ArrayType *)Array)->size;
 ").
 :- pragma foreign_proc("C",
 		array__size(Array::in, Max::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Max = ((MR_ArrayType *)Array)->size;
 ").
 
 :- pragma foreign_proc("C#",
 		array__size(Array::array_ui, Max::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Max = Array.Length;
 ").
 :- pragma foreign_proc("C#",
 		array__size(Array::in, Max::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Max = Array.Length;
 ").
 
@@ -908,25 +908,25 @@
 
 :- pragma foreign_proc("C",
 		array__unsafe_lookup(Array::array_ui, Index::in, Item::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_ArrayType *array = (MR_ArrayType *)Array;
 	Item = array->elements[Index];
 }").
 :- pragma foreign_proc("C",
 		array__unsafe_lookup(Array::in, Index::in, Item::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_ArrayType *array = (MR_ArrayType *)Array;
 	Item = array->elements[Index];
 }").
 
 :- pragma foreign_proc("C#",
 		array__unsafe_lookup(Array::array_ui, Index::in, Item::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	Item = Array.GetValue(Index);
 }").
 :- pragma foreign_proc("C#",
 		array__unsafe_lookup(Array::in, Index::in, Item::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	Item = Array.GetValue(Index);
 }").
 
@@ -946,7 +946,7 @@
 :- pragma foreign_proc("C",
 		array__unsafe_set(Array0::array_di, Index::in,
 		Item::in, Array::array_uo),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_ArrayType *array = (MR_ArrayType *)Array0;
 	array->elements[Index] = Item;	/* destructive update! */
 	Array = Array0;
@@ -955,7 +955,7 @@
 :- pragma foreign_proc("C#",
 		array__unsafe_set(Array0::array_di, Index::in,
 		Item::in, Array::array_uo),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	Array0.SetValue(Item, Index);	/* destructive update! */
 	Array = Array0;
 }").
@@ -1004,7 +1004,8 @@
 
 :- pragma foreign_proc("C",
 		array__resize(Array0::array_di, Size::in, Item::in,
-		Array::array_uo), [will_not_call_mercury, thread_safe], "
+		Array::array_uo),
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	MR_maybe_record_allocation(Size + 1, MR_PROC_LABEL, ""array:array/1"");
 	Array = (MR_Word) ML_resize_array(
 				(MR_ArrayType *) Array0, Size, Item);
@@ -1012,7 +1013,8 @@
 
 :- pragma foreign_proc("C#",
 		array__resize(Array0::array_di, Size::in, Item::in,
-		Array::array_uo), [will_not_call_mercury, thread_safe], "
+		Array::array_uo),
+		[will_not_call_mercury, promise_pure, thread_safe], "
 
 	if (Array0.Length == Size) {
 		Array = Array0;
@@ -1075,7 +1077,7 @@
 
 :- pragma foreign_proc("C",
 		array__shrink_2(Array0::array_di, Size::in, Array::array_uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	MR_maybe_record_allocation(Size + 1, MR_PROC_LABEL, ""array:array/1"");
 	Array = (MR_Word) ML_shrink_array(
 				(MR_ArrayType *) Array0, Size);
@@ -1083,7 +1085,7 @@
 
 :- pragma foreign_proc("C#",
 		array__shrink_2(Array0::array_di, Size::in, Array::array_uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Array = System.Array.CreateInstance(
 				Array0.GetType().GetElementType(), Size);
 	System.Array.Copy(Array0, Array, Size);
@@ -1121,7 +1123,7 @@
 
 :- pragma foreign_proc("C",
 		array__copy(Array0::array_ui, Array::array_uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	MR_maybe_record_allocation((((MR_ArrayType *) Array0)->size) + 1,
 		MR_PROC_LABEL, ""array:array/1"");
 	Array = (MR_Word) ML_copy_array((MR_ArrayType *) Array0);
@@ -1129,7 +1131,7 @@
 
 :- pragma foreign_proc("C",
 		array__copy(Array0::in, Array::array_uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	MR_maybe_record_allocation((((MR_ArrayType *) Array0)->size) + 1,
 		MR_PROC_LABEL, ""array:array/1"");
 	Array = (MR_Word) ML_copy_array((MR_ArrayType *) Array0);
@@ -1137,7 +1139,7 @@
 
 :- pragma foreign_proc("C#",
 		array__copy(Array0::array_ui, Array::array_uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 
 	// XXX we implement the same as ML_copy_array, which doesn't appear
 	// to deep copy the array elements
@@ -1148,7 +1150,7 @@
 
 :- pragma foreign_proc("C#",
 		array__copy(Array0::in, Array::array_uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	mercury.runtime.Errors.SORRY(""foreign code for this function"");
 		// XXX need to deep copy it
 	Array = Array0;
Index: library/benchmarking.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/benchmarking.m,v
retrieving revision 1.44
diff -u -r1.44 benchmarking.m
--- library/benchmarking.m	22 Nov 2001 11:37:08 -0000	1.44
+++ library/benchmarking.m	15 Jan 2002 03:59:17 -0000
@@ -75,24 +75,28 @@
 
 "). % end pragma foreign_decl
 
-:- pragma foreign_proc("C", report_stats, will_not_call_mercury,
+:- pragma foreign_proc("C", report_stats,
+	[will_not_call_mercury, promise_pure],
 "
 	ML_report_stats();
 ").
 
-:- pragma foreign_proc("C", report_full_memory_stats, will_not_call_mercury,
+:- pragma foreign_proc("C", report_full_memory_stats,
+	[will_not_call_mercury, promise_pure],
 "
 #ifdef	MR_MPROF_PROFILE_MEMORY
 	ML_report_full_memory_stats();
 #endif
 ").
 
-:- pragma foreign_proc("MC++", report_stats, will_not_call_mercury,
+:- pragma foreign_proc("MC++", report_stats,
+	[will_not_call_mercury, promise_pure],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
-:- pragma foreign_proc("MC++", report_full_memory_stats, will_not_call_mercury,
+:- pragma foreign_proc("MC++", report_full_memory_stats,
+	[will_not_call_mercury, promise_pure],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
@@ -706,13 +710,13 @@
 :- impure pred new_int_reference(int::in, int_reference::out) is det.
 :- pragma inline(new_int_reference/2).
 :- pragma foreign_proc("C",
-	new_int_reference(X::in, Ref::out), will_not_call_mercury,
+	new_int_reference(X::in, Ref::out), [will_not_call_mercury],
 "
 	MR_incr_hp(Ref, 1);
 	* (MR_Integer *) Ref = X;
 ").
 :- pragma foreign_proc("MC++",
-	new_int_reference(_X::in, _Ref::out), will_not_call_mercury, 
+	new_int_reference(_X::in, _Ref::out), [will_not_call_mercury], 
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
@@ -725,23 +729,25 @@
 
 :- semipure pred ref_value(int_reference::in, int::out) is det.
 :- pragma inline(ref_value/2).
-:- pragma foreign_proc("C",
-	ref_value(Ref::in, X::out), will_not_call_mercury, "
+:- pragma foreign_proc("C", ref_value(Ref::in, X::out),
+		[will_not_call_mercury, promise_semipure],
+"
 	X = * (MR_Integer *) Ref;
 ").
-:- pragma foreign_proc("MC++",
-	ref_value(_Ref::in, _X::out), will_not_call_mercury, "
+:- pragma foreign_proc("MC++", ref_value(_Ref::in, _X::out),
+		[will_not_call_mercury, promise_semipure],
+"
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- impure pred update_ref(int_reference::in, T::in) is det.
 :- pragma inline(update_ref/2).
 :- pragma foreign_proc("C",
-	update_ref(Ref::in, X::in), will_not_call_mercury, "
+	update_ref(Ref::in, X::in), [will_not_call_mercury], "
 	* (MR_Integer *) Ref = X;
 ").
 :- pragma foreign_proc("MC++",
-	update_ref(_Ref::in, _X::in), will_not_call_mercury, "
+	update_ref(_Ref::in, _X::in), [will_not_call_mercury], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
Index: library/builtin.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/builtin.m,v
retrieving revision 1.64
diff -u -r1.64 builtin.m
--- library/builtin.m	19 Dec 2001 02:54:04 -0000	1.64
+++ library/builtin.m	15 Jan 2002 03:59:17 -0000
@@ -234,19 +234,19 @@
 
 :- pragma foreign_proc("C", cc_cast(X :: (pred(out) is cc_multi)) =
                         (Y :: out(pred(out) is det)),
-                [will_not_call_mercury, thread_safe],
+                [will_not_call_mercury, promise_pure, thread_safe],
                 "Y = X;").
 :- pragma foreign_proc("C", cc_cast(X :: (pred(out) is cc_nondet)) =
                         (Y :: out(pred(out) is semidet)),
-                [will_not_call_mercury, thread_safe],
+                [will_not_call_mercury, promise_pure, thread_safe],
                 "Y = X;").
 :- pragma foreign_proc("C#", cc_cast(X :: (pred(out) is cc_multi)) =
                         (Y :: out(pred(out) is det)),
-                [will_not_call_mercury, thread_safe],
+                [will_not_call_mercury, promise_pure, thread_safe],
                 "Y = X;").
 :- pragma foreign_proc("C#", cc_cast(X :: (pred(out) is cc_nondet)) =
                         (Y :: out(pred(out) is semidet)),
-                [will_not_call_mercury, thread_safe],
+                [will_not_call_mercury, promise_pure, thread_safe],
                 "Y = X;").
 
 promise_only_solution_io(Pred, X) -->
@@ -259,12 +259,12 @@
 :- pragma foreign_proc("C",
 	cc_cast_io(X :: (pred(out, di, uo) is cc_multi)) = 
 		(Y :: out(pred(out, di, uo) is det)),
-                [will_not_call_mercury, thread_safe],
+                [will_not_call_mercury, promise_pure, thread_safe],
                 "Y = X;").
 :- pragma foreign_proc("C#", 
 		cc_cast_io(X :: (pred(out, di, uo) is cc_multi)) =
 		(Y :: out(pred(out, di, uo) is det)),
-                [will_not_call_mercury, thread_safe],
+                [will_not_call_mercury, promise_pure, thread_safe],
                 "Y = X;").
 
 %-----------------------------------------------------------------------------%
Index: library/char.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/char.m,v
retrieving revision 1.34
diff -u -r1.34 char.m
--- library/char.m	14 Jun 2001 22:36:18 -0000	1.34
+++ library/char.m	15 Jan 2002 03:59:17 -0000
@@ -415,19 +415,19 @@
 
 :- pragma foreign_proc("C",
 	char__to_int(Character::in, Int::out),
-               [will_not_call_mercury, thread_safe] , "
+               [will_not_call_mercury, promise_pure, thread_safe] , "
 	Int = (MR_UnsignedChar) Character;
 ").
 
 :- pragma foreign_proc("C",
 	char__to_int(Character::in, Int::in),
-               [will_not_call_mercury, thread_safe] , "
+               [will_not_call_mercury, promise_pure, thread_safe] , "
 	SUCCESS_INDICATOR = ((MR_UnsignedChar) Character == Int);
 ").
 
 :- pragma foreign_proc("C",
 	char__to_int(Character::out, Int::in),
-               [will_not_call_mercury, thread_safe] , "
+               [will_not_call_mercury, promise_pure, thread_safe] , "
 	/*
 	** If the integer doesn't fit into a char, then
 	** the assignment `Character = Int' below will truncate it.
@@ -440,19 +440,19 @@
 
 :- pragma foreign_proc("MC++",
 	char__to_int(Character::in, Int::out),
-               [will_not_call_mercury, thread_safe] , "
+               [will_not_call_mercury, promise_pure, thread_safe] , "
 	Int = Character;
 ").
 
 :- pragma foreign_proc("MC++",
 	char__to_int(Character::in, Int::in),
-               [will_not_call_mercury, thread_safe] , "
+               [will_not_call_mercury, promise_pure, thread_safe] , "
 	SUCCESS_INDICATOR = (Character == Int);
 ").
 
 :- pragma foreign_proc("MC++",
 	char__to_int(Character::out, Int::in),
-               [will_not_call_mercury, thread_safe] , "
+               [will_not_call_mercury, promise_pure, thread_safe] , "
 	Character = Int;
 	SUCCESS_INDICATOR = (Character == Int);
 ").
@@ -465,13 +465,13 @@
 :- pragma foreign_decl("C", "#include <limits.h>").
 :- pragma foreign_proc("C",
 		char__max_char_value(Max::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Max = UCHAR_MAX;
 ").
 
 :- pragma foreign_proc("MC++",
 		char__max_char_value(_Max::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	mercury::runtime::Errors::SORRY(""c code for this function"");
 ").
 
Index: library/exception.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/exception.m,v
retrieving revision 1.55
diff -u -r1.55 exception.m
--- library/exception.m	4 Dec 2001 00:44:31 -0000	1.55
+++ library/exception.m	15 Jan 2002 03:59:17 -0000
@@ -251,51 +251,51 @@
 :- pragma foreign_proc("C",
 	get_determinism(_Pred::pred(out) is det,
 			Det::out(bound(det))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"Det = ML_DET"
 ).
 :- pragma foreign_proc("C",
 	get_determinism(_Pred::pred(out) is semidet,
 			Det::out(bound(semidet))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"Det = ML_SEMIDET"
 ).
 :- pragma foreign_proc("C",
 	get_determinism(_Pred::pred(out) is cc_multi,
 			Det::out(bound(cc_multi))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"Det = ML_CC_MULTI"
 ).
 :- pragma foreign_proc("C",
 	get_determinism(_Pred::pred(out) is cc_nondet,
 			Det::out(bound(cc_nondet))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"Det = ML_CC_NONDET"
 ).
 :- pragma foreign_proc("C",
 	get_determinism(_Pred::pred(out) is multi,
 			Det::out(bound(multi))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"Det = ML_MULTI"
 ).
 :- pragma foreign_proc("C",
 	get_determinism(_Pred::pred(out) is nondet,
 			Det::out(bound(nondet))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"Det = ML_NONDET"
 ).
 
 :- pragma foreign_proc("C",
 	get_determinism_2(_Pred::pred(out, di, uo) is det,
 			Det::out(bound(det))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"Det = ML_DET"
 ).
 
 :- pragma foreign_proc("C",
 	get_determinism_2(_Pred::pred(out, di, uo) is cc_multi,
 			Det::out(bound(cc_multi))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"Det = ML_CC_MULTI"
 ).
 
@@ -327,51 +327,51 @@
 :- pragma foreign_proc("MC++",
 	get_determinism(_Pred::pred(out) is det,
 			Det::out(bound(det))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"MR_newenum(Det, ML_DET);"
 ).
 :- pragma foreign_proc("MC++",
 	get_determinism(_Pred::pred(out) is semidet,
 			Det::out(bound(semidet))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"MR_newenum(Det, ML_SEMIDET);"
 ).
 :- pragma foreign_proc("MC++",
 	get_determinism(_Pred::pred(out) is cc_multi,
 			Det::out(bound(cc_multi))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"MR_newenum(Det, ML_CC_MULTI);"
 ).
 :- pragma foreign_proc("MC++",
 	get_determinism(_Pred::pred(out) is cc_nondet,
 			Det::out(bound(cc_nondet))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"MR_newenum(Det, ML_CC_NONDET);"
 ).
 :- pragma foreign_proc("MC++",
 	get_determinism(_Pred::pred(out) is multi,
 			Det::out(bound(multi))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"MR_newenum(Det, ML_MULTI);"
 ).
 :- pragma foreign_proc("MC++",
 	get_determinism(_Pred::pred(out) is nondet,
 			Det::out(bound(nondet))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"MR_newenum(Det, ML_NONDET);"
 ).
 
 :- pragma foreign_proc("MC++",
 	get_determinism_2(_Pred::pred(out, di, uo) is det,
 			Det::out(bound(det))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"MR_newenum(Det, ML_DET);"
 ).
 
 :- pragma foreign_proc("MC++",
 	get_determinism_2(_Pred::pred(out, di, uo) is cc_multi,
 			Det::out(bound(cc_multi))),
-	will_not_call_mercury,
+	[will_not_call_mercury, promise_pure],
 	"MR_newenum(Det, ML_CC_MULTI);"
 ).
 
@@ -1102,14 +1102,15 @@
 	% For the .NET backend we override throw_impl as it is easier to 
 	% implement these things using foreign_proc.
 
-:- pragma foreign_proc("C#", throw_impl(T::in), [will_not_call_mercury], "
+:- pragma foreign_proc("C#", throw_impl(T::in),
+		[will_not_call_mercury, promise_pure], "
 	throw new mercury.runtime.Exception(T);
 ").
 
 
 :- pragma foreign_proc("C#", 
-	catch_impl(Pred::pred(out) is det,
-		Handler::in(handler), T::out), [will_not_call_mercury], "
+	catch_impl(Pred::pred(out) is det, Handler::in(handler), T::out),
+		[will_not_call_mercury, promise_pure], "
 	try {
 		mercury.exception.mercury_code.ML_call_goal_det(
 			TypeInfo_for_T, Pred, ref T);
@@ -1120,8 +1121,8 @@
 	}
 ").
 :- pragma foreign_proc("C#", 
-	catch_impl(Pred::pred(out) is cc_multi,
-		Handler::in(handler), T::out), [will_not_call_mercury], "
+	catch_impl(Pred::pred(out) is cc_multi, Handler::in(handler), T::out),
+		[will_not_call_mercury, promise_pure], "
 	try {
 		mercury.exception.mercury_code.ML_call_goal_det(
 			TypeInfo_for_T, Pred, ref T);
@@ -1137,14 +1138,14 @@
 	% for the C# interface.
 
 :- pragma foreign_proc("C#", 
-	catch_impl(Pred::pred(out) is semidet,
-		Handler::in(handler), T::out), [will_not_call_mercury], "
+	catch_impl(Pred::pred(out) is semidet, Handler::in(handler), T::out),
+		[will_not_call_mercury, promise_pure], "
 	mercury.runtime.Errors.SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("C#", 
-	catch_impl(Pred::pred(out) is cc_nondet,
-		Handler::in(handler), T::out), [will_not_call_mercury], "
+	catch_impl(Pred::pred(out) is cc_nondet, Handler::in(handler), T::out),
+		[will_not_call_mercury, promise_pure], "
 	mercury.runtime.Errors.SORRY(""foreign code for this function"");
 ").
 
@@ -1153,8 +1154,8 @@
 	% is not possible.
 
 :- pragma foreign_proc("C#", 
-	catch_impl(_Pred::pred(out) is multi,
-		_Handler::in(handler), _T::out), [will_not_call_mercury], 
+	catch_impl(_Pred::pred(out) is multi, _Handler::in(handler), _T::out),
+		[will_not_call_mercury, promise_pure], 
 	local_vars(""),
 	first_code(""),
 	retry_code(""),
@@ -1163,8 +1164,8 @@
 	")
 ).
 :- pragma foreign_proc("C#", 
-	catch_impl(_Pred::pred(out) is nondet,
-		_Handler::in(handler), _T::out), [will_not_call_mercury], 
+	catch_impl(_Pred::pred(out) is nondet, _Handler::in(handler), _T::out),
+		[will_not_call_mercury, promise_pure], 
 	local_vars(""),
 	first_code(""),
 	retry_code(""),
Index: library/float.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/float.m,v
retrieving revision 1.39
diff -u -r1.39 float.m
--- library/float.m	4 Jan 2002 07:49:09 -0000	1.39
+++ library/float.m	15 Jan 2002 03:59:17 -0000
@@ -229,7 +229,7 @@
 :- pragma inline(domain_checks/0).
 
 :- pragma foreign_proc("C", domain_checks,
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 #ifdef ML_OMIT_MATH_DOMAIN_CHECKS
 	SUCCESS_INDICATOR = FALSE;
 #else
@@ -256,12 +256,12 @@
 	% float__ceiling_to_int(X) returns the
 	% smallest integer not less than X.
 :- pragma foreign_proc("C", float__ceiling_to_int(X :: in) = (Ceil :: out),
-	[will_not_call_mercury, thread_safe],
+	[will_not_call_mercury, promise_pure, thread_safe],
 "
 	Ceil = (MR_Integer) ceil(X);
 ").
 :- pragma foreign_proc("C#", float__ceiling_to_int(X :: in) = (Ceil :: out),
-	[will_not_call_mercury, thread_safe],
+	[will_not_call_mercury, promise_pure, thread_safe],
 "
 	Ceil = System.Convert.ToInt32(System.Math.Ceiling(X));
 ").
@@ -269,12 +269,12 @@
 	% float__floor_to_int(X) returns the
 	% largest integer not greater than X.
 :- pragma foreign_proc("C", float__floor_to_int(X :: in) = (Floor :: out),
-	[will_not_call_mercury, thread_safe],
+	[will_not_call_mercury, promise_pure, thread_safe],
 "
 	Floor = (MR_Integer) floor(X);
 ").
 :- pragma foreign_proc("C#", float__floor_to_int(X :: in) = (Floor :: out),
-	[will_not_call_mercury, thread_safe],
+	[will_not_call_mercury, promise_pure, thread_safe],
 "
 	Floor = System.Convert.ToInt32(System.Math.Floor(X));
 ").
@@ -282,12 +282,12 @@
 	% float__round_to_int(X) returns the integer closest to X.
 	% If X has a fractional value of 0.5, it is rounded up.
 :- pragma foreign_proc("C", float__round_to_int(X :: in) = (Round :: out),
-	[will_not_call_mercury, thread_safe],
+	[will_not_call_mercury, promise_pure, thread_safe],
 "
 	Round = (MR_Integer) floor(X + 0.5);
 ").
 :- pragma foreign_proc("C#", float__round_to_int(X :: in) = (Round :: out),
-	[will_not_call_mercury, thread_safe],
+	[will_not_call_mercury, promise_pure, thread_safe],
 "
 	Round = System.Convert.ToInt32(System.Math.Floor(X + 0.5));
 ").
@@ -295,12 +295,12 @@
 	% float__truncate_to_int(X) returns the integer closest
 	% to X such that |float__truncate_to_int(X)| =< |X|.
 :- pragma foreign_proc("C", float__truncate_to_int(X :: in) = (Trunc :: out),
-	[will_not_call_mercury, thread_safe],
+	[will_not_call_mercury, promise_pure, thread_safe],
 "
 	Trunc = (MR_Integer) X;
 ").
 :- pragma foreign_proc("C#", float__truncate_to_int(X :: in) = (Trunc :: out),
-	[will_not_call_mercury, thread_safe],
+	[will_not_call_mercury, promise_pure, thread_safe],
 "
 	Trunc = System.Convert.ToInt32(X);
 ").
@@ -353,12 +353,12 @@
 	).
 
 :- pragma foreign_proc("C", float__hash(F::in) = (H::out),
-	[will_not_call_mercury, thread_safe],
+	[will_not_call_mercury, promise_pure, thread_safe],
 "
 	H = MR_hash_float(F);
 ").
 :- pragma foreign_proc("C#", float__hash(F::in) = (H::out),
-	[will_not_call_mercury, thread_safe],
+	[will_not_call_mercury, promise_pure, thread_safe],
 "
 	H = F.GetHashCode();
 ").
@@ -394,45 +394,45 @@
 
 	% Maximum floating-point number
 :- pragma foreign_proc("C", float__max = (Max::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 	"Max = ML_FLOAT_MAX;").
 :- pragma foreign_proc("C#", float__max = (Max::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 	"Max = System.Double.MaxValue;").
 
 
 	% Minimum normalised floating-point number */
 :- pragma foreign_proc("C", float__min = (Min::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 	"Min = ML_FLOAT_MIN;").
 :- pragma foreign_proc("C#", float__min = (Min::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 	"Min = System.Double.MinValue;").
 
 	% Smallest x such that x \= 1.0 + x
 :- pragma foreign_proc("C", float__epsilon = (Eps::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 	"Eps = ML_FLOAT_EPSILON;").
 :- pragma foreign_proc("C#", float__epsilon = (Eps::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 	"Eps = System.Double.Epsilon;").
 
 	% Radix of the floating-point representation.
 :- pragma foreign_proc("C", float__radix = (Radix::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 	"Radix = ML_FLOAT_RADIX;").
 :- pragma foreign_proc("C#", float__radix = (_Radix::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	mercury.runtime.Errors.SORRY(""foreign code for this function"");
 	_Radix = 0;
 ").
 
 	% The number of base-radix digits in the mantissa.
 :- pragma foreign_proc("C", float__mantissa_digits = (MantDig::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 	"MantDig = ML_FLOAT_MANT_DIG;").
 :- pragma foreign_proc("C#", float__mantissa_digits = (_MantDig::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	mercury.runtime.Errors.SORRY(""foreign code for this function"");
 	_MantDig = 0;
 ").
@@ -441,10 +441,10 @@
 	%	radix ** (min_exponent - 1)
 	% is a normalised floating-point number.
 :- pragma foreign_proc("C", float__min_exponent = (MinExp::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 	"MinExp = ML_FLOAT_MIN_EXP;").
 :- pragma foreign_proc("C#", float__min_exponent = (_MinExp::out),
-		[will_not_call_mercury, thread_safe], "	
+		[will_not_call_mercury, promise_pure, thread_safe], "	
 	mercury.runtime.Errors.SORRY(""foreign code for this function"");
 	_MinExp = 0;
 ").
@@ -453,11 +453,11 @@
 	%	radix ** (max_exponent - 1)
 	% is a normalised floating-point number.
 :- pragma foreign_proc("C", float__max_exponent = (MaxExp::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 	"MaxExp = ML_FLOAT_MAX_EXP;").
 
 :- pragma foreign_proc("C#", float__max_exponent = (_MaxExp::out),
-		[will_not_call_mercury, thread_safe], "	
+		[will_not_call_mercury, promise_pure, thread_safe], "	
 	mercury.runtime.Errors.SORRY(""foreign code for this function"");
 	_MaxExp = 0;
 ").
Index: library/int.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/int.m,v
retrieving revision 1.80
diff -u -r1.80 int.m
--- library/int.m	6 Nov 2001 15:44:59 -0000	1.80
+++ library/int.m	15 Jan 2002 03:59:17 -0000
@@ -318,7 +318,7 @@
 :- pragma inline(domain_checks/0).
 
 :- pragma foreign_proc("C", domain_checks,
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 #ifdef ML_OMIT_MATH_DOMAIN_CHECKS
 	SUCCESS_INDICATOR = FALSE;
 #else
@@ -476,12 +476,12 @@
 :- mode int__to_float(in, out) is det.
 */
 :- pragma foreign_proc("C", int__to_float(IntVal::in, FloatVal::out),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "
 	FloatVal = IntVal;
 ").
 :- pragma foreign_proc("MC++", int__to_float(IntVal::in, FloatVal::out),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "
 	FloatVal = (MR_Float) IntVal;
 ").
@@ -505,7 +505,7 @@
 ").
 
 :- pragma foreign_proc("C", int__max_int(Max::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	if (sizeof(MR_Integer) == sizeof(int))
 		Max = INT_MAX;
 	else if (sizeof(MR_Integer) == sizeof(long))
@@ -515,7 +515,7 @@
 ").
 
 :- pragma foreign_proc("C", int__min_int(Min::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	if (sizeof(MR_Integer) == sizeof(int))
 		Min = INT_MIN;
 	else if (sizeof(MR_Integer) == sizeof(long))
@@ -525,38 +525,38 @@
 ").
 
 :- pragma foreign_proc("C", int__bits_per_int(Bits::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Bits = ML_BITS_PER_INT;
 ").
 
 :- pragma foreign_proc("C", int__quot_bits_per_int(Int::in) = (Div::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Div = Int / ML_BITS_PER_INT;
 ").
 
 :- pragma foreign_proc("C", int__times_bits_per_int(Int::in) = (Result::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Result = Int * ML_BITS_PER_INT;
 ").
 
 :- pragma foreign_proc("C", int__rem_bits_per_int(Int::in) = (Rem::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Rem = Int % ML_BITS_PER_INT;
 ").
 
 
 :- pragma foreign_proc("MC++", int__max_int(Max::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Max = System::Int32::MaxValue;
 ").
 
 :- pragma foreign_proc("MC++", int__min_int(Min::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Min = System::Int32::MinValue;
 ").
 
 :- pragma foreign_proc("MC++", int__bits_per_int(Bits::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Bits = ML_BITS_PER_INT;
 ").
 
Index: library/io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/io.m,v
retrieving revision 1.237
diff -u -r1.237 io.m
--- library/io.m	14 Dec 2001 16:05:40 -0000	1.237
+++ library/io.m	15 Jan 2002 03:59:17 -0000
@@ -1389,7 +1389,8 @@
 
 :- pragma foreign_proc("C", io__read_line_as_string_2(File::in, Res :: out,
 			RetString::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure,
+			tabled_for_io, thread_safe],
 "
 #define ML_IO_READ_LINE_GROW(n)	((n) * 3 / 2)
 #define ML_IO_BYTES_TO_WORDS(n)	(((n) + sizeof(MR_Word) - 1) / sizeof(MR_Word))
@@ -1447,7 +1448,8 @@
 
 :- pragma foreign_proc("MC++", 
 	io__read_line_as_string_2(_File::in, _Res :: out, _RetString::out,
-		IO0::di, IO::uo), [will_not_call_mercury, thread_safe],
+		IO0::di, IO::uo),
+		[will_not_call_mercury, promise_pure,thread_safe],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 	update_io(IO0, IO);
@@ -1543,7 +1545,8 @@
 % same as ANSI C's clearerr().
 
 :- pragma foreign_proc("C", io__clear_err(Stream::in, _IO0::di, _IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure,
+			tabled_for_io, thread_safe],
 "{
 	MercuryFile *f = (MercuryFile *) Stream;
 
@@ -1555,7 +1558,7 @@
 }").
 
 :- pragma foreign_proc("MC++", io__clear_err(_Stream::in, IO0::di, IO::uo),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "{
 	// XXX no error flag to reset as in MC++ an error throws directly an
 	// exception (we should create an error indicator in MF_Mercury_file
@@ -1581,7 +1584,8 @@
 
 :- pragma foreign_proc("C", ferror(Stream::in, RetVal::out, RetStr::out,
 		_IO0::di, _IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure,
+			tabled_for_io, thread_safe],
 "{
 	MercuryFile *f = (MercuryFile *) Stream;
 
@@ -1597,7 +1601,7 @@
 
 :- pragma foreign_proc("MC++", ferror(_Stream::in, RetVal::out, _RetStr::out,
 		IO0::di, IO::uo),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "{
 	// XXX see clearerr
 	RetVal = 0;
@@ -1614,14 +1618,14 @@
 
 :- pragma foreign_proc("C",
 	make_err_msg(Msg0::in, Msg::out, _IO0::di, _IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "{
 	ML_maybe_make_err_msg(TRUE, Msg0, MR_PROC_LABEL, Msg);
 }").
 
 :- pragma foreign_proc("MC++", 
 	make_err_msg(Msg0::in, Msg::out, _IO0::di, _IO::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "{
 	Msg = System::String::Concat(Msg0, MR_io_exception->Message);
 }").
@@ -1646,7 +1650,8 @@
 
 :- pragma foreign_proc("C", io__stream_file_size(Stream::in, Size::out,
 		_IO0::di, _IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "{
 	MercuryFile *f = (MercuryFile *) Stream;
 #if defined(HAVE_FSTAT) && \
@@ -1671,7 +1676,7 @@
 
 :- pragma foreign_proc("MC++", io__stream_file_size(Stream::in, Size::out,
 		IO0::di, IO::uo),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "{
 	MR_MercuryFile mf = ML_DownCast(MR_MercuryFile, 
 		MR_word_to_c_pointer(Stream));
@@ -1697,7 +1702,7 @@
 
 :- pragma foreign_proc("C", io__file_modification_time_2(FileName::in,
 		Status::out, Msg::out, Time::out, IO0::di, IO::uo),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "{
 #ifdef HAVE_STAT
 	struct stat s;
@@ -1722,7 +1727,7 @@
 
 :- pragma foreign_proc("MC++", io__file_modification_time_2(_FileName::in,
 		_Status::out, _Msg::out, _Time::out, _IO0::di, _IO::uo),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
@@ -1737,7 +1742,8 @@
 :- pred io__alloc_buffer(int::in, buffer::uo) is det.
 :- pragma foreign_proc("C", 
 	io__alloc_buffer(Size::in, Buffer::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "{
 	MR_incr_hp_atomic_msg(Buffer,
 		(Size * sizeof(MR_Char) + sizeof(MR_Word) - 1)
@@ -1749,7 +1755,7 @@
 :- pragma foreign_proc("C",
 	io__resize_buffer(Buffer0::di, OldSize::in,
 		NewSize::in, Buffer::uo),
-	[will_not_call_mercury, tabled_for_io, thread_safe],
+	[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "{
 	MR_Char *buffer0 = (MR_Char *) Buffer0;
 	MR_Char *buffer;
@@ -1787,7 +1793,7 @@
 :- pred io__buffer_to_string(buffer::di, int::in, string::uo) is det.
 :- pragma foreign_proc("C", 
 	io__buffer_to_string(Buffer::di, Len::in, Str::uo),
-	[will_not_call_mercury, tabled_for_io, thread_safe],
+	[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "{
 	Str = (MR_String) Buffer;
 	Str[Len] = '\\0';
@@ -1797,7 +1803,7 @@
 :- pred io__buffer_to_string(buffer::di, string::uo) is det.
 :- pragma foreign_proc("C",
 	io__buffer_to_string(Buffer::di, Str::uo),
-	[will_not_call_mercury, tabled_for_io, thread_safe],
+	[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "{
 	Str = (MR_String) Buffer;
 }").
@@ -1809,7 +1815,8 @@
 :- pragma foreign_proc("C",
 	io__read_into_buffer(Stream::in, Buffer0::di, Pos0::in, Size::in,
 		    Buffer::uo, Pos::out, _IO0::di, _IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "{
 	MercuryFile *f = (MercuryFile *) Stream;
 	char *buffer = (MR_Char *) Buffer0;
@@ -1823,7 +1830,8 @@
 
 :- pragma foreign_proc("MC++",
 	io__alloc_buffer(_Size::in, _Buffer::uo),
-		[will_not_call_mercury, thread_safe, tabled_for_io],
+		[will_not_call_mercury, promise_pure, thread_safe,
+			tabled_for_io],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
@@ -1831,21 +1839,23 @@
 :- pragma foreign_proc("MC++",
 	io__resize_buffer(_Buffer0::di, _OldSize::in,
 		_NewSize::in, _Buffer::uo),
-	[will_not_call_mercury, thread_safe, tabled_for_io],
+	[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
 
 :- pragma foreign_proc("MC++", 
 	io__buffer_to_string(_Buffer::di, _Len::in, _Str::uo),
-		[will_not_call_mercury, thread_safe, tabled_for_io],
+		[will_not_call_mercury, promise_pure, thread_safe,
+			tabled_for_io],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
 
 :- pragma foreign_proc("MC++",
 	io__buffer_to_string(_Buffer::di, _Str::uo),
-		[will_not_call_mercury, thread_safe, tabled_for_io],
+		[will_not_call_mercury, promise_pure, thread_safe,
+			tabled_for_io],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
@@ -1853,7 +1863,8 @@
 :- pragma foreign_proc("MC++",
 	io__read_into_buffer(_Stream::in, _Buffer0::di, _Pos0::in, _Size::in,
 		    _Buffer::uo, _Pos::out, _IO0::di, _IO::uo),
-		[will_not_call_mercury, thread_safe, tabled_for_io],
+		[will_not_call_mercury, promise_pure, thread_safe,
+			tabled_for_io],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
@@ -2655,7 +2666,7 @@
 
 :- pragma foreign_proc("C", 
 		io__get_stream_names(StreamNames::out, IO0::di, IO::uo), 
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	StreamNames = ML_io_stream_names;
 	update_io(IO0, IO);
@@ -2663,7 +2674,7 @@
 
 :- pragma foreign_proc("C", 
 		io__set_stream_names(StreamNames::in, IO0::di, IO::uo), 
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	ML_io_stream_names = StreamNames;
 	update_io(IO0, IO);
@@ -2671,7 +2682,7 @@
 
 :- pragma foreign_proc("MC++", 
 		io__get_stream_names(StreamNames::out, IO0::di, IO::uo), 
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	StreamNames = ML_io_stream_names;
 	update_io(IO0, IO);
@@ -2679,7 +2690,7 @@
 
 :- pragma foreign_proc("MC++", 
 		io__set_stream_names(StreamNames::in, IO0::di, IO::uo), 
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	ML_io_stream_names = StreamNames;
 	update_io(IO0, IO);
@@ -2711,7 +2722,7 @@
 
 :- pragma foreign_proc("C", 
 		io__get_globals(Globals::uo, IOState0::di, IOState::uo), 
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	Globals = ML_io_user_globals;
 	update_io(IOState0, IOState);
@@ -2719,7 +2730,7 @@
 
 :- pragma foreign_proc("C", 
 		io__set_globals(Globals::di, IOState0::di, IOState::uo), 
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	/* XXX need to globalize the memory */
 	ML_io_user_globals = Globals;
@@ -2728,7 +2739,7 @@
 
 :- pragma foreign_proc("MC++", 
 		io__get_globals(Globals::uo, IOState0::di, IOState::uo), 
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	Globals = ML_io_user_globals;
 	update_io(IOState0, IOState);
@@ -2736,7 +2747,7 @@
 
 :- pragma foreign_proc("MC++", 
 		io__set_globals(Globals::di, IOState0::di, IOState::uo), 
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	ML_io_user_globals = Globals;
 	update_io(IOState0, IOState);
@@ -2758,7 +2769,7 @@
 
 :- pragma foreign_proc("C",
 	io__get_stream_id(Stream::in, Id::out), 
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	/* 
 	** Most of the time, we can just use the pointer to the stream
 	** as a unique identifier.
@@ -2777,7 +2788,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__get_stream_id(Stream::in, Id::out), 
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_MercuryFile mf = ML_DownCast(MR_MercuryFile,
 		MR_word_to_c_pointer(Stream));
 	Id = mf->id;
@@ -2884,7 +2895,7 @@
 :- pragma foreign_proc("C", 
 		io__gc_init(StreamNamesType::in, UserGlobalsType::in,
 		IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	/* for Windows DLLs, we need to call GC_INIT() from each DLL */
 #ifdef CONSERVATIVE_GC
@@ -2897,7 +2908,7 @@
 
 :- pragma foreign_proc("MC++", 
 		io__gc_init(_StreamNamesType::in, _UserGlobalsType::in,
-		IO0::di, IO::uo), will_not_call_mercury, "
+		IO0::di, IO::uo), [will_not_call_mercury, promise_pure], "
 	update_io(IO0, IO);
 	ascii_encoder =	new System::Text::ASCIIEncoding();
 ").
@@ -2906,13 +2917,15 @@
 :- mode io__stream_init(di, uo) is det.
 
 :- pragma foreign_proc("MC++", 
-		io__stream_init(IO0::di, IO::uo), will_not_call_mercury, "
+		io__stream_init(IO0::di, IO::uo), [will_not_call_mercury,
+			promise_pure], "
 	ascii_encoder =	new System::Text::ASCIIEncoding();
 	update_io(IO0, IO);
 ").
 
 :- pragma foreign_proc("C", 
-		io__stream_init(IO0::di, IO::uo), will_not_call_mercury, "
+		io__stream_init(IO0::di, IO::uo), [will_not_call_mercury,
+			promise_pure], "
 	update_io(IO0, IO);
 ").
 
@@ -3569,7 +3582,7 @@
 
 :- pragma foreign_proc("C", 
 	io__read_char_code(File::in, CharCode::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	CharCode = mercury_getc((MercuryFile *) File);
 	update_io(IO0, IO);
@@ -3577,7 +3590,7 @@
 
 :- pragma foreign_proc("C", 
 	io__putback_char(File::in, Character::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io],
+		[may_call_mercury, promise_pure, tabled_for_io],
 "{
 	MercuryFile* mf = (MercuryFile *) File;
 	if (Character == '\\n') {
@@ -3592,7 +3605,7 @@
 
 :- pragma foreign_proc("C",
 	io__putback_byte(File::in, Character::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io],
+		[may_call_mercury, promise_pure, tabled_for_io],
 "{
 	MercuryFile* mf = (MercuryFile *) File;
 	/* XXX should work even if ungetc() fails */
@@ -3604,7 +3617,7 @@
 
 :- pragma foreign_proc("MC++", 
 	io__read_char_code(File::in, CharCode::out, IO0::di, IO::uo),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_MercuryFile mf = ML_DownCast(MR_MercuryFile, 
 		MR_word_to_c_pointer(File));
 	CharCode = mercury_getc(mf);
@@ -3613,7 +3626,7 @@
 
 :- pragma foreign_proc("MC++", 
 	io__putback_char(File::in, Character::in, IO0::di, IO::uo),
-		may_call_mercury, "{
+		[may_call_mercury, promise_pure], "{
 
 	MR_MercuryFile mf = ML_DownCast(MR_MercuryFile,
 		MR_word_to_c_pointer(File));
@@ -3626,7 +3639,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__putback_byte(File::in, _Character::in, IO0::di, IO::uo),
-		may_call_mercury, "{
+		[may_call_mercury, promise_pure], "{
 
 	MR_MercuryFile mf = ML_DownCast(MR_MercuryFile, 
 		MR_word_to_c_pointer(File));
@@ -3639,7 +3652,7 @@
 
 :- pragma foreign_proc("C", 
 	io__write_string(Message::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe],
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "
 	mercury_print_string(mercury_current_text_output, Message);
 	update_io(IO0, IO);
@@ -3647,7 +3660,7 @@
 
 :- pragma foreign_proc("C", 
 	io__write_char(Character::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe],
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "
 	if (MR_PUTCH(*mercury_current_text_output, Character) < 0) {
 		mercury_output_error(mercury_current_text_output);
@@ -3660,7 +3673,7 @@
 
 :- pragma foreign_proc("C",
 	io__write_int(Val::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe],
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "
 	if (ML_fprintf(mercury_current_text_output, ""%ld"", (long) Val) < 0) {
 		mercury_output_error(mercury_current_text_output);
@@ -3670,7 +3683,7 @@
 
 :- pragma foreign_proc("C",
 	io__write_float(Val::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe],
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "
 	if (ML_fprintf(mercury_current_text_output, ""%#.15g"", Val) < 0) {
 		mercury_output_error(mercury_current_text_output);
@@ -3680,7 +3693,7 @@
 
 :- pragma foreign_proc("C",
 	io__write_byte(Byte::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe],
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "
 	/* call putc with a strictly non-negative byte-sized integer */
 	if (MR_PUTCH(*mercury_current_binary_output,
@@ -3693,7 +3706,7 @@
 
 :- pragma foreign_proc("C",
 	io__write_bytes(Message::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe],
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "{
 	mercury_print_binary_string(mercury_current_binary_output, Message);
 	update_io(IO0, IO);
@@ -3701,7 +3714,7 @@
 
 :- pragma foreign_proc("C", 
 	io__flush_output(IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe],
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "
 	if (MR_FLUSH(*mercury_current_text_output) < 0) {
 		mercury_output_error(mercury_current_text_output);
@@ -3711,7 +3724,7 @@
 
 :- pragma foreign_proc("C",
 	io__flush_binary_output(IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe],
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "
 	if (MR_FLUSH(*mercury_current_binary_output) < 0) {
 		mercury_output_error(mercury_current_binary_output);
@@ -3721,7 +3734,7 @@
 
 :- pragma foreign_proc("MC++", 
 	io__write_string(Message::in, IO0::di, IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io],
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "
 	mercury_print_string(mercury_current_text_output, Message);
 	update_io(IO0, IO);
@@ -3729,7 +3742,7 @@
 
 :- pragma foreign_proc("MC++", 
 	io__write_char(Character::in, IO0::di, IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io],
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "
 	System::IO::StreamWriter *w = new System::IO::StreamWriter(
 		mercury_current_text_output->stream);
@@ -3743,7 +3756,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__write_int(Val::in, IO0::di, IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io],
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "
 	mercury_print_string(mercury_current_text_output, Val.ToString());
 	update_io(IO0, IO);
@@ -3751,7 +3764,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__write_float(Val::in, IO0::di, IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io],
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "
 	mercury_print_string(mercury_current_text_output, Val.ToString());
 	update_io(IO0, IO);
@@ -3759,7 +3772,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__write_byte(Byte::in, _IO0::di, _IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io],
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 		// XXX something like this...
@@ -3771,7 +3784,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__write_bytes(Message::in, IO0::di, IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io],
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "{
 	mercury_print_binary_string(mercury_current_binary_output, Message);
 	update_io(IO0, IO);
@@ -3779,7 +3792,7 @@
 
 :- pragma foreign_proc("MC++", 
 	io__flush_output(IO0::di, IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io],
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "
 	mercury_current_text_output->stream->Flush();
 	update_io(IO0, IO);
@@ -3787,7 +3800,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__flush_binary_output(IO0::di, IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io],
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "
 	mercury_current_binary_output->stream->Flush();
 	update_io(IO0, IO);
@@ -3812,7 +3825,8 @@
 :- pragma foreign_proc("C",
 	io__seek_binary_2(Stream::in, Flag::in, Off::in,
 		IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "{
 	static const int seek_flags[] = { SEEK_SET, SEEK_CUR, SEEK_END };
 	MercuryFile *stream = (MercuryFile *) Stream;
@@ -3831,7 +3845,8 @@
 :- pragma foreign_proc("C",
 	io__binary_stream_offset(Stream::in, Offset::out,
 		IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "{
 	MercuryFile *stream = (MercuryFile *) Stream;
 	/* XXX should check for failure */
@@ -3848,7 +3863,8 @@
 :- pragma foreign_proc("MC++",
 	io__seek_binary_2(_Stream::in, _Flag::in, _Off::in,
 		IO0::di, IO::uo),
-		[will_not_call_mercury, thread_safe, tabled_for_io],
+		[will_not_call_mercury, promise_pure, thread_safe,
+			tabled_for_io],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 	IO = IO0;
@@ -3857,7 +3873,8 @@
 :- pragma foreign_proc("MC++",
 	io__binary_stream_offset(_Stream::in, _Offset::out,
 		IO0::di, IO::uo),
-		[will_not_call_mercury, thread_safe, tabled_for_io],
+		[will_not_call_mercury, promise_pure, thread_safe,
+			tabled_for_io],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 	IO = IO0;
@@ -3868,7 +3885,7 @@
 
 :- pragma foreign_proc("C",
 	io__write_string(Stream::in, Message::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe], 
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe], 
 "{
 	MercuryFile *stream = (MercuryFile *) Stream;
 	mercury_print_string(stream, Message);
@@ -3877,7 +3894,7 @@
 
 :- pragma foreign_proc("C",
 	io__write_char(Stream::in, Character::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe], 
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe], 
 "{
 	MercuryFile *stream = (MercuryFile *) Stream;
 	if (MR_PUTCH(*stream, Character) < 0) {
@@ -3891,7 +3908,7 @@
 
 :- pragma foreign_proc("C",
 	io__write_int(Stream::in, Val::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe],
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "{
 	MercuryFile *stream = (MercuryFile *) Stream;
 	if (ML_fprintf(stream, ""%ld"", (long) Val) < 0) {
@@ -3902,7 +3919,7 @@
 
 :- pragma foreign_proc("C",
 	io__write_float(Stream::in, Val::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe],
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "{
 	MercuryFile *stream = (MercuryFile *) Stream;
 	if (ML_fprintf(stream, ""%#.15g"", Val) < 0) {
@@ -3913,7 +3930,7 @@
 
 :- pragma foreign_proc("C",
 	io__write_byte(Stream::in, Byte::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe],
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "{
 	MercuryFile *stream = (MercuryFile *) Stream;
 	/* call putc with a strictly non-negative byte-sized integer */
@@ -3925,7 +3942,7 @@
 
 :- pragma foreign_proc("C",
 	io__write_bytes(Stream::in, Message::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe],
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "{
 	MercuryFile *stream = (MercuryFile *) Stream;
 	mercury_print_binary_string(stream, Message);
@@ -3934,7 +3951,7 @@
 
 :- pragma foreign_proc("C",
 	io__flush_output(Stream::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe],
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "{
 	MercuryFile *stream = (MercuryFile *) Stream;
 	if (MR_FLUSH(*stream) < 0) {
@@ -3945,7 +3962,7 @@
 
 :- pragma foreign_proc("C",
 	io__flush_binary_output(Stream::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe],
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "{
 	MercuryFile *stream = (MercuryFile *) Stream;
 	if (MR_FLUSH(*stream) < 0) {
@@ -3956,7 +3973,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__write_string(Stream::in, Message::in, IO0::di, IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io], 
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io], 
 "{
 	MR_MercuryFile stream = ML_DownCast(MR_MercuryFile, 
 		MR_word_to_c_pointer(Stream));
@@ -3966,7 +3983,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__write_char(Stream::in, Character::in, IO0::di, IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io], 
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io], 
 "{
 	MR_MercuryFile stream = ML_DownCast(MR_MercuryFile, 
 		MR_word_to_c_pointer(Stream));
@@ -3979,7 +3996,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__write_int(Stream::in, Val::in, IO0::di, IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io],
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "{
 	MR_MercuryFile stream = ML_DownCast(MR_MercuryFile, 
 		MR_word_to_c_pointer(Stream));
@@ -3992,7 +4009,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__write_float(Stream::in, Val::in, IO0::di, IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io],
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "{
 	MR_MercuryFile stream = ML_DownCast(MR_MercuryFile, 
 		MR_word_to_c_pointer(Stream));
@@ -4005,7 +4022,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__write_byte(Stream::in, Byte::in, IO0::di, IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io],
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 		// something like this...
@@ -4020,7 +4037,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__write_bytes(Stream::in, Message::in, IO0::di, IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io],
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "{
 	MR_MercuryFile stream = ML_DownCast(MR_MercuryFile, 
 		MR_word_to_c_pointer(Stream));
@@ -4030,7 +4047,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__flush_output(Stream::in, IO0::di, IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io],
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "{
 	MR_MercuryFile stream = ML_DownCast(MR_MercuryFile, 
 		MR_word_to_c_pointer(Stream));
@@ -4040,7 +4057,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__flush_binary_output(Stream::in, IO0::di, IO::uo),
-		[may_call_mercury, thread_safe, tabled_for_io],
+		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "{
 	MR_MercuryFile stream = ML_DownCast(MR_MercuryFile, 
 		MR_word_to_c_pointer(Stream));
@@ -4057,7 +4074,8 @@
 
 :- pragma foreign_proc("C",
 	io__stdin_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "
 	Stream = (MR_Word) &mercury_stdin;
 	update_io(IO0, IO);
@@ -4065,7 +4083,8 @@
 
 :- pragma foreign_proc("C",
 	io__stdout_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "
 	Stream = (MR_Word) &mercury_stdout;
 	update_io(IO0, IO);
@@ -4073,7 +4092,8 @@
 
 :- pragma foreign_proc("C",
 	io__stderr_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "
 	Stream = (MR_Word) &mercury_stderr;
 	update_io(IO0, IO);
@@ -4081,7 +4101,8 @@
 
 :- pragma foreign_proc("C",
 	io__stdin_binary_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "
 	Stream = (MR_Word) &mercury_stdin_binary;
 	update_io(IO0, IO);
@@ -4089,7 +4110,8 @@
 
 :- pragma foreign_proc("C",
 	io__stdout_binary_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "
 	Stream = (MR_Word) &mercury_stdout_binary;
 	update_io(IO0, IO);
@@ -4097,7 +4119,7 @@
 
 :- pragma foreign_proc("C",
 	io__input_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	Stream = (MR_Word) mercury_current_text_input;
 	update_io(IO0, IO);
@@ -4105,7 +4127,7 @@
 
 :- pragma foreign_proc("C",
 	io__output_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	Stream = (MR_Word) mercury_current_text_output;
 	update_io(IO0, IO);
@@ -4113,7 +4135,7 @@
 
 :- pragma foreign_proc("C",
 	io__binary_input_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	Stream = (MR_Word) mercury_current_binary_input;
 	update_io(IO0, IO);
@@ -4121,7 +4143,7 @@
 
 :- pragma foreign_proc("C",
 	io__binary_output_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	Stream = (MR_Word) mercury_current_binary_output;
 	update_io(IO0, IO);
@@ -4129,7 +4151,7 @@
 
 :- pragma foreign_proc("C",
 	io__get_line_number(LineNum::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	LineNum = MR_line_number(*mercury_current_text_input);
 	update_io(IO0, IO);
@@ -4137,7 +4159,7 @@
 	
 :- pragma foreign_proc("C",
 	io__get_line_number(Stream::in, LineNum::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "{
 	MercuryFile *stream = (MercuryFile *) Stream;
 	LineNum = MR_line_number(*stream);
@@ -4146,7 +4168,7 @@
 	
 :- pragma foreign_proc("C",
 	io__set_line_number(LineNum::in, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	MR_line_number(*mercury_current_text_input) = LineNum;
 	update_io(IO0, IO);
@@ -4154,7 +4176,7 @@
 	
 :- pragma foreign_proc("C",
 	io__set_line_number(Stream::in, LineNum::in, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "{
 	MercuryFile *stream = (MercuryFile *) Stream;
 	MR_line_number(*stream) = LineNum;
@@ -4163,7 +4185,7 @@
 	
 :- pragma foreign_proc("C",
 	io__get_output_line_number(LineNum::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	LineNum = MR_line_number(*mercury_current_text_output);
 	update_io(IO0, IO);
@@ -4171,7 +4193,7 @@
 	
 :- pragma foreign_proc("C",
 	io__get_output_line_number(Stream::in, LineNum::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "{
 	MercuryFile *stream = (MercuryFile *) Stream;
 	LineNum = MR_line_number(*stream);
@@ -4180,7 +4202,7 @@
 
 :- pragma foreign_proc("C",
 	io__set_output_line_number(LineNum::in, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	MR_line_number(*mercury_current_text_output) = LineNum;
 	update_io(IO0, IO);
@@ -4189,7 +4211,7 @@
 :- pragma foreign_proc("C",
 	io__set_output_line_number(Stream::in, LineNum::in,
 		IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "{
 	MercuryFile *stream = (MercuryFile *) Stream;
 	MR_line_number(*stream) = LineNum;
@@ -4202,7 +4224,7 @@
 :- pragma foreign_proc("C",
 	io__set_input_stream(NewStream::in, OutStream::out,
 		IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	OutStream = (MR_Word) mercury_current_text_input;
 	mercury_current_text_input = (MercuryFile *) NewStream;
@@ -4212,7 +4234,7 @@
 :- pragma foreign_proc("C",
 	io__set_output_stream(NewStream::in, OutStream::out,
 		IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	OutStream = (MR_Word) mercury_current_text_output;
 	mercury_current_text_output = (MercuryFile *) NewStream;
@@ -4222,7 +4244,7 @@
 :- pragma foreign_proc("C",
 	io__set_binary_input_stream(NewStream::in, OutStream::out,
 		IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	OutStream = (MR_Word) mercury_current_binary_input;
 	mercury_current_binary_input = (MercuryFile *) NewStream;
@@ -4232,7 +4254,7 @@
 :- pragma foreign_proc("C",
 	io__set_binary_output_stream(NewStream::in, OutStream::out,
 		IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	OutStream = (MR_Word) mercury_current_binary_output;
 	mercury_current_binary_output = (MercuryFile *) NewStream;
@@ -4241,7 +4263,8 @@
 
 :- pragma foreign_proc("MC++",
 	io__stdin_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, thread_safe, tabled_for_io],
+		[will_not_call_mercury, promise_pure, thread_safe,
+			tabled_for_io],
 "
 	MR_c_pointer_to_word(Stream, mercury_stdin);
 	update_io(IO0, IO);
@@ -4249,7 +4272,8 @@
 
 :- pragma foreign_proc("MC++",
 	io__stdout_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, thread_safe, tabled_for_io],
+		[will_not_call_mercury, promise_pure, thread_safe,
+			tabled_for_io],
 "
 	MR_c_pointer_to_word(Stream, mercury_stdout);
 	update_io(IO0, IO);
@@ -4257,7 +4281,8 @@
 
 :- pragma foreign_proc("MC++",
 	io__stderr_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, thread_safe, tabled_for_io],
+		[will_not_call_mercury, promise_pure, thread_safe,
+			tabled_for_io],
 "
 	MR_c_pointer_to_word(Stream, mercury_stderr);
 	update_io(IO0, IO);
@@ -4265,7 +4290,8 @@
 
 :- pragma foreign_proc("MC++",
 	io__stdin_binary_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, thread_safe, tabled_for_io],
+		[will_not_call_mercury, promise_pure, thread_safe,
+			tabled_for_io],
 "
 	MR_c_pointer_to_word(Stream, mercury_stdin_binary);
 	update_io(IO0, IO);
@@ -4273,7 +4299,8 @@
 
 :- pragma foreign_proc("MC++",
 	io__stdout_binary_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, thread_safe, tabled_for_io],
+		[will_not_call_mercury, promise_pure, thread_safe,
+			tabled_for_io],
 "
 	MR_c_pointer_to_word(Stream, mercury_stdout_binary);
 	update_io(IO0, IO);
@@ -4281,7 +4308,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__input_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	MR_c_pointer_to_word(Stream, mercury_current_text_input);
 	update_io(IO0, IO);
@@ -4289,7 +4316,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__output_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	MR_c_pointer_to_word(Stream, mercury_current_text_output);
 	update_io(IO0, IO);
@@ -4297,7 +4324,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__binary_input_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	MR_c_pointer_to_word(Stream, mercury_current_binary_input);
 	update_io(IO0, IO);
@@ -4305,7 +4332,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__binary_output_stream(Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	MR_c_pointer_to_word(Stream, mercury_current_binary_output);
 	update_io(IO0, IO);
@@ -4313,7 +4340,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__get_line_number(LineNum::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	LineNum = mercury_current_text_input->line_number;
 	update_io(IO0, IO);
@@ -4321,7 +4348,7 @@
 	
 :- pragma foreign_proc("MC++",
 	io__get_line_number(Stream::in, LineNum::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "{
 	MR_MercuryFile stream = ML_DownCast(MR_MercuryFile, 
 		MR_word_to_c_pointer(Stream));
@@ -4331,7 +4358,7 @@
 	
 :- pragma foreign_proc("MC++",
 	io__set_line_number(LineNum::in, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	mercury_current_text_input->line_number = LineNum;
 	update_io(IO0, IO);
@@ -4339,7 +4366,7 @@
 	
 :- pragma foreign_proc("MC++",
 	io__set_line_number(Stream::in, LineNum::in, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "{
 	MR_MercuryFile stream = ML_DownCast(MR_MercuryFile, 
 		MR_word_to_c_pointer(Stream));
@@ -4349,14 +4376,14 @@
 	
 :- pragma foreign_proc("MC++",
 	io__get_output_line_number(LineNum::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io], "
+		[will_not_call_mercury, promise_pure, tabled_for_io], "
 	LineNum = mercury_current_text_output->line_number;
 	update_io(IO0, IO);
 ").
 	
 :- pragma foreign_proc("MC++",
 	io__get_output_line_number(Stream::in, LineNum::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io], "{
+		[will_not_call_mercury, promise_pure, tabled_for_io], "{
 	MR_MercuryFile stream = ML_DownCast(MR_MercuryFile, 
 		MR_word_to_c_pointer(Stream));
 	LineNum = stream->line_number;
@@ -4365,14 +4392,14 @@
 
 :- pragma foreign_proc("MC++",
 	io__set_output_line_number(LineNum::in, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io], "
+		[will_not_call_mercury, promise_pure, tabled_for_io], "
 	mercury_current_text_output->line_number = LineNum;
 	update_io(IO0, IO);
 ").
 	
 :- pragma foreign_proc("MC++",
 	io__set_output_line_number(Stream::in, LineNum::in, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io], "{
+		[will_not_call_mercury, promise_pure, tabled_for_io], "{
 	MR_MercuryFile stream = ML_DownCast(MR_MercuryFile, 
 		MR_word_to_c_pointer(Stream));
 	stream->line_number = LineNum;
@@ -4384,7 +4411,7 @@
 %	Returns the previous stream.
 :- pragma foreign_proc("MC++",
 	io__set_input_stream(NewStream::in, OutStream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io], "
+		[will_not_call_mercury, promise_pure, tabled_for_io], "
 	MR_c_pointer_to_word(OutStream, mercury_current_text_input);
 	mercury_current_text_input = 
 		ML_DownCast(MR_MercuryFile, MR_word_to_c_pointer(NewStream));
@@ -4393,7 +4420,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__set_output_stream(NewStream::in, OutStream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io], "
+		[will_not_call_mercury, promise_pure, tabled_for_io], "
 	MR_c_pointer_to_word(OutStream, mercury_current_text_output);
 	mercury_current_text_output = 
 		ML_DownCast(MR_MercuryFile, MR_word_to_c_pointer(NewStream));
@@ -4403,7 +4430,7 @@
 :- pragma foreign_proc("MC++",
 	io__set_binary_input_stream(NewStream::in, OutStream::out,
 		IO0::di, IO::uo), 
-		[will_not_call_mercury, tabled_for_io], "
+		[will_not_call_mercury, promise_pure, tabled_for_io], "
 	MR_c_pointer_to_word(OutStream, mercury_current_binary_input);
 	mercury_current_binary_input = 
 		ML_DownCast(MR_MercuryFile, MR_word_to_c_pointer(NewStream));
@@ -4413,7 +4440,7 @@
 :- pragma foreign_proc("MC++",
 	io__set_binary_output_stream(NewStream::in, OutStream::out,
 		IO0::di, IO::uo), 
-		[will_not_call_mercury, tabled_for_io], "
+		[will_not_call_mercury, promise_pure, tabled_for_io], "
 	MR_c_pointer_to_word(OutStream, mercury_current_binary_output);
 	mercury_current_binary_output = 
 		ML_DownCast(MR_MercuryFile, MR_word_to_c_pointer(NewStream));
@@ -4429,7 +4456,8 @@
 :- pragma foreign_proc("C",
 	io__do_open(FileName::in, Mode::in, ResultCode::out,
 		Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "
 	Stream = (MR_Word) mercury_open(FileName, Mode);
@@ -4439,7 +4467,8 @@
 :- pragma foreign_proc("MC++",
 	io__do_open(FileName::in, Mode::in, ResultCode::out,
 		Stream::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "
 	MR_MercuryFile mf = mercury_open(FileName, Mode);
 	MR_c_pointer_to_word(Stream, mf);
@@ -4466,13 +4495,13 @@
 :- pred io__close_stream(stream::in, io__state::di, io__state::uo) is det.
 
 :- pragma foreign_proc("C", io__close_stream(Stream::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe], "
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe], "
 	mercury_close((MercuryFile *) Stream);
 	update_io(IO0, IO);
 ").
 
 :- pragma foreign_proc("MC++", io__close_stream(Stream::in, IO0::di, IO::uo),
-		[may_call_mercury, tabled_for_io, thread_safe], "
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe], "
 	MR_MercuryFile mf = ML_DownCast(MR_MercuryFile, 
 		MR_word_to_c_pointer(Stream));
 	mercury_close(mf);
@@ -4483,7 +4512,8 @@
 
 :- pragma foreign_proc("C",
 	io__progname(DefaultProgname::in, PrognameOut::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "
 	if (MR_progname) {
 		/*
@@ -4505,7 +4535,8 @@
 
 :- pragma foreign_proc("C",
 	io__command_line_arguments(Args::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "
 	/* convert mercury_argv from a vector to a list */
 	{ int i = mercury_argc;
@@ -4520,7 +4551,7 @@
 
 :- pragma foreign_proc("C",
 	io__get_exit_status(ExitStatus::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io], 
+		[will_not_call_mercury, promise_pure, tabled_for_io], 
 "
 	ExitStatus = mercury_exit_status;
 	update_io(IO0, IO);
@@ -4528,7 +4559,7 @@
 
 :- pragma foreign_proc("C",
 	io__set_exit_status(ExitStatus::in, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	mercury_exit_status = ExitStatus;
 	update_io(IO0, IO);
@@ -4536,7 +4567,7 @@
 
 :- pragma foreign_proc("C",
 	io__call_system_code(Command::in, Status::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	Status = system(Command);
 	if ( Status == -1 || Status == 127 ) {
@@ -4571,14 +4602,16 @@
 
 :- pragma foreign_proc("MC++",
 	io__progname(_DefaultProgname::in, _PrognameOut::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe], "
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 	update_io(IO0, IO);
 ").
 
 :- pragma foreign_proc("MC++",
 	io__command_line_arguments(Args::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe], "
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe], "
 	MR_String arg_vector __gc[] = System::Environment::GetCommandLineArgs();
 	int i = arg_vector->Length;
 	MR_list_nil(Args);
@@ -4591,7 +4624,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__get_exit_status(ExitStatus::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	ExitStatus = System::Environment::get_ExitCode();
 	update_io(IO0, IO);
@@ -4599,7 +4632,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__set_exit_status(ExitStatus::in, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 	System::Environment::set_ExitCode(ExitStatus);
 	update_io(IO0, IO);
@@ -4607,7 +4640,7 @@
 
 :- pragma foreign_proc("MC++",
 	io__call_system_code(Command::in, Status::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_pure, tabled_for_io],
 "
 		// XXX This could be better... need to handle embedded spaces.
 	MR_Integer index = Command->IndexOf("" "");
@@ -4626,7 +4659,7 @@
 /* io__getenv and io__putenv, from io.m */
 
 :- pragma foreign_proc("C", io__getenv(Var::in, Value::out),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_semipure, tabled_for_io],
 "{
 	Value = getenv(Var);
 	SUCCESS_INDICATOR = (Value != 0);
@@ -4639,7 +4672,7 @@
 ").
 
 :- pragma foreign_proc("MC++", io__getenv(Var::in, Value::out),
-		[will_not_call_mercury, tabled_for_io],
+		[will_not_call_mercury, promise_semipure, tabled_for_io],
 "{
 	Value = System::Environment::GetEnvironmentVariable(Var);
 	SUCCESS_INDICATOR = (Value != 0);
@@ -4722,7 +4755,7 @@
 :- pragma foreign_proc("C",
 	io__do_make_temp(Dir::in, Prefix::in, FileName::out,
 		Error::out, ErrorMessage::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "{
 	/*
 	** Constructs a temporary name by concatenating Dir, `/',
@@ -4773,7 +4806,7 @@
 :- pragma foreign_proc("MC++",
 	io__do_make_temp(_Dir::in, _Prefix::in, _FileName::out,
 		_Error::out, _ErrorMessage::out, IO0::di, IO::uo),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 	update_io(IO0, IO);
@@ -4794,7 +4827,7 @@
 **
 ** WARNING: this must only be called when the `hp' register is valid.
 ** That means it must only be called from procedures declared
-** `will_not_call_mercury'.
+** `[will_not_call_mercury, promise_pure]'.
 **
 ** This is defined as a macro rather than a C function
 ** to avoid worrying about the `hp' register being
@@ -4840,7 +4873,8 @@
 :- pragma foreign_proc("C",
 	io__remove_file_2(FileName::in, RetVal::out, RetStr::out,
 		IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "{
 	RetVal = remove(FileName);
 	ML_maybe_make_err_msg(RetVal != 0, ""remove failed: "",
@@ -4851,7 +4885,8 @@
 :- pragma foreign_proc("MC++",
 	io__remove_file_2(FileName::in, RetVal::out, RetStr::out,
 		IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 	System::IO::File::Delete(FileName);
@@ -4875,7 +4910,8 @@
 :- pragma foreign_proc("C",
 		io__rename_file_2(OldFileName::in, NewFileName::in,
 			RetVal::out, RetStr::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "{
 	RetVal = rename(OldFileName, NewFileName);
 	ML_maybe_make_err_msg(RetVal != 0, ""rename failed: "",
@@ -4886,7 +4922,8 @@
 :- pragma foreign_proc("MC++",
 		io__rename_file_2(_OldFileName::in, _NewFileName::in,
 			_RetVal::out, _RetStr::out, IO0::di, IO::uo),
-		[will_not_call_mercury, tabled_for_io, thread_safe],
+		[will_not_call_mercury, promise_pure, tabled_for_io,
+			thread_safe],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 	update_io(IO0, IO);
Index: library/library.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/library.m,v
retrieving revision 1.58
diff -u -r1.58 library.m
--- library/library.m	29 Aug 2001 06:50:50 -0000	1.58
+++ library/library.m	15 Jan 2002 03:59:17 -0000
@@ -52,7 +52,7 @@
 % might not have a Mercury compiler around to compile library.m with.
 
 :- pragma foreign_proc("C",
-	library__version(Version::out), will_not_call_mercury,
+	library__version(Version::out), [will_not_call_mercury, promise_pure],
 "
 	MR_ConstString version_string = 
 		MR_VERSION "", configured for "" MR_FULLARCH;
@@ -68,7 +68,7 @@
 ").
 
 :- pragma foreign_proc("MC++",
-	library__version(Version::out), will_not_call_mercury,
+	library__version(Version::out), [will_not_call_mercury, promise_pure],
 "
 	// XXX we should use string literals with an S at the start
 	// so this code uses just managed types.
Index: library/math.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/math.m,v
retrieving revision 1.35
diff -u -r1.35 math.m
--- library/math.m	10 Jan 2002 04:11:38 -0000	1.35
+++ library/math.m	15 Jan 2002 03:59:17 -0000
@@ -247,7 +247,7 @@
 :- pred domain_checks is semidet.
 
 :- pragma foreign_proc("C", domain_checks,
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 #ifdef ML_OMIT_MATH_DOMAIN_CHECKS
 	SUCCESS_INDICATOR = FALSE;
 #else
@@ -268,22 +268,23 @@
 % Mathematical constants from math.m
 %
 	% Pythagoras' number
-:- pragma foreign_proc("C", 
-	math__pi = (Pi::out), [will_not_call_mercury, thread_safe],"
+:- pragma foreign_proc("C", math__pi = (Pi::out),
+		[will_not_call_mercury, promise_pure, thread_safe],
+"
 	Pi = ML_FLOAT_PI;
 ").
-:- pragma foreign_proc("C#", 
-	math__pi = (Pi::out), [will_not_call_mercury, thread_safe],"
+:- pragma foreign_proc("C#", math__pi = (Pi::out),
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	Pi = System.Math.PI;
 ").
 
 	% Base of natural logarithms
-:- pragma foreign_proc("C", 
-	math__e = (E::out), [will_not_call_mercury, thread_safe],"
+:- pragma foreign_proc("C", math__e = (E::out),
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	E = ML_FLOAT_E;
 ").
-:- pragma foreign_proc("C#", 
-	math__e = (E::out), [will_not_call_mercury, thread_safe],"
+:- pragma foreign_proc("C#", math__e = (E::out),
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	E = System.Math.E;
 ").
 
@@ -291,14 +292,14 @@
 % math__ceiling(X) = Ceil is true if Ceil is the smallest integer
 % not less than X.
 %
-:- pragma foreign_proc("C", 
-	math__ceiling(Num::in) = (Ceil::out),
-		[will_not_call_mercury, thread_safe],"
+:- pragma foreign_proc("C", math__ceiling(Num::in) = (Ceil::out),
+		[will_not_call_mercury, promise_pure, thread_safe],
+"
 	Ceil = ceil(Num);
 ").
-:- pragma foreign_proc("C#", 
-	math__ceiling(Num::in) = (Ceil::out),
-		[will_not_call_mercury, thread_safe],"
+:- pragma foreign_proc("C#", math__ceiling(Num::in) = (Ceil::out),
+		[will_not_call_mercury, promise_pure, thread_safe],
+"
 	Ceil = System.Math.Ceiling(Num);
 ").
 
@@ -306,14 +307,14 @@
 % math__floor(X) = Floor is true if Floor is the largest integer
 % not greater than X.
 %
-:- pragma foreign_proc("C", 
-	math__floor(Num::in) = (Floor::out),
-		[will_not_call_mercury, thread_safe],"
+:- pragma foreign_proc("C", math__floor(Num::in) = (Floor::out),
+		[will_not_call_mercury, promise_pure, thread_safe],
+"
 	Floor = floor(Num);
 ").
-:- pragma foreign_proc("C#", 
-	math__floor(Num::in) = (Floor::out),
-		[will_not_call_mercury, thread_safe],"
+:- pragma foreign_proc("C#", math__floor(Num::in) = (Floor::out),
+		[will_not_call_mercury, promise_pure, thread_safe],
+"
 	Floor = System.Math.Floor(Num);
 ").
 
@@ -322,14 +323,14 @@
 % closest to X.  If X has a fractional component of 0.5,
 % it is rounded up.
 %
-:- pragma foreign_proc("C", 
-	math__round(Num::in) = (Rounded::out),
-		[will_not_call_mercury, thread_safe],"
+:- pragma foreign_proc("C", math__round(Num::in) = (Rounded::out),
+		[will_not_call_mercury, promise_pure, thread_safe],
+"
 	Rounded = floor(Num+0.5);
 ").
-:- pragma foreign_proc("C#", 
-	math__round(Num::in) = (Rounded::out),
-		[will_not_call_mercury, thread_safe],"
+:- pragma foreign_proc("C#", math__round(Num::in) = (Rounded::out),
+		[will_not_call_mercury, promise_pure, thread_safe],
+"
 	// XXX the semantics of System.Math.Round() are not the same as ours.
 	// Unfortunately they are better (round to nearest even number).
 	Rounded = System.Math.Floor(Num+0.5);
@@ -358,7 +359,7 @@
 :- func math__sqrt_2(float) = float.
 
 :- pragma foreign_proc("C", math__sqrt_2(X::in) = (SquareRoot::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	SquareRoot = sqrt(X);
 ").
 :- pragma foreign_proc("C#", math__sqrt_2(X::in) = (SquareRoot::out),
@@ -434,7 +435,7 @@
 :- func math__pow_2(float, float) = float.
 
 :- pragma foreign_proc("C", math__pow_2(X::in, Y::in) = (Res::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Res = pow(X, Y);
 ").
 
@@ -449,11 +450,11 @@
 % power of e.
 %
 :- pragma foreign_proc("C", math__exp(X::in) = (Exp::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	Exp = exp(X);
 ").
 :- pragma foreign_proc("C#", math__exp(X::in) = (Exp::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	Exp = System.Math.Exp(X);
 ").
 
@@ -474,7 +475,7 @@
 :- func math__ln_2(float) = float.
 
 :- pragma foreign_proc("C", math__ln_2(X::in) = (Log::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Log = log(X);
 ").
 :- pragma foreign_proc("C#", math__ln_2(X::in) = (Log::out),
@@ -499,7 +500,7 @@
 :- func math__log10_2(float) = float.
 
 :- pragma foreign_proc("C", math__log10_2(X::in) = (Log10::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Log10 = log10(X);
 ").
 :- pragma foreign_proc("C#", math__log10_2(X::in) = (Log10::out),
@@ -524,7 +525,7 @@
 :- func math__log2_2(float) = float.
 
 :- pragma foreign_proc("C", math__log2_2(X::in) = (Log2::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Log2 = log(X) / ML_FLOAT_LN2;
 ").
 :- pragma foreign_proc("C#", math__log2_2(X::in) = (Log2::out),
@@ -557,7 +558,7 @@
 :- func math__log_2(float, float) = float.
 
 :- pragma foreign_proc("C", math__log_2(B::in, X::in) = (Log::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Log = log(X)/log(B);
 ").
 :- pragma foreign_proc("C#", math__log_2(B::in, X::in) = (Log::out),
@@ -570,11 +571,11 @@
 % math__sin(X) = Sin is true if Sin is the sine of X.
 %
 :- pragma foreign_proc("C", math__sin(X::in) = (Sin::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	Sin = sin(X);
 ").
 :- pragma foreign_proc("C#", math__sin(X::in) = (Sin::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	Sin = System.Math.Sin(X);
 ").
 
@@ -583,11 +584,11 @@
 % math__cos(X) = Sin is true if Cos is the cosine of X.
 %
 :- pragma foreign_proc("C", math__cos(X::in) = (Cos::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	Cos = cos(X);
 ").
 :- pragma foreign_proc("C#", math__cos(X::in) = (Cos::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	Cos = System.Math.Cos(X);
 ").
 
@@ -595,11 +596,11 @@
 % math__tan(X) = Tan is true if Tan is the tangent of X.
 %
 :- pragma foreign_proc("C", math__tan(X::in) = (Tan::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	Tan = tan(X);
 ").
 :- pragma foreign_proc("C#", math__tan(X::in) = (Tan::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	Tan = System.Math.Tan(X);
 ").
 
@@ -625,7 +626,7 @@
 :- func math__asin_2(float) = float.
 
 :- pragma foreign_proc("C", math__asin_2(X::in) = (ASin::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	ASin = asin(X);
 ").
 :- pragma foreign_proc("C#", math__asin_2(X::in) = (ASin::out),
@@ -655,7 +656,7 @@
 :- func math__acos_2(float) = float.
 
 :- pragma foreign_proc("C", math__acos_2(X::in) = (ACos::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	ACos = acos(X);
 ").
 :- pragma foreign_proc("C#", math__acos_2(X::in) = (ACos::out),
@@ -669,11 +670,11 @@
 % tangent of X, where ATan is in the range [-pi/2,pi/2].
 %
 :- pragma foreign_proc("C", math__atan(X::in) = (ATan::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	ATan = atan(X);
 ").
 :- pragma foreign_proc("C#", math__atan(X::in) = (ATan::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	ATan = System.Math.Atan(X);
 ").
 
@@ -682,11 +683,11 @@
 % tangent of Y/X, where ATan is in the range [-pi,pi].
 %
 :- pragma foreign_proc("C", math__atan2(Y::in, X::in) = (ATan2::out), 
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	ATan2 = atan2(Y, X);
 ").
 :- pragma foreign_proc("C#", math__atan2(Y::in, X::in) = (ATan2::out), 
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	ATan2 = System.Math.Atan2(Y, X);
 ").
 
@@ -695,11 +696,11 @@
 % sine of X.
 %
 :- pragma foreign_proc("C", math__sinh(X::in) = (Sinh::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	Sinh = sinh(X);
 ").
 :- pragma foreign_proc("C#", math__sinh(X::in) = (Sinh::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	Sinh = System.Math.Sinh(X);
 ").
 
@@ -708,11 +709,11 @@
 % cosine of X.
 %
 :- pragma foreign_proc("C", math__cosh(X::in) = (Cosh::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	Cosh = cosh(X);
 ").
 :- pragma foreign_proc("C#", math__cosh(X::in) = (Cosh::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	Cosh = System.Math.Cosh(X);
 ").
 
@@ -721,11 +722,11 @@
 % tangent of X.
 %
 :- pragma foreign_proc("C", math__tanh(X::in) = (Tanh::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	Tanh = tanh(X);
 ").
 :- pragma foreign_proc("C#", math__tanh(X::in) = (Tanh::out),
-		[will_not_call_mercury, thread_safe],"
+		[will_not_call_mercury, promise_pure, thread_safe],"
 	Tanh = System.Math.Tanh(X);
 ").
 
Index: library/private_builtin.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/private_builtin.m,v
retrieving revision 1.84
diff -u -r1.84 private_builtin.m
--- library/private_builtin.m	13 Dec 2001 09:06:09 -0000	1.84
+++ library/private_builtin.m	15 Jan 2002 03:59:17 -0000
@@ -161,11 +161,11 @@
 :- mode builtin_strcmp(out, in, in) is det.
 
 :- pragma foreign_proc("C", builtin_strcmp(Res::out, S1::in, S2::in),
-	[will_not_call_mercury, thread_safe],
+	[will_not_call_mercury, promise_pure, thread_safe],
 	"Res = strcmp(S1, S2);").
 
 :- pragma foreign_proc("MC++", builtin_strcmp(Res::out, S1::in, S2::in),
-	[will_not_call_mercury, thread_safe],
+	[will_not_call_mercury, promise_pure, thread_safe],
 "
 	Res = System::String::Compare(S1, S2);
 ").
@@ -734,14 +734,16 @@
 
 :- pragma foreign_proc("C",
 	type_info_from_typeclass_info(TypeClassInfo::in, Index::in,
-		TypeInfo::out), [will_not_call_mercury, thread_safe],
+		TypeInfo::out),
+			[will_not_call_mercury, promise_pure, thread_safe],
 "
 	TypeInfo = MR_typeclass_info_type_info(TypeClassInfo, Index);
 ").
 
 :- pragma foreign_proc("C",
 	unconstrained_type_info_from_typeclass_info(TypeClassInfo::in,
-		Index::in, TypeInfo::out), [will_not_call_mercury, thread_safe],
+		Index::in, TypeInfo::out),
+			[will_not_call_mercury, promise_pure, thread_safe],
 "
 	TypeInfo = MR_typeclass_info_unconstrained_type_info(TypeClassInfo,
 			Index);
@@ -749,7 +751,8 @@
 
 :- pragma foreign_proc("C",
 	superclass_from_typeclass_info(TypeClassInfo0::in, Index::in,
-		TypeClassInfo::out), [will_not_call_mercury, thread_safe],
+		TypeClassInfo::out),
+			[will_not_call_mercury, promise_pure, thread_safe],
 "
 	TypeClassInfo =
 		MR_typeclass_info_superclass_info(TypeClassInfo0, Index);
@@ -758,7 +761,7 @@
 :- pragma foreign_proc("C",
 	instance_constraint_from_typeclass_info(TypeClassInfo0::in,
 		Index::in, TypeClassInfo::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	TypeClassInfo =
 		MR_typeclass_info_arg_typeclass_info(TypeClassInfo0, Index);
@@ -766,14 +769,16 @@
 
 :- pragma foreign_proc("MC++",
 	type_info_from_typeclass_info(TypeClassInfo::in, Index::in,
-		TypeInfo::out), [will_not_call_mercury, thread_safe],
+		TypeInfo::out),
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	TypeInfo = MR_typeclass_info_type_info(TypeClassInfo, Index);
 ").
 
 :- pragma foreign_proc("MC++",
 	unconstrained_type_info_from_typeclass_info(TypeClassInfo::in,
-		Index::in, TypeInfo::out), [will_not_call_mercury, thread_safe],
+		Index::in, TypeInfo::out),
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	TypeInfo = MR_typeclass_info_unconstrained_type_info(TypeClassInfo,
 			Index);
@@ -781,7 +786,8 @@
 
 :- pragma foreign_proc("MC++",
 	superclass_from_typeclass_info(TypeClassInfo0::in, Index::in,
-		TypeClassInfo::out), [will_not_call_mercury, thread_safe],
+		TypeClassInfo::out),
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	TypeClassInfo =
 		MR_typeclass_info_superclass_info(TypeClassInfo0, Index);
@@ -790,7 +796,7 @@
 :- pragma foreign_proc("MC++",
 	instance_constraint_from_typeclass_info(TypeClassInfo0::in,
 		Index::in, TypeClassInfo::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	TypeClassInfo =
 		MR_typeclass_info_arg_typeclass_info(TypeClassInfo0, Index);
@@ -1069,11 +1075,11 @@
 	error("private_builtin__free_heap/1").
 
 :- pragma foreign_proc("C", free_heap(Val::di),
-	[will_not_call_mercury, thread_safe],
+	[will_not_call_mercury, promise_pure, thread_safe],
 	"MR_free_heap((void *) Val);").
 
 :- pragma foreign_proc("MC++", free_heap(_Val::di),
-	[will_not_call_mercury, thread_safe], "
+	[will_not_call_mercury, promise_pure, thread_safe], "
 	mercury::runtime::Errors::SORRY(""foreign code for free_heap/1"");
 ").
 
Index: library/rtti_implementation.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/rtti_implementation.m,v
retrieving revision 1.8
diff -u -r1.8 rtti_implementation.m
--- library/rtti_implementation.m	31 Dec 2001 04:26:46 -0000	1.8
+++ library/rtti_implementation.m	15 Jan 2002 03:59:17 -0000
@@ -124,12 +124,16 @@
 :- type pseudo_type_info ---> pred_type(c_pointer).
 
 :- pragma foreign_proc("C#",
-	get_type_info(_T::unused) = (TypeInfo::out), [], " 
+	get_type_info(_T::unused) = (TypeInfo::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+" 
 	TypeInfo = TypeInfo_for_T;
 ").
 
 :- pragma foreign_proc("C",
-	get_type_info(_T::unused) = (TypeInfo::out), [], "
+	get_type_info(_T::unused) = (TypeInfo::out), 
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	TypeInfo = TypeInfo_for_T;
 ").
 
@@ -327,28 +331,28 @@
 
 :- pragma foreign_proc("MC++",
 	semidet_call_3(Pred::in, X::in, Y::in), 
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	SUCCESS_INDICATOR =
 		mercury::runtime::GenericCall::semidet_call_3(Pred, X, Y);
 ").
 :- pragma foreign_proc("MC++",
 	semidet_call_4(Pred::in, A::in, X::in, Y::in), 
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	SUCCESS_INDICATOR =
 		mercury::runtime::GenericCall::semidet_call_4(Pred, A, X, Y);
 ").
 :- pragma foreign_proc("MC++",
 	semidet_call_5(Pred::in, A::in, B::in, X::in, Y::in), 
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	SUCCESS_INDICATOR =
 		mercury::runtime::GenericCall::semidet_call_5(Pred, A, B, X, Y);
 ").
 :- pragma foreign_proc("MC++",
 	semidet_call_6(Pred::in, A::in, B::in, C::in, X::in, Y::in), 
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	SUCCESS_INDICATOR =
 		mercury::runtime::GenericCall::semidet_call_6(Pred, A, B, C,
@@ -356,7 +360,7 @@
 ").
 :- pragma foreign_proc("MC++",
 	semidet_call_7(Pred::in, A::in, B::in, C::in, D::in, X::in, Y::in), 
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	SUCCESS_INDICATOR =
 		mercury::runtime::GenericCall::semidet_call_7(Pred, A, B, C, D,
@@ -365,7 +369,7 @@
 :- pragma foreign_proc("MC++",
 	semidet_call_8(Pred::in, A::in, B::in, C::in, D::in, E::in,
 		X::in, Y::in), 
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	SUCCESS_INDICATOR =
 		mercury::runtime::GenericCall::semidet_call_8(Pred, A, B, C, D,
@@ -376,32 +380,32 @@
 
 :- pragma foreign_proc("C#",
 	result_call_4(Pred::in, Res::out, X::in, Y::in), 
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	mercury.runtime.GenericCall.result_call_4(Pred, ref Res, X, Y);
 ").
 
 :- pragma foreign_proc("C#",
 	result_call_5(Pred::in, Res::out, A::in, X::in, Y::in), 
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	mercury.runtime.GenericCall.result_call_5(Pred, A, ref Res, X, Y);
 ").
 :- pragma foreign_proc("C#",
 	result_call_6(Pred::in, Res::out, A::in, B::in, X::in, Y::in), 
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	mercury.runtime.GenericCall.result_call_6(Pred, A, B, ref Res, X, Y);
 ").
 :- pragma foreign_proc("C#",
 	result_call_7(Pred::in, Res::out, A::in, B::in, C::in, X::in, Y::in), 
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	mercury.runtime.GenericCall.result_call_7(Pred, A, B, C, ref Res, X, Y);
 ").
 :- pragma foreign_proc("C#",
 	result_call_8(Pred::in, Res::out, A::in, B::in, C::in, D::in, X::in, Y::in), 
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	mercury.runtime.GenericCall.result_call_8(Pred, A, B, C, D,
 		ref Res, X, Y);
@@ -409,7 +413,7 @@
 :- pragma foreign_proc("C#",
 	result_call_9(Pred::in, Res::out, A::in, B::in, C::in, D::in, E::in,
 		X::in, Y::in), 
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	mercury.runtime.GenericCall.result_call_9(Pred, 
 		A, B, C, D, E, ref Res, X, Y);
@@ -1039,7 +1043,8 @@
 ").
 
 :- pragma foreign_proc("C#",
-	get_type_ctor_info(TypeInfo::in) = (TypeCtorInfo::out), [],
+	get_type_ctor_info(TypeInfo::in) = (TypeCtorInfo::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
 "
 	try {
 		TypeCtorInfo = (object[]) TypeInfo[0];
@@ -1049,7 +1054,8 @@
 ").
 
 :- pragma foreign_proc("C",
-	get_type_ctor_info(TypeInfo::in) = (TypeCtorInfo::out), [],
+	get_type_ctor_info(TypeInfo::in) = (TypeCtorInfo::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
 "
 	TypeCtorInfo = (MR_Word) MR_TYPEINFO_GET_TYPE_CTOR_INFO(
 		(MR_TypeInfo) TypeInfo);
@@ -1062,14 +1068,19 @@
 same_pointer_value(X, Y) :- same_pointer_value_untyped(X, Y).
 
 :- pragma foreign_proc("MC++",
-	same_pointer_value_untyped(T1::in, T2::in), [], "
+	same_pointer_value_untyped(T1::in, T2::in),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	SUCCESS_INDICATOR = (T1 == T2);
 ").
 :- pragma foreign_proc("C",
-	same_pointer_value_untyped(T1::in, T2::in), [], "
+	same_pointer_value_untyped(T1::in, T2::in), 
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	SUCCESS_INDICATOR = (T1 == T2);
 ").
 
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -1298,7 +1309,8 @@
 	det_unimplemented("type_info_index").
 
 :- pragma foreign_proc("C#",
-	type_info_index(X::in, TypeInfo::in) = (TypeInfoAtIndex::out), [], "
+	type_info_index(X::in, TypeInfo::in) = (TypeInfoAtIndex::out),
+		[will_not_call_mercury, promise_pure], "
 	TypeInfoAtIndex = (object[]) TypeInfo[X];
 ").
 
@@ -1310,7 +1322,7 @@
 
 :- pragma foreign_proc("C#",
 	update_type_info_index(X::in, NewValue::in, OldTypeInfo::di,
-		NewTypeInfo::uo), [], "
+		NewTypeInfo::uo), [will_not_call_mercury, promise_pure], "
 	OldTypeInfo[X] = NewValue;
 	NewTypeInfo = OldTypeInfo;
 ").
@@ -1338,36 +1350,48 @@
 
 :- func type_ctor_arity(type_ctor_info) = int.
 :- pragma foreign_proc("C#",
-	type_ctor_arity(TypeCtorInfo::in) = (Arity::out), [], "
+	type_ctor_arity(TypeCtorInfo::in) = (Arity::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	Arity = (int) TypeCtorInfo[
 			(int) type_ctor_info_field_nums.type_ctor_arity];
 ").
 :- pragma foreign_proc("C",
-	type_ctor_arity(TypeCtorInfo::in) = (Arity::out), [], "
+	type_ctor_arity(TypeCtorInfo::in) = (Arity::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	MR_TypeCtorInfo tci = (MR_TypeCtorInfo) TypeCtorInfo;
 	Arity = tci->arity;
 ").
 
 :- some [P] func type_ctor_unify_pred(type_ctor_info) = P.
 :- pragma foreign_proc("C#",
-	type_ctor_unify_pred(TypeCtorInfo::in) = (UnifyPred::out), [], "
+	type_ctor_unify_pred(TypeCtorInfo::in) = (UnifyPred::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	UnifyPred = TypeCtorInfo[
 			(int) type_ctor_info_field_nums.type_ctor_unify_pred];
 ").
 :- pragma foreign_proc("C",
-	type_ctor_unify_pred(TypeCtorInfo::in) = (UnifyPred::out), [], "
+	type_ctor_unify_pred(TypeCtorInfo::in) = (UnifyPred::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	MR_TypeCtorInfo tci = (MR_TypeCtorInfo) TypeCtorInfo;
 	UnifyPred = (MR_Integer) tci->unify_pred;
 ").
 
 :- some [P] func type_ctor_compare_pred(type_ctor_info) = P.
 :- pragma foreign_proc("C#",
-	type_ctor_compare_pred(TypeCtorInfo::in) = (UnifyPred::out), [], "
+	type_ctor_compare_pred(TypeCtorInfo::in) = (UnifyPred::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	UnifyPred = TypeCtorInfo[
 			(int) type_ctor_info_field_nums.type_ctor_compare_pred];
 ").
 :- pragma foreign_proc("C",
-	type_ctor_compare_pred(TypeCtorInfo::in) = (UnifyPred::out), [], "
+	type_ctor_compare_pred(TypeCtorInfo::in) = (UnifyPred::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	MR_TypeCtorInfo tci = (MR_TypeCtorInfo) TypeCtorInfo;
 	UnifyPred = (MR_Integer) tci->compare_pred;
 ").
@@ -1376,14 +1400,18 @@
 
 :- func type_ctor_rep(type_ctor_info) = type_ctor_rep.
 :- pragma foreign_proc("C#",
-	type_ctor_rep(TypeCtorInfo::in) = (TypeCtorRep::out), [], "
+	type_ctor_rep(TypeCtorInfo::in) = (TypeCtorRep::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	int rep;
 	rep = (int) TypeCtorInfo[
 		(int) type_ctor_info_field_nums.type_ctor_rep];
 	TypeCtorRep = mercury.runtime.LowLevelData.make_enum(rep);
 ").
 :- pragma foreign_proc("C",
-	type_ctor_rep(TypeCtorInfo::in) = (TypeCtorRep::out), [], "
+	type_ctor_rep(TypeCtorInfo::in) = (TypeCtorRep::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	MR_TypeCtorInfo tci = (MR_TypeCtorInfo) TypeCtorInfo;
 	TypeCtorRep = MR_type_ctor_rep(tci);
 ").
@@ -1392,14 +1420,18 @@
 :- func type_ctor_module_name(type_ctor_info) = string.
 
 :- pragma foreign_proc("C#",
-	type_ctor_module_name(TypeCtorInfo::in) = (Name::out), [], "
+	type_ctor_module_name(TypeCtorInfo::in) = (Name::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	Name = (string)
 		TypeCtorInfo[(int)
 		type_ctor_info_field_nums.type_ctor_module_name];
 ").
 
 :- pragma foreign_proc("C",
-	type_ctor_module_name(TypeCtorInfo::in) = (Name::out), [], "
+	type_ctor_module_name(TypeCtorInfo::in) = (Name::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	MR_TypeCtorInfo tci = (MR_TypeCtorInfo) TypeCtorInfo;
 	Name = (MR_String) tci->type_ctor_module_name;
 ").
@@ -1409,12 +1441,16 @@
 :- func type_ctor_name(type_ctor_info) = string.
 
 :- pragma foreign_proc("C#",
-	type_ctor_name(TypeCtorInfo::in) = (Name::out), [], "
+	type_ctor_name(TypeCtorInfo::in) = (Name::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	Name = (string)
 		TypeCtorInfo[(int) type_ctor_info_field_nums.type_ctor_name];
 ").
 :- pragma foreign_proc("C",
-	type_ctor_name(TypeCtorInfo::in) = (Name::out), [], "
+	type_ctor_name(TypeCtorInfo::in) = (Name::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	MR_TypeCtorInfo tci = (MR_TypeCtorInfo) TypeCtorInfo;
 	Name = (MR_String) tci->type_ctor_name;
 ").
@@ -1423,25 +1459,29 @@
 :- func type_layout(type_ctor_info) = type_layout.
 
 :- pragma foreign_proc("C#",
-	type_layout(TypeCtorInfo::in) = (TypeLayout::out), [], "
+	type_layout(TypeCtorInfo::in) = (TypeLayout::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	TypeLayout = (object[])
 		TypeCtorInfo[(int) type_ctor_info_field_nums.type_layout];
 ").
 :- pragma foreign_proc("C",
-	type_layout(TypeCtorInfo::in) = (TypeLayout::out), [], "
+	type_layout(TypeCtorInfo::in) = (TypeLayout::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
 	MR_TypeCtorInfo tci = (MR_TypeCtorInfo) TypeCtorInfo;
 	TypeLayout = (MR_Word) &(tci->type_layout); 
 ").
 
 :- pragma foreign_proc("C",
 	unsafe_cast(VarIn::in) = (VarOut::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	VarOut = VarIn;
 ").
 :- pragma foreign_proc("C#",
 	unsafe_cast(VarIn::in) = (VarOut::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "
 	VarOut = VarIn;
 ").
Index: library/sparse_bitset.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/sparse_bitset.m,v
retrieving revision 1.11
diff -u -r1.11 sparse_bitset.m
--- library/sparse_bitset.m	25 Sep 2001 09:37:04 -0000	1.11
+++ library/sparse_bitset.m	15 Jan 2002 03:59:17 -0000
@@ -769,7 +769,7 @@
 	% Doing this slows down the compiler by about 1%,
 	% but in a library module it's better to be safe.
 :- pragma foreign_proc("C", make_bitset_elem(A::in, B::in) = (Pair::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "{
 
 #define ML_BITSET_TAG MR_FIRST_UNRESERVED_RAW_TAG
@@ -782,7 +782,7 @@
 
 % XXX this needs to take reserve-tag into account too
 :- pragma foreign_proc("C#", make_bitset_elem(A::in, B::in) = (Pair::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "{
 #if MR_RESERVE_TAG
     #error ""sparse_bitset not implemented for .NET in .rt grades""
Index: library/std_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/std_util.m,v
retrieving revision 1.253
diff -u -r1.253 std_util.m
--- library/std_util.m	9 Jan 2002 06:50:18 -0000	1.253
+++ library/std_util.m	15 Jan 2002 03:59:17 -0000
@@ -906,7 +906,7 @@
 	is det.
 :- pragma foreign_proc("C", 
 		get_registers(HeapPtr::out, SolutionsHeapPtr::out,
-		TrailPtr::out), will_not_call_mercury,
+		TrailPtr::out), [will_not_call_mercury],
 "
 	/* save heap states */
 #ifndef CONSERVATIVE_GC
@@ -926,7 +926,7 @@
 
 :- pragma foreign_proc("MC++", 
 		get_registers(HeapPtr::out, SolutionsHeapPtr::out,
-		TrailPtr::out), will_not_call_mercury,
+		TrailPtr::out), [will_not_call_mercury],
 "
 	/*
 	** For MC++, we always use the MS garbage collector,
@@ -986,7 +986,7 @@
 :- impure pred swap_heap_and_solutions_heap is det.
 :- pragma foreign_proc("C", 
 	swap_heap_and_solutions_heap,
-	will_not_call_mercury,
+	[will_not_call_mercury],
 "
 #ifndef CONSERVATIVE_GC
     {
@@ -1004,7 +1004,7 @@
 ").
 :- pragma foreign_proc("MC++", 
 	swap_heap_and_solutions_heap,
-	will_not_call_mercury,
+	[will_not_call_mercury],
 "
 	/*
 	** For the .NET back-end, we use the system heap, rather
@@ -1054,28 +1054,28 @@
 
 :- pragma foreign_proc("C",
     partial_deep_copy(SolutionsHeapPtr::in, OldVal::in, NewVal::out),
-    [will_not_call_mercury],
+    [will_not_call_mercury, promise_pure],
 "
 	MR_PARTIAL_DEEP_COPY(SolutionsHeapPtr, OldVal, NewVal, TypeInfo_for_T);
 ").
 
 :- pragma foreign_proc("C", 
     partial_deep_copy(SolutionsHeapPtr::in, OldVal::mdi, NewVal::muo),
-    [will_not_call_mercury],
+    [will_not_call_mercury, promise_pure],
 "
 	MR_PARTIAL_DEEP_COPY(SolutionsHeapPtr, OldVal, NewVal, TypeInfo_for_T);
 ").
 
 :- pragma foreign_proc("C",
     partial_deep_copy(SolutionsHeapPtr::in, OldVal::di, NewVal::uo),
-    [will_not_call_mercury],
+    [will_not_call_mercury, promise_pure],
 "
 	MR_PARTIAL_DEEP_COPY(SolutionsHeapPtr, OldVal, NewVal, TypeInfo_for_T);
 ").
 
 :- pragma foreign_proc("MC++",
     partial_deep_copy(_SolutionsHeapPtr::in, OldVal::in, NewVal::out),
-    [will_not_call_mercury],
+    [will_not_call_mercury, promise_pure],
 "
 	/*
 	** For the IL back-end, we don't do heap reclamation on failure,
@@ -1086,13 +1086,13 @@
 ").
 :- pragma foreign_proc("MC++", 
     partial_deep_copy(_SolutionsHeapPtr::in, OldVal::mdi, NewVal::muo),
-    [will_not_call_mercury],
+    [will_not_call_mercury, promise_pure],
 "
 	NewVal = OldVal;
 ").
 :- pragma foreign_proc("MC++",
     partial_deep_copy(_SolutionsHeapPtr::in, OldVal::di, NewVal::uo),
-    [will_not_call_mercury],
+    [will_not_call_mercury, promise_pure],
 "
 	NewVal = OldVal;
 ").
@@ -1106,7 +1106,7 @@
 :- impure pred reset_solutions_heap(heap_ptr::in) is det.
 :- pragma foreign_proc("C", 
     reset_solutions_heap(SolutionsHeapPtr::in),
-    [will_not_call_mercury],
+    [will_not_call_mercury, promise_pure],
 "
 #ifndef CONSERVATIVE_GC
 	MR_sol_hp = (MR_Word *) SolutionsHeapPtr;
@@ -1115,7 +1115,7 @@
 
 :- pragma foreign_proc("MC++", 
 	reset_solutions_heap(_SolutionsHeapPtr::in),
-    [will_not_call_mercury],
+    [will_not_call_mercury, promise_pure],
 "
 	/*
 	** For the IL back-end, we don't have a separate `solutions heap'.
@@ -1159,36 +1159,38 @@
 :- type mutvar(T) ---> mutvar(c_pointer).
 
 :- pragma inline(new_mutvar/2).
-:- pragma foreign_proc("C", new_mutvar(X::in, Ref::out), will_not_call_mercury,
+:- pragma foreign_proc("C", new_mutvar(X::in, Ref::out),
+		[will_not_call_mercury],
 "
 	MR_incr_hp_msg(Ref, 1, MR_PROC_LABEL, ""std_util:mutvar/1"");
 	*(MR_Word *) Ref = X;
 ").
-:- pragma foreign_proc("C", new_mutvar(X::di, Ref::uo), will_not_call_mercury,
+:- pragma foreign_proc("C", new_mutvar(X::di, Ref::uo),
+		[will_not_call_mercury],
 "
 	MR_incr_hp_msg(Ref, 1, MR_PROC_LABEL, ""std_util:mutvar/1"");
 	*(MR_Word *) Ref = X;
 ").
 
 :- pragma inline(get_mutvar/2).
-:- pragma foreign_proc("C", get_mutvar(Ref::in, X::uo), will_not_call_mercury,
+:- pragma foreign_proc("C", get_mutvar(Ref::in, X::uo), [will_not_call_mercury],
 "
 	X = *(MR_Word *) Ref;
 ").
 
 :- pragma inline(set_mutvar/2).
-:- pragma foreign_proc("C", set_mutvar(Ref::in, X::in), will_not_call_mercury, "
+:- pragma foreign_proc("C", set_mutvar(Ref::in, X::in), [will_not_call_mercury], "
 	*(MR_Word *) Ref = X;
 ").
 
 :- pragma foreign_proc("MC++", 
-	new_mutvar(X::in, Ref::out), will_not_call_mercury,
+	new_mutvar(X::in, Ref::out), [will_not_call_mercury],
 "
 	MR_untagged_newobj(Ref, 1);
 	Ref[0] = X;
 ").
 :- pragma foreign_proc("MC++", 
-	new_mutvar(X::di, Ref::uo), will_not_call_mercury,
+	new_mutvar(X::di, Ref::uo), [will_not_call_mercury],
 "
 	MR_untagged_newobj(Ref, 1);
 	Ref[0] = X;
@@ -1196,14 +1198,14 @@
 
 :- pragma inline(get_mutvar/2).
 :- pragma foreign_proc("MC++",
-	get_mutvar(Ref::in, X::uo), will_not_call_mercury,
+	get_mutvar(Ref::in, X::uo), [will_not_call_mercury],
 "
 	X = Ref[0];
 ").
 
 :- pragma inline(set_mutvar/2).
 :- pragma foreign_proc("MC++",
-	set_mutvar(Ref::in, X::in), will_not_call_mercury,
+	set_mutvar(Ref::in, X::in), [will_not_call_mercury],
 "
 	Ref[0] = X;
 ").
@@ -1258,28 +1260,29 @@
 % for them.
 
 :- pragma foreign_proc("C", semidet_succeed, 
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 		"SUCCESS_INDICATOR = TRUE;").
-:- pragma foreign_proc("C", semidet_fail, [will_not_call_mercury, thread_safe],
+:- pragma foreign_proc("C", semidet_fail,
+		[will_not_call_mercury, promise_pure, thread_safe],
 		"SUCCESS_INDICATOR = FALSE;").
 :- pragma foreign_proc("C", cc_multi_equal(X::in, Y::out),
-               [will_not_call_mercury, thread_safe],
+               [will_not_call_mercury, promise_pure, thread_safe],
 		"Y = X;").
 :- pragma foreign_proc("C", cc_multi_equal(X::di, Y::uo),
-               [will_not_call_mercury, thread_safe],
+               [will_not_call_mercury, promise_pure, thread_safe],
 		"Y = X;").
 
 :- pragma foreign_proc("MC++", semidet_succeed, 
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 		"SUCCESS_INDICATOR = TRUE;").
 :- pragma foreign_proc("MC++", semidet_fail, 
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 		"SUCCESS_INDICATOR = FALSE;").
 :- pragma foreign_proc("MC++", cc_multi_equal(X::in, Y::out),
-               [will_not_call_mercury, thread_safe],
+               [will_not_call_mercury, promise_pure, thread_safe],
 		"Y = X;").
 :- pragma foreign_proc("MC++", cc_multi_equal(X::di, Y::uo),
-               [will_not_call_mercury, thread_safe],
+               [will_not_call_mercury, promise_pure, thread_safe],
 		"Y = X;").
 
 
@@ -1709,7 +1712,7 @@
 :- type type_ctor_desc ---> type_ctor_desc(c_pointer).
 
 :- pragma foreign_proc("C", type_of(_Value::unused) = (TypeInfo::out),
-	will_not_call_mercury, "
+	[will_not_call_mercury, promise_pure], "
 {
 	TypeInfo = TypeInfo_for_T;
 
@@ -1730,7 +1733,7 @@
 ").
 
 :- pragma foreign_proc("C#", type_of(_Value::unused) = (TypeInfo::out),
-	will_not_call_mercury, "
+	[will_not_call_mercury, promise_pure], "
 {
 	TypeInfo = TypeInfo_for_T;
 }
@@ -1738,12 +1741,14 @@
 
 
 :- pragma foreign_proc("C", 
-	has_type(_Arg::unused, TypeInfo::in), will_not_call_mercury, "
+	has_type(_Arg::unused, TypeInfo::in),
+	[will_not_call_mercury, promise_pure], "
 	TypeInfo_for_T = TypeInfo;
 ").
 
 :- pragma foreign_proc("C#", 
-	has_type(_Arg::unused, TypeInfo::in), will_not_call_mercury, "
+	has_type(_Arg::unused, TypeInfo::in),
+	[will_not_call_mercury, promise_pure], "
 	TypeInfo_for_T = TypeInfo;
 ").
 
@@ -1839,7 +1844,7 @@
 	).
 
 :- pragma foreign_proc("C", type_ctor(TypeInfo::in) = (TypeCtor::out),
-	will_not_call_mercury, "
+	[will_not_call_mercury, promise_pure], "
 {
 	MR_TypeCtorInfo type_ctor_info;
 	MR_TypeInfo	type_info;
@@ -1855,7 +1860,7 @@
 ").
 
 :- pragma foreign_proc("C#", type_ctor(_TypeInfo::in) = (_TypeCtor::out),
-	will_not_call_mercury, "
+	[will_not_call_mercury, promise_pure], "
 {
 	mercury.runtime.Errors.SORRY(""foreign code for type_ctor"");
 	_TypeCtor = null;
@@ -1941,7 +1946,8 @@
 ").
 
 :- pragma foreign_proc("C", type_ctor_and_args(TypeDesc::in,
-		TypeCtorDesc::out, ArgTypes::out), will_not_call_mercury, "
+		TypeCtorDesc::out, ArgTypes::out),
+		[will_not_call_mercury, promise_pure], "
 {
 	MR_TypeCtorDesc type_ctor_desc;
 	MR_TypeInfo	type_info;
@@ -1975,7 +1981,7 @@
 
 :- pragma foreign_proc("C", 
 	make_type(TypeCtorDesc::in, ArgTypes::in) = (TypeDesc::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 {
 	MR_TypeCtorDesc type_ctor_desc;
 	MR_TypeCtorInfo type_ctor_info;
@@ -2012,7 +2018,7 @@
 
 :- pragma foreign_proc("C#", 
 	make_type(_TypeCtorDesc::in, _ArgTypes::in) = (_TypeDesc::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 {
 	mercury.runtime.Errors.SORRY(""make_type"");
 	// XXX this is required to keep the C# compiler quiet
@@ -2029,7 +2035,7 @@
 
 :- pragma foreign_proc("C", 
 	make_type(TypeCtorDesc::out, ArgTypes::out) = (TypeDesc::in),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 {
 	MR_TypeCtorDesc type_ctor_desc;
 	MR_TypeInfo	type_info;
@@ -2046,7 +2052,7 @@
 
 :- pragma foreign_proc("C", type_ctor_name_and_arity(TypeCtorDesc::in,
 		TypeCtorModuleName::out, TypeCtorName::out, TypeCtorArity::out),
-        will_not_call_mercury, "
+        [will_not_call_mercury, promise_pure], "
 {
 	MR_TypeCtorDesc type_ctor_desc;
 
@@ -2079,7 +2085,7 @@
 ").
 
 :- pragma foreign_proc("C", num_functors(TypeInfo::in) = (Functors::out),
-	will_not_call_mercury, "
+	[will_not_call_mercury, promise_pure], "
 {
 	MR_save_transient_registers();
 	Functors = ML_get_num_functors((MR_TypeInfo) TypeInfo);
@@ -2089,7 +2095,7 @@
 
 :- pragma foreign_proc("C", get_functor(TypeDesc::in, FunctorNumber::in,
         FunctorName::out, Arity::out, TypeInfoList::out),
-    will_not_call_mercury, "
+    [will_not_call_mercury, promise_pure], "
 {
     MR_TypeInfo         type_info;
     int                 arity;
@@ -2151,11 +2157,13 @@
 :- pred null(string).
 :- mode null(in) is semidet.
 
-:- pragma foreign_proc("C", null(S::in), will_not_call_mercury, "
+:- pragma foreign_proc("C", null(S::in),
+	[will_not_call_mercury, promise_pure], "
     SUCCESS_INDICATOR = (S == NULL);
 ").
 
-:- pragma foreign_proc("MC++", null(S::in), will_not_call_mercury, "
+:- pragma foreign_proc("MC++", null(S::in),
+	[will_not_call_mercury, promise_pure], "
     SUCCESS_INDICATOR = (S == NULL);
 ").
 
@@ -2164,7 +2172,7 @@
 
 :- pragma foreign_proc("C", get_functor_2(TypeDesc::in, FunctorNumber::in,
         FunctorName::out, Arity::out, TypeInfoList::out, ArgNameList::out),
-    will_not_call_mercury, "
+    [will_not_call_mercury, promise_pure], "
 {
     MR_TypeInfo         type_info;
     int                 arity;
@@ -2219,14 +2227,14 @@
 
 :- pragma foreign_proc("MC++", get_functor_2(_TypeDesc::in, _FunctorNumber::in,
         _FunctorName::out, _Arity::out, _TypeInfoList::out, _ArgNameList::out),
-    will_not_call_mercury, "
+    [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for get_functor_2"");
 	SUCCESS_INDICATOR = FALSE;
 ").
 
 :- pragma foreign_proc("C", 
 	get_functor_ordinal(TypeDesc::in, FunctorNumber::in,
-		Ordinal::out), will_not_call_mercury, "
+		Ordinal::out), [will_not_call_mercury, promise_pure], "
 {
     MR_TypeInfo         type_info;
     ML_Construct_Info   construct_info;
@@ -2281,7 +2289,7 @@
 
 :- pragma foreign_proc("C", 
 	construct(TypeDesc::in, FunctorNumber::in, ArgList::in) = (Term::out),
-	will_not_call_mercury, "
+	[will_not_call_mercury, promise_pure], "
 {
     MR_TypeInfo         type_info;
     MR_TypeCtorInfo     type_ctor_info;
@@ -2488,7 +2496,7 @@
 
 :- pragma foreign_proc("C#", 
 	make_type(_TypeCtorDesc::out, _ArgTypes::out) = (_TypeDesc::in),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 {
 	mercury.runtime.Errors.SORRY(""foreign code for make_type"");
 }
@@ -2502,7 +2510,7 @@
 
 
 :- pragma foreign_proc("C#", num_functors(_TypeInfo::in) = (Functors::out),
-	will_not_call_mercury, "
+	[will_not_call_mercury, promise_pure], "
 {
 	mercury.runtime.Errors.SORRY(""foreign code for num_functors"");
 	// XXX keep the C# compiler quiet
@@ -2512,7 +2520,7 @@
 
 :- pragma foreign_proc("MC++", get_functor(_TypeDesc::in, _FunctorNumber::in,
         _FunctorName::out, _Arity::out, _TypeInfoList::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 {
 	mercury::runtime::Errors::SORRY(""foreign code for get_functor"");
 }
@@ -2520,7 +2528,7 @@
 
 :- pragma foreign_proc("MC++", 
 	get_functor_ordinal(_TypeDesc::in, _FunctorNumber::in,
-		_Ordinal::out), will_not_call_mercury, "
+		_Ordinal::out), [will_not_call_mercury, promise_pure], "
 {
 	mercury::runtime::Errors::SORRY(""foreign code for get_functor_ordinal"");
 }
@@ -2528,7 +2536,8 @@
 
 :- pragma foreign_proc("C#", 
 	construct(_TypeDesc::in, _FunctorNumber::in,
-		_ArgList::in) = (_Term::out), will_not_call_mercury, "
+		_ArgList::in) = (_Term::out),
+	[will_not_call_mercury, promise_pure], "
 {
 	mercury.runtime.Errors.SORRY(""foreign code for construct"");
 	_Term = null;
@@ -2546,7 +2555,7 @@
 
 :- pragma foreign_proc("C", 
 	construct_tuple_2(Args::in, ArgTypes::in, Arity::in) = (Term::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 {
 	MR_TypeInfo type_info;
 	MR_Word new_data;
@@ -2587,7 +2596,7 @@
 
 :- pragma foreign_proc("C#", 
 	construct_tuple_2(_Args::in, _ArgTypes::in, _Arity::in) = (_Term::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 {
 	mercury.runtime.Errors.SORRY(""construct_tuple_2"");
 	_Term = null;
@@ -3115,7 +3124,7 @@
 
 :- pragma foreign_proc("C",
 	functor(Term::in, Functor::out, Arity::out),
-	[will_not_call_mercury], "
+	[will_not_call_mercury, promise_pure], "
 {
 #define	PREDNAME			""functor/3""
 #define	TYPEINFO_ARG			TypeInfo_for_T
@@ -3132,7 +3141,7 @@
 
 :- pragma foreign_proc("C",
 	functor_cc(Term::in, Functor::out, Arity::out),
-	will_not_call_mercury, "
+	[will_not_call_mercury, promise_pure], "
 {
 #define	PREDNAME			""functor_cc/3""
 #define	ALLOW_NONCANONICAL
@@ -3156,7 +3165,7 @@
 
 :- pragma foreign_proc("C",
 	arg(Term::in, ArgumentIndex::in) = (Argument::out),
-        [will_not_call_mercury], "
+        [will_not_call_mercury, promise_pure], "
 {
 #define	PREDNAME 		""arg/2""
 #define	NONCANON_HANDLING	MR_ABORT_ON_NONCANONICAL
@@ -3177,7 +3186,7 @@
 
 :- pragma foreign_proc("C",
 	arg_cc(Term::in, ArgumentIndex::in, Argument::out),
-        [will_not_call_mercury], "
+        [will_not_call_mercury, promise_pure], "
 {
 #define	PREDNAME 		""arg/2""
 #define	NONCANON_HANDLING	MR_ALLOW_NONCANONICAL
@@ -3198,7 +3207,7 @@
 
 :- pragma foreign_proc("C",
 	argument(Term::in, ArgumentIndex::in) = (ArgumentUniv::out),
-        [will_not_call_mercury], "
+        [will_not_call_mercury, promise_pure], "
 {
 #define	PREDNAME 		""argument/2""
 #define	NONCANON_HANDLING	MR_FAIL_ON_NONCANONICAL
@@ -3217,7 +3226,7 @@
 
 :- pragma foreign_proc("C",
 	argument_cc(Term::in, ArgumentIndex::in, ArgumentUniv::out),
-        [will_not_call_mercury], "
+        [will_not_call_mercury, promise_pure], "
 {
 #define	PREDNAME 		""argument_cc/3""
 #define	NONCANON_HANDLING	MR_ALLOW_NONCANONICAL
@@ -3236,7 +3245,7 @@
 
 :- pragma foreign_proc("C",
 	named_argument(Term::in, ArgumentName::in) = (ArgumentUniv::out),
-	[will_not_call_mercury], "
+	[will_not_call_mercury, promise_pure], "
 {
 #define	PREDNAME 		""named_argument/2""
 #define	NONCANON_HANDLING	MR_FAIL_ON_NONCANONICAL
@@ -3257,7 +3266,7 @@
 
 :- pragma foreign_proc("C",
 	named_argument_cc(Term::in, ArgumentName::in, ArgumentUniv::out),
-	[will_not_call_mercury], "
+	[will_not_call_mercury, promise_pure], "
 {
 #define	PREDNAME 		""named_argument_cc/3""
 #define	NONCANON_HANDLING	MR_ALLOW_NONCANONICAL
@@ -3278,7 +3287,7 @@
 
 :- pragma foreign_proc("C", 
 	deconstruct(Term::in, Functor::out, Arity::out, Arguments::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 #define	PREDNAME		""deconstruct/4""
 #define	EXPAND_INFO_TYPE	MR_Expand_Functor_Args_Info
@@ -3301,7 +3310,7 @@
 
 :- pragma foreign_proc("C", 
 	deconstruct_cc(Term::in, Functor::out, Arity::out, Arguments::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 #define	PREDNAME		""deconstruct_cc/4""
 #define	EXPAND_INFO_TYPE	MR_Expand_Functor_Args_Info
@@ -3328,7 +3337,7 @@
 :- pragma foreign_proc("C", 
 	limited_deconstruct(Term::in, MaxArity::in, Functor::out,
 		Arity::out, Arguments::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 " {
 #define	PREDNAME		""limited_deconstruct/5""
 #define	EXPAND_INFO_TYPE	MR_Expand_Functor_Args_Limit_Info
@@ -3354,7 +3363,7 @@
 :- pragma foreign_proc("C", 
 	limited_deconstruct_cc(Term::in, MaxArity::in, Functor::out,
 		Arity::out, Arguments::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 " {
 #define	PREDNAME		""limited_deconstruct_cc/5""
 #define	EXPAND_INFO_TYPE	MR_Expand_Functor_Args_Limit_Info
@@ -3380,7 +3389,7 @@
 }").
 
 :- pragma foreign_proc("MC++", functor(_Term::in, _Functor::out, _Arity::out),
-	[will_not_call_mercury], "
+	[will_not_call_mercury, promise_pure], "
 {
 	mercury::runtime::Errors::SORRY(""foreign code for functor"");
 }").
@@ -3392,7 +3401,7 @@
 
 :- pragma foreign_proc("C#", 
 	arg(_Term::in, _ArgumentIndex::in) = (_Argument::out),
-        [will_not_call_mercury], "
+        [will_not_call_mercury, promise_pure], "
 {
 	mercury.runtime.Errors.SORRY(""foreign code for arg"");
 	// XXX this is required to keep the C# compiler quiet
@@ -3410,7 +3419,7 @@
 
 :- pragma foreign_proc("C#",
 	argument(_Term::in, _ArgumentIndex::in) = (_ArgumentUniv::out),
-        [will_not_call_mercury], "
+        [will_not_call_mercury, promise_pure], "
 {
 	mercury.runtime.Errors.SORRY(""foreign code for argument"");
 	// XXX this is required to keep the C# compiler quiet
@@ -3428,7 +3437,7 @@
 
 :- pragma foreign_proc("C#",
         named_argument(_Term::in, _ArgumentName::in) = (_ArgumentUniv::out),
-        [will_not_call_mercury], "
+        [will_not_call_mercury, promise_pure], "
 {
 	mercury.runtime.Errors.SORRY(""foreign code for named_argument"");
 	// XXX this is required to keep the C# compiler quiet
@@ -3500,7 +3509,7 @@
 :- pragma foreign_proc("MC++", 
 	limited_deconstruct(_Term::in, _MaxArity::in, _Functor::out,
 	_Arity::out, _Arguments::out),
-	[will_not_call_mercury], "
+	[will_not_call_mercury, promise_pure], "
 {
 	mercury::runtime::Errors::SORRY(""foreign code for limited_deconstruct"");
 	SUCCESS_INDICATOR = FALSE;
@@ -3541,7 +3550,7 @@
 
 :- pragma foreign_proc("C", 
 	get_notag_functor_info(Univ::in, ExpUniv::out),
-	will_not_call_mercury, "
+	[will_not_call_mercury, promise_pure], "
 {
     MR_TypeInfo         type_info;
     MR_TypeInfo         exp_type_info;
@@ -3579,7 +3588,7 @@
 
 :- pragma foreign_proc("MC++", 
 	get_notag_functor_info(_Univ::in, _ExpUniv::out),
-	will_not_call_mercury, "
+	[will_not_call_mercury, promise_pure], "
 {
 	mercury::runtime::Errors::SORRY(""foreign code for get_notag_functor_info"");
 }").
@@ -3592,7 +3601,7 @@
 
 :- pragma foreign_proc("C",
 	get_equiv_functor_info(Univ::in, ExpUniv::out),
-    will_not_call_mercury, "
+    [will_not_call_mercury, promise_pure], "
 {
     MR_TypeInfo     type_info;
     MR_TypeInfo     exp_type_info;
@@ -3625,7 +3634,7 @@
 
 :- pragma foreign_proc("MC++",
 	get_equiv_functor_info(_Univ::in, _ExpUniv::out),
-    will_not_call_mercury, "
+    [will_not_call_mercury, promise_pure], "
 {
 	mercury::runtime::Errors::SORRY(""foreign code for get_equiv_functor_info"");
 }").
@@ -3636,7 +3645,7 @@
 
 :- pragma foreign_proc("C",
 	get_enum_functor_info(Univ::in, Enum::out),
-	will_not_call_mercury, "
+	[will_not_call_mercury, promise_pure], "
 {
     MR_TypeInfo     type_info;
     MR_TypeCtorInfo type_ctor_info;
@@ -3659,7 +3668,7 @@
 
 :- pragma foreign_proc("MC++",
 	get_enum_functor_info(_Univ::in, _Enum::out),
-	will_not_call_mercury, "
+	[will_not_call_mercury, promise_pure], "
 {
 	mercury::runtime::Errors::SORRY(""foreign code for get_enum_functor_info"");
 }").
@@ -3675,7 +3684,7 @@
     list(univ)::out) is semidet.
 
 :- pragma foreign_proc("C", get_du_functor_info(Univ::in, Where::out,
-    Ptag::out, Sectag::out, Args::out), will_not_call_mercury, "
+    Ptag::out, Sectag::out, Args::out), [will_not_call_mercury, promise_pure], "
 {
     MR_TypeInfo             type_info;
     MR_TypeCtorInfo         type_ctor_info;
@@ -3761,7 +3770,8 @@
 }").
 
 :- pragma foreign_proc("MC++", get_du_functor_info(_Univ::in, _Where::out,
-    _Ptag::out, _Sectag::out, _Args::out), will_not_call_mercury, "
+    _Ptag::out, _Sectag::out, _Args::out),
+    	[will_not_call_mercury, promise_pure], "
 {
 	mercury::runtime::Errors::SORRY(""foreign code for get_du_functor_info"");
 }").
Index: library/store.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/store.m,v
retrieving revision 1.29
diff -u -r1.29 store.m
--- library/store.m	9 Jan 2002 06:41:33 -0000	1.29
+++ library/store.m	15 Jan 2002 03:59:17 -0000
@@ -250,7 +250,8 @@
 :- pred store__do_init(store(some_store_type)).
 :- mode store__do_init(uo) is det.
 
-:- pragma foreign_proc("C", store__do_init(_S0::uo), will_not_call_mercury, "").
+:- pragma foreign_proc("C", store__do_init(_S0::uo),
+	[will_not_call_mercury, promise_pure], "").
 
 /* 
 Note -- the syntax for the operations on stores
@@ -270,7 +271,7 @@
 */
 
 :- pragma foreign_proc("C", new_mutvar(Val::in, Mutvar::out, S0::di, S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "
 	MR_incr_hp_msg(Mutvar, 1, MR_PROC_LABEL, ""store:mutvar/2"");
 	* (MR_Word *) Mutvar = Val;
@@ -278,14 +279,14 @@
 ").
 
 :- pragma foreign_proc("C", get_mutvar(Mutvar::in, Val::out, S0::di, S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "
 	Val = * (MR_Word *) Mutvar;
 	S = S0;
 ").
 
 :- pragma foreign_proc("C", set_mutvar(Mutvar::in, Val::in, S0::di, S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "
 	* (MR_Word *) Mutvar = Val;
 	S = S0;
@@ -296,7 +297,7 @@
 :- mode store__unsafe_new_uninitialized_mutvar(out, di, uo) is det.
 
 :- pragma foreign_proc("C", unsafe_new_uninitialized_mutvar(Mutvar::out, S0::di, S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "
 	MR_incr_hp_msg(Mutvar, 1, MR_PROC_LABEL, ""store:mutvar/2"");
 	S = S0;
@@ -310,7 +311,7 @@
 %-----------------------------------------------------------------------------%
 
 :- pragma foreign_proc("C", new_ref(Val::di, Ref::out, S0::di, S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "
 	MR_incr_hp_msg(Ref, 1, MR_PROC_LABEL, ""store:ref/2"");
 	* (MR_Word *) Ref = Val;
@@ -328,7 +329,7 @@
 :- pred store__unsafe_ref_value(generic_ref(T, S), T, S, S) <= store(S).
 :- mode store__unsafe_ref_value(in, uo, di, uo) is det.
 :- pragma foreign_proc("C", unsafe_ref_value(Ref::in, Val::uo, S0::di, S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "
 	Val = * (MR_Word *) Ref;
 	S = S0;
@@ -348,7 +349,7 @@
 
 :- pragma foreign_proc("C", 
 	arg_ref(Ref::in, ArgNum::in, ArgRef::out, S0::di, S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "{
 	MR_TypeInfo	type_info;
 	MR_TypeInfo	arg_type_info;
@@ -381,7 +382,7 @@
 
 :- pragma foreign_proc("C", 
 	new_arg_ref(Val::di, ArgNum::in, ArgRef::out, S0::di, S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "{
 	MR_TypeInfo	type_info;
 	MR_TypeInfo	arg_type_info;
@@ -427,7 +428,7 @@
 
 :- pragma foreign_proc("C", 
 	set_ref(Ref::in, ValRef::in, S0::di, S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "
 	* (MR_Word *) Ref = * (MR_Word *) ValRef;
 	S = S0;
@@ -435,7 +436,7 @@
 
 :- pragma foreign_proc("C",	
 	set_ref_value(Ref::in, Val::di, S0::di, S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "
 	* (MR_Word *) Ref = Val;
 	S = S0;
@@ -443,7 +444,7 @@
 
 :- pragma foreign_proc("C",
 	extract_ref_value(_S::di, Ref::in, Val::out),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "
 	Val = * (MR_Word *) Ref;
 ").
@@ -452,7 +453,7 @@
 
 :- pragma foreign_proc("C",
 	unsafe_arg_ref(Ref::in, Arg::in, ArgRef::out, S0::di, S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "{
 	/* unsafe - does not check type & arity, won't handle no_tag types */
 	MR_Word *Ptr = (MR_Word *) MR_strip_tag((MR_Word) Ref);
@@ -461,7 +462,8 @@
 }").
 
 :- pragma foreign_proc("C", unsafe_new_arg_ref(Val::di, Arg::in, ArgRef::out,
-				S0::di, S::uo), will_not_call_mercury,
+				S0::di, S::uo),
+		[will_not_call_mercury, promise_pure],
 "{
 	/* unsafe - does not check type & arity, won't handle no_tag types */
 	MR_Word *Ptr = (MR_Word *) MR_strip_tag((MR_Word) Val);
@@ -472,89 +474,90 @@
 %-----------------------------------------------------------------------------%
 
 :- pragma foreign_proc("MC++", store__do_init(_S0::uo),
-	will_not_call_mercury, "").
+	[will_not_call_mercury, promise_pure], "").
 
 :- pragma foreign_proc("MC++", new_mutvar(_Val::in, _Mutvar::out,
-		_S0::di, _S::uo), will_not_call_mercury,
+		_S0::di, _S::uo), [will_not_call_mercury, promise_pure],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++", get_mutvar(_Mutvar::in, _Val::out,
-		_S0::di, _S::uo), will_not_call_mercury,
+		_S0::di, _S::uo), [will_not_call_mercury, promise_pure],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++", set_mutvar(_Mutvar::in, _Val::in,
-		_S0::di, _S::uo), will_not_call_mercury,
+		_S0::di, _S::uo), [will_not_call_mercury, promise_pure],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++", unsafe_new_uninitialized_mutvar(
-		_Mutvar::out, _S0::di, _S::uo), will_not_call_mercury,
+		_Mutvar::out, _S0::di, _S::uo),
+	[will_not_call_mercury, promise_pure],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++", new_ref(_Val::di, _Ref::out, _S0::di, _S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++", unsafe_ref_value(_Ref::in, _Val::uo,
-		_S0::di, _S::uo), will_not_call_mercury,
+		_S0::di, _S::uo), [will_not_call_mercury, promise_pure],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++", 
 	arg_ref(_Ref::in, _ArgNum::in, _ArgRef::out, _S0::di, _S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
 
 :- pragma foreign_proc("MC++", 
 	new_arg_ref(_Val::di, _ArgNum::in, _ArgRef::out, _S0::di, _S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
 
 :- pragma foreign_proc("MC++", 
 	set_ref(_Ref::in, _ValRef::in, _S0::di, _S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",	
 	set_ref_value(_Ref::in, _Val::di, _S0::di, _S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	extract_ref_value(_S::di, _Ref::in, _Val::out),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	unsafe_arg_ref(_Ref::in, _Arg::in, _ArgRef::out, _S0::di, _S::uo),
-		will_not_call_mercury,
+		[will_not_call_mercury, promise_pure],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
 
 :- pragma foreign_proc("MC++",
 	unsafe_new_arg_ref(_Val::di, _Arg::in, _ArgRef::out,
-			_S0::di, _S::uo), will_not_call_mercury,
+			_S0::di, _S::uo), [will_not_call_mercury, promise_pure],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
Index: library/string.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/string.m,v
retrieving revision 1.164
diff -u -r1.164 string.m
--- library/string.m	26 Oct 2001 07:55:47 -0000	1.164
+++ library/string.m	15 Jan 2002 03:59:17 -0000
@@ -697,7 +697,7 @@
 */
 
 :- pragma foreign_proc("C", string__to_char_list(Str::in, CharList::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_ConstString p = Str + strlen(Str);
 	CharList = MR_list_empty_msg(MR_PROC_LABEL);
 	while (p > Str) {
@@ -708,7 +708,7 @@
 }").
 
 :- pragma foreign_proc("C", string__to_char_list(Str::out, CharList::in),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 		/* mode (out, in) is det */
 	MR_Word char_list_ptr;
 	size_t size;
@@ -751,7 +751,7 @@
 % it improves the overall speed of parsing by about 7%.
 %
 :- pragma foreign_proc("C", string__from_rev_char_list(Chars::in, Str::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 {
 	MR_Word list_ptr;
 	MR_Word size, len;
@@ -790,7 +790,7 @@
 }").
 
 :- pragma foreign_proc("MC++", string__to_char_list(Str::in, CharList::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
         MR_Integer length, i; 
         MR_Word tmp;
         MR_Word prev;
@@ -807,7 +807,7 @@
 }").
 
 :- pragma foreign_proc("MC++", string__to_char_list(Str::out, CharList::in),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
         System::Text::StringBuilder *tmp;
 	MR_Char c;
        
@@ -950,7 +950,7 @@
 	% Implementation of string__append_list that uses C as this
 	% minimises the amount of garbage created.
 :- pragma foreign_proc("C", string__append_list(Strs::in) = (Str::uo),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_Word	list = Strs;
 	MR_Word	tmp;
 	size_t	len;
@@ -981,7 +981,7 @@
 	% Implementation of string__join_list that uses C as this
 	% minimises the amount of garbage created.
 :- pragma foreign_proc("C", string__join_list(Sep::in, Strs::in) = (Str::uo),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_Word	list = Strs;
 	MR_Word	tmp;
 	size_t	len = 0;
@@ -1027,7 +1027,7 @@
 
 :- pragma foreign_proc("C#",
 		string__append_list(Strs::in) = (Str::uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 {
         System.Text.StringBuilder tmp = new System.Text.StringBuilder();
 
@@ -1048,7 +1048,7 @@
 
 :- pragma foreign_proc("C#",
 		string__join_list(Sep::in, Strs::in) = (Str::uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 {	
 	System.Text.StringBuilder tmpStr = new System.Text.StringBuilder();
 
@@ -1095,7 +1095,8 @@
 
 :- pragma foreign_proc("C", 
 	string__sub_string_search(WholeString::in, SubString::in,
-			Index::out) , [will_not_call_mercury, thread_safe],
+			Index::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
 "{
 	char *match;
 	match = strstr(WholeString, SubString);
@@ -1109,7 +1110,8 @@
 
 :- pragma foreign_proc("MC++", 
 	string__sub_string_search(WholeString::in, SubString::in,
-			Index::out) , [will_not_call_mercury, thread_safe],
+			Index::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
 "{
 	Index = WholeString->IndexOf(SubString);
 }").
@@ -1477,11 +1479,11 @@
 :- pred using_sprintf is semidet.
 
 :- pragma foreign_proc("C", using_sprintf,
-	[will_not_call_mercury, thread_safe], "
+	[will_not_call_mercury, promise_pure, thread_safe], "
 	SUCCESS_INDICATOR = TRUE;
 ").
 :- pragma foreign_proc("MC++", using_sprintf,
-	[will_not_call_mercury, thread_safe], "
+	[will_not_call_mercury, promise_pure, thread_safe], "
 	SUCCESS_INDICATOR = FALSE;
 ").
 		
@@ -1548,14 +1550,14 @@
 :- func int_length_modifer = string.
 :- pragma foreign_proc("C", 
 	int_length_modifer = (LengthModifier::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_make_aligned_string(LengthModifier,
 		(MR_String) (MR_Word) MR_INTEGER_LENGTH_MODIFIER);
 }").
 
 :- pragma foreign_proc("C#", 
 	int_length_modifer = (LengthModifier::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	LengthModifier = """";
 }").
 
@@ -1566,14 +1568,14 @@
 :- func format_float(string, float) = string.
 :- pragma foreign_proc("C",
 	format_float(FormatStr::in, Val::in) = (Str::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_save_transient_hp();
 	Str = MR_make_string(MR_PROC_LABEL, FormatStr, (double) Val);
 	MR_restore_transient_hp();
 }").
 :- pragma foreign_proc("C#",
 	format_float(FormatStr::in, Val::in) = (Str::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	Str = System.String.Format(FormatStr, Val);
 }").
 
@@ -1583,14 +1585,14 @@
 :- func format_int(string, int) = string.
 :- pragma foreign_proc("C",
 	format_int(FormatStr::in, Val::in) = (Str::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_save_transient_hp();
 	Str = MR_make_string(MR_PROC_LABEL, FormatStr, Val);
 	MR_restore_transient_hp();
 }").
 :- pragma foreign_proc("C#",
 	format_int(FormatStr::in, Val::in) = (Str::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	Str = System.String.Format(FormatStr, Val);
 }").
 
@@ -1600,12 +1602,12 @@
 :- func format_string(string, string) = string.
 :- pragma foreign_proc("C", 
 	format_string(FormatStr::in, Val::in) = (Str::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	Str = MR_make_string(MR_PROC_LABEL, FormatStr, Val);
 }").
 :- pragma foreign_proc("C#", 
 	format_string(FormatStr::in, Val::in) = (Str::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	Str = System.String.Format(FormatStr, Val);
 }").
 
@@ -1615,14 +1617,14 @@
 :- func format_char(string, char) = string.
 :- pragma foreign_proc("C", 
 	format_char(FormatStr::in, Val::in) = (Str::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_save_transient_hp();
 	Str = MR_make_string(MR_PROC_LABEL, FormatStr, Val);
 	MR_restore_transient_hp();
 }").
 :- pragma foreign_proc("C#", 
 	format_char(FormatStr::in, Val::in) = (Str::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	Str = System.String.Format(FormatStr, Val);
 }").
 
@@ -1643,7 +1645,7 @@
 
 :- pragma foreign_proc("C",
 	string__float_to_string(FloatVal::in, FloatString::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	char buf[500];
 	sprintf(buf, ""%#.15g"", FloatVal);
 	MR_allocate_aligned_string_msg(FloatString, strlen(buf), MR_PROC_LABEL);
@@ -1652,7 +1654,7 @@
 
 :- pragma foreign_proc("MC++",
 	string__float_to_string(FloatVal::in, FloatString::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	FloatString = System::Convert::ToString(FloatVal);
 }").
 
@@ -1663,7 +1665,7 @@
 
 :- pragma foreign_proc("C",
 	string__float_to_f_string(FloatVal::in, FloatString::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	char buf[500];
 	sprintf(buf, ""%.15f"", FloatVal);
 	MR_allocate_aligned_string_msg(FloatString, strlen(buf), MR_PROC_LABEL);
@@ -1672,7 +1674,7 @@
 
 :- pragma foreign_proc("C",
 	string__to_float(FloatString::in, FloatVal::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	/* use a temporary, since we can't don't know whether FloatVal
 	   is a double or float */
 	double tmp;
@@ -1683,13 +1685,13 @@
 
 :- pragma foreign_proc("MC++",
 	string__float_to_f_string(FloatVal::in, FloatString::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	FloatString = System::Convert::ToString(FloatVal);
 }").
 
 :- pragma foreign_proc("MC++",
 	string__to_float(FloatString::in, FloatVal::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	SUCCESS_INDICATOR = TRUE;
 	try {
 	    FloatVal = System::Convert::ToDouble(FloatString);
@@ -1708,7 +1710,7 @@
 
 :- pragma foreign_proc("C",
 	string__to_int_list(Str::in, IntList::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_ConstString p = Str + strlen(Str);
 	IntList = MR_list_empty_msg(MR_PROC_LABEL);
 	while (p > Str) {
@@ -1720,7 +1722,7 @@
 
 :- pragma foreign_proc("C",
 	string__to_int_list(Str::out, IntList::in),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 		/* mode (out, in) is det */
 	MR_Word int_list_ptr;
 	size_t size;
@@ -1758,7 +1760,7 @@
 
 :- pragma foreign_proc("MC++",
 	string__to_int_list(Str::in, IntList::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
         MR_Integer length, i; 
         MR_Word tmp;
         MR_Word prev;
@@ -1776,7 +1778,7 @@
 
 :- pragma foreign_proc("MC++",
 	string__to_int_list(Str::out, IntList::in),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
         System::Text::StringBuilder *tmp;
        
         tmp = new System::Text::StringBuilder();
@@ -1800,11 +1802,11 @@
 :- mode string__contains_char(in, in) is semidet.
 */
 :- pragma foreign_proc("C", string__contains_char(Str::in, Ch::in),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	SUCCESS_INDICATOR = (strchr(Str, Ch) != NULL);
 ").
 :- pragma foreign_proc("MC++", string__contains_char(Str::in, Ch::in),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	SUCCESS_INDICATOR = (Str->IndexOf(Ch) != -1);
 ").
 
@@ -1815,7 +1817,7 @@
 :- mode string__index(in, in, out) is semidet.
 */
 :- pragma foreign_proc("C", string__index(Str::in, Index::in, Ch::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 
                 /*
 		** We do not test for negative values of Index
@@ -1835,7 +1837,7 @@
 	}
 ").
 :- pragma foreign_proc("MC++", string__index(Str::in, Index::in, Ch::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	if (Index < 0 || Index >= Str->get_Length()) {
 		SUCCESS_INDICATOR = FALSE;
 	} else {
@@ -1848,12 +1850,12 @@
 
 :- pragma foreign_proc("C", 
 	string__unsafe_index(Str::in, Index::in, Ch::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Ch = Str[Index];
 ").
 :- pragma foreign_proc("MC++", 
 	string__unsafe_index(Str::in, Index::in, Ch::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Ch = Str->get_Chars(Index);
 ").
 
@@ -1882,7 +1884,7 @@
 */
 :- pragma foreign_proc("C",
 	string__set_char(Ch::in, Index::in, Str0::in, Str::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	size_t len = strlen(Str0);
 	if ((MR_Unsigned) Index >= len) {
 		SUCCESS_INDICATOR = FALSE;
@@ -1895,7 +1897,7 @@
 ").
 :- pragma foreign_proc("MC++",
 	string__set_char(Ch::in, Index::in, Str0::in, Str::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	if (Index >= Str0->get_Length()) {
 		SUCCESS_INDICATOR = FALSE;
 	} else {
@@ -1913,7 +1915,7 @@
 /*
 :- pragma foreign_proc("C",
 	string__set_char(Ch::in, Index::in, Str0::di, Str::uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	if ((MR_Unsigned) Index >= strlen(Str0)) {
 		SUCCESS_INDICATOR = FALSE;
 	} else {
@@ -1925,7 +1927,7 @@
 
 :- pragma foreign_proc("MC++",
 	string__set_char(Ch::in, Index::in, Str0::di, Str::uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	if (Index >= Str0->get_Length()) {
 		SUCCESS_INDICATOR = FALSE;
 	} else {
@@ -1945,7 +1947,7 @@
 */
 :- pragma foreign_proc("C",
 	string__unsafe_set_char(Ch::in, Index::in, Str0::in, Str::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	size_t len = strlen(Str0);
 	MR_allocate_aligned_string_msg(Str, len, MR_PROC_LABEL);
 	strcpy(Str, Str0);
@@ -1953,7 +1955,7 @@
 ").
 :- pragma foreign_proc("MC++",
 	string__unsafe_set_char(Ch::in, Index::in, Str0::in, Str::out),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Str = System::String::Concat(Str0->Substring(0, Index),
 		System::Convert::ToString(Ch), 
 		Str0->Substring(Index + 1));
@@ -1966,13 +1968,13 @@
 /*
 :- pragma foreign_proc("C",
 	string__unsafe_set_char(Ch::in, Index::in, Str0::di, Str::uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Str = Str0;
 	MR_set_char(Str, Index, Ch);
 ").
 :- pragma foreign_proc("MC++",
 	string__unsafe_set_char(Ch::in, Index::in, Str0::di, Str::uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Str = System::String::Concat(Str0->Substring(0, Index),
 		System::Convert::ToString(Ch), 
 		Str0->Substring(Index + 1));
@@ -1987,12 +1989,12 @@
 */
 :- pragma foreign_proc("C",
 	string__length(Str::in, Length::uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Length = strlen(Str);
 ").
 :- pragma foreign_proc("MC++",
 	string__length(Str::in, Length::uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Length = Str->get_Length();
 ").
 
@@ -2002,12 +2004,12 @@
 */
 :- pragma foreign_proc("C",
 	string__length(Str::ui, Length::uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Length = strlen(Str);
 ").
 :- pragma foreign_proc("MC++",
 	string__length(Str::ui, Length::uo),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	Length = Str->get_Length();
 ").
 
@@ -2028,7 +2030,7 @@
 
 :- pragma foreign_proc("C",
 	string__append_iii(S1::in, S2::in, S3::in),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	size_t len_1 = strlen(S1);
 	SUCCESS_INDICATOR = (
 		strncmp(S1, S3, len_1) == 0 &&
@@ -2038,7 +2040,7 @@
 
 :- pragma foreign_proc("MC++",
 	string__append_iii(S1::in, S2::in, S3::in),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	SUCCESS_INDICATOR = S3->Equals(System::String::Concat(S1, S2));
 }").
 
@@ -2046,7 +2048,7 @@
 
 :- pragma foreign_proc("C",
 	string__append_ioi(S1::in, S2::out,S3::in),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	size_t len_1, len_2, len_3;
 
 	len_1 = strlen(S1);
@@ -2067,7 +2069,7 @@
 
 :- pragma foreign_proc("MC++",
 	string__append_ioi(S1::in, S2::out, S3::in),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	if (S3->StartsWith(S1)) {
 		S2 = S3->Remove(0, S1->Length);
 		SUCCESS_INDICATOR = TRUE;
@@ -2080,7 +2082,7 @@
 
 :- pragma foreign_proc("C",
 	string__append_iio(S1::in, S2::in, S3::uo),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	size_t len_1, len_2;
 	len_1 = strlen(S1);
 	len_2 = strlen(S2);
@@ -2091,7 +2093,7 @@
 
 :- pragma foreign_proc("MC++",
 	string__append_iio(S1::in, S2::in, S3::uo),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	S3 = System::String::Concat(S1, S2);
 }").
 
@@ -2122,7 +2124,7 @@
 
 :- pragma foreign_proc("C",
 	string__append_ooi_3(S1Len::in, S3Len::in, S1::out, S2::out, S3::in),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_allocate_aligned_string_msg(S1, S1Len, MR_PROC_LABEL);
 	memcpy(S1, S3, S1Len);
 	S1[S1Len] = '\\0';
@@ -2133,7 +2135,7 @@
 :- pragma foreign_proc("MC++",
 	string__append_ooi_3(S1Len::in, _S3Len::in,
 			S1::out, S2::out, S3::in),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	S1 = S3->Substring(0, S1Len);
 	S2 = S3->Substring(S1Len);
 ").
@@ -2161,7 +2163,7 @@
 :- pragma foreign_proc("C",
 	string__substring(Str::in, Start::in, Count::in,
 		SubString::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "{
 	MR_Integer len;
 	MR_Word tmp;
@@ -2189,7 +2191,7 @@
 :- pragma foreign_proc("C",
 	string__unsafe_substring(Str::in, Start::in, Count::in,
 		SubString::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "{
 	MR_Integer len;
 	MR_allocate_aligned_string_msg(SubString, Count, MR_PROC_LABEL);
@@ -2199,7 +2201,7 @@
 :- pragma foreign_proc("MC++",
 	string__unsafe_substring(Str::in, Start::in, Count::in,
 		SubString::out),
-		[will_not_call_mercury, thread_safe],
+		[will_not_call_mercury, promise_pure, thread_safe],
 "{
 	SubString = Str->Substring(Start, Count);
 }").
@@ -2218,7 +2220,7 @@
 
 :- pragma foreign_proc("C",
 	string__split(Str::in, Count::in, Left::out, Right::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_Integer len;
 	MR_Word tmp;
 	if (Count <= 0) {
@@ -2243,7 +2245,7 @@
 
 :- pragma foreign_proc("MC++",
 	string__split(Str::in, Count::in, Left::out, Right::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_Integer len;
 	MR_Word tmp;
 	if (Count <= 0) {
@@ -2279,7 +2281,7 @@
 */
 :- pragma foreign_proc("C",
 	string__first_char(Str::in, First::in, Rest::in),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	SUCCESS_INDICATOR = (
 		Str[0] == First &&
 		First != '\\0' &&
@@ -2288,7 +2290,7 @@
 ").
 :- pragma foreign_proc("MC++",
 	string__first_char(Str::in, First::in, Rest::in),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	MR_Integer len = Str->get_Length();
 	SUCCESS_INDICATOR = (
 		len > 0 &&
@@ -2302,13 +2304,13 @@
 */
 :- pragma foreign_proc("C",
 	string__first_char(Str::in, First::out, Rest::in),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	First = Str[0];
 	SUCCESS_INDICATOR = (First != '\\0' && strcmp(Str + 1, Rest) == 0);
 ").
 :- pragma foreign_proc("MC++",
 	string__first_char(Str::in, First::out, Rest::in),
-		[will_not_call_mercury, thread_safe], "
+		[will_not_call_mercury, promise_pure, thread_safe], "
 	MR_Integer len = Str->get_Length();
 	if (len > 0) {
 		SUCCESS_INDICATOR = 
@@ -2324,7 +2326,7 @@
 */
 :- pragma foreign_proc("C",
 	string__first_char(Str::in, First::in, Rest::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	if (Str[0] != First || First == '\\0') {
 		SUCCESS_INDICATOR = FALSE;
 	} else {
@@ -2341,7 +2343,7 @@
 }").
 :- pragma foreign_proc("MC++",
 	string__first_char(Str::in, First::in, Rest::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_Integer len = Str->get_Length();
 	if (len > 0) {
 		SUCCESS_INDICATOR = (First == Str->get_Chars(0));
@@ -2356,7 +2358,7 @@
 */
 :- pragma foreign_proc("C", 
 	string__first_char(Str::in, First::out, Rest::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	First = Str[0];
 	if (First == '\\0') {
 		SUCCESS_INDICATOR = FALSE;
@@ -2374,7 +2376,7 @@
 }").
 :- pragma foreign_proc("MC++", 
 	string__first_char(Str::in, First::out, Rest::out),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	if (Str->get_Length() == 0) {
 		SUCCESS_INDICATOR = FALSE;
 	} else {
@@ -2390,7 +2392,7 @@
 */
 :- pragma foreign_proc("C",
 	string__first_char(Str::out, First::in, Rest::in),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	size_t len = strlen(Rest) + 1;
 	MR_allocate_aligned_string_msg(Str, len, MR_PROC_LABEL);
 	Str[0] = First;
@@ -2398,7 +2400,7 @@
 }").
 :- pragma foreign_proc("MC++",
 	string__first_char(Str::out, First::in, Rest::in),
-		[will_not_call_mercury, thread_safe], "{
+		[will_not_call_mercury, promise_pure, thread_safe], "{
 	MR_String FirstStr;
 	FirstStr = new System::String(First, 1);
 	Str = System::String::Concat(FirstStr, Rest);
Index: library/table_builtin.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/table_builtin.m,v
retrieving revision 1.11
diff -u -r1.11 table_builtin.m
--- library/table_builtin.m	31 Dec 2001 04:26:49 -0000	1.11
+++ library/table_builtin.m	15 Jan 2002 03:59:17 -0000
@@ -180,7 +180,7 @@
 :- implementation.
 
 :- pragma foreign_proc("C",
-	table_simple_is_complete(T::in), will_not_call_mercury, "
+	table_simple_is_complete(T::in), [will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -198,7 +198,7 @@
 ").
 
 :- pragma foreign_proc("C",
-	table_simple_has_succeeded(T::in), will_not_call_mercury, "
+	table_simple_has_succeeded(T::in), [will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -215,7 +215,7 @@
 ").
 
 :- pragma foreign_proc("C",
-	table_simple_has_failed(T::in), will_not_call_mercury, "
+	table_simple_has_failed(T::in), [will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -232,7 +232,7 @@
 ").
 
 :- pragma foreign_proc("C",
-	table_simple_is_active(T::in), will_not_call_mercury, "
+	table_simple_is_active(T::in), [will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -249,7 +249,7 @@
 ").
 
 :- pragma foreign_proc("C",
-	table_simple_is_inactive(T::in), will_not_call_mercury, "
+	table_simple_is_inactive(T::in), [will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -266,7 +266,7 @@
 ").
 
 :- pragma foreign_proc("C",
-	table_simple_mark_as_succeeded(T::in), will_not_call_mercury, "
+	table_simple_mark_as_succeeded(T::in), [will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -280,7 +280,7 @@
 ").
 
 :- pragma foreign_proc("C",
-	table_simple_mark_as_failed(T::in), will_not_call_mercury, "
+	table_simple_mark_as_failed(T::in), [will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -294,7 +294,7 @@
 ").
 
 :- pragma foreign_proc("C",
-	table_simple_mark_as_active(T::in), will_not_call_mercury, "
+	table_simple_mark_as_active(T::in), [will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -308,7 +308,7 @@
 ").
 
 :- pragma foreign_proc("C",
-	table_simple_mark_as_inactive(T::in), will_not_call_mercury, "
+	table_simple_mark_as_inactive(T::in), [will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -324,47 +324,47 @@
 
 
 :- pragma foreign_proc("MC++",
-	table_simple_is_complete(_T::in), will_not_call_mercury, "
+	table_simple_is_complete(_T::in), [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
-	table_simple_has_succeeded(_T::in), will_not_call_mercury, "
+	table_simple_has_succeeded(_T::in), [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
-	table_simple_has_failed(_T::in), will_not_call_mercury, "
+	table_simple_has_failed(_T::in), [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
-	table_simple_is_active(_T::in), will_not_call_mercury, "
+	table_simple_is_active(_T::in), [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
-	table_simple_is_inactive(_T::in), will_not_call_mercury, "
+	table_simple_is_inactive(_T::in), [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
-	table_simple_mark_as_succeeded(_T::in), will_not_call_mercury, "
+	table_simple_mark_as_succeeded(_T::in), [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
-	table_simple_mark_as_failed(_T::in), will_not_call_mercury, "
+	table_simple_mark_as_failed(_T::in), [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
-	table_simple_mark_as_active(_T::in), will_not_call_mercury, "
+	table_simple_mark_as_active(_T::in), [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
-	table_simple_mark_as_inactive(_T::in), will_not_call_mercury, "
+	table_simple_mark_as_inactive(_T::in), [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
@@ -463,7 +463,7 @@
 
 :- pragma foreign_proc("C",
 	table_io_in_range(T::out, Counter::out, Start::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "
 	if (MR_io_tabling_enabled) {
 		MR_io_tabling_counter++;
@@ -490,7 +490,7 @@
 ").
 
 :- pragma foreign_proc("C", table_io_has_occurred(T::in),
-		[will_not_call_mercury],
+		[will_not_call_mercury, promise_pure],
 "
 	MR_TrieNode	table;
 
@@ -506,26 +506,26 @@
 ").
 
 :- pragma foreign_proc("C", table_io_copy_io_state(S0::di, S::uo),
-		[will_not_call_mercury],
+		[will_not_call_mercury, promise_pure],
 "
 	S = S0;
 ").
 
 :- pragma foreign_proc("MC++", 
 	table_io_in_range(_T::out, _Counter::out, _Start::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++", table_io_has_occurred(_T::in),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++", table_io_copy_io_state(_S0::di, _S::uo),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
@@ -598,7 +598,7 @@
 :- implementation.
 
 :- pragma foreign_proc("C",
-	table_nondet_setup(T0::in, T::out), will_not_call_mercury, "
+	table_nondet_setup(T0::in, T::out), [will_not_call_mercury, promise_pure], "
 #ifndef	MR_USE_MINIMAL_MODEL
 	MR_fatal_error(""minimal model code entered when not enabled"");
 #else
@@ -660,7 +660,7 @@
 ").
 
 :- pragma foreign_proc("MC++",
-	table_nondet_setup(_T0::in, _T::out), will_not_call_mercury, "
+	table_nondet_setup(_T0::in, _T::out), [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
@@ -674,7 +674,7 @@
 XXX :- external stops us from using this
 
 :- pragma foreign_proc("MC++",
-	table_nondet_suspend(_A::in, _B::out), [will_not_call_mercury],
+	table_nondet_suspend(_A::in, _B::out), [will_not_call_mercury, promise_pure],
 	local_vars(""),
 	first_code(""),
 	retry_code(""),
@@ -685,14 +685,14 @@
 ).
 
 :- pragma foreign_proc("MC++",
-	table_nondet_resume(_A::in), [will_not_call_mercury], "
+	table_nondet_resume(_A::in), [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 */
 
 :- pragma foreign_proc("C",
-	table_nondet_is_complete(T::in), [will_not_call_mercury], "
+	table_nondet_is_complete(T::in), [will_not_call_mercury, promise_pure], "
 #ifdef	MR_USE_MINIMAL_MODEL
 	MR_TrieNode	table;
 
@@ -705,7 +705,7 @@
 ").
 
 :- pragma foreign_proc("C",
-	table_nondet_is_active(T::in), will_not_call_mercury, "
+	table_nondet_is_active(T::in), [will_not_call_mercury, promise_pure], "
 #ifdef	MR_USE_MINIMAL_MODEL
 	MR_TrieNode	table;
 
@@ -718,7 +718,7 @@
 ").
 
 :- pragma foreign_proc("C",
-	table_nondet_mark_as_active(T::in), will_not_call_mercury, "
+	table_nondet_mark_as_active(T::in), [will_not_call_mercury, promise_pure], "
 #ifdef	MR_USE_MINIMAL_MODEL
 	MR_TrieNode	table;
 
@@ -734,7 +734,7 @@
 
 :- pragma foreign_proc("C",
 	table_nondet_get_ans_table(T::in, AT::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 #ifdef	MR_USE_MINIMAL_MODEL
 	MR_TrieNode	table;
 
@@ -748,7 +748,7 @@
 
 :- pragma foreign_proc("C",
 	table_nondet_answer_is_not_duplicate(T::in),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 #ifndef	MR_USE_MINIMAL_MODEL
 	MR_fatal_error(""minimal model code entered when not enabled"");
 #else
@@ -772,7 +772,7 @@
 
 :- pragma foreign_proc("C",
 	table_nondet_new_ans_slot(T::in, Slot::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 #ifndef	MR_USE_MINIMAL_MODEL
 	MR_fatal_error(""minimal model code entered when not enabled"");
 #else
@@ -843,7 +843,7 @@
 	is det.
 
 :- pragma foreign_proc("C", pickup_answer_list(T::in, CurNode::out),
-	[will_not_call_mercury], "
+	[will_not_call_mercury, promise_pure], "
 #ifdef MR_USE_MINIMAL_MODEL
 		MR_TrieNode	table;
 
@@ -864,7 +864,7 @@
 
 :- pragma foreign_proc("C",
 	return_next_answer(CurNode0::in, AnswerBlock::out, CurNode::out),
-	[will_not_call_mercury], "
+	[will_not_call_mercury, promise_pure], "
 #ifdef MR_USE_MINIMAL_MODEL
 	MR_AnswerList	cur_node0;
 
@@ -882,47 +882,47 @@
 ").
 
 :- pragma foreign_proc("MC++",
-	table_nondet_is_complete(_T::in), [will_not_call_mercury], "
+	table_nondet_is_complete(_T::in), [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
-	table_nondet_is_active(_T::in), will_not_call_mercury, "
+	table_nondet_is_active(_T::in), [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
-	table_nondet_mark_as_active(_T::in), will_not_call_mercury, "
+	table_nondet_mark_as_active(_T::in), [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_nondet_get_ans_table(_T::in, _AT::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_nondet_answer_is_not_duplicate(_T::in),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_nondet_new_ans_slot(_T::in, _Slot::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	pickup_answer_list(_T::in, _CurNode::out),
-		[will_not_call_mercury], "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	return_next_answer(_CurNode0::in, _AnswerBlock::out, _CurNode::out),
-		[will_not_call_mercury], "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
@@ -1081,7 +1081,7 @@
 ").
 
 :- pragma foreign_proc("C", table_lookup_insert_int(T0::in, I::in, T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table0, table;
 
 	table0 = (MR_TrieNode) T0;
@@ -1091,7 +1091,7 @@
 
 :- pragma foreign_proc("C",
 	table_lookup_insert_start_int(T0::in, S::in, I::in, T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table0, table;
 
 	table0 = (MR_TrieNode) T0;
@@ -1102,7 +1102,7 @@
 
 :- pragma foreign_proc("C",
 	table_lookup_insert_char(T0::in, C::in, T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table0, table;
 
 	table0 = (MR_TrieNode) T0;
@@ -1111,7 +1111,7 @@
 ").
 
 :- pragma foreign_proc("C", table_lookup_insert_string(T0::in, S::in, T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table0, table;
 
 	table0 = (MR_TrieNode) T0;
@@ -1120,7 +1120,7 @@
 ").
 
 :- pragma foreign_proc("C", table_lookup_insert_float(T0::in, F::in, T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table0, table;
 
 	table0 = (MR_TrieNode) T0;
@@ -1130,7 +1130,7 @@
 
 :- pragma foreign_proc("C", 
 	table_lookup_insert_enum(T0::in, R::in, V::in, T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table0, table;
 
 	table0 = (MR_TrieNode) T0;
@@ -1140,7 +1140,7 @@
 
 :- pragma foreign_proc("C",
 	table_lookup_insert_user(T0::in, V::in, T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table0, table;
 
 	table0 = (MR_TrieNode) T0;
@@ -1150,7 +1150,7 @@
 
 :- pragma foreign_proc("C",
 	table_lookup_insert_poly(T0::in, V::in, T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table0, table;
 
 	table0 = (MR_TrieNode) T0;
@@ -1160,7 +1160,7 @@
 
 :- pragma foreign_proc("C",
 	table_save_int_ans(T::in, Offset::in, I::in),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -1170,7 +1170,7 @@
 
 :- pragma foreign_proc("C",
 	table_save_char_ans(T::in, Offset::in, C::in),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -1180,7 +1180,7 @@
 
 :- pragma foreign_proc("C",
 	table_save_string_ans(T::in, Offset::in, S::in),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -1190,7 +1190,7 @@
 
 :- pragma foreign_proc("C",
 	table_save_float_ans(T::in, Offset::in, F::in),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -1207,7 +1207,7 @@
 
 :- pragma foreign_proc("C",
 	table_save_io_state_ans(T::in, Offset::in, S::ui),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -1217,7 +1217,7 @@
 
 :- pragma foreign_proc("C", 
 	table_save_any_ans(T::in, Offset::in, V::in),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -1226,7 +1226,7 @@
 
 :- pragma foreign_proc("C",
 	table_restore_int_ans(T::in, Offset::in, I::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -1235,7 +1235,7 @@
 
 :- pragma foreign_proc("C",
 	table_restore_char_ans(T::in, Offset::in, C::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -1244,7 +1244,7 @@
 
 :- pragma foreign_proc("C",
 	table_restore_string_ans(T::in, Offset::in, S::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -1253,7 +1253,7 @@
 
 :- pragma foreign_proc("C",
 	table_restore_float_ans(T::in, Offset::in, F::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -1266,7 +1266,7 @@
 
 :- pragma foreign_proc("C",
 	table_restore_io_state_ans(T::in, Offset::in, V::uo),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -1275,7 +1275,7 @@
 
 :- pragma foreign_proc("C",
 	table_restore_any_ans(T::in, Offset::in, V::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table;
 
 	table = (MR_TrieNode) T;
@@ -1284,7 +1284,7 @@
 
 :- pragma foreign_proc("C",
 	table_create_ans_block(T0::in, Size::in, T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	MR_TrieNode	table0;
 
 	table0 = (MR_TrieNode) T0;
@@ -1296,140 +1296,140 @@
 	error(Message).
 
 :- pragma foreign_proc("C",
-	table_report_statistics, will_not_call_mercury, "
+	table_report_statistics, [will_not_call_mercury, promise_pure], "
 	MR_table_report_statistics(stderr);
 ").
 
 
 :- pragma foreign_proc("MC++",
 	table_lookup_insert_int(_T0::in, _I::in, _T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_lookup_insert_start_int(_T0::in, _S::in, _I::in, _T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_lookup_insert_char(_T0::in, _C::in, _T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_lookup_insert_string(_T0::in, _S::in, _T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_lookup_insert_float(_T0::in, _F::in, _T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++", 
 	table_lookup_insert_enum(_T0::in, _R::in, _V::in, _T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_lookup_insert_user(_T0::in, _V::in, _T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_lookup_insert_poly(_T0::in, _V::in, _T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_save_int_ans(_T::in, _Offset::in, _I::in),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_save_char_ans(_T::in, _Offset::in, _C::in),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_save_string_ans(_T::in, _Offset::in, _S::in),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_save_float_ans(_T::in, _Offset::in, _F::in),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_save_io_state_ans(_T::in, _Offset::in, _S::ui),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 
 :- pragma foreign_proc("MC++",
 	table_save_any_ans(_T::in, _Offset::in, _V::in),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_restore_int_ans(_T::in, _Offset::in, _I::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_restore_char_ans(_T::in, _Offset::in, _C::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_restore_string_ans(_T::in, _Offset::in, _S::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_restore_float_ans(_T::in, _Offset::in, _F::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_restore_io_state_ans(_T::in, _Offset::in, _V::uo),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_restore_any_ans(_T::in, _Offset::in, _V::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
 	table_create_ans_block(_T0::in, _Size::in, _T::out),
-		will_not_call_mercury, "
+		[will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
 :- pragma foreign_proc("MC++",
-	table_report_statistics, will_not_call_mercury, "
+	table_report_statistics, [will_not_call_mercury, promise_pure], "
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 ").
 
Index: library/time.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/time.m,v
retrieving revision 1.22
diff -u -r1.22 time.m
--- library/time.m	31 May 2001 17:12:51 -0000	1.22
+++ library/time.m	15 Jan 2002 03:59:17 -0000
@@ -189,13 +189,13 @@
 :- mode time__c_clock(out, di, uo) is det.
 
 :- pragma foreign_proc("C", time__c_clock(Ret::out, IO0::di, IO::uo),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	Ret = (MR_Integer) clock();
 	update_io(IO0, IO);
 }").
 :- pragma foreign_proc("MC++", time__c_clock(_Ret::out, _IO0::di, _IO::uo),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
@@ -212,12 +212,12 @@
 :- mode time__c_clocks_per_sec(out) is det.
 
 :- pragma foreign_proc("C", time__c_clocks_per_sec(Ret::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	Ret = (MR_Integer) CLOCKS_PER_SEC;
 }").
 :- pragma foreign_proc("MC++", time__c_clocks_per_sec(_Ret::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
@@ -242,7 +242,7 @@
 :- pragma foreign_proc("C",
 	time__c_times(Ret::out, Ut::out, St::out, CUt::out,
                                CSt::out, IO0::di, IO::uo),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 #ifdef MR_HAVE_POSIX_TIMES
 	struct tms t;
@@ -261,7 +261,7 @@
 :- pragma foreign_proc("MC++",
 	time__c_times(_Ret::out, _Ut::out, _St::out, _CUt::out,
                                _CSt::out, _IO0::di, _IO::uo),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
@@ -285,14 +285,14 @@
 
 :- pragma foreign_proc("C",
 	time__c_time(Ret::out, IO0::di, IO::uo),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	Ret = (MR_Integer) time(NULL);
 	update_io(IO0, IO);
 }").
 :- pragma foreign_proc("MC++",
 	time__c_time(_Ret::out, _IO0::di, _IO::uo),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
@@ -309,13 +309,13 @@
 
 :- pragma foreign_proc("C",
 	time__c_difftime(T1::in, T0::in, Diff::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	Diff = (MR_Float) difftime((time_t) T1, (time_t) T0);
 }").
 :- pragma foreign_proc("MC++",
 	time__c_difftime(_T1::in, _T0::in, _Diff::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
@@ -335,7 +335,7 @@
 :- pragma foreign_proc("C",
 	time__c_localtime(Time::in, Yr::out, Mnt::out, MD::out, Hrs::out,
 		Min::out, Sec::out, YD::out, WD::out, N::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	struct tm* p;
 	time_t t;
@@ -360,7 +360,7 @@
 :- pragma foreign_proc("MC++",
 	time__c_localtime(_Time::in, _Yr::out, _Mnt::out, _MD::out, _Hrs::out,
 		_Min::out, _Sec::out, _YD::out, _WD::out, _N::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
@@ -379,7 +379,7 @@
 :- pragma foreign_proc("C",
 	time__c_gmtime(Time::in, Yr::out, Mnt::out, MD::out, Hrs::out,
 		Min::out, Sec::out, YD::out, WD::out, N::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	struct tm* p;
 	time_t t;
@@ -404,7 +404,7 @@
 :- pragma foreign_proc("MC++",
 	time__c_gmtime(_Time::in, _Yr::out, _Mnt::out, _MD::out, _Hrs::out,
 		_Min::out, _Sec::out, _YD::out, _WD::out, _N::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
@@ -435,7 +435,7 @@
 :- pragma foreign_proc("C",
 	time__c_mktime(Yr::in, Mnt::in, MD::in, Hrs::in, Min::in, Sec::in,
 		YD::in, WD::in, N::in, Time::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
  "{
 	struct tm t;
 
@@ -455,7 +455,7 @@
 :- pragma foreign_proc("MC++",
 	time__c_mktime(_Yr::in, _Mnt::in, _MD::in, _Hrs::in,
 		_Min::in, _Sec::in, _YD::in, _WD::in, _N::in, _Time::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
@@ -486,7 +486,7 @@
 :- pragma foreign_proc("C",
 	time__c_asctime(Yr::in, Mnt::in, MD::in, Hrs::in, Min::in, Sec::in,
 		YD::in, WD::in, N::in, Str::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	struct tm t;
 	char* s;
@@ -509,7 +509,7 @@
 :- pragma foreign_proc("MC++",
 	time__c_asctime(_Yr::in, _Mnt::in, _MD::in, _Hrs::in,
 		_Min::in, _Sec::in, _YD::in, _WD::in, _N::in, _Str::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
@@ -526,7 +526,7 @@
 
 :- pragma foreign_proc("C",
 	time__c_ctime(Time::in, Str::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	char *s;
 	time_t t;
@@ -540,7 +540,7 @@
 
 :- pragma foreign_proc("MC++",
 	time__c_ctime(_Time::in, _Str::out),
-	[will_not_call_mercury],
+	[will_not_call_mercury, promise_pure],
 "{
 	mercury::runtime::Errors::SORRY(""foreign code for this function"");
 }").
Index: tests/hard_coded/unused_float_box_test.m
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/unused_float_box_test.m,v
retrieving revision 1.1
diff -u -r1.1 unused_float_box_test.m
--- tests/hard_coded/unused_float_box_test.m	27 May 2001 09:59:55 -0000	1.1
+++ tests/hard_coded/unused_float_box_test.m	15 Jan 2002 04:00:04 -0000
@@ -75,7 +75,7 @@
 
 :- pragma foreign_proc("C", 
 	get_notag_functor_info(_Univ::in, _ExpUniv::out),
-	will_not_call_mercury, "
+	[will_not_call_mercury, promise_pure], "
 {
 	abort();
 }").
@@ -85,7 +85,7 @@
 
 :- pragma foreign_proc("C",
 	get_equiv_functor_info(_Univ::in, _ExpUniv::out),
-    will_not_call_mercury, "
+    [will_not_call_mercury, promise_pure], "
 {
 	abort();
 }").
@@ -94,7 +94,7 @@
 
 :- pragma foreign_proc("C",
 	get_enum_functor_info(_Univ::in, _Enum::out),
-	will_not_call_mercury, "
+	[will_not_call_mercury, promise_pure], "
 {
 	abort();
 }").
@@ -103,7 +103,8 @@
     list(univ)::out) is semidet.
 
 :- pragma foreign_proc("C", get_du_functor_info(_Univ::in, _Where::out,
-    _Ptag::out, _Sectag::out, _Args::out), will_not_call_mercury, "
+    _Ptag::out, _Sectag::out, _Args::out),
+    [will_not_call_mercury, promise_pure], "
 {
 	abort();
 }").


-- 
       Tyson Dowd           # 
                            #  Surreal humour isn't everyone's cup of fur.
     trd at cs.mu.oz.au        # 
http://www.cs.mu.oz.au/~trd #
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list