Tau Prolog: JavaScript Prolog Interpreter
Tau Prolog is an open-source, client-side Prolog interpreter implemented entirely in JavaScript. It aims for high compliance with the ISO Prolog Standard, enabling the development and portability of Prolog applications across various systems. The current stable version is 0.3.4, with releases appearing to be infrequent and focused on bug fixes and minor feature additions. A key differentiator is its compatibility with both web browsers (client-side) and Node.js environments, allowing for seamless integration. It uniquely supports DOM manipulation and event handling using Prolog predicates, and incorporates an asynchronous, callback-based execution model to prevent UI blocking in browsers, which contrasts with many other Prolog systems that operate server-side or via WebAssembly.
Common errors
-
Error parsing program
cause The Prolog program string passed to `session.consult()` contains syntax errors or uses unsupported predicates/constructs.fixReview the Prolog program for syntax correctness according to the ISO Prolog Standard and Tau Prolog's specific implementation. Check for missing periods, misplaced commas, or incorrect predicate arity. The error callback for `consult` will provide details. -
Error parsing goal
cause The Prolog goal string passed to `session.query()` contains syntax errors.fixExamine the goal string for proper Prolog syntax. Ensure variables are correctly capitalized, predicates exist, and terms are well-formed. The error callback for `query` will provide specific error information. -
Uncaught exception
cause A runtime error occurred during the Prolog inference process (e.g., division by zero, invalid argument type for a predicate, an infinite loop exhausting resources).fixImplement robust error handling in the `session.answer()`'s `error` callback to catch and inspect the exception. Debug the Prolog program's logic to identify the source of the exception. For performance-intensive programs, consider using the `limit` option in `session.answer()` to prevent infinite loops from freezing the application. -
Resolution limit exceeded
cause The Prolog interpreter reached the maximum number of resolution steps (default 1000) while trying to find an answer, often indicating an inefficient or infinitely recursive program.fixOptimize your Prolog program to reduce the search space or prevent infinite recursion. Alternatively, increase the `limit` option in `session.answer()` if the computation is legitimately long, but be mindful of potential browser blocking.
Warnings
- breaking As of version 0.3.0, the `consult` and `query` methods on `pl.type.Session` and `pl.type.Thread` prototypes became asynchronous, requiring callback functions for success and error handling. Direct synchronous usage from previous versions will no longer work.
- gotcha Tau Prolog primarily uses a callback-based asynchronous API, especially for `consult`, `query`, and `answer` methods. This can lead to 'callback hell' in complex scenarios. While it supports asynchronous predicates for non-blocking operations, direct Promises or async/await are not part of the core API for resolution flow.
- gotcha When comparing Prolog systems, be aware that Tau Prolog aims for ISO Prolog Standard compliance but may have differences in specific built-in predicates or behavior compared to other implementations like SWI-Prolog. For example, `sub_string/5` might not be supported, while `sub_atom/5` is.
- gotcha Tau Prolog does not support a `trace` predicate for debugging in the same way some other Prolog systems (like SWI-Prolog) do. Debugging complex Prolog execution within Tau Prolog requires alternative strategies.
Install
-
npm install tau-prolog -
yarn add tau-prolog -
pnpm add tau-prolog
Imports
- pl
import pl from 'tau-prolog';
const pl = require('tau-prolog'); - pl
<script src="tau-prolog.js"></script> // pl is then available globally
- pl.create()
import { create } from 'tau-prolog'; const session = create();const session = pl.create();
Quickstart
const pl = require('tau-prolog');
const session = pl.create();
session.consult(`
likes(sam, salad).
likes(dean, pie).
likes(sam, apples).
likes(dean, whiskey).
`, {
success: function() {
console.log("Program loaded correctly.");
session.query("likes(sam, X).", {
success: function(goal) {
console.log("Goal loaded correctly.");
// Look for answers
function findAnswer() {
session.answer({
success: function(answer) {
console.log(session.format_answer(answer));
findAnswer(); // Try to find the next answer
},
fail: function() {
console.log("No more answers.");
},
error: function(err) {
console.error("Uncaught exception:", err);
},
limit: function() {
console.warn("Resolution limit exceeded.");
}
});
}
findAnswer();
},
error: function(err) {
console.error("Error parsing goal:", err);
}
});
},
error: function(err) {
console.error("Error parsing program:", err);
}
});