// vim: ts=4 sw=4 et

// The MercuryRuntime class in the jmercury.runtime package provides various
// Mercury runtime services that we may require.
// All Mercury runtime and generated Java code lives in the jmercury package.
//
import jmercury.runtime.MercuryRuntime;

// The library class in the jmercury package contains the initialisation method
// for Mercury's standard library.
import jmercury.library;

// The mercury_lib class is generated by the compiler when we build
// mercury_lib library.
//
import jmercury.mercury_lib;

import static java.lang.System.out;

public class JavaMain {

    public static void main(String[] args)
    {
        // We do not need to do anything to initialise the Java version of the
        // Mercury runtime.  It will be automatically initialised as the
        // relevant classes are loaded by the JVM.

        // Initialise the Java version of Mercury's standard library.
        //
        out.println("JavaMain: initialising Mercury standard library");
        library.ML_std_library_init();

        out.println("JavaMain: start main");

        try {
            runProgram(args);
        } finally {
            // When we have finished calling Mercury procedures then we need
            // to tell the Mercury Runtime that we have finished using it.
            // The static method finalise() in the MercuryRuntime class does
            // this.  This call is (currently) mandatory otherwise the JVM
            // may not exit cleanly, therefore it should be called in a
            // finally block as in this example.
            //
            // This call will invoke any finalisers specified using
            // ':- finalise' declarations in the set of Mercury libraries we
            // are using.  It also tells the thread pool to shutdown, if the
            // thread pool is not running then this does nothing.  Set the
            // parameter to "true" if the program is aborting (finalisers
            // will be skipped).
            //
            MercuryRuntime.finalise(false);

            // The Mercury exit status (as set by io.set_exit_status/1) may
            // be read from the MercuryRuntime class.
            //
            out.println("JavaMain: Mercury exit status = "
                + MercuryRuntime.getExitStatus());

            out.println("JavaMain: end main");
        }

        System.exit(MercuryRuntime.getExitStatus());
    }

    public static void runProgram(String[] args)
    {
        // This is a call to an exported Mercury procedure that does some I/O.
        // The mercury_lib class contains a static method for each procedure
        // that is foreign exported to Java.
        //
        mercury_lib.writeHello();

        // This is a call to an exported Mercury function.
        //
        out.println("3^3 = " + mercury_lib.cube(3));

        // Try a parallelised Mercury function.
        out.println("fibs(40) = " + mercury_lib.fibs(40));
   }
}
