[m-rev.] for review: update and rewrite README.Java

Julien Fischer jfischer at opturion.com
Tue Jan 10 19:45:11 AEDT 2023


For review by anyone.

I've attached both the diff and the updated version of README.Java.

-------------------------------------------

Update and rewrite README.Java.

Convert it to Markdown.

README.Java:
     Add a .md extension.

     Update many of the details in this file.

     Add a table-of-contents.

     Break up the FAQ into separate named sections.

README.md:
     Conform to the above change of name.

Julien.
-------------- next part --------------
diff --git a/README.Java.md b/README.Java.md
index cf0293708..4a0ab7207 100644
--- a/README.Java.md
+++ b/README.Java.md
@@ -1,247 +1,283 @@
------------------------------------------------------------------------------
-
-INTRODUCTION
-
-The Mercury compiler can generate Java source code that can be compiled into
-Java bytecode suitable for running the Java SE runtime system.  The port is
-mostly complete, but some parts of the Mercury standard library are not yet
-implemented (for a full list see the FAQ below).
-
-The port requires Java SE 8 or higher -- older versions of Java are *not*
-supported.
-
-PREREQUISITES
+Mercury Java Backend
+====================
 
-In order to try this system you will need 
+The Mercury compiler has a backend that generates Java source code, that can
+then be compiled into Java bytecode suitable for running using the Java SE
+runtime system. The backend is mostly complete, but some parts of the Mercury
+standard library are not yet implemented.
 
-    * The J2SE SDK, which can be downloaded for free from
-      <http://www.oracle.com/technetwork/indexes/downloads/index.html>
+The Java backend requires Java SE 8 or higher -- older versions of Java are
+*not* supported.
 
-    * OR any other compatible Java implementation, such as OpenJDK.
+Contents
+--------
 
------------------------------------------------------------------------------
-
-THE JAVA GRADE
+* Prerequisites.
+* Installing the `java` grade
+* Compiling programs with the `java` grade
+* Running programs with the `java` grade
+* Limitations
+* Library support
+* Interfacing with Java
+* Performance
+* Path length restrictions on Windows
+* Java compiler memory exhaustion
+* Mercury-level debugging
+* Java-level debugging
+* Building the Mercury compiler in the `java` grade
 
-The Mercury compiler currently supports the grade `java' to target Java
-bytecode.  The java grade is enabled by using the option `--grade java'.
+Prerequisites
+-------------
 
-To run a Mercury program using the java grade, you need to build the Mercury
-library and runtime in the java grade, using the Mercury source distribution.
+In order to use Mercury's Java backend you will need:
 
