Maude bindings for other languages

The maude library is implemented using the Simple Wrapper and Interface Generator (SWIG), which allows generating bindings for some more languages other than Python. All the functionality of the Python library documented here 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. For example, to build the Java binding in the java-build subdirectory of the source tree you should write:

$ 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.

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

$ 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.

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

$ 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.

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

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

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 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 is also possible, see Swig’s documentation on Guile for the details.

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

(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.

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.

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

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.

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.

load ./maude.so

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