mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 17:33:38 +00:00
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.
This commit is contained in:
283
README.Java.md
Normal file
283
README.Java.md
Normal file
@@ -0,0 +1,283 @@
|
||||
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
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user