-You can now build programs such as hello.m or calculator.m in the samples
-directory.
-	
-	cd samples
-	mmc --grade java --make hello
+* The [Java SE platform](https://www.oracle.com/java/technologies/downloads/).
 
-Note that when building programs using the java grade you *must* use
-mmc --make.
+* OR another compatible Java implementation, such as
+  [OpenJDK](https://openjdk.org) or [Amazon Coretto](https://asw.amazon.com/coretto/).
 
-Now you can run hello
+Installing the `java` grade
+---------------------------
 
-	./hello
+The Mercury compiler uses the grade `java` to target Java source code that is
+then compiled into Java bytecode by the Java compiler.
 
-Note that hello is a simple shell script that invokes the program using the
-Java interpreter.  The actual class files are packaged up into a Java
-archive (JAR) named `hello.jar'.
+Mercury's autoconfiguration script will cause the `java` grade to be installed
+if it finds a suitable Java compiler (e.g. `javac`) and Java runtime
+(e.g. `java`) in your `PATH`.
 
-If you are using the Windows command-line interpreter, i.e. cmd.exe, then
-setting the value of the option --target-env-type to "windows" will cause the
-compiler to generate a batch file that invokes the program, rather than a shell
-script.
+You can check if your Mercury installation has been configured to include the
+`java` grade by looking if `java` is included in the output of the Mercury
+compiler's `--output-stdlib-grades` option.
 
-Problems at higher optimisation levels are still being resolved.
-For now we recommend sticking with -O2 or below and not enabling intermodule
-optimisation.
-
------------------------------------------------------------------------------
+Compiling programs with the `java` grade
+----------------------------------------
 
-USING JAVA
+Once you have a Mercury installation that includes the `java` grade, you can
+build programs such as `hello.m` or `calculator.m` in the [samples](samples)
+directory.
 
-The Mercury standard library has not been fully ported to Java yet.
-The use of unimplemented procedures will result in a run-time error,
-with a message such as "Sorry, not implemented: foreign code for this
-function", and a stack trace.
+```
+    $ cd samples
+    $ mmc --grade java --make hello
+```
 
-If you find missing functionality, you can interface to Java using Mercury's
-foreign language interface.
+When building programs with the `java` grade you *must* use `mmc --make`; using
+`mmake` to build programs using the `java` grade is _not_ supported.
 
-For example:
+Running programs with the `java` grade
+--------------------------------------
 
-:- pred to_string(T::in, string::out) is det.
-:- pragma foreign_proc("Java",
-    to_string(T::in, Str::out),
-    [promise_pure, will_not_call_mercury],
-"
-    Str = T.toString();
-").
+You can run the `hello` program from the previous section by doing:
 
-The implementation will include this Java code in the module's .java file, and
-you can then call the predicate to_string exactly the same as if it were
-implemented using pure mercury code.
+```
+    $ ./hello
+```
 
-For more information about the foreign language interface, see the Mercury
-Language Reference Manual, which you can find at:
-	
-     <http://www.mercurylang.org/information/documentation.html>
+Note that `hello` is a simple shell script generated by the Mercury compiler
+that invokes the program using the Java interpreter. The actual class files are
+packaged up into a Java archive (JAR) named `hello.jar`.
 
-Some short programs may run much more slowly in the Java grade than the C
-grades.  The runtime is probably dominated by Java class loading and running
-in interpreted mode.  A long running program should perform reasonably well
-with a Just-In-Time compiler.  It may also be possible to use an Ahead-Of-Time
-Java compiler, but we haven't tried that yet.
+If you are using the Windows command-line interpreter, i.e. `cmd.exe`, then
+setting the value of the option `--target-env-type` to "windows" will cause the
+Mercury compiler to generate a batch file that invokes the program, instead of
+a shell script.
 
------------------------------------------------------------------------------
-
-BUILDING THE JAVA GRADE ON WINDOWS
+(See the "Using the Mercury compiler" section of the
+[The Mercury User's Guide](https://www.mercurylang.org/information/documentation.html)
+for further details.)
 
-When building the Java grade on Windows it is sometimes possible for the fully
-qualified names of some generated files to exceed the maximum path length.
-If this occurs the Mercury compiler will abort with a message like:
+Limitations
+-----------
 
-   Uncaught Mercury exception:
-   Software Error: parse_tree.module_cmds: predicate \
-   `parse_tree.module_cmds.list_class_files_for_jar'/6: \
-   Unexpected: io.file_type failed: No such file or directory
+The following features of the Mercury implementation are not (currently)
+supported by the Java backend:
 
-In this case all that can (currently) be done is to reduce the length of the
-build path, for example by shifting the build directory closer to the root of
-the file system (e.g. C:\mercury).
+* Mercury-level debugging (however, see further down).
+* Mercury-level profiling.
+* Trailing.
+* Tabling.
+* Backjumping.
 
------------------------------------------------------------------------------
+Library support
+---------------
 
-BUILDING THE MERCURY COMPILER IN THE JAVA GRADE
+The Mercury standard library has not been fully ported to Java yet.
+The use of unimplemented procedures will result in a run-time error,
+with a stack trace and a message like:
 
-Building the Mercury compiler and other related tools in the Java grade
-is NOT generally supported and should be considered experimental.
-In particular, a Mercury compiler built in the Java grade may be slower than
-normal and some features may not be available.
+```
+    Sorry, not implemented: foreign code for this function
+```
 
-However, if you want to give it a try, the required steps are:
+If you find missing functionality, you can interface to Java using Mercury's
+foreign language interface.
 
-(1) Ensure that you have an existing working Mercury compiler in your PATH
-and a clean version of the Mercury source tree.
+The following individual Mercury standard library procedures are either not
+supported or not fully implemented:
 
-(2) Run ./prepare.sh; ./configure as normal.
+1. `io.read_binary/{3,4}`    
+   `io.write_binary/{3,4}`
 
-(3) Add the line:
+    The current implementation of `read_binary` does not work with the
+    way Mercury file streams are implemented for the Java backend.
 
-      GRADE=java
+2. `benchmarking.report_stats/0`    
+   `benchmarking.report_full_memory_stats/0`
 
-    to a file named Mmake.params at the top-level of the source tree.
+    Memory usage statistics are not yet available, and cpu time
+    is not the same as in the C backends, as per `time.m`.
 
-(4) Begin the build process using the following command:
+3. `io.environment.set_environment_var/{4,5}`
 
-    $ mmake --use-mmc-make GRADE=java
+    The Java APIs do not support setting environment variables, hence
+    this predicate throws an exception.
 
-The Java version of the compiler MUST be built using mmake's --use-mmc-make
-option; the build will not work otherwise.  Setting the variable GRADE in the
-invocation of mmake is currently necessary in order to avoid some variable
-definition ordering problems in Mmake.workspace.
+4. `store.arg_ref/5`    
+   `store.new_arg_ref/5`
+		
+    Due to some limits in RTTI support, dynamic type checking is missing for
+    these predicates. They should be used with care.
 
-(5) To install the Java version of the compiler, do:
+5.  `time.clock/3`    
+    `time.clocks_per_sec/0`    
+    `time.times/7`    
+    `time.clk_tck/0`
 
-   $ mmake --use-mmc-make install GRADE=java
+     Because the Java APIs do not provide a way of implementing these
+     procedures exactly in pure Java, we have approximated them with what is
+     available.
 
------------------------------------------------------------------------------
+6.  `math.fma/3`
 
-RESOURCES
+    This function is not available because it is not supported by Java 8.
+    (It will be supported once the minimum version of Java required by
+    Mercury increases.)
 
-You might find the following pages useful:
-    
-    <http://www.mercurylang.org/backends.html>
+Interfacing with Java
+----------------------
 
-    <http://java.sun.com/reference/api/index.html>
+You can call Java code directly from Mercury using the foreign language
+interface. For example:
 
-    <http://www.mercurylang.org/information/documentation.html>>
+```
+    :- pred to_string(T::in, string::out) is det.
+    :- pragma foreign_proc("Java",
+        to_string(T::in, Str::out),
+        [promise_pure, will_not_call_mercury],
+    "
+        Str = T.toString();
+    ").
+```
 
------------------------------------------------------------------------------
+The implementation will include this Java code in the module's .java file.
+You can then call the predicate `to_string/2` exactly the same as if it were
+implemented using pure Mercury code.
 
-FREQUENTLY ASKED QUESTIONS (FAQS)
+For more information about the foreign language interface, see the
+[Mercury Language Reference Manual](https://www.mercurylang.org/information/documentation.html).
+Additionally, the [samples/java_interface](samples/java_interface) directory in
+the Mercury distribution contains examples of how to use the foreign language
+interface with Java.
 
-Q. What are the advantages of using the Java back-end?
+Performance
+-----------
 
-A. The main advantages are easy access to the wide range of libraries available
-   for the J2SE platform, including web applet development, and the portability
-   you get from using Java bytecode.
+Short programs may run much more slowly in the `java` grade than the C grades.
+The runtime is probably dominated by Java class loading and running in
+interpreted mode. A long running program should perform reasonably well with a
+Just-In-Time compiler. It may also be possible to use an Ahead-Of-Time Java
+compiler, but we have not tried that yet.
 
+Path length restrictions on Windows
+-----------------------------------
 
-Q. What version of Java should I be using?
+When using the `java` grade on Windows, it is sometimes possible for the fully
+qualified names of generated files to exceed the maximum path length. If this
+occurs the Mercury compiler will abort with a message like:
 
-A. Java 2 Platform Standard Edition, version 1.5 or greater.
+```
+    Uncaught Mercury exception:
+    Software Error: parse_tree.module_cmds: predicate \
+    `parse_tree.module_cmds.list_class_files_for_jar'/6: \
+    Unexpected: io.file_type failed: No such file or directory
+```
 
+In this case all that can (currently) be done is to reduce the length of the
+build path, for example by shifting the build directory closer to the root of
+the file system (e.g. `C:\mercury`).
 
-Q. What features are not yet implemented for the Java back-end?
+Java compiler memory exhaustion
+-------------------------------
 
-A. The following implementation features are not supported:
+It is possible for the Java compiler to run out of memory when compiling
+Java code generated by the Mercury compiler. If that occurs, you can pass
+an option to the `javac` program to increase the limit. For example:
 
-	Mercury-level debugging (but see next question)
-	Mercury-level profiling
-	trailing
-	tabling
-	backjumping
+```
+    $ mmc --make foo --java --java-flag -J-Xmx512m
+```
 
-   In addition, the following individual procedures are incompletely
-   implemented:
+Or pass an option to `javac` using a `Mercury.options` file:
 
-   	io.read_binary/{3,4}:
-   	io.write_binary/{3,4}:
-		io.read_binary is broken.
+```
+    JAVACFLAGS += -J-Xmx512m
+```
 
-	benchmarking.report_stats/0:
-	benchmarking.report_full_memory_stats/0:
-		Memory usage statistics are not yet available, and cpu time
-		is not the same as in the C backends, as per time.m.
+Mercury-level debugging
+-----------------------
 
-	io.set_environment_var/4:
-		The Java APIs do not allow setting environment variables hence
-		this predicate simply throws an exception.
+The only Mercury-level debugger available for the Java backend is the
+_experimental_ source-to-source debugger; see [README.ssdebug](README.ssdebug)
+for details.
 
-	store.arg_ref/5:
-	store.new_arg_ref/5:
-		Due to the absence of RTTI, dynamic type checking is missing
-		for these predicates.  They should be used with care.
+Java-level debugging
+--------------------
 
-	time.clock/3:
-	time.clocks_per_sec/0:
-	time.times/7:
-	time.clk_tck/0:
-		Because the current Java APIs do not provide any way of
-		implementing these procedures exactly in pure Java, we have
-		approximated them with what is available.
+By default, `javac` already generates line number and source file debugging
+information. You can include local variable debugging information by specifying
+`--target-debug` when invoking the Mercury compiler. For example:
 
-   This list is probably not complete.
+```
+    $ mmc --grade java --target-debug --make <progname>
+```
 
+You can then use the `jdb` debugging tool, which comes as part of the Java SDK
+distribution, to debug your program. For more information, see the
+documentation for `javac` and `jdb`.
 
-Q. How do I debug Mercury programs on Java?
+Building the Mercury compiler in the `java` grade
+--------------------------------------------------
 
-A. The only Mercury-level debugger available for Java grades is the
-   source-to-source debugger; see README.ssdebug.
+Building the Mercury compiler and other related tools in the Java grade
+is NOT generally supported and should be considered experimental.
+In particular, a Mercury compiler built in the Java grade may be slower than
+normal and some features may not be available.
 
+However, if you want to give it a try, the required steps are:
 
-Q. How do I enable Java-level debugging?
+1. Ensure that you have an existing working Mercury compiler in your `PATH`
+   and a clean version of the Mercury source tree.
 
-A. By default, javac already generates line number and source file debugging
-   information.  You can include local variable debugging information by
-   specifying "--target-debug" when invoking the Mercury compiler, e.g.
+2. Run `prepare.sh` and `configure` as normal.
 
-        mmc --make --java --target-debug <progname>
+3. Add the line:
 
-   You can then use Sun's "jdb" debugging tool, which comes
-   as part of the Java SDK distribution, to debug your program.
-   For more information, see the documentation for javac and jdb.
+        GRADE=java
 
+   to a file named `Mmake.params` at the top-level of the source tree.
 
-Q. The Java compiler runs out of memory!
+4. Begin the build process using the following command:
 
-A. You are probably hitting an artificial limit. You can pass an option to
-   the javac program to increase the limit, e.g.
+        $ mmake --use-mmc-make GRADE=java
 
-        mmc --make foo --java --java-flag -J-Xmx512m
+   The Java version of the compiler MUST be built using `mmake`'s `--use-mmc-make`
+   option; the build will not work otherwise. Setting the variable `GRADE` in the
+   invocation of `mmake` is currently necessary in order to avoid variable
+   definition ordering problems in `Mmake.workspace`.
 
-   Or in a Mercury.options file:
+5. To install the Java version of the compiler, do:
 
-        JAVACFLAGS += -J-Xmx512m
+       $ mmake --use-mmc-make install GRADE=java
 
 -----------------------------------------------------------------------------
diff --git a/README.md b/README.md
index 7100b001a..02eec9d6f 100644
--- a/README.md
+++ b/README.md
@@ -35,7 +35,7 @@ Specific information is contained in individual README files:
 
       * C
       * [C#](README.CSharp)
-      * [Java](README.Java)
+      * [Java](README.Java.md)
 
   * Supported operating systems
 
-------------- next part --------------
Mercury Java Backend
====================

The Mercury compiler has a backend that generates Java source code, that can
then be compiled into Java bytecode suitable for running using the Java SE
runtime system. The backend is mostly complete, but some parts of the Mercury
standard library are not yet implemented.

The Java backend requires Java SE 8 or higher -- older versions of Java are
*not* supported.

Contents
--------

* Prerequisites.
* Installing the `java` grade
* Compiling programs with the `java` grade
* Running programs with the `java` grade
* Limitations
* Library support
* Interfacing with Java
* Performance
* Path length restrictions on Windows
* Java compiler memory exhaustion
* Mercury-level debugging
* Java-level debugging
* Building the Mercury compiler in the `java` grade

Prerequisites
-------------

In order to use Mercury's Java backend you will need:

* The [Java SE platform](https://www.oracle.com/java/technologies/downloads/).

* OR another compatible Java implementation, such as
  [OpenJDK](https://openjdk.org) or [Amazon Coretto](https://asw.amazon.com/coretto/).

Installing the `java` grade
---------------------------

The Mercury compiler uses the grade `java` to target Java source code that is
then compiled into Java bytecode by the Java compiler.

Mercury's autoconfiguration script will cause the `java` grade to be installed
if it finds a suitable Java compiler (e.g. `javac`) and Java runtime
(e.g. `java`) in your `PATH`.

You can check if your Mercury installation has been configured to include the
`java` grade by looking if `java` is included in the output of the Mercury
compiler's `--output-stdlib-grades` option.

Compiling programs with the `java` grade
----------------------------------------

Once you have a Mercury installation that includes the `java` grade, you can
build programs such as `hello.m` or `calculator.m` in the [samples](samples)
directory.

```
    $ cd samples
    $ mmc --grade java --make hello
```

When building programs with the `java` grade you *must* use `mmc --make`; using
`mmake` to build programs using the `java` grade is _not_ supported.

Running programs with the `java` grade
--------------------------------------

You can run the `hello` program from the previous section by doing:

```
    $ ./hello
```

Note that `hello` is a simple shell script generated by the Mercury compiler
that invokes the program using the Java interpreter. The actual class files are
packaged up into a Java archive (JAR) named `hello.jar`.

If you are using the Windows command-line interpreter, i.e. `cmd.exe`, then
setting the value of the option `--target-env-type` to "windows" will cause the
Mercury compiler to generate a batch file that invokes the program, instead of
a shell script.

(See the "Using the Mercury compiler" section of the
[The Mercury User's Guide](https://www.mercurylang.org/information/documentation.html)
for further details.)

Limitations
-----------

The following features of the Mercury implementation are not (currently)
supported by the Java backend:

* Mercury-level debugging (however, see further down).
* Mercury-level profiling.
* Trailing.
* Tabling.
* Backjumping.

Library support
---------------

The Mercury standard library has not been fully ported to Java yet.
The use of unimplemented procedures will result in a run-time error,
with a stack trace and a message like:

```
    Sorry, not implemented: foreign code for this function
```

If you find missing functionality, you can interface to Java using Mercury's
foreign language interface.

The following individual Mercury standard library procedures are either not
supported or not fully implemented:

1. `io.read_binary/{3,4}`    
   `io.write_binary/{3,4}`

    The current implementation of `read_binary` does not work with the
    way Mercury file streams are implemented for the Java backend.

2. `benchmarking.report_stats/0`    
   `benchmarking.report_full_memory_stats/0`

    Memory usage statistics are not yet available, and cpu time
    is not the same as in the C backends, as per `time.m`.

3. `io.environment.set_environment_var/{4,5}`

    The Java APIs do not support setting environment variables, hence
    this predicate throws an exception.

4. `store.arg_ref/5`    
   `store.new_arg_ref/5`
		
    Due to some limits in RTTI support, dynamic type checking is missing for
    these predicates. They should be used with care.

5.  `time.clock/3`    
    `time.clocks_per_sec/0`    
    `time.times/7`    
    `time.clk_tck/0`

     Because the Java APIs do not provide a way of implementing these
     procedures exactly in pure Java, we have approximated them with what is
     available.

6.  `math.fma/3`

    This function is not available because it is not supported by Java 8.
    (It will be supported once the minimum version of Java required by
    Mercury increases.)

Interfacing with Java
----------------------

You can call Java code directly from Mercury using the foreign language
interface. For example:

```
    :- pred to_string(T::in, string::out) is det.
    :- pragma foreign_proc("Java",
        to_string(T::in, Str::out),
        [promise_pure, will_not_call_mercury],
    "
        Str = T.toString();
    ").
```

The implementation will include this Java code in the module's .java file.
You can then call the predicate `to_string/2` exactly the same as if it were
implemented using pure Mercury code.

For more information about the foreign language interface, see the
[Mercury Language Reference Manual](https://www.mercurylang.org/information/documentation.html).
Additionally, the [samples/java_interface](samples/java_interface) directory in
the Mercury distribution contains examples of how to use the foreign language
interface with Java.

Performance
-----------

Short programs may run much more slowly in the `java` grade than the C grades.
The runtime is probably dominated by Java class loading and running in
interpreted mode. A long running program should perform reasonably well with a
Just-In-Time compiler. It may also be possible to use an Ahead-Of-Time Java
compiler, but we have not tried that yet.

Path length restrictions on Windows
-----------------------------------

When using the `java` grade on Windows, it is sometimes possible for the fully
qualified names of generated files to exceed the maximum path length. If this
occurs the Mercury compiler will abort with a message like:

```
    Uncaught Mercury exception:
    Software Error: parse_tree.module_cmds: predicate \
    `parse_tree.module_cmds.list_class_files_for_jar'/6: \
    Unexpected: io.file_type failed: No such file or directory
```

In this case all that can (currently) be done is to reduce the length of the
build path, for example by shifting the build directory closer to the root of
the file system (e.g. `C:\mercury`).

Java compiler memory exhaustion
-------------------------------

It is possible for the Java compiler to run out of memory when compiling
Java code generated by the Mercury compiler. If that occurs, you can pass
an option to the `javac` program to increase the limit. For example:

```
    $ mmc --make foo --java --java-flag -J-Xmx512m
```

Or pass an option to `javac` using a `Mercury.options` file:

```
    JAVACFLAGS += -J-Xmx512m
```

Mercury-level debugging
-----------------------

The only Mercury-level debugger available for the Java backend is the
_experimental_ source-to-source debugger; see [README.ssdebug](README.ssdebug)
for details.

Java-level debugging
--------------------

By default, `javac` already generates line number and source file debugging
information. You can include local variable debugging information by specifying
`--target-debug` when invoking the Mercury compiler. For example:

```
    $ mmc --grade java --target-debug --make <progname>
```

You can then use the `jdb` debugging tool, which comes as part of the Java SDK
distribution, to debug your program. For more information, see the
documentation for `javac` and `jdb`.

Building the Mercury compiler in the `java` grade
--------------------------------------------------

Building the Mercury compiler and other related tools in the Java grade
is NOT generally supported and should be considered experimental.
In particular, a Mercury compiler built in the Java grade may be slower than
normal and some features may not be available.

However, if you want to give it a try, the required steps are:

1. Ensure that you have an existing working Mercury compiler in your `PATH`
   and a clean version of the Mercury source tree.

2. Run `prepare.sh` and `configure` as normal.

3. Add the line:

        GRADE=java

   to a file named `Mmake.params` at the top-level of the source tree.

4. Begin the build process using the following command:

        $ mmake --use-mmc-make GRADE=java

   The Java version of the compiler MUST be built using `mmake`'s `--use-mmc-make`
   option; the build will not work otherwise. Setting the variable `GRADE` in the
   invocation of `mmake` is currently necessary in order to avoid variable
   definition ordering problems in `Mmake.workspace`.

5. To install the Java version of the compiler, do:

       $ mmake --use-mmc-make install GRADE=java

-----------------------------------------------------------------------------


More information about the reviews mailing list