[m-rev.] for review: improve standard library error handling

Simon Taylor stayl at cs.mu.OZ.AU
Sun Sep 2 22:08:01 AEST 2001


On 31-Aug-2001, Tyson Dowd <trd at cs.mu.OZ.AU> wrote:
> On 30-Aug-2001, Simon Taylor <stayl at cs.mu.OZ.AU> wrote:

> > Index: library/array.m
> > ===================================================================
> > RCS file: /home/mercury1/repository/mercury/library/array.m,v
> > retrieving revision 1.97
> > diff -u -u -r1.97 array.m
> > --- library/array.m	2001/08/13 01:19:56	1.97
> > +++ library/array.m	2001/08/29 13:52:47
> > @@ -91,6 +91,11 @@
> >  :- mode array_muo == out(mostly_uniq_array).
> >  :- mode array_mui == in(mostly_uniq_array).
> >  
> > +	% An `array__error' is the exception thrown if any of the
> > +	% operations fail. The string is a description of the error.
> > +:- type array__error
> > +	---> array__error(string).
> > +
> 
> 
> I feel a specific error for array index out-of-bounds would be nice, but
> I'm not adamant about it.

I've renamed that array__index_out_of_bounds. Any errors in array.
which aren't index out-of-bounds are now reported using error/1.
 
> > -#ifdef	ML_ARRAY_THROW_EXCEPTIONS
> > -  #include ""exception.h"" 		/* for ML_throw_string */
> > -  /* shut up warnings about casting away const */
> > -  #define	ML_array_raise(s)	ML_throw_string((char *) (void *) s)
> > +:- pragma foreign_proc("C#", bounds_checks,
> > +		[thread_safe], "
> > +#if ML_OMIT_ARRAY_BOUNDS_CHECKS
> > +	SUCCESS_INDICATOR = FALSE;
> >  #else
> > -  #include ""mercury_misc.h""		/* for MR_fatal_error() */
> > -  #define	ML_array_raise(s)	MR_fatal_error(s)
> > +	SUCCESS_INDICATOR = TRUE;
> >  #endif
> > +").		
> > +
> 
> Unfortunately there is no C# support for SUCCESS_INDICATOR (yet).
> Instead please use MC++ for the moment (the code is fine, just change
> "C#" to be "MC++".
> 
> Same in math.m.

Done.

> It's also not worth putting in #if ML_OMIT_ARRAY_BOUNDS_CHECKS
> because array bounds checking is done by the .NET runtime, and cannot be
> switched off.

I'm not totally sure what you mean here. Defining ML_OMIT_ARRAY_BOUNDS_CHECKS 
stops the checking being done twice, once by array.m and once by the .NET
runtime. The default behaviour (ML_OMIT_ARRAY_BOUNDS_CHECKS undefined)
ensures that the exception thrown is the same on every platform.

> The issue regarding pow should be resolved before making any changes --
> I'll leave that up to you and Fergus and whoever else wants to duke it
> out.

That's a side issue. I'll commit this now, throwing an exception for
math__pow(0.0, 0.0), and deal with it properly in a separate change.

I've also fixed a bug in my change to int__log2 which caused
it to abort if domain checking was turned off, and removed some
code in exception.m to throw exceptions across the C interface.

Simon.


Estimated hours taken: 6
Branches: main

Generate exceptions rather than program aborts for domain errors
and out of bounds array accesses.

Improve the handling of the arithmetic functions.

library/float.m:
library/int.m:
compiler/builtin_ops.m:
	Handle division by zero with an exception rather than a
	program abort.

	Add int__unchecked_quotient and float__unchecked_quotient,
	which don't check for division by zero.

	Remove reverse modes of the arithmetic functions in float.m.
	Richard O'Keefe pointed out a while ago that they don't work
	because of rounding errors.

	Remove the long obsolete `int__builtin_*' and
	`float__builtin_float_*' predicates.

library/math.m:
library/array.m:
	Generate exceptions rather than program aborts.
	The bounds and domain checks are now implemented in
	Mercury, so they do not need to be duplicated for each
	target language.

library/exception.m:
	Remove predicate throw_string/1, which was used to throw
	exceptions from array.m across the C interface, which would
	not work in LLDS grades.

NEWS:
	Document the changes.

tests/general/float_test.m:
tests/general/string_format_test.m:
tests/hard_coded/ho_solns.m:
tests/hard_coded/ho_univ_to_type.m:
tests/hard_coded/qual_strang.m:
tests/hard_coded/qual_strung.m:
	Rename occurrences of `builtin_*'.


--- NEWS	2001/09/02 11:43:23	1.3
+++ NEWS	2001/09/02 11:43:30
@@ -29,8 +29,6 @@
 * We've removed the buggy reverse modes of the arithmetic functions in
   float.m (because of rounding errors the functions aren't actually
   reversible).
-
-* math__pow(0.0, 0.0) now returns 1.0, not 0.0.
  
 * The exception module has a new predicate `try_store', which is
   like `try_io', but which works with stores rather than io__states.

--- array.m	2001/08/31 14:14:15	1.1
+++ array.m	2001/09/02 11:15:16
@@ -91,10 +91,11 @@
 :- mode array_muo == out(mostly_uniq_array).
 :- mode array_mui == in(mostly_uniq_array).
 
-	% An `array__error' is the exception thrown if any of the
-	% operations fail. The string is a description of the error.
-:- type array__error
-	---> array__error(string).
+	% An `array__index_out_of_bounds' is the exception thrown
+	% on out-of-bounds array accesses. The string describes
+	% the predicate or function reporting the error.
+:- type array__index_out_of_bounds
+	---> array__index_out_of_bounds(string).
 
 %-----------------------------------------------------------------------------%
 
