mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 09:23:44 +00:00
287 lines
9.1 KiB
Markdown
287 lines
9.1 KiB
Markdown
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://aws.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.
|
|
|
|
```
|
|
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://mercurylang.org/documentation/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/documentation/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.md](README.ssdebug.md)
|
|
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. Build the dependencies using the following command:
|
|
|
|
mmake --use-mmc-make depend GRADE=java
|
|
|
|
5. Compile using the following command:
|
|
|
|
mmake --use-mmc-make GRADE=java
|
|
|
|
6. To install the Java version of the compiler, do:
|
|
|
|
mmake --use-mmc-make install 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
|
|
invocations of `mmake` is currently required to avoid variable definition
|
|
ordering problems in `Mmake.workspace`.
|
|
|
|
-----------------------------------------------------------------------------
|