[m-rev.] for review: finalisers and exceptions
Julien Fischer
juliensf at csse.unimelb.edu.au
Fri Feb 9 19:15:55 AEDT 2007
Estimated hours taken: 1
Branches: main
Specify the behaviour of finalisers and mutable initial value expressions
w.r.t to exceptions.
doc/reference_manual.texi:
Specify what happens if a finaliser terminates with an uncaught
exception.
Specify the order of initialisation for mutables w.r.t initialise
declarations.
Specify what happens if a mutable initial value expression
terminates with an uncaught exception.
tests/hard_coded/Mmakefile:
Add the new test cases.
tests/hard_coded/final_excp.{m,exp}:
Test the behaviour of finalisers that throw exceptions.
test/hard_coded/mutable_init_order.{m,exp}:
Test that mutables are initialised in the correct order relative
to initialise declarations.
tests/hard_coded/mutabel_excp.{m,exp}:
Test the behaviour of mutable initial value expressions that
throw exceptions.
Julien.
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.381
diff -u -r1.381 reference_manual.texi
--- doc/reference_manual.texi 8 Feb 2007 01:08:10 -0000 1.381
+++ doc/reference_manual.texi 9 Feb 2007 08:12:06 -0000
@@ -4771,6 +4771,11 @@
standard library will always occur after any finalisation predicates have been
invoked.
+If @samp{finalpredname/arity} terminates with an uncaught exception then
+the program will immediately abort execution. No predicates specified
+by other @samp{finalise} directives that have not yet been executed will
+be executed.
+
@samp{finalize} is also allowed as a synonym for @samp{finalise}.
Note: @samp{finalise} declarations are currently only supported on
@@ -4886,6 +4891,23 @@
It is an error for a @samp{mutable} directive to appear in the
interface section of a module. The usual visibility rules for sub-modules
apply to the mutable variable access predicates.
+
+For the purposes of determining when mutables are assigned their inital
+values, the expression @samp{inital_value} behaves as though it were
+a predicate specified in an @samp{initialise} directive.
+
+ at example
+ :- initialise foo/2.
+ :- mutable(bar, int, 561, ground, [untrailed]).
+ :- initialise baz/2.
+ at end example
+
+In the above example @samp{foo/2} is invoked first, then the initial
+value of @samp{bar} is set to 561 and then @samp{baz/2} is invoked.
+
+The effect of a mutable initial value expression terminating with
+an uncaught exception is also the same as though it were a predicate
+specified in a @samp{initialise} directive.
Note: @samp{mutable} declarations are currently only supported on
the C backends.
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.307
diff -u -r1.307 Mmakefile
--- tests/hard_coded/Mmakefile 8 Feb 2007 01:08:11 -0000 1.307
+++ tests/hard_coded/Mmakefile 9 Feb 2007 08:12:06 -0000
@@ -130,6 +130,7 @@
mode_choice \
multi_map_test \
multimode \
+ mutable_init_order \
myset_test \
name_mangling \
no_fully_strict \
@@ -431,8 +432,10 @@
allow_stubs \
backend_external \
dir_test \
+ final_excp \
init_excp \
map_merge_test \
+ mutable_excp \
io_globals_deadlock \
test_array2d \
test_injection \
@@ -614,10 +617,30 @@
rm -f $@.tmp; \
fi
+# final_excp.out is expected to fail (it calls throw/1).
+#
+final_excp.out: final_excp
+ if ./final_excp > $@.tmp 2>&1; then \
+ grep . $@.tmp; \
+ exit 1; \
+ else \
+ mv $@.tmp $@; \
+ fi
+
# init_excp.out is expected to fail (it calls throw/1).
#
init_excp.out: init_excp
if ./init_excp > $@.tmp 2>&1; then \
+ grep . $@.tmp; \
+ exit 1; \
+ else \
+ mv $@.tmp $@; \
+ fi
+
+# mutable_excp.out is expected to fail (it calls throw/1).
+#
+mutable_excp.out: mutable_excp
+ if ./mutable_excp > $@.tmp 2>&1; then \
grep . $@.tmp; \
exit 1; \
else \
Index: tests/hard_coded/final_excp.exp
===================================================================
RCS file: tests/hard_coded/final_excp.exp
diff -N tests/hard_coded/final_excp.exp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/final_excp.exp 9 Feb 2007 08:12:06 -0000
@@ -0,0 +1,4 @@
+This is final_pred_a/2
+EXCEPTION
+Uncaught Mercury exception:
+magic_number_exception
Index: tests/hard_coded/final_excp.m
===================================================================
RCS file: tests/hard_coded/final_excp.m
diff -N tests/hard_coded/final_excp.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/final_excp.m 9 Feb 2007 08:12:06 -0000
@@ -0,0 +1,63 @@
+% Check that finalisers that terminate with an uncaught exception
+% cause the program to abort rather than keep running (i.e. execute
+% other finalisers).
+:- module final_excp.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module exception.
+
+:- finalise final_pred_a/2. % Should be called first and succeed.
+:- finalise final_pred_b/2. % Should be called second and abort.
+:- finalise final_pred_c/2. % Should *not* be called.
+
+main(!IO).
+
+:- pred final_pred_a(io::di, io::uo) is cc_multi.
+
+final_pred_a(!IO) :-
+ io.write_string("This is final_pred_a/2\n", !IO),
+ try(get_string(561), Result),
+ (
+ Result = succeeded(_),
+ io.write_string("SUCCEEDED\n", !IO)
+ ;
+ Result = exception(_),
+ io.write_string("EXCEPTION\n", !IO)
+ ),
+ io.flush_output(!IO).
+
+:- pred final_pred_b(io::di, io::uo) is det.
+
+final_pred_b(!IO) :-
+ get_magic_number(X, !IO),
+ ( X = 3 ->
+ throw(magic_number_exception)
+ ;
+ io.write_string("This is final_pred_b/2\n", !IO)
+ ).
+
+:- pred final_pred_c(io::di, io::uo) is det.
+
+final_pred_c(!IO) :-
+ io.write_string("final_pred_c/2: I should not be running.\n", !IO).
+
+:- type magic_number_exception ---> magic_number_exception.
+
+:- pred get_string(int::in, string::out) is det.
+
+get_string(X, Str) :-
+ ( X = 561 ->
+ throw(magic_number_exception)
+ ;
+ Str = "not 561"
+ ).
+
+:- pred get_magic_number(int::out, io::di, io::uo) is det.
+
+get_magic_number(3, !IO).
Index: tests/hard_coded/mutable_excp.exp
===================================================================
RCS file: tests/hard_coded/mutable_excp.exp
diff -N tests/hard_coded/mutable_excp.exp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/mutable_excp.exp 9 Feb 2007 08:12:06 -0000
@@ -0,0 +1,3 @@
+init_foo: X = 40
+Uncaught Mercury exception:
+magic_number_exception
Index: tests/hard_coded/mutable_excp.m
===================================================================
RCS file: tests/hard_coded/mutable_excp.m
diff -N tests/hard_coded/mutable_excp.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/mutable_excp.m 9 Feb 2007 08:12:06 -0000
@@ -0,0 +1,70 @@
+% Test mutables whose inital value expressions throw exceptions.
+%
+:- module mutable_excp.
+:- interface.
+
+:- import_module io.
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module exception.
+
+:- mutable(foo, int, init_foo, ground, [untrailed, attach_to_io_state]).
+:- mutable(bar, int, init_bar, ground, [untrailed, attach_to_io_state]).
+:- mutable(baz, int, init_baz, ground, [untrailed, attach_to_io_state]).
+
+:- func init_foo = int.
+
+init_foo = X :-
+ promise_equivalent_solutions [X] (
+ try(get_string(561), Result),
+ (
+ Result = succeeded(_),
+ X = 80
+ ;
+ Result = exception(_),
+ X = 40
+ ),
+ trace [io(!IO)] (
+ io.write_string("init_foo: X = ", !IO),
+ io.write_int(X, !IO),
+ io.nl(!IO),
+ io.flush_output(!IO)
+ )
+ ).
+
+:- func init_bar = int.
+
+init_bar =
+ ( get_magic_number(3) ->
+ throw(magic_number_exception)
+ ;
+ 561
+ ).
+
+:- func init_baz = int.
+
+init_baz = X :-
+ trace [io(!IO)] (
+ io.write_string("init_baz: I should not be running.\n", !IO)
+ ),
+ X = 10.
+
+:- pred get_string(int::in, string::out) is det.
+
+get_string(X, Str) :-
+ ( X = 561 ->
+ throw(magic_number_exception)
+ ;
+ Str = "not 561"
+ ).
+
+:- type magic_number_exception ---> magic_number_exception.
+
+:- pred get_magic_number(int::out) is det.
+
+get_magic_number(3).
+
+main(!IO) :-
+ io.write_string("main: I should not be running.\n", !IO).
Index: tests/hard_coded/mutable_init_order.exp
===================================================================
RCS file: tests/hard_coded/mutable_init_order.exp
diff -N tests/hard_coded/mutable_init_order.exp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/mutable_init_order.exp 9 Feb 2007 08:12:06 -0000
@@ -0,0 +1 @@
+V = 908
Index: tests/hard_coded/mutable_init_order.m
===================================================================
RCS file: tests/hard_coded/mutable_init_order.m
diff -N tests/hard_coded/mutable_init_order.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/mutable_init_order.m 9 Feb 2007 08:12:06 -0000
@@ -0,0 +1,24 @@
+% Test that mutable initialisation occurs in the correct order
+% relative to initialise declarations.
+%
+:- module mutable_init_order.
+:- interface.
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- mutable(global, int, 561, ground, [untrailed, attach_to_io_state]).
+:- initialise foo/2.
+
+:- pred foo(io::di, io::uo) is det.
+
+foo(!IO) :-
+ set_global(908, !IO).
+
+main(!IO) :-
+ get_global(V, !IO),
+ io.write_string("V = ", !IO),
+ io.write_int(V, !IO),
+ io.nl(!IO).
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list