[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