@@ -387,7 +388,7 @@
 %-----------------------------------------------------------------------------%
 
 :- implementation.
-:- import_module exception, int.
+:- import_module exception, int, require.
 
 /****
 lower bounds other than zero are not supported
@@ -710,7 +711,7 @@
 #endif
 ").		
 
-:- pragma foreign_proc("C#", bounds_checks,
+:- pragma foreign_proc("MC++", bounds_checks,
 		[thread_safe], "
 #if ML_OMIT_ARRAY_BOUNDS_CHECKS
 	SUCCESS_INDICATOR = FALSE;
@@ -748,7 +749,7 @@
 
 array__init(Size, Item, Array) :-
 	( Size < 0 ->
-		throw(array__error("array__init: negative size"))
+		error("array__init: negative size")
 	;
 		array__init_2(Size, Item, Array)
 	).	
@@ -891,7 +892,7 @@
 
 array__lookup(Array, Index, Item) :-
 	( bounds_checks, \+ array__in_bounds(Array, Index) ->
-		throw(array__error("array__lookup: array index out of bounds"))
+		throw(array__index_out_of_bounds("array__lookup"))
 	;
 		array__unsafe_lookup(Array, Index, Item)
 	).
@@ -929,7 +930,7 @@
 
 array__set(Array0, Index, Item, Array) :-
 	( bounds_checks, \+ array__in_bounds(Array0, Index) ->
-		throw(array__error("array__set: array index out of bounds"))
+		throw(array__index_out_of_bounds("array__set"))
 	;
 		array__unsafe_set(Array0, Index, Item, Array)
 	).
@@ -1046,8 +1047,7 @@
 
 array__shrink(Array0, Size, Array) :-
 	( Size > array__size(Array0) ->
-		throw(array__error(
-			"array__shrink: can't shrink to a larger size"))
+		error("array__shrink: can't shrink to a larger size")
 	;
 		array__shrink_2(Array0, Size, Array)
 	).
--- exception.m	2001/09/02 11:17:06	1.2
+++ exception.m	2001/09/02 11:17:23
@@ -31,9 +31,6 @@
 :- func throw(T) = _.
 :- mode throw(in) = out is erroneous.
 
-:- pred throw_string(string).
-:- mode throw_string(in) is erroneous.
-
 % The following types are used by try/3 and try/5.
 
 :- type exception_result(T)
@@ -594,11 +591,6 @@
 wrap_exception(Exception, exception(Exception)).
 
 %-----------------------------------------------------------------------------%
-
-:- pragma export(throw_string(in), "ML_throw_string").
-
-throw_string(Msg) :-
-	throw(Msg).
 
 :- pred throw_impl(univ).
 :- mode throw_impl(in) is erroneous.
--- float.m	2001/08/31 14:13:41	1.1
+++ float.m	2001/08/31 15:35:04
@@ -367,7 +367,7 @@
 #endif
 ").
 
-:- pragma foreign_proc("C#", domain_checks,
+:- pragma foreign_proc("MC++", domain_checks,
 		[thread_safe], "
 #if ML_OMIT_MATH_DOMAIN_CHECKS
 	SUCCESS_INDICATOR = FALSE;
--- int.m	2001/08/31 14:13:41	1.1
+++ int.m	2001/08/31 17:38:08
@@ -311,7 +311,7 @@
 #endif
 ").
 
-:- pragma foreign_proc("C#", domain_checks,
+:- pragma foreign_proc("MC++", domain_checks,
 		[thread_safe], "
 #if ML_OMIT_MATH_DOMAIN_CHECKS
 	SUCCESS_INDICATOR = FALSE;
@@ -437,10 +437,10 @@
 	int__log2(X, N).
 
 int__log2(X, N) :-
-	( domain_checks, X > 0 ->
-		int__log2_2(X, 0, N)
-	;
+	( domain_checks, X =< 0 ->
 		throw(math__domain_error("int__log2"))
+	;
+		int__log2_2(X, 0, N)
 	).
 
 :- pred int__log2_2(int, int, int).
--- math.m	2001/08/31 14:13:41	1.1
+++ math.m	2001/09/02 11:08:45
@@ -103,8 +103,7 @@
 	% math__pow(X, Y) = Res is true if Res is X raised to the
 	% power of Y.
 	%
-	% Domain restriction: X >= 0 and (X = 0 implies Y >= 0)
-	% (math__pow(0.0, 0.0) = 1.0).
+	% Domain restriction: X >= 0 and (X = 0 implies Y > 0)
 :- func math__pow(float, float) = float.
 :- mode math__pow(in, in) = out is det.
 
@@ -256,7 +255,7 @@
 #endif
 ").
 
-:- pragma foreign_proc("C#", domain_checks,
+:- pragma foreign_proc("MC++", domain_checks,
 		[thread_safe], "
 #if ML_OMIT_MATH_DOMAIN_CHECKS
 	SUCCESS_INDICATOR = FALSE;
@@ -417,16 +416,14 @@
 %
 % Domain restrictions:
 %		X >= 0
-%		X = 0 implies Y >= 0
+%		X = 0 implies Y > 0
 %
 math__pow(X, Y) = Res :-
 	( domain_checks, X < 0.0 ->
 		throw(domain_error("math__pow"))
 	; X = 0.0 ->
-		( domain_checks, Y < 0.0 ->
+		( Y =< 0.0 ->
 			throw(domain_error("math__pow"))
-		; Y = 0.0 ->
-			Res = 1.0
 		;
 			Res = 0.0
 		)
--------------------------------------------------------------------------
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