@ciao-lang/ts-ciao-interface
Version:
Simple Ciao interface for node.
1,435 lines (1,432 loc) • 55 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __accessCheck = (obj, member, msg) => {
if (!member.has(obj))
throw TypeError("Cannot " + msg);
};
var __privateAdd = (obj, member, value) => {
if (member.has(obj))
throw TypeError("Cannot add the same private member more than once");
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
};
var __privateMethod = (obj, member, method) => {
__accessCheck(obj, member, "access private method");
return method;
};
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/core/js/ciao-prolog.js
var require_ciao_prolog = __commonJS({
"src/core/js/ciao-prolog.js"(exports2) {
"use strict";
var CiaoPromiseProxy = class _CiaoPromiseProxy {
/* TODO: similar to (:- block) implementation */
/* TODO: 'reject' not supported */
/* TODO: Make sure that this passes the Promises tests suite: https://github.com/promises-aplus/promises-tests */
constructor() {
this.hasValue = false;
this.value = null;
this.handler = null;
this.next = null;
}
setValue(value) {
if (typeof this.handler === "function") {
var ret = this.handler(value);
if (typeof ret === "undefined") {
this.next.setValue(void 0);
} else {
if (typeof ret.then === "function") {
var this_next = this.next;
ret.then(function(r) {
this_next.setValue(r);
});
} else {
this.next.setValue(ret);
}
}
} else {
this.value = value;
this.hasValue = true;
}
}
/* Note: assume that handler returns undefined or a promise */
then(handler) {
if (this.hasValue === true) {
var ret = handler(this.value);
if (typeof ret.then === "function") {
return ret;
} else {
return _CiaoPromiseProxy.resolve(ret);
}
} else {
var next = new _CiaoPromiseProxy();
this.next = next;
this.handler = handler;
return next;
}
}
/* A promise with resolved value `v` */
static resolve(v) {
var p = new _CiaoPromiseProxy();
p.setValue(v);
return p;
}
};
function new_LLCiao() {
var ENVIRONMENT_IS_WORKER = typeof importScripts === "function";
var ENVIRONMENT_IS_NODE2 = typeof process == "object" && typeof process.versions == "object" && typeof process.versions.node == "string";
if (ENVIRONMENT_IS_NODE2) {
const fs2 = require("fs/promises");
const vm = require("vm");
var tryImportScript = function(src) {
return __async(this, null, function* () {
global.require = require;
global.__dirname = __dirname;
global.tryImportScript = tryImportScript;
var data = yield fs2.readFile(src);
vm.runInThisContext(data, { displayErrors: false, filename: src });
});
};
var tryFetchJSON = function(src) {
return __async(this, null, function* () {
var data = yield fs2.readFile(src);
return JSON.parse(data);
});
};
} else {
if (ENVIRONMENT_IS_WORKER) {
var tryImportScript = function(src) {
return __async(this, null, function* () {
importScripts(src);
});
};
} else {
var tryImportScript = globalThis.tryImportScript;
}
var tryFetchJSON = function(src) {
return __async(this, null, function* () {
const response = yield fetch(src);
return yield response.json();
});
};
}
var EMCiao = {};
var stdout = "";
var stderr = "";
var LLCiao = {};
LLCiao.emciao_initialized = false;
LLCiao.stats = {};
LLCiao.bundle = {};
LLCiao.depends = [];
LLCiao.root_URL = null;
LLCiao.get_stats = function() {
return LLCiao.stats;
};
LLCiao.get_ciao_root = function() {
return LLCiao.bundle["core"].wksp;
};
function mkdir_noerr(path) {
let FS = LLCiao.getFS();
try {
FS.mkdir(path);
} catch (e) {
}
;
}
function mkpath(path) {
var spath = path.split("/");
var len = spath.length;
var dir = "";
if (len > 0) {
dir += spath[0];
mkdir_noerr(dir);
for (var i = 1; i < len; i++) {
dir += "/" + spath[i];
mkdir_noerr(dir);
}
}
}
LLCiao.preload_file = function(dir, relpath) {
if (LLCiao.root_URL === null)
throw new Error("null root_URL");
var srcurl = LLCiao.root_URL + relpath;
var srcdir = dir + "/" + relpath;
var dirsplit = srcdir.split("/");
var base = dirsplit.pop();
var dir = dirsplit.join("/");
mkpath(dir);
let FS = LLCiao.getFS();
FS.createPreloadedFile(dir, base, srcurl, true, true);
};
function maybeImportData(b_data, key) {
return __async(this, null, function* () {
if (b_data.hasOwnProperty(key)) {
yield tryImportScript(EMCiao.locateFile(b_data[key], ""));
}
});
}
LLCiao.preload_bundle = function(b) {
return __async(this, null, function* () {
globalThis.__emciao = EMCiao;
const b_data = LLCiao.bundle[b];
if (b_data.hasOwnProperty("preload_files")) {
for (const rel_path of b_data.preload_files) {
LLCiao.preload_file(b_data.wksp, rel_path);
}
}
yield Promise.all([
maybeImportData(b_data, "src_data"),
maybeImportData(b_data, "mods_data")
]);
});
};
LLCiao.collect_wksps = function() {
let wksps = [];
let seen = {};
for (const j of LLCiao.depends) {
var wksp = LLCiao.bundle[j].wksp;
if (!seen[wksp]) {
wksps.unshift(wksp);
seen[wksp] = true;
}
}
return wksps;
};
LLCiao.update_timestamps = function(wksps) {
let FS = LLCiao.getFS();
var tsnow = Date.now();
for (const wksp of wksps) {
const dir = wksp + "/build/cache";
for (const f2 of FS.readdir(dir)) {
if (f2.endsWith(".po") || f2.endsWith(".itf")) {
const path = dir + "/" + f2;
FS.utime(path, tsnow, tsnow);
}
}
}
};
LLCiao.mount_dir = function(srcdir, dstdir) {
mkpath(dstdir);
var FS = LLCiao.getFS();
FS.mount(FS.filesystems.NODEFS, { root: srcdir }, dstdir);
};
var pending_load = false;
var pending_load_resolve = void 0;
LLCiao.wait_no_deps = function() {
return new Promise((resolve, reject) => {
if (pending_load) {
if (pending_load_resolve !== void 0) {
throw new Error("unresolved pending load");
}
;
pending_load_resolve = function() {
resolve(true);
};
} else {
resolve(true);
}
});
};
function monitor_deps(numdeps) {
if (numdeps == 0) {
if (pending_load_resolve !== void 0) {
pending_load_resolve();
pending_load_resolve = void 0;
}
pending_load = false;
}
}
LLCiao.use_bundle = function(bundle) {
return __async(this, null, function* () {
if (!ENVIRONMENT_IS_NODE2)
console.log(`{loading bundle '${bundle}'}`);
const b_data = yield tryFetchJSON(LLCiao.root_URL + "build/dist/" + bundle + ".bundle.json");
if (!LLCiao.depends)
LLCiao.depends = [];
LLCiao.depends.push(b_data.name);
LLCiao.bundle[b_data.name] = b_data;
if (LLCiao.emciao_initialized) {
pending_load = true;
yield LLCiao.preload_bundle(bundle);
}
return true;
});
};
LLCiao.eng_load = function(url, eng) {
return __async(this, null, function* () {
LLCiao.root_URL = url;
if (!ENVIRONMENT_IS_NODE2)
console.log(`{loading engine '${eng}'}`);
yield tryImportScript(LLCiao.root_URL + "build/bin/" + eng + ".js");
return true;
});
};
LLCiao.init_emciao = function() {
return new Promise((resolve, reject) => {
LLCiao.init_emciao_(resolve);
});
};
LLCiao.init_emciao_ = function(resolve) {
EMCiao["locateFile"] = function(path, prefix) {
let root_URL = LLCiao.root_URL;
if (root_URL === null)
throw new Error("null root_URL");
if (path.endsWith(".mem"))
return root_URL + "build/bin/" + path;
if (path.endsWith(".wasm"))
return root_URL + "build/bin/" + path;
if (path.endsWith(".src.data"))
return root_URL + "build/dist/" + path;
if (path.endsWith(".src.js"))
return root_URL + "build/dist/" + path;
if (path.endsWith(".mods.data"))
return root_URL + "build/dist/" + path;
if (path.endsWith(".mods.js"))
return root_URL + "build/dist/" + path;
return prefix + path;
};
let wksps = LLCiao.collect_wksps();
EMCiao.print = function(out) {
stdout += out + "\n";
};
EMCiao.printErr = function(err) {
stderr += err + "\n";
};
EMCiao.noExitRuntime = true;
EMCiao.preRun = [];
EMCiao.preRun.push(function() {
EMCiao["monitorRunDependencies"] = monitor_deps;
for (const b of LLCiao.depends) {
var dep = "preload bundle " + b;
EMCiao["addRunDependency"](dep);
LLCiao.preload_bundle(b).then((result) => {
EMCiao["removeRunDependency"](dep);
});
}
LLCiao.preload_file(LLCiao.get_ciao_root(), "build/bin/" + LLCiao.bootfile);
EMCiao.getENV()["CIAOPATH"] = wksps.join(":");
});
EMCiao.onRuntimeInitialized = function() {
LLCiao.update_timestamps(wksps);
var bootfile = LLCiao.get_ciao_root() + "/build/bin/" + LLCiao.bootfile;
let bootfile_ptr = EMCiao.stringToNewUTF8(bootfile);
EMCiao._ciaowasm_init(bootfile_ptr);
EMCiao._free(bootfile_ptr);
EMCiao._ciaowasm_boot();
LLCiao.emciao_initialized = true;
resolve(null);
};
if (!ENVIRONMENT_IS_NODE2)
console.log(`{booting engine}`);
globalThis.CIAOENGINE.run(EMCiao);
};
LLCiao.bootfile = "ciaowasm";
LLCiao.query_one_begin = function(goal) {
var query;
query = "q((" + goal + ")).";
let FS = LLCiao.getFS();
FS.writeFile("/.q-i", query, { encoding: "utf8" });
let q_ptr = EMCiao.stringToNewUTF8("ciaowasm:query_one_fs");
EMCiao._ciaowasm_query_begin(q_ptr);
EMCiao._free(q_ptr);
return query_result();
};
LLCiao.query_one_next = function() {
EMCiao._ciaowasm_query_next();
return query_result();
};
LLCiao.query_one_resume = function() {
EMCiao._ciaowasm_query_resume();
return query_result();
};
LLCiao.query_end = function() {
EMCiao._ciaowasm_query_end();
};
function recv_jscmd() {
let str;
let cmd;
let FS = LLCiao.getFS();
try {
str = FS.readFile("/.j-c", { encoding: "utf8" });
FS.unlink("/.j-c");
} catch (err) {
return null;
}
return JSON.parse(str);
}
function query_result() {
let is_ok = EMCiao._ciaowasm_query_ok();
if (is_ok) {
let is_suspended = EMCiao._ciaowasm_query_suspended();
if (is_suspended) {
let cmd = recv_jscmd();
if (cmd !== null && cmd.cmd === "acall" && cmd.name === "$dbgtrace_get_line") {
return { cont: "dbgtrace", arg: null };
}
return { cont: "suspended", arg: cmd };
} else {
let FS = LLCiao.getFS();
let cont = FS.readFile("/.q-c", { encoding: "utf8" });
let arg = FS.readFile("/.q-a", { encoding: "utf8" });
return { cont, arg };
}
} else {
return { cont: "failed", arg: "" };
}
}
LLCiao.getFS = function() {
return EMCiao["FS"];
};
LLCiao.read_stdout = function() {
var out = stdout.replaceAll("\n$$$fake_flush$$$\n", "");
stdout = "";
return out;
};
LLCiao.read_stderr = function() {
var err = stderr.replaceAll("\n$$$fake_flush$$$\n", "");
stderr = "";
return err;
};
LLCiao.writeFile = function(a, b) {
try {
return LLCiao.getFS().writeFile(a, b, { encoding: "utf8" });
} catch (err) {
return null;
}
};
LLCiao.readFile = function(a) {
try {
return LLCiao.getFS().readFile(a, { encoding: "utf8" });
} catch (err) {
return null;
}
};
LLCiao.send_jsret = function(x) {
if (x === void 0)
return true;
try {
let str = JSON.stringify(x);
return LLCiao.getFS().writeFile("/.j-o", str, { encoding: "utf8" });
} catch (err) {
return null;
}
};
var f = {};
f["get_stats"] = true;
f["get_ciao_root"] = true;
f["writeFile"] = true;
f["readFile"] = true;
f["read_stdout"] = true;
f["read_stderr"] = true;
f["send_jsret"] = true;
f["query_one_begin"] = true;
f["query_one_resume"] = true;
f["query_one_next"] = true;
f["query_end"] = true;
var af = {};
af["eng_load"] = true;
af["init_emciao"] = true;
af["wait_no_deps"] = true;
af["use_bundle"] = true;
LLCiao.run_cmd = function(cmd, args) {
return __async(this, null, function* () {
if (af.hasOwnProperty(cmd)) {
return LLCiao[cmd].apply(void 0, args);
} else if (f.hasOwnProperty(cmd)) {
return new Promise((resolve, reject) => {
resolve(LLCiao[cmd].apply(void 0, args));
});
} else {
throw new Error("unknown cmd " + cmd);
}
});
};
return LLCiao;
}
function ciao_worker_fun() {
var __ciao = new_LLCiao();
this.onmessage = function(event) {
var resolve = function(x) {
postMessage({ id: event.data.id, ret: x });
};
__ciao.run_cmd(event.data.cmd, event.data.args).then(resolve);
};
console = self.console;
}
function ciao_worker_url() {
let code = new_LLCiao.toString();
let worker_code = ciao_worker_fun.toString();
worker_code = worker_code.slice(worker_code.indexOf("{") + 1, worker_code.lastIndexOf("}"));
code += "\n" + worker_code;
const blob = new Blob([code], { type: "text/javascript" });
return URL.createObjectURL(blob);
}
var use_webworker = true;
var _async_, async__fn, _query_complete, query_complete_fn;
var CiaoWorker2 = class {
constructor(root_URL) {
/**
* Perform a request to `this.w` (the worker running the Ciao
* engine). It creates and returns a CiaoPromiseProxy, whose value
* is set on completion.
*/
__privateAdd(this, _async_);
/** Resume query until completed (not suspended). Process jscmd if needed
*/
__privateAdd(this, _query_complete);
this.eng_loaded = false;
this.eng_booted = false;
this.root_URL = root_URL;
if (use_webworker) {
var listeners = [];
this.listeners = listeners;
this.w = new Worker(ciao_worker_url());
this.w.onmessage = function(event) {
listeners[event.data.id].setValue(event.data.ret);
delete listeners[event.data.id];
};
} else {
this.llciao = new_LLCiao();
}
}
/**
* Ensure that Ciao is initialized. Level can be:
* 1: engine loaded
* 2: engine loaded and booted
*/
ensure_init(level) {
return __async(this, null, function* () {
if (this.pending_level >= level)
return;
this.pending_level = level;
if (level >= 1 && !this.eng_loaded) {
this.eng_loaded = true;
var url = this.root_URL;
if (use_webworker) {
let a = document.createElement("a");
a.href = url;
url = a.href;
}
yield __privateMethod(this, _async_, async__fn).call(this, "eng_load", [url, "ciaoengwasm"]);
}
if (level >= 2 && !this.eng_booted) {
this.eng_booted = true;
yield __privateMethod(this, _async_, async__fn).call(this, "init_emciao", []);
}
});
}
/**
* Use the bundle passed as a parameter, loading the engine if needed.
* @param {string} name - Name of the bundle.
*/
use_bundle(name) {
return __async(this, null, function* () {
yield this.ensure_init(1);
return yield __privateMethod(this, _async_, async__fn).call(this, "use_bundle", [name]);
});
}
wait_no_deps() {
return __async(this, null, function* () {
yield this.ensure_init(1);
return yield __privateMethod(this, _async_, async__fn).call(this, "wait_no_deps", []);
});
}
/**
* Get the stats of the latest call.
*/
get_stats() {
return __async(this, null, function* () {
yield this.ensure_init(1);
return yield __privateMethod(this, _async_, async__fn).call(this, "get_stats", []);
});
}
/**
* Get the Ciao root path.
*/
get_ciao_root() {
return __async(this, null, function* () {
yield this.ensure_init(1);
return yield __privateMethod(this, _async_, async__fn).call(this, "get_ciao_root", []);
});
}
/**
* Begins the query passed as parameter and obtains one solution. The
* decision tree stays awake and waits for user's input.
* @param {string} goal - Query to be launched.
*/
query_one_begin(goal) {
return __async(this, null, function* () {
console.log("Query sent: ", goal);
yield this.ensure_init(2);
let q_out = yield __privateMethod(this, _async_, async__fn).call(this, "query_one_begin", [goal]);
return yield __privateMethod(this, _query_complete, query_complete_fn).call(this, q_out);
});
}
/**
* Obtain the next solution for the query previously launched.
*/
query_one_next() {
return __async(this, null, function* () {
let q_out = yield __privateMethod(this, _async_, async__fn).call(this, "query_one_next", []);
return yield __privateMethod(this, _query_complete, query_complete_fn).call(this, q_out);
});
}
/** Resume a query suspended in dbgtrace
*/
query_resume_dbgtrace(dbgcmd) {
return __async(this, null, function* () {
yield __privateMethod(this, _async_, async__fn).call(this, "send_jsret", [dbgcmd]);
let q_out = yield __privateMethod(this, _async_, async__fn).call(this, "query_one_resume", []);
return yield __privateMethod(this, _query_complete, query_complete_fn).call(this, q_out);
});
}
/**
* End the query.
*/
query_end() {
return __async(this, null, function* () {
return yield __privateMethod(this, _async_, async__fn).call(this, "query_end", []);
});
}
/**
* Read file specified in path parameter.
* @param {string} path - Path of the file to read.
*/
readFile(path) {
return __async(this, null, function* () {
yield this.ensure_init(2);
return yield __privateMethod(this, _async_, async__fn).call(this, "readFile", [path]);
});
}
/**
* Write a string in a file.
* @param {string} path - Path of the file to write.
* @param {string} contents - String of the contents to write in the file.
*/
writeFile(path, contents) {
return __async(this, null, function* () {
yield this.ensure_init(2);
return yield __privateMethod(this, _async_, async__fn).call(this, "writeFile", [path, contents]);
});
}
/**
* Capture the stdout of the most recent query.
*/
read_stdout() {
return __async(this, null, function* () {
return yield __privateMethod(this, _async_, async__fn).call(this, "read_stdout", []);
});
}
/**
* Capture the stderr of the most recent query.
*/
read_stderr() {
return __async(this, null, function* () {
return yield __privateMethod(this, _async_, async__fn).call(this, "read_stderr", []);
});
}
/**
* Terminate the worker `w`
*/
terminate() {
if (use_webworker) {
return this.w.terminate();
} else {
throw new Error("terminate needs Web Worker");
}
}
};
_async_ = new WeakSet();
async__fn = function(cmd, args) {
if (use_webworker) {
var proxy = new CiaoPromiseProxy();
var id = 0;
for (var id = 0; id < this.listeners.length; id++) {
if (this.listeners[id] === void 0)
break;
}
if (id === this.listeners.length) {
this.listeners.push(proxy);
} else {
this.listeners[id] = proxy;
}
this.w.postMessage({
id,
/* id of message in listener array */
cmd,
args
});
return proxy;
} else {
return this.llciao.run_cmd(cmd, args);
}
};
_query_complete = new WeakSet();
query_complete_fn = function(q_out) {
return __async(this, null, function* () {
while (q_out.cont === "suspended") {
let cmd = q_out.arg;
if (cmd !== null) {
let ret = yield jscmd_run(this, cmd);
yield __privateMethod(this, _async_, async__fn).call(this, "send_jsret", [ret]);
}
q_out = yield __privateMethod(this, _async_, async__fn).call(this, "query_one_resume", []);
}
return q_out;
});
};
var jscmd_f = {};
function jscmd_run(w, jscmd) {
return __async(this, null, function* () {
let ret;
switch (jscmd.cmd) {
case "def":
jscmd_f[jscmd.name] = Function('"use strict";return (' + jscmd.code + ")")();
return null;
case "call":
jscmd.args.unshift(w);
return jscmd_f[jscmd.name].apply(void 0, jscmd.args);
case "acall":
jscmd.args.unshift(w);
return yield jscmd_f[jscmd.name].apply(void 0, jscmd.args);
default:
console.log("error: unknown jscmd: " + jscmd);
}
});
}
var toplevelCfg_defaults = {
// Show statistics (and some logging info) per query (in the JS console)
statistics: true,
// Query timeout (seconds) (0 to disable)
query_timeout: 200,
// Special queries // TODO: missing arity
special_query: {
"use_module": { read_code: true, mark_errs: true },
"run_tests_in_module": {
read_code: true,
mark_errs: true,
depends: ["ciaodbg"],
on_init: ["use_module(library(unittest))"]
},
// "clean_mods": {
// on_init: ['use_module(ciaobld(ciaoc_batch_call), [clean_mods/1])']
// },
"doc_cmd": {
read_code: true,
mark_errs: true,
depends: ["lpdoc"],
on_init: ["use_module(lpdoc(docmaker))"]
},
//
"set_menu_flag": {
// arity {3}
read_code: false,
mark_errs: false,
depends: ["ciaopp", "typeslib"],
on_init: ["use_module(ciaopp(ciaopp))"]
},
"module": {
read_code: true,
mark_errs: true,
depends: ["ciaopp", "typeslib"],
on_init: ["use_module(ciaopp(ciaopp))"]
},
"auto_analyze": {
// arity {1,2}
read_code: true,
mark_errs: true,
depends: ["ciaopp", "typeslib"],
on_init: ["use_module(ciaopp(ciaopp))"]
},
"auto_optimize": {
// arity {1,2}
read_code: true,
mark_errs: true,
depends: ["ciaopp", "typeslib"],
on_init: ["use_module(ciaopp(ciaopp))"]
},
"auto_check_assert": {
// arity {1,2}
read_code: true,
mark_errs: true,
depends: ["ciaopp", "typeslib"],
on_init: ["use_module(ciaopp(ciaopp))"]
},
"filter_analyze": {
// arity {1,2}
read_code: true,
mark_errs: true,
depends: ["ciaopp", "typeslib", "exfilter"],
on_init: ["use_module(exfilter(exfilter))"]
},
"filter_analyze_exercise_mode": {
// arity {1,2}
read_code: true,
mark_errs: true,
depends: ["ciaopp", "typeslib", "exfilter"],
on_init: ["use_module(exfilter(exfilter))"]
}
},
// Default bundles and initialization queries
init_bundles: [
"ciaowasm",
// (for foreign-js)
"core",
"builder"
],
init_queries: [
"use_module(engine(internals), [reload_bundleregs/0])",
"use_module(library(classic/classic_predicates))"
]
// Query for loading code
// toplevelCfg.custom_load_query = ((m) => ...);
// Transformation for user queries
// toplevelCfg.custom_run_query = ((q) => ... );
// Post-print code (before update_inner_layout())
// toplevelCfg.custom_postprint_sol = (async (pg) => ...);
};
if (typeof toplevelCfg === "undefined") {
toplevelCfg = {};
}
var toplevelCfg;
toplevelCfg = Object.assign(__spreadValues({}, toplevelCfg_defaults), toplevelCfg);
var QueryState = {
READY: 0,
// ready for a query
RUNNING: 1,
// query running
VALIDATING: 2,
// prompt waiting for validating solution
DBGTRACE: 3
// prompt in a debugging state
};
var ToplevelProc = class {
constructor(root_URL) {
this.root_URL = root_URL;
this.w = null;
this.comint = null;
this.muted = false;
this.state = null;
this.q_opts = {};
this.timer = void 0;
}
/* ---------------------------------------------------------------------- */
/* Is the worker started? */
is_started() {
return this.w !== null;
}
/* Start the worker (and load defaults, show prompt, load program) */
start() {
return __async(this, null, function* () {
if (!this.muted)
this.comint.set_log("Loading bundles and booting");
this.w = new CiaoWorker2(this.root_URL);
yield this.load_ciao_defaults();
if (!this.muted)
this.comint.set_log("");
this.update_state(QueryState.READY);
this.q_opts = {};
if (!this.muted)
this.comint.display_status_new_prompt("silent");
yield this.comint.pg.on_cproc_start();
});
}
/* Restart the worker */
restart() {
return __async(this, null, function* () {
this.shutdown();
this.update_state(QueryState.READY);
this.q_opts = {};
const pmuted = this.set_muted(true);
yield this.start();
this.muted = pmuted;
});
}
/* Terminate worker */
shutdown() {
if (!this.is_started())
return;
this.w.terminate();
this.w = null;
}
/* Make sure that worker is started */
ensure_started(comint) {
return __async(this, null, function* () {
if (this.is_started())
return;
this.comint = comint;
yield this.start();
});
}
// set muted and return previous value
set_muted(v) {
const prev = this.muted;
this.muted = v;
return prev;
}
/* ---------------------------------------------------------------------- */
// Load the default bundles and modules
load_ciao_defaults() {
return __async(this, null, function* () {
for (const b of toplevelCfg.init_bundles) {
yield this.w.use_bundle(b);
}
{
this.w.curr_cproc = this;
yield this.w.query_one_begin("'$:'('internals:$bootversion')");
let out = yield this.w.read_stdout();
let err = yield this.w.read_stderr();
yield this.w.query_end();
this.comint.pg.show_version(out + err);
}
for (const q of toplevelCfg.init_queries) {
yield this.muted_query_dumpout(q);
}
return true;
});
}
// Add (and execute) a new initialization query
push_on_init(qs) {
return __async(this, null, function* () {
const started = this.is_started();
for (const q of qs) {
if (!toplevelCfg.init_queries.includes(q)) {
toplevelCfg.init_queries.push(q);
if (started)
yield this.muted_query_dumpout(q);
}
}
});
}
// Add (and load) a new bundle dependency
push_depends(bs) {
return __async(this, null, function* () {
let updated = false;
const started = this.is_started();
for (const b of bs) {
if (!toplevelCfg.init_bundles.includes(b)) {
toplevelCfg.init_bundles.push(b);
if (started)
yield this.w.use_bundle(b);
updated = true;
}
}
if (started && updated) {
yield this.w.wait_no_deps();
yield this.muted_query_dumpout("reload_bundleregs");
}
});
}
/* ---------------------------------------------------------------------- */
// Do a query, only one solution, dump stdout/stderr,
muted_query_dumpout(q) {
return __async(this, null, function* () {
if (toplevelCfg.statistics)
console.log(`{implicit: ${q}}`);
this.w.curr_cproc = this;
yield this.w.query_one_begin(q);
yield this.dumpout();
yield this.w.query_end();
});
}
// Dump last query stdout/stderr (ignore or show in console)
dumpout() {
return __async(this, null, function* () {
let out = yield this.w.read_stdout();
let err = yield this.w.read_stderr();
if (toplevelCfg.statistics)
console.log(out + err);
});
}
/* ---------------------------------------------------------------------- */
set_query_timeout() {
if (toplevelCfg.query_timeout == 0)
return;
this.timer = setTimeout(() => __async(this, null, function* () {
if (!this.muted)
this.comint.print_msg("\n{ABORTED: Time limit exceeded.}\n");
yield this.restart();
if (!this.muted)
this.comint.display_status_new_prompt("silent");
}), toplevelCfg.query_timeout * 1e3);
}
cancel_query_timeout() {
if (this.timer !== void 0) {
clearTimeout(this.timer);
this.timer = void 0;
}
}
/* ---------------------------------------------------------------------- */
// TODO: only works for single goal queries; this needs to be done
// at Prolog level with Prolog->JS communication
trans_query(query) {
return __async(this, null, function* () {
let treat_outerr = null;
if (toplevelCfg.custom_run_query !== void 0) {
query = toplevelCfg.custom_run_query(query);
}
let f_match = query.match(/([a-z][_a-zA-Z0-9]*)(?:\(|$)/);
if (f_match != null && f_match.length == 2) {
const special_query = toplevelCfg.special_query[f_match[1]];
if (special_query !== void 0) {
if (special_query.depends !== void 0) {
yield this.push_depends(special_query.depends);
}
if (special_query.on_init !== void 0) {
yield this.push_on_init(special_query.on_init);
}
if (special_query.read_code === true) {
yield this.comint.pg.upload_code_to_worker();
}
if (special_query.action !== void 0) {
this.comint.pg.set_auto_action(special_query.action);
}
if (special_query.mark_errs === true) {
treat_outerr = (out, err) => __async(this, null, function* () {
this.comint.pg.mark_errs(out, err);
});
}
}
}
return { q: query, treat_outerr };
});
}
/* ---------------------------------------------------------------------- */
update_state(state) {
this.state = state;
this.comint.update_inner_layout();
}
/* Alert if we are still running */
check_not_running() {
if (this.state === QueryState.RUNNING) {
alert("Already running a query");
return false;
}
return true;
}
/* Alert if we are locked validating/debugging in another comint */
check_not_locked(comint) {
if (this.comint !== comint) {
alert("Already validating/debugging a query in other comint");
return false;
}
return true;
}
/* Waiting for a line (validating query or debugging state) */
is_waiting_for_line() {
return this.state === QueryState.VALIDATING || this.state === QueryState.DBGTRACE;
}
/**
* Execute a new query on the toplevel (Pre: this.state === QueryState.READY)
* @param {string} query - Query to be executed.
*/
run_query(comint, query, opts) {
return __async(this, null, function* () {
if (this.state !== QueryState.READY) {
console.log("bug: already running or validating a query");
return;
}
this.comint = comint;
let tr = yield this.trans_query(query);
query = tr.q;
this.update_state(QueryState.RUNNING);
this.q_opts = opts;
if (!this.muted && opts.msg !== void 0)
this.comint.set_log(opts.msg);
this.set_query_timeout();
this.w.curr_cproc = this;
let q_out = yield this.w.query_one_begin(query);
this.cancel_query_timeout();
if (!this.muted && opts.msg !== void 0)
this.comint.set_log("");
yield this.treat_sol(q_out, tr.treat_outerr);
});
}
/**
* Send a line command (`action`). This is used to validate
* solutions (if this.state === QueryState.VALIDATING) or send a
* debugger command (if this.state === QueryState.DBGTRACE)
*/
send_line(comint, action) {
return __async(this, null, function* () {
this.comint = comint;
if (this.state === QueryState.VALIDATING) {
if (action === "") {
this.w.curr_cproc = this;
yield this.w.query_end();
this.update_state(QueryState.READY);
this.q_opts = {};
this.comint.display_status_new_prompt("yes");
} else {
this.update_state(QueryState.RUNNING);
this.set_query_timeout();
this.w.curr_cproc = this;
let q_out = yield this.w.query_one_next();
this.cancel_query_timeout();
yield this.treat_sol(q_out, null);
}
} else if (this.state === QueryState.DBGTRACE) {
this.update_state(QueryState.RUNNING);
this.set_query_timeout();
this.w.curr_cproc = this;
let q_out = yield this.w.query_resume_dbgtrace(action);
this.cancel_query_timeout();
yield this.treat_sol(q_out, null);
} else {
console.log("bug: not in a validating/debugging solution state");
}
});
}
/**
* If current query has a solution, print it and asks for more if
* there are more solutions available. If it has no solutions, finish
* the query.
* @param {Object} q_out - Object containing an array with the solution of a query.
*/
treat_sol(q_out, treat_outerr) {
return __async(this, null, function* () {
let out = yield this.w.read_stdout();
let err = yield this.w.read_stderr();
if (!this.muted)
this.comint.print_out(out + err);
if (q_out.cont === "dbgtrace") {
this.update_state(QueryState.DBGTRACE);
return;
}
let solstatus;
if (q_out.cont === "failed") {
solstatus = "no";
} else {
if (q_out.cont === "success") {
if (this.comint.with_prompt) {
let prettysol = q_out.arg;
if (prettysol === "") {
solstatus = "yes";
} else {
solstatus = "?";
if (!this.muted)
this.comint.print_sol(prettysol);
}
}
} else if (q_out.cont === "exception") {
let ball = q_out.arg;
if (!this.muted)
this.comint.print_msg(`{ERROR: No handle found for thrown exception ${ball}}
`);
solstatus = "aborted";
} else if (q_out.cont === "malformed") {
solstatus = "silent";
if (!this.muted)
this.comint.print_msg("{SYNTAX ERROR: Malformed query}\n");
} else {
solstatus = "silent";
console.log(`bug: unrecognized query result cont: ${q_out.cont} ${q_out.arg}`);
}
}
const no_treat_outerr = this.q_opts.no_treat_outerr;
if (solstatus === "?") {
this.update_state(QueryState.VALIDATING);
if (!this.muted)
this.comint.print_promptval();
} else {
yield this.w.query_end();
this.update_state(QueryState.READY);
this.q_opts = {};
if (!this.muted)
this.comint.display_status_new_prompt(solstatus);
}
if (treat_outerr !== null) {
if (no_treat_outerr !== true) {
yield treat_outerr(out, err);
}
} else if (!this.muted) {
if (toplevelCfg.custom_postprint_sol !== void 0) {
yield toplevelCfg.custom_postprint_sol(this.comint.pg);
}
}
});
}
/* ---------------------------------------------------------------------- */
/**
* Abort the execution of the current query (if inside of `run_query(query)`).
*/
abort() {
return __async(this, null, function* () {
if (this.state === QueryState.RUNNING) {
this.cancel_query_timeout();
if (!this.muted)
this.comint.print_msg("\n{ Execution aborted (resetting dynamic database) }\n");
yield this.restart();
if (!this.muted)
this.comint.display_status_new_prompt("silent");
}
});
}
};
var ENVIRONMENT_IS_NODE = typeof process == "object" && typeof process.versions == "object" && typeof process.versions.node == "string";
var _treat_enter_, treat_enter__fn;
if (ENVIRONMENT_IS_NODE) {
const path = require("path");
const process2 = require("process");
const printout = function(x) {
process2.stdout.write(x);
};
site_path = path.join(__dirname, "..");
class RLPGCell {
constructor(cproc) {
this.cproc = cproc;
}
setup(rl2) {
return __async(this, null, function* () {
this.comint = new RLComint(rl2, this, {});
yield this.cproc.ensure_started(this.comint);
});
}
on_cproc_start() {
return __async(this, null, function* () {
});
}
show_version(str) {
this.cproc.comint.display(str);
}
upload_code_to_worker() {
return __async(this, null, function* () {
});
}
mark_errs(out, err) {
}
/* mark source debug info */
mark_srcdbg_info(info) {
this.comint.display(` In ${info.src} (${info.ln0}-${info.ln1}) ${info.pred}-${info.num}
`);
}
}
class RLComint {
constructor(rl2, pg, opts) {
// TODO: refactor with ciao_playground.js
__privateAdd(this, _treat_enter_);
this.prompt = "?- ";
this.promptval = " ? ";
this.with_prompt = opts.noprompt === true ? false : true;
this.pg = pg;
this.rl = rl2;
this.next_prompt = "";
}
update_inner_layout() {
}
display(text) {
process2.stdout.write(text);
}
print_out(str) {
this.display(str);
}
print_sol(str) {
this.next_prompt = "\n" + str;
}
print_msg(str) {
this.display(str);
}
print_prompt() {
if (!this.with_prompt)
return;
this.next_prompt = this.prompt;
}
print_promptval() {
if (!this.with_prompt)
return;
this.next_prompt += this.promptval;
}
display_status(str) {
if (!this.with_prompt)
return;
if (str === "silent")
return;
this.display("\n");
this.display(str);
this.display("\n");
}
display_status_new_prompt(str) {
this.display_status(str);
this.print_prompt();
}
set_log(text) {
}
/* Interaction loop */
loop() {
return __async(this, null, function* () {
const cproc = this.pg.cproc;
let q_prompt = this.prompt;
while (true) {
let text;
try {
text = yield this.rl.question(q_prompt);
} catch (err) {
console.log("Err: " + Err);
process2.exit(1);
}
if (text.slice(-1) === "." && text.slice(0, -1) === "halt") {
break;
}
yield __privateMethod(this, _treat_enter_, treat_enter__fn).call(this, text);
q_prompt = this.next_prompt;
this.next_prompt = "";
}
});
}
}
_treat_enter_ = new WeakSet();
treat_enter__fn = function(text) {
return __async(this, null, function* () {
const cproc = this.pg.cproc;
if (cproc.is_waiting_for_line()) {
if (!cproc.check_not_locked(this))
return;
yield cproc.send_line(this, text);
} else {
if (text === "") {
this.print_prompt();
} else {
if (text.slice(-1) !== ".") {
this.display(`{SYNTAX ERROR: Malformed query. It must end with a period.}
`);
this.display_status_new_prompt("silent");
} else {
let q = text.slice(0, -1);
yield cproc.run_query(this, q, {});
}
}
}
});
};
toplevelCfg.statistics = false;
use_webworker = false;
() => __async(exports2, null, function* () {
const cproc = new ToplevelProc(site_path + "/ciao/");
var pg = new RLPGCell(cproc);
yield pg.setup(rl);
var currdir = process2.cwd();
var dstdir = "/local";
cproc.w.llciao.mount_dir(currdir, dstdir);
yield cproc.muted_query_dumpout(`working_directory(_,'${dstdir}')`);
});
}
var site_path;
exports2.CiaoWorker = CiaoWorker2;
}
});
// src/index.ts
var src_exports = {};
__export(src_exports, {
CiaoPrologInterface: () => CiaoPrologInterface,
InterfaceBuilder: () => InterfaceBuilder
});
module.exports = __toCommonJS(src_exports);
// src/controllers/ciao-prolog-interface.ts
var import_ciao_prolog = __toESM(require_ciao_prolog());
var CiaoPrologInterface = class {
constructor(curr_dir, bundles, cust_modules = [], cust_modules_path, boot_path) {
this.c_config = {
boot_path: boot_path != null ? boot_path : "./node_modules/@ciao-lang/ts-ciao-interface/dist/core/ciao/",
curr_dir,
init_bundles: bundles,
cust_modules,
cust_modules_path: cust_modules_path != null ? cust_modules_path : "src/ciao-modules/",
init_queries: [
"use_module(engine(internals), [reload_bundleregs/0])",
"use_module(library(classic/classic_predicates))"
]
};
this.c_worker = new import_ciao_prolog.CiaoWorker(this.c_config.boot_path);
}
ciao_init(dstdir) {
return __async(this, null, function* () {
this.c_worker = new import_ciao_prolog.CiaoWorker(this.c_config.boot_path);
yield this.c_worker.ensure_init(1);
for (const bundle of this.c_config.init_bundles)
yield this.c_worker.use_bundle(bundle);
for (const query of this.c_config.init_queries)
yield this.c_worker.query_one_begin(query);
this.c_worker.llciao.mount_dir(this.c_config.curr_dir, dstdir);
yield this.c_worker.query_one_begin(`working_directory(_,'${dstdir}')`);
for (const cust_module of this.c_config.cust_modules)
yield this.c_worker.query_one_begin(`use_module('${this.c_config.cust_modules_path}${cust_module}.pl')`);
console.log("Ciao worker initiated");
});
}
/* Helper functions for term creation */
ciao_mk_int(value) {
return this.ciao_term("int", value);
}
ciao_mk_flt(value) {
return this.ciao_term("flt", value);
}
ciao_mk_atm(value) {
return this.ciao_term("atm", value);
}
ciao_mk_string(value) {
return this.ciao_term("string", value);
}
ciao_mk_struct(name, args) {
const value = { name };
f