OCaml-Java: scripting


Since version 2.0-early-access5, scripting from a Java application is supported, by providing an OCaml script engine for the javax.script framework. This page first shows how the support for scripting can be used to interpret OCaml code. Then, the mapping of Java types to OCaml is presented. Finally, an example shows how the scripting framework can be used to compile code.

Warning! scripting does not currently support the typer extension allowing to access Java elements.

Code interpretation

In order to be able to use the script engine, it is sufficient to add the archive lib/ocamlrun-scripting.jar to the classpath. It is then possible to interpret OCaml phrases from a Java application as shown by the following code sample:

import javax.script.*;
import org.ocamljava.runtime.support.scripting.OCamlContext;

public final class SimpleInterpreted {

    private static final String SCRIPT =
        "external get_binding : string -> 'a = \"script_get_binding\";;\n" +
        "let n = Int32.to_int (get_binding \"repetitions\");;\n" +
        "let s : string = get_binding \"message\";;\n" +
        "for i = 1 to n do print_endline s done;;\n";

    public static void main(final String[] args) throws Throwable {
        final ScriptEngineManager manager = new ScriptEngineManager();
        final ScriptEngine engine = manager.getEngineByName("OCaml");
        final ScriptContext ctxt = new OCamlContext();
        ctxt.getBindings(ScriptContext.ENGINE_SCOPE).put("repetitions", 3);
        ctxt.getBindings(ScriptContext.ENGINE_SCOPE).put("message", "hello!!!");
        engine.eval(SCRIPT, ctxt);
    }

}

where the external get_binding function allows to access bindings registered on the Java side of the application.

Type mapping

The mapping of Java types to OCaml types is given by the following table (notice that Java primitive types are necessarily promoted to their wrapper equivalents through the use of the binding API):

Java type OCaml type
java.lang.Boolean bool
java.lang.Byte int
java.lang.Character int
java.lang.Double float
java.lang.Float float
java.lang.Integer int32
java.lang.Long int64
java.lang.Short int
java.lang.String string

Code compilation

Besides interpretation, it is also possible to compile OCaml sources in order to benefit from better performance. To do so, the archive lib/ocamljava.jar has to be added to the classpath in addition to the archive lib/ocamlrun-scripting.jar. The following code shows how to compile and then run an OCaml snippet from a Java application.

import javax.script.*;
import org.ocamljava.runtime.support.scripting.OCamlContext;

public final class SimpleCompiled {

    private static final String SCRIPT =
        "external get_binding : string -> 'a = \"script_get_binding\"\n" +
        "let () =\n" +
        "  let n = Int32.to_int (get_binding \"repetitions\") in\n" +
        "  let s : string = get_binding \"message\" in\n" +
        "  for i = 1 to n do print_endline s done\n";

    public static void main(final String[] args) throws Throwable {
        final ScriptEngineManager manager = new ScriptEngineManager();
        final ScriptEngine engine = manager.getEngineByName("OCaml");
        final ScriptContext ctxt = new OCamlContext();
        ctxt.getBindings(ScriptContext.ENGINE_SCOPE).put("repetitions", 3);
        ctxt.getBindings(ScriptContext.ENGINE_SCOPE).put("message", "hello!!!");
        final CompiledScript compiled = ((Compilable) engine).compile(SCRIPT);
        compiled.eval(ctxt);
    }

}