Maude bindings for other languages
==================================

.. _other-languages:

The :mod:`maude` library is implemented using the Simple Wrapper and Interface Generator (`SWIG <https://www.swig.org/>`_), which allows generating bindings for some more languages other than Python. All the functionality of the Python library documented :ref:`here <main>` is available through the same API to the other languages, although the Python instance includes several adaptations to its specific features and conventions (iterators, automatic conversion of data structures, default arguments, and so on) that may not match or not be implemented in the other targets. Furthermore, only the Python version has been extensively used and tested for the moment.

For building the library in a specific language, you should pass the appropriate value of the ``LANGUAGE`` variable to the CMake `build script <https://github.com/fadoss/maude-bindings/blob/master/CMakeLists.txt>`_. For example, to build the Java binding in the ``java-build`` subdirectory of the source tree you should write:

.. code-block:: console

   $ cd java-build
   $ cmake .. -DLANGUAGE=java
   $ make

In general, this would generate some language-specific code and a binary plugin. For simplicity, we will use Linux file names like ``maude.so`` for the plugin in the following explanations, but the extension would be ``dll`` in Windows, ``dylib`` in macOS, etc.

To avoid building Maude itself by reusing an already compiled version of Maude as a library, the option ``-DBUILD_LIBMAUDE=OFF`` may be useful. More information is available in the `repository <https://github.com/fadoss/maude-bindings/>`_.

Java
----

For building the Java binding, pass ``-DLANGUAGE=java`` to CMake and make the generated project. This yields a shared library ``libmaudejni.so`` and a JAR file ``maudejni.jar`` including all the Java classes in the bindings. When running Java, ``maudejni.jar`` should be included in the class path and ``libmaudejni.so`` in the library path. For example, to run the following piece of code with ``libmaudejni.so`` in the current directory in Linux, run

.. code-block:: console

   $ javac -cp maudejni.jar Example.java
   $ LD_LIBRARY_PATH=. java -cp libmaude.jar:. Example

The method ``System.loadLibrary`` should be called before using any function in the language bindings.

.. code-block:: java

   import es.ucm.maude.bindings.*;

   public class Example {
   	public static void main(String[] args) {
   		System.loadLibrary("maudejni");

   		maude.init();
   		var m = maude.getModule("NAT");
   		Term t = m.parseTerm("2 * 3");
   		t.reduce();
   		System.out.println(t);
   	}
   }

Unless you have set the ``JAVA_PACKAGE_NAME`` CMake variable otherwise, all classes in the library will belong to the ``es.maude.ucm.bindings`` package.

C#
--

For building the C# binding, pass ``-DLANGUAGE=chsarp`` to CMake, build the project, and then compile the generated ``.cs`` with the C# implementation of choice. The machine-code library ``libmaudecs.so`` is generated by the build system. The user may also generate a .NET assembly out of the C# code to better distribute the bindings. For example, the following code works with `Mono <https://www.mono-project.com/>`_

.. code-block:: console

   $ cmake .. -DLANGUAGE=csharp
   $ make
   $ mcs *.cs -target:library -out:maudecs.dll

and produces an assembly ``maudecs.dll`` that should be referenced when compiling the desired C# program and will be used when running it.

.. code-block:: console

   $ mcs -r:maudecs.dll elsewhere/Main.cs
   $ mono Main.exe

All classes of the Maude library are gathered in the ``Maude`` namespace.

.. code-block:: c#

   using System;
   using Maude;

   class Example
   {
   	public static void Main()
   	{
   		maude.init();
   		var m = maude.getModule("NAT");
   		var t = m.parseTerm("2 * 3");
   		t.reduce();
   		Console.WriteLine(t);
   	}
   }

Guile
-----

`Guile <https://www.gnu.org/software/guile>`_ is an implementation of Scheme, a dialect of Lisp.

For building the binding, pass ``-DLANGUAGE=guile`` to CMake. Native module linkage is used by default, but this can be changed in the ``CMakeLists.txt`` file. Generating an object-oriented module with `GOOPS <https://www.gnu.org/software/guile/manual/html_node/GOOPS.html>`_ is also possible, see Swig's `documentation on Guile <http://www.swig.org/Doc4.0/Guile.html>`_ for the details.

Finally, load the generated module as shown below within Guile (``maude.so`` is assumed to be in the current working directory).

.. code-block:: scheme

   (load-extension "./maude" "scm_init_maude_module")
   (use-modules (maude))

   (init)
   (define m (getModule "NAT"))
   (define t (Module-parseTerm m "2 * 3"))
   (Term-reduce t)
   (display (Term-toString t))
   (newline)

Javascript
----------

Javascript modules can be generated for Node, JavaScriptCore, and V8. The CMake build script only supports the first two, with ``-DLANGUAGE=node`` and ``-DLANGUAGE=jsc`` respectively. Moreover, the second case requires some manual intervention. Swig does not work out of the box with the most recent versions of Node.

.. code-block:: javascript

   var maude = require('maude')

   maude.init()
   var m = maude.getModule('NAT')
   var t = m.parseTerm('2 * 3')
   t.reduce()
   console.log(t.toString())


Lua
---

For building the binding as a dynamic Lua module, simply pass ``-DLANGUAGE=lua`` to CMake. For building a Lua interpreter statically linked to the bindings, see Swig's `documentation on Lua <http://www.swig.org/Doc4.0/Lua.html#Lua_nn4>`_.

Finally, run Lua with the generated ``maude.so`` in the package path, and load it with ``require("maude")``.

.. code-block:: lua

   require("maude")

   maude.init()
   m = maude.getModule("NAT")
   t = m:parseTerm("2 * 3")
   t:reduce()
   print(t)

R
-

For building the R binding, simply pass ``-DLANGUAGE=r`` to CMake. Two files are produced, ``maude.so`` and ``maude.R``. The library is loaded into R as shown below.

.. code-block:: r

   dyn.load(paste("maude", .Platform$dynlib.ext, sep=""))
   source("maude.R")
   cacheMetaData(1)

   init()
   m = getCurrentModule()
   t = m$parseTerm('1 + 2')
   t$reduce()
   print(t$show())

Tcl
---

For building the Tcl binding as a dynamic module, simply pass ``-DLANGUAGE=tcl`` to CMake. The generated ``maude.so`` should be loaded with ``load`` in Tcl.

.. code-block:: tcl

   load ./maude.so

   init
   set m [getModule "NAT"]
   set t [$m parseTerm "2 * 3"]
   $t reduce
   puts [$t toString]
