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

INTRODUCTION

This release of Mercury contains a port to Erlang.  The Mercury
compiler will generate Erlang source code that can be compiled into
bytecode or native code suitable for running in the Erlang runtime
system.

The port is incomplete.  Large parts of the Mercury standard library
are not yet implemented.  Some RTTI related features are incompletely
or incorrectly implemented.

PREREQUISITES

In order to try this system you will need 

        - The Erlang/OTP distribution, which is open source and can be
          downloaded from
                <http://www.erlang.org/download.html>

        - A Unix-like environment.  The Erlang support has not been
          tested on Windows, but you will need a shell script
          interpreter.

        - Users of Debian or Ubuntu who are using the Erlang that is
          packaged for those systems also need have the erlang-dev
          package installed.

WARNING

Please note that the Erlang backend is still an experimental feature.

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

INSTALLATION

Invoke configure with the option `--enable-erlang-grade' in order to
enable Erlang support.  Make sure it was detected properly by running:

    mmake echo_libgrades

Then run:

    mmake install
or
    mmake install LIBGRADES=erlang

For better performance you will need to add the following line to
Mmake.params before installing:

    EXTRA_MCFLAGS += --erlang-native-code

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

THE ERLANG GRADE

The Mercury compiler currently supports the grade `erlang'.
The erlang grade is enabled by using any of the options
`--grade erlang', `--target erlang', or just `--erlang',
in combination with `mmc --make'.  Mmake does _not_ currently support
the erlang grade.

To run a Mercury program using the erlang grade, you need to install the
Mercury library in the erlang grade, as described above.

You can now build programs such as hello.m or calculator.m in the samples
directory.

        cd samples
        mmc --make --erlang hello

Note that when building programs using the erlang grade you *must* use
mmc --make.

Now you can run hello

        ./hello

Note that hello is a simple shell script that starts the Erlang runtime system.
The actual object files will be stored in the Mercury subdirectory, in `beams'.

If you are using the Windows command-line interpreter, i.e. cmd.exe, then
setting the value of option --target-env-type to "windows" will cause the
compiler to generate a batch file that starts the Erlang runtime system, rather
than a shell script.

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

USING ERLANG

The Mercury standard library has not been fully ported to Erlang 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.

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

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>

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

BUILDING THE MERCURY COMPILER IN THE ERLANG GRADE

Building the Mercury compiler and other related tools in the Erlang grade
is NOT generally supported and should be considered experimental.
In particular, a Mercury compiler built in the Erlang 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 aclocal -I m4; autoconf; ./configure as normal.

(3) Add the line:

      GRADE=erlang

    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=erlang

The Erlang 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.

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

PERFORMANCE NOTES

The Erlang code generated by the Mercury compiler is designed to be compiled
to native code, using the HiPE compiler.  The Erlang bytecode compiler does
not recognise static data structures so some run-time type information can
get created repeatedly again at runtime.  HiPE treats static data structures
specially so this problem does not occur.

You can pass the `--erlang-native-code' option to mmc to use HiPE to compile
.erl files to .beam files.  It is recommended to add this flag to
Mmake.params before installing the standard library.

The need to support user-defined equality and comparison predicates can
cause significant slowdowns, even when they are unused.  This problem
usually exists when a type contains an abstract type in its definition.  The
compiler does not know if an abstract type has user-defined equality or not,
so it makes a conservative assumption.  Enabling intermodule optimisation
gives the compiler more information to avoid this problem.

For some programs you may want to increase the default heap size.
You can do this by setting the ERL_FLAGS environment variable, e.g.
export ERL_FLAGS="+h8000".

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

DIFFERENCES FROM OTHER BACKENDS

* Discriminated union values are ordered according to Erlang conventions
  (e.g. alphabetically) instead of according to the order that data
  constructors appear in the type definition.

* Some legal Mercury code making use of partial instantiation will be
  rejected when compiling to Erlang (you will get a compiler abort).
  An example is:

    foo(Xs) :-
        ( Xs = []
        ; Xs = [1 | _]
        ),
        ( Xs = []
        ; Xs = [_ | []]
        ).

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

RESOURCES

You might find the following pages useful:

    <http://www.mercurylang.org/backends.html>

    <http://www.mercurylang.org/information/documentation.html>

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

FREQUENTLY ASKED QUESTIONS (FAQS)

Q. What are the advantages of using the Erlang back-end?

A. The goal is to take advantage of the Erlang implementation for writing
   scalable and reliable server programs, which can be distributed over
   multiple machines and, possibly, updated at run-time.


Q. What version of Erlang should I be using?

A. Erlang/OTP R14B04 or later is required.


Q. What features are not yet implemented for the Erlang back-end?

A. The following language features are not supported and will not be:

        trailing
        tabling

   The following implementation features are not supported:

        Mercury-level debugging
        Mercury-level profiling

   The following standard library modules are completely unimplemented:

        bit_buffer
        thread
        thread.semaphore
        time
        version_array

   In addition, many modules are incompletely implemented or have placeholder
   implementations.

Q. How do I enable Erlang-level debugging?

A. With great difficulty.  One way is to copy or symlink all the .erl and
   .hrl files used by the program, including those of the standard library,
   into a single directory.  Then build the .beam files with debugging
   enabled, e.g.

        erlc +debug_info *.erl

   Start up the Erlang runtime system and the debugger:

        % erl
        ...
        1> debugger:start().

   In the debugger, select Module > Interpret... and choose the modules to
   interpret (probably "All").  At the erl prompt, the program can be started
   like so:

        % hello:mercury__main_wrapper().

   To run it a second time you may need to call `main_2_p_0' instead.

   For more information, see the documentation for erlc and the Erlang
   debugger.

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