A downside of the Pengines approach is that the Prolog is run in one module. The code sent to a pengine is executed in the context of the module pengine_sandbox and the safety of goals is validated using safe_goal/1 prior to execution. Any pengine has access to the safe predicates defined in library(sandbox).
The JavaScript API I’m hoping to provide for a number of projects utilizes modules.
Here is some source code from the project. By utilizing ClearScript, I initialize a V8 JavaScript engine. Then, I initialize a custom Prolog engine which uses SWI-Prolog. Then, I add some console functionality and the Prolog engine to the JavaScript environment.
using (var engine = new V8ScriptEngine())
{
using (var prolog = new Prolog())
{
engine.AddHostType("Console", typeof(Console));
engine.AddHostObject("prolog", prolog);
Using the Prolog engine’s API, here is some JavaScript which works:
var module1 = prolog.createModule('module1');
var module2 = prolog.createModule('module2');
module1.assert('p(1, 1)');
module1.assert('p(2, 1)');
module1.assert('p(3, 1)');
module2.assert('p(a, 1)');
module2.assert('p(b, 1)');
module2.assert('p(c, 1)');
for (var r of module1.query('p(X, Y)'))
{
Console.WriteLine('p({0}, {1})', r['X'], r['Y']);
}
Console.WriteLine();
for (var r of module2.query('p(X, Y)'))
{
Console.WriteLine('p({0}, {1})', r.X, r.Y);
}
Console.WriteLine();
module1.assertRule('p2(X)', 'p(X, X)');
for (var r of module1.query('p2(X)'))
{
Console.WriteLine('p2({0})', r.X);
}
module1.addPredicate('p3', 2, function(x, y) { return x.toInteger() > y.toInteger(); });
if (module1.contains('p3(2, 1)')) { Console.WriteLine('2 > 1'); }
if (!module1.contains('p3(1, 2)')) { Console.WriteLine('1 <= 2'); }
The API provides developers with multiple modules, which differs from the Pengines approach. Also, one can observe the smooth registration of foreign predicates from JavaScript with addPredicate.
In summary, the API desires to provide developers with multiple modules and pengines executes Prolog in the context of one module, pengine_sandbox, and validates the safety of goals using safe_goal/1.
What I’m hoping for is one or more flags to initialize SWI-Prolog with so that it only loads a very minimal set of Prolog functionality. In this way, we could secure or sandbox SWI-Prolog while providing use of multiple modules to developers.