JavaScript "hacklib"

         
/**
* 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 {
set, deref, is_structure, make_check, MAX_ARITY, check_nil,
exec_build, exec_unify, fs, Compound, get_ctx, make_error
} from "../../nova/core.mjs";
let workers;
if (typeof window === 'undefined') {
workers = await import("node:worker_threads");
} else {
workers = undefined;
}
const GROUP_SIZE = 8;
function CpuMap() {
this.code = undefined;
this.offset = undefined;
this.state = undefined;
}
/******************************************************************/
/* Hack Input/Output */
/******************************************************************/
function read_ints() {
fs.writeSync(process.stdout.fd, ": ");
let res = Buffer.alloc(1024);
let len = fs.readSync(0, res, 0, 1024);
let line = res.toString('utf8', 0, len);
return line.split(" ")
.filter(s => s !== "")
.map(t => Number(BigInt.asIntN(32, BigInt(t))));
}
function write_ints(res) {
for (let i = 0; i < res.length; i++) {
fs.writeSync(process.stdout.fd, res[i].toString());
fs.writeSync(process.stdout.fd, " ");
}
fs.writeSync(process.stdout.fd, "\n");
}
/******************************************************************/
/* Hack Constructors */
/******************************************************************/
/**
* test_cpu_data_new(A, B): internal only
* The predicate succeeds in B with a pi-WAM buffer for the list A.
*/
function test_cpu_data_new(args) {
let alpha = exec_build(args[0]);
let res = cpu_list_ints(alpha);
return exec_unify(args[1], res);
}
function cpu_list_ints(obj) {
let peek = obj;
let i = 0;
while (is_structure(peek) &&
"." === peek.functor &&
peek.args.length === 2 &&
i < MAX_ARITY) {
i++;
peek = deref(peek.args[1]);
}
check_nil(peek);
if (typeof SharedArrayBuffer === 'undefined')
throw make_error(new Compound("resource_error", ["shared_missing"]));
let buf = new SharedArrayBuffer(i * 4);
let args = new Int32Array(buf);
peek = obj;
i = 0;
while (is_structure(peek) &&
"." === peek.functor &&
peek.args.length === 2) {
let val = deref(peek.args[0]);
args[i++] = int32(val);
peek = deref(peek.args[1]);
}
return args;
}
export function int32(val) {
if (typeof val === 'number') {
return val | 0;
} else {
return Number(BigInt.asIntN(32, val));
}
}
/**
* test_cpu_comp_new(C, O, S, M): internal only
* The predicate succeeds in M with a new CPU backed π-WAM for
* the code buffer C, the offsets O and the state buffer S.
*/
function test_cpu_comp_new(args) {
let res = new CpuMap();
res.code = exec_build(args[0]);
res.offset = exec_build(args[1]);
res.state = exec_build(args[2]);
return exec_unify(args[3], res);
}
/**
* test_cpu_comp_work(M, W): internal only
* The predicate succeeds in W with the current
* group size of the CPU backed π-WAM M.
*/
function test_cpu_comp_work(args) {
let alpha = exec_build(args[0]);
let res = GROUP_SIZE;
return exec_unify(args[1], res);
}
/******************************************************************/
/* Worker Utility */
/******************************************************************/
function thread_handler(worker, msg) {
switch (msg.cmd) {
case "finish":
if (worker.func !== undefined) {
let temp = worker.func;
worker.func = undefined;
temp();
} else {
worker.res = null;
}
break;
case "output":
write_ints(msg.arg);
break;
case "input":
let para = read_ints();
worker.postMessage({cmd: "result", arg: para});
break;
default:
throw new Error("illegal cmd");
}
}
function thread_new() {
let worker;
if (fs !== undefined) {
worker = new workers.Worker(new URL('worker.mjs', import.meta.url),
{ type: 'module' });
} else {
worker = new Worker(new URL('worker.mjs', import.meta.url),
{ type: 'module' });
}
if (fs !== undefined) {
worker.on('message', (msg) => thread_handler(worker, msg));
} else {
worker.onmessage = (event) => thread_handler(worker, event.data);
}
return worker;
}
/******************************************************************/
/* Hack Interface */
/******************************************************************/
/**
* test_cpu_group_new(M, G): internal only
* The predicate succeeds in G with a
* new group for the CPU backed π-WAM M.
*/
function test_cpu_group_new(args) {
let alpha = exec_build(args[0]);
let res = thread_new();
res.map = alpha;
res.postMessage({cmd: "init", code: alpha.code,
offset: alpha.offset, state: alpha.state});
return exec_unify(args[1], res);
}
/**
* test_cpu_group_start(G, I): internal only
* The predicate succeeds. As a side effect it
* starts the group G at group index I.
*/
function test_cpu_group_start(args) {
let alpha = exec_build(args[0]);
let beta = exec_build(args[1]);
let at = int32(beta)*GROUP_SIZE;
let len = Math.min(alpha.map.offset.length - at, GROUP_SIZE);
alpha.postMessage({cmd: "run", at: at, len: len});
return true;
}
/**
* test_cpu_group_join(G, P): internal only
* The predicate succeeds in P with a new promise
* that waits for the group G to finish.
*/
function test_cpu_group_join(args) {
let alpha = exec_build(args[0]);
let buf = get_ctx();
return exec_unify(args[1], join_promise(buf, alpha));
}
function join_promise(buf, alpha) {
return new Promise((resolve) => {
if (alpha.res !== undefined) {
alpha.res = undefined;
resolve();
} else {
alpha.func = resolve;
}
});
}
/**
* test_cpu_group_free(G): internal only
* The predicate succeeds. As a side effect
* it frees the group G.
*/
function test_cpu_group_free(args) {
let alpha = exec_build(args[0]);
alpha.terminate();
return true;
}
/******************************************************************/
/* Hack Lib Init */
/******************************************************************/
export function main() {
set("cpu_data_new", 2, make_check(test_cpu_data_new));
set("cpu_comp_new", 4, make_check(test_cpu_comp_new));
set("cpu_comp_work", 2, make_check(test_cpu_comp_work));
set("cpu_group_new", 2, make_check(test_cpu_group_new));
set("cpu_group_start", 2, make_check(test_cpu_group_start));
set("cpu_group_join", 2, make_check(test_cpu_group_join));
set("cpu_group_free", 1, make_check(test_cpu_group_free));
}

Use Privacy (c) 2005-2026 XLOG Technologies AG