UNPKG

@ciao-lang/ts-ciao-interface

Version:

Simple Ciao interface for node.

1,429 lines (1,427 loc) 54.8 kB
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 __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) { if (typeof require !== "undefined") return require.apply(this, arguments); throw Error('Dynamic require of "' + x + '" is not supported'); }); var __commonJS = (cb, mod) => function __require2() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; 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 __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"(exports) { "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(exports, 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; exports.CiaoWorker = CiaoWorker2; } }); // 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 }; for (let i = 0; i < args.length; i++) value[i] = args[i]