A node.js interface to the SWI-Prolog library.
Switch branches/tags
Nothing to show
Clone or download
Pull request Compare This branch is 32 commits ahead of Sleepyowl:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
lib
scripts
src
tests
.gitignore
.npmignore
.travis.yml
AUTHORS
LICENSE.txt
README.md
binding.gyp
index.js
package.json

README.md

node-swipl

A Node.js interface to the SWI-Prolog.

Build Status

Installation:

You need to have SWI-Prolog installed and swipl binary available in PATH and compiler installed. See "Platform support" for operating system support. The library requires Node.js version 7+ and SWI-Prolog 6+.

npm install swipl

Also see "Known issues" for currently unsolved problems.

Usage

Calling a predicate and returning bindings with the first solution:

const swipl = require('swipl');
const ret = swipl.call('member(X, [1,2,3,4])');
if (ret) {
    console.log(`Variable X value is: ${ret.X}`);
} else {
    console.log('Call failed.');
}

Outputs:

Variable X value is: 1

Calling a predicate and returning all solutions:

const swipl = require('swipl');
const query = new swipl.Query('member(X, [1,2,3,4])');
let ret = null;
while (ret = query.next()) {
    console.log(`Variable X value is: ${ret.X}`);
}

Outputs:

Variable X value is: 1
Variable X value is: 2
Variable X value is: 3
Variable X value is: 4

There can be only one query open at a time.

Create modules and specify context

Use module operator : to call code in different modules. The default call assumes the user module.

swipl.call('assert(mymodule:test(1))');
console.log(swipl.call('mymodule:test(X)'));

Consult external files

Load code from external files. You might have to set the working directory if you want to use relative paths.

swipl.call('working_directory(_, prolog)');
swipl.call('consult(mycode)');

Constructing safe queries

Queries with data requiring proper escaping can be constructed by using helper functions from swipl.term.

Example:

const swipl = require('./');
const { list, compound, variable, serialize } = swipl.term;

const escaped = serialize(
    compound('member', [
        variable('X'),
        list([1, 2, 3, 4])]));

console.log(swipl.call(escaped));

Blobs and dicts are not supported.

Output term representation

Prolog terms in variable bindings are converted into JavaScript objects under the following rules:

  • Integers are converted to numbers.
  • Floats are converted to numbers.
  • Atoms and strings are converted to strings.
  • Empty list is converted to string [].
  • List head tail pair is converted to object { head, tail } where head and tail are converted terms.
  • Compound term is converted to object { name, args } where name is the compound functor name and args is the array of converted argument terms.
  • Blobs and dicts are not supported and will throw an error.

Error handling

Syntax errors in queries are thrown. Error messages are read from the prolog. The current query is automatically closed.

Invalid query example: member(X, [1,2,3,4] (missing closing paren):

swipl.call('member(X, [1,2,3,4]');

Throws error with message:

Error: Error during query execution. Syntax error:
Operator expected
member(X, 1,2,3,4
** here **

Known errors are thrown with the error message.

swipl.call('error:must_be(ground, _)');

Throws error with message:

Error: Error during query execution. Arguments are
not sufficiently instantiated.

Custom errors without a message are thrown with JavaScript error containing the error term:

swipl.call('throw(error(test))');

Throws error with message:

Error: Error during query execution. Unknown message: error(test).

Disable autoinitialization

The embedded SWI-Prolog engine is automatically initialized when creating the first query. This behavior can be disabled by calling swipl.autoInitialise(false) before any query is executed. The engine can be initialized later manually with the swipl.initialise() function.

Platform support

The bindings are tested on various Linux distributions, on Windows, and on MacOS. SWI-Prolog command swipl must be available in PATH on all of these operating systems.

Windows

Microsoft build tools must be installed:

npm install --global --production windows-build-tools

SWI-Prolog command swipl must be available in PATH.

MacOS

SWI-Prolog must be installed or compiled through Macports. This is described here http://www.swi-prolog.org/build/macos.html. The setup was tested on MacOS Sierra by installing dependencies from ports and compiling with prefix /usr/local (adjust build.templ).

Known issues

  • Unicode data cannot be exchanged.
  • Exporting PL_BLOB terms is not handled.
  • Exporting PL_DICT terms is not supported. It is not supported at all by SWI-Prolog foreign interface.
  • Installed files cannot be copied around on *nix. The linker has libswipl location specified absolutely in the binding object file. The location of SWI_HOME_DIR is determined install-time and written into the file plbase.conf.
  • Attempt to use native SWI packages leads to symbol lookup errors like readutil.so: undefined symbol: PL_new_atom.
  • Custom initialization parameters are not yet implemented.

Development

A list of helpful resources:

Alternatives

Authors

Please see the AUTHORS file.

License

Licensed under LGPL 3.0. A copy is available in the LICENSE.txt file. File lib/serialize_string.js is ported from the pengines project and is licensed under BSD (see the file header).