Admin User, created Apr 18. 2025
/**
* Modern Albufeira Prolog Interpreter
*
* Warranty & Liability
* To the extent permitted by applicable law and unless explicitly
* otherwise agreed upon, XLOG Technologies AG makes no warranties
* regarding the provided information. XLOG Technologies AG assumes
* no liability that any problems might be solved with the information
* provided by XLOG Technologies AG.
*
* Rights & License
* All industrial property rights regarding the information - copyright
* and patent rights in particular - are the sole property of XLOG
* Technologies AG. If the company was not the originator of some
* excerpts, XLOG Technologies AG has at least obtained the right to
* reproduce, change and translate the information.
*
* Reproduction is restricted to the whole unaltered document. Reproduction
* of the information is only allowed for non-commercial uses. Selling,
* giving away or letting of the execution of the library is prohibited.
* The library can be distributed as part of your applications and libraries
* for execution provided this comment remains unchanged.
*
* Restrictions
* Only to be distributed with programs that add significant and primary
* functionality to the library. Not to be distributed with additional
* software intended to replace any components of the library.
*
* Trademarks
* Jekejeke is a registered trademark of XLOG Technologies AG.
*/
import {
get_engine, Compound, set_stage, set_partition
} from "./nova/core.mjs";
import {
fs, url, make_error
} from "./nova/core.mjs";
import {
get_bootbase, Source, set_bootbase, Sink, set_codebase,
MASK_SRC_AREAD, map_stream_error, file_read_promise
} from "./nova/core.mjs";
import {
post, perform, perform_async, goto_async, set_cursor,
set_input
} from "./nova/core.mjs";
/**
* Initializes the Prolog interpreter.
*/
export function init() {
set_stage(0);
set_partition("user");
}
/**************************************************************/
/* Plain Console */
/**************************************************************/
function plain_out(data, buf) {
try {
fs.writeSync(data, buf);
return data;
} catch (err) {
throw make_error(map_stream_error(err));
}
}
/**************************************************************/
/* Color Console */
/**************************************************************/
const ANSI_RESET = "\x1B[0m";
const ANSI_INPUT = "\x1B[32m"; // Green
const ANSI_ERROR = "\x1B[31m"; // Red
function ansi_out(data, buf) {
try {
fs.writeSync(data, ANSI_RESET);
fs.writeSync(data, buf);
fs.writeSync(data, ANSI_INPUT);
return data;
} catch (err) {
throw make_error(map_stream_error(err));
}
}
function ansi_err(data, buf) {
try {
fs.writeSync(data, ANSI_ERROR);
fs.writeSync(data, buf);
fs.writeSync(data, ANSI_INPUT);
return data;
} catch (err) {
throw make_error(map_stream_error(err));
}
}
/****************************************************************/
/* Notebook Creators */
/****************************************************************/
/**
* Setup the Prolog interpreter and the notebook instrumentation.
*/
export function notebook() {
init();
let pres = Array.from(document.getElementsByClassName("code"));
for (let num = 0; num < pres.length; num++) {
let pre = pres[num];
/* modify text */
let text = pre.innerHTML;
text = '<div class="nb_txt" contenteditable="true">' + text + '</div>';
text = text + '<div class="nb_out"></div>';
pre.innerHTML = text;
pre.className = "nb_box";
/* create button */
pre.insertAdjacentHTML("beforebegin", '<button class="nb_btn" disabled>⏵</button>');
let btn = pre.previousElementSibling;
btn.addEventListener("click", async function () {
await goto_async(pre)
});
btn.disabled = false;
}
}
/**
* Setup the Prolog interpreter and the notebook instrumentation.
*/
export async function notebook_async() {
let spec = new Compound("library",["tester/fancy"]);
await perform_async(new Compound("ensure_loaded", [spec]));
init();
let pres = Array.from(document.getElementsByClassName("code"));
for (let num = 0; num < pres.length; num++) {
let pre = pres[num];
/* modify text */
let text = pre.innerHTML;
text = '<div class="nb_txt" contenteditable="true">' + text + '</div>';
text = text + '<div class="nb_out"></div>';
pre.innerHTML = text;
pre.className = "nb_box";
/* create button */
pre.insertAdjacentHTML("beforebegin", '<button class="nb_btn" disabled>⏵</button>');
let btn = pre.previousElementSibling;
btn.addEventListener("click", async function () {
await goto_async(pre)
});
btn.disabled = false;
/* colorize text */
let txt = pre.getElementsByClassName("nb_txt")[0];
await perform_async(new Compound("colorize_elem", [txt]));
}
}
/**************************************************************/
/* When Main or Browser */
/**************************************************************/
function ctrlc_abort() {
post(new Compound("system_error", ["user_abort"]));
}
/**
* Simply colored process standard input/output.
*/
async function dogelog_async() {
process.on("SIGINT", ctrlc_abort);
try {
init();
perform("sys_baseline");
if (process.argv.length > 2) {
await perform_async("sys_launch");
} else {
let dst = new Sink();
dst.data = process.stdout.fd;
dst.send = ansi_out;
get_engine().text_output = dst;
dst = new Sink();
dst.data = process.stderr.fd;
dst.send = ansi_err;
get_engine().text_error = dst;
await perform_async("sys_launch");
fs.writeSync(process.stdout.fd, ANSI_RESET);
}
} finally {
process.off("SIGINT", ctrlc_abort);
}
}
if (fs !== undefined) {
set_bootbase(url.fileURLToPath(import.meta.url));
let dst = new Sink();
dst.data = process.stdout.fd;
dst.send = plain_out;
get_engine().text_output = dst;
dst = new Sink();
dst.data = process.stderr.fd;
dst.send = plain_out;
get_engine().text_error = dst;
let src = new Source();
src.data = 0;
src.receive = (buf, stream) => file_read_promise("utf8", buf, stream);
src.partial = Buffer.alloc(0);
src.flags |= MASK_SRC_AREAD;
get_engine().text_input = src;
if (get_bootbase() === process.argv[1])
(async () => {
try {
await dogelog_async()
} catch (err) {
perform(new Compound("sys_print_error", [err]));
process.exit(1);
}
})();
} else {
set_bootbase(import.meta.url);
set_cursor(document.body);
set_input("");
if (self.document !== undefined)
set_codebase(document.URL);
}