[m-rev.] diff: report uncaught exceptions in Java grades

Peter Wang novalazy at gmail.com
Mon Jun 22 16:13:09 AEST 2009


Branches: main

Report uncaught Mercury exceptions in Java grades.

compiler/mlds_to_java.m:
        Make the generated main method catch and report uncaught Mercury
        exceptions.  Print out the stack trace if the
        MERCURY_SUPPRESS_STACK_TRACE environment variable is unset.

library/exception.m:
        Export report_uncaught_exception/3 in Java grades.

diff --git a/compiler/mlds_to_java.m b/compiler/mlds_to_java.m
index 0f67bec..0c7a995 100644
--- a/compiler/mlds_to_java.m
+++ b/compiler/mlds_to_java.m
@@ -1146,51 +1146,57 @@ output_src_start(Indent, MercuryModuleName,
Imports, ForeignDecls, Defns,
     mangle_sym_name_for_java(MercuryModuleName, module_qual, "__", ClassName),
     io.write_string(ClassName, !IO),
     io.write_string(" {\n", !IO),
-    maybe_write_main_driver(Indent + 1, ClassName, Defns, !IO).

     % Check if this module contains a `main' predicate and if it does insert
-    % a `main' method in the resulting Java class that calls the
-    % `main' predicate. Save the command line arguments in the class
-    % variable `args' in the class `jmercury.runtime.JavaInternal'.
-    %
-:- pred maybe_write_main_driver(indent::in, string::in,
-    list(mlds_defn)::in, io::di, io::uo) is det.
-
-maybe_write_main_driver(Indent, ClassName, Defns, !IO) :-
+    % a `main' method in the resulting Java class that calls the `main'
+    % predicate.
     ( defns_contain_main(Defns) ->
-        indent_line(Indent, !IO),
-        io.write_string("public static void main", !IO),
-        io.write_string("(java.lang.String[] args)\n", !IO),
-        indent_line(Indent, !IO),
-        io.write_string("{\n", !IO),
-
-        % Save the progname and command line arguments in the class variables
-        % of `jmercury.runtime.JavaInternal', as well as setting the default
-        % exit status.
-        indent_line(Indent + 1, !IO),
-        io.write_string("jmercury.runtime.JavaInternal.progname = """, !IO),
-        io.write_string(ClassName, !IO),
-        io.write_string(""";\n", !IO),
-        indent_line(Indent + 1, !IO),
-        io.write_string("jmercury.runtime.JavaInternal.args = args;\n", !IO),
-        indent_line(Indent + 1, !IO),
-        io.write_string("jmercury.runtime.JavaInternal.exit_status = ", !IO),
-        io.write_string("0;\n", !IO),
-        indent_line(Indent + 1, !IO),
-        io.write_string(ClassName, !IO),
-        io.write_string(".main_2_p_0();\n", !IO),
-        indent_line(Indent + 1, !IO),
-        io.write_string("jmercury.runtime.JavaInternal.run_finalisers();\n",
-            !IO),
-        indent_line(Indent + 1, !IO),
-        io.write_string("java.lang.System.exit", !IO),
-        io.write_string("(jmercury.runtime.JavaInternal.exit_status);", !IO),
-        io.nl(!IO),
-        indent_line(Indent, !IO),
-        io.write_string("}\n", !IO)
+        write_main_driver(Indent + 1, ClassName, !IO)
     ;
         true
-    ),
+    ).
+
+:- pred write_main_driver(indent::in, string::in, io::di, io::uo) is det.
+
+write_main_driver(Indent, ClassName, !IO) :-
+    indent_line(Indent, !IO),
+    io.write_string("public static void main", !IO),
+    io.write_string("(java.lang.String[] args)\n", !IO),
+    indent_line(Indent, !IO),
+    io.write_string("{\n", !IO),
+
+    % Save the progname and command line arguments in the class variables
+    % of `jmercury.runtime.JavaInternal', as well as setting the default
+    % exit status.
+    Body = [
+        "jmercury.runtime.JavaInternal.progname = """ ++ ClassName ++ """;",
+        "jmercury.runtime.JavaInternal.args = args;",
+        "jmercury.runtime.JavaInternal.exit_status = 0;",
+        "try {",
+        "   " ++ ClassName ++ ".main_2_p_0();",
+        "   jmercury.runtime.JavaInternal.run_finalisers();",
+        "} catch (jmercury.runtime.Exception e) {",
+        "   exception.ML_report_uncaught_exception(",
+        "       (univ.Univ_0) e.exception);",
+        "   if (System.getenv(""MERCURY_SUPPRESS_STACK_TRACE"") == null) {",
+        "       e.printStackTrace(System.err);",
+        "   }",
+        "   if (jmercury.runtime.JavaInternal.exit_status == 0) {",
+        "       jmercury.runtime.JavaInternal.exit_status = 1;",
+        "   }",
+        "}",
+        "java.lang.System.exit(jmercury.runtime.JavaInternal.exit_status);"
+    ],
+    list.foldl(write_indented_line(Indent + 1), Body, !IO),
+
+    indent_line(Indent, !IO),
+    io.write_string("}\n", !IO).
+
+:- pred write_indented_line(indent::in, string::in, io::di, io::uo) is det.
+
+write_indented_line(Indent, Line, !IO) :-
+    indent_line(Indent, !IO),
+    io.write_string(Line, !IO),
     io.nl(!IO).

 :- pred output_src_end(indent::in, mercury_module_name::in, io::di, io::uo)
diff --git a/library/exception.m b/library/exception.m
index 7543a09..ca93e04 100644
--- a/library/exception.m
+++ b/library/exception.m
@@ -2764,6 +2764,8 @@
mercury_sys_init_exceptions_write_out_proc_statics(FILE *deep_fp,
     "ML_report_uncaught_exception").
 :- pragma foreign_export("IL", report_uncaught_exception(in, di, uo),
     "ML_report_uncaught_exception").
+:- pragma foreign_export("Java", report_uncaught_exception(in, di, uo),
+    "ML_report_uncaught_exception").
 :- pragma foreign_export("Erlang", report_uncaught_exception(in, di, uo),
     "ML_report_uncaught_exception").
--------------------------------------------------------------------------
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