Update to Hoot 0.5.0.
This commit is contained in:
parent
b628b655cf
commit
825fdbc372
3 changed files with 339 additions and 40 deletions
24
manifest.scm
24
manifest.scm
|
@ -1,28 +1,8 @@
|
||||||
(use-modules (guix git-download)
|
(use-modules (guix git-download)
|
||||||
(guix packages)
|
(guix packages)
|
||||||
(gnu packages autotools)
|
|
||||||
(gnu packages base)
|
(gnu packages base)
|
||||||
(gnu packages compression)
|
(gnu packages compression)
|
||||||
(gnu packages guile)
|
(gnu packages guile)
|
||||||
(gnu packages guile-xyz)
|
(gnu packages guile-xyz))
|
||||||
(gnu packages pkg-config)
|
|
||||||
(gnu packages texinfo))
|
|
||||||
|
|
||||||
(define guile-hoot-next
|
(packages->manifest (list guile-next guile-hoot gnu-make zip))
|
||||||
(let ((commit "66eca43e7fc0478b265c7826b7e52eec866e0b21")
|
|
||||||
(revision "1"))
|
|
||||||
(package
|
|
||||||
(inherit guile-hoot)
|
|
||||||
(version (git-version "0.4.1" revision commit))
|
|
||||||
(source (origin
|
|
||||||
(method git-fetch)
|
|
||||||
(uri (git-reference
|
|
||||||
(url "https://gitlab.com/spritely/guile-hoot.git")
|
|
||||||
(commit commit)))
|
|
||||||
(file-name (git-file-name "guile-hoot" version))
|
|
||||||
(sha256
|
|
||||||
(base32 "0pd81wg6adzf1kvmgcxylailzwa0d5vdrhfpy4d54ddl31j6h824"))))
|
|
||||||
(native-inputs
|
|
||||||
(list autoconf automake pkg-config texinfo)))))
|
|
||||||
|
|
||||||
(packages->manifest (list guile-next guile-hoot-next gnu-make zip))
|
|
||||||
|
|
355
reflect.js
355
reflect.js
|
@ -141,7 +141,7 @@ class Port extends HeapObject { toString() { return "#<port>"; } }
|
||||||
class Struct extends HeapObject { toString() { return "#<struct>"; } }
|
class Struct extends HeapObject { toString() { return "#<struct>"; } }
|
||||||
|
|
||||||
function instantiate_streaming(path, imports) {
|
function instantiate_streaming(path, imports) {
|
||||||
if (typeof fetch !== 'undefined')
|
if (typeof fetch !== 'undefined' && typeof window !== 'undefined')
|
||||||
return WebAssembly.instantiateStreaming(fetch(path), imports);
|
return WebAssembly.instantiateStreaming(fetch(path), imports);
|
||||||
let bytes;
|
let bytes;
|
||||||
if (typeof read !== 'undefined') {
|
if (typeof read !== 'undefined') {
|
||||||
|
@ -155,6 +155,168 @@ function instantiate_streaming(path, imports) {
|
||||||
return WebAssembly.instantiate(bytes, imports);
|
return WebAssembly.instantiate(bytes, imports);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class IterableWeakSet {
|
||||||
|
#array;
|
||||||
|
#set;
|
||||||
|
constructor() { this.#array = []; this.#set = new WeakSet; }
|
||||||
|
#kill(i) {
|
||||||
|
let tail = this.#array.pop();
|
||||||
|
if (i < this.#array.length)
|
||||||
|
this.#array[i] = tail;
|
||||||
|
}
|
||||||
|
#get(i) {
|
||||||
|
if (i >= this.#array.length)
|
||||||
|
return null;
|
||||||
|
let obj = this.#array[i].deref();
|
||||||
|
if (obj)
|
||||||
|
return obj;
|
||||||
|
this.#kill(i);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
#cleanup() {
|
||||||
|
let i = 0;
|
||||||
|
while (this.#get(i)) i++;
|
||||||
|
}
|
||||||
|
has(x) { return this.#set.has(x); }
|
||||||
|
add(x) {
|
||||||
|
if (this.has(x))
|
||||||
|
return;
|
||||||
|
if (this.#array.length % 32 == 0)
|
||||||
|
this.#cleanup();
|
||||||
|
this.#set.add(x);
|
||||||
|
this.#array.push(new WeakRef(x));
|
||||||
|
}
|
||||||
|
delete(x) {
|
||||||
|
if (!this.has(x))
|
||||||
|
return;
|
||||||
|
this.#set.delete(x);
|
||||||
|
let i = 0;
|
||||||
|
while (this.#get(i) != x) i++;
|
||||||
|
this.#kill(i);
|
||||||
|
}
|
||||||
|
*[Symbol.iterator]() {
|
||||||
|
for (let i = 0, x; x = this.#get(i); i++)
|
||||||
|
yield x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See:
|
||||||
|
// https://github.com/tc39/proposal-weakrefs?tab=readme-ov-file#iterable-weakmaps
|
||||||
|
class IterableWeakMap {
|
||||||
|
#weakMap = new WeakMap();
|
||||||
|
#refSet = new Set();
|
||||||
|
#finalizationGroup = new FinalizationRegistry(IterableWeakMap.#cleanup);
|
||||||
|
|
||||||
|
static #cleanup({ set, ref }) {
|
||||||
|
set.delete(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(iterable) {
|
||||||
|
for (const [key, value] of iterable) {
|
||||||
|
this.set(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set(key, value) {
|
||||||
|
const ref = new WeakRef(key);
|
||||||
|
|
||||||
|
this.#weakMap.set(key, { value, ref });
|
||||||
|
this.#refSet.add(ref);
|
||||||
|
this.#finalizationGroup.register(key, {
|
||||||
|
set: this.#refSet,
|
||||||
|
ref
|
||||||
|
}, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
get(key) {
|
||||||
|
const entry = this.#weakMap.get(key);
|
||||||
|
return entry && entry.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(key) {
|
||||||
|
const entry = this.#weakMap.get(key);
|
||||||
|
if (!entry) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#weakMap.delete(key);
|
||||||
|
this.#refSet.delete(entry.ref);
|
||||||
|
this.#finalizationGroup.unregister(entry.ref);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*[Symbol.iterator]() {
|
||||||
|
for (const ref of this.#refSet) {
|
||||||
|
const key = ref.deref();
|
||||||
|
if (!key) continue;
|
||||||
|
const { value } = this.#weakMap.get(key);
|
||||||
|
yield [key, value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entries() {
|
||||||
|
return this[Symbol.iterator]();
|
||||||
|
}
|
||||||
|
|
||||||
|
*keys() {
|
||||||
|
for (const [key, value] of this) {
|
||||||
|
yield key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*values() {
|
||||||
|
for (const [key, value] of this) {
|
||||||
|
yield value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// class IterableWeakMap {
|
||||||
|
// #array;
|
||||||
|
// #map;
|
||||||
|
// constructor() { this.#array = []; this.#map = new WeakMap; }
|
||||||
|
// #kill(i) {
|
||||||
|
// let tail = this.#array.pop();
|
||||||
|
// if (i < this.#array.length)
|
||||||
|
// this.#array[i] = tail;
|
||||||
|
// }
|
||||||
|
// #geti(i) {
|
||||||
|
// // If a dead weak ref is at i then kill it and try again with
|
||||||
|
// // the next weak ref.
|
||||||
|
// while (true) {
|
||||||
|
// if (i >= this.#array.length)
|
||||||
|
// return null;
|
||||||
|
// let obj = this.#array[i].deref();
|
||||||
|
// if (obj)
|
||||||
|
// return obj;
|
||||||
|
// this.#kill(i);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// #cleanup() {
|
||||||
|
// let i = 0;
|
||||||
|
// while (this.#get(i)) i++;
|
||||||
|
// }
|
||||||
|
// has(k) { return this.#map.has(k); }
|
||||||
|
// get(k) { return this.#map.get(k); }
|
||||||
|
// set(k, v) {
|
||||||
|
// if (this.#array.length % 32 == 0)
|
||||||
|
// this.#cleanup();
|
||||||
|
// this.#map.set(k, v);
|
||||||
|
// this.#array.push(new WeakRef(k));
|
||||||
|
// }
|
||||||
|
// delete(k) {
|
||||||
|
// if (!this.has(k))
|
||||||
|
// return;
|
||||||
|
// this.#map.delete(k);
|
||||||
|
// let i = 0;
|
||||||
|
// while (this.#geti(i) != k) i++;
|
||||||
|
// this.#kill(i);
|
||||||
|
// }
|
||||||
|
// *[Symbol.iterator]() {
|
||||||
|
// for (let i = 0, k; k = this.#geti(i); i++)
|
||||||
|
// yield [k, this.get(k)];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
class Scheme {
|
class Scheme {
|
||||||
#instance;
|
#instance;
|
||||||
#abi;
|
#abi;
|
||||||
|
@ -170,9 +332,11 @@ class Scheme {
|
||||||
debug_str_scm: (x, y) => {
|
debug_str_scm: (x, y) => {
|
||||||
console.log(`reflect debug: ${x}: #<scm>`);
|
console.log(`reflect debug: ${x}: #<scm>`);
|
||||||
},
|
},
|
||||||
|
code_source(x) { return ['???', 0, 0]; }
|
||||||
};
|
};
|
||||||
let reflect_wasm = reflect_wasm_dir + '/reflect.wasm';
|
let reflect_wasm = reflect_wasm_dir + '/reflect.wasm';
|
||||||
let rt = {
|
let rt = {
|
||||||
|
quit(status) { throw new SchemeQuitError(status); },
|
||||||
die(tag, data) { throw new SchemeTrapError(tag, data); },
|
die(tag, data) { throw new SchemeTrapError(tag, data); },
|
||||||
wtf8_to_string(wtf8) { return wtf8_to_string(wtf8); },
|
wtf8_to_string(wtf8) { return wtf8_to_string(wtf8); },
|
||||||
string_to_wtf8(str) { return string_to_wtf8(str); },
|
string_to_wtf8(str) { return string_to_wtf8(str); },
|
||||||
|
@ -348,6 +512,11 @@ class SchemeTrapError extends Error {
|
||||||
toString() { return `SchemeTrap(${this.tag}, <data>)`; }
|
toString() { return `SchemeTrap(${this.tag}, <data>)`; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SchemeQuitError extends Error {
|
||||||
|
constructor(status) { super(); this.status = status; }
|
||||||
|
toString() { return `SchemeQuit(status=${this.status})`; }
|
||||||
|
}
|
||||||
|
|
||||||
function string_repr(str) {
|
function string_repr(str) {
|
||||||
// FIXME: Improve to match Scheme.
|
// FIXME: Improve to match Scheme.
|
||||||
return '"' + str.replace(/(["\\])/g, '\\$1').replace(/\n/g, '\\n') + '"';
|
return '"' + str.replace(/(["\\])/g, '\\$1').replace(/\n/g, '\\n') + '"';
|
||||||
|
@ -415,6 +584,18 @@ async function load_wtf8_helper_module(reflect_wasm_dir = '') {
|
||||||
wtf8_helper = instance;
|
wtf8_helper = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function make_textual_writable_stream(write_chars) {
|
||||||
|
const decoder = new TextDecoder("utf-8");
|
||||||
|
return new WritableStream({
|
||||||
|
write(chunk) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
write_chars(decoder.decode(chunk, { stream: true }));
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
class SchemeModule {
|
class SchemeModule {
|
||||||
#instance;
|
#instance;
|
||||||
#io_handler;
|
#io_handler;
|
||||||
|
@ -469,7 +650,6 @@ class SchemeModule {
|
||||||
bignum_logand(a, b) { return BigInt(a) & BigInt(b); },
|
bignum_logand(a, b) { return BigInt(a) & BigInt(b); },
|
||||||
bignum_logior(a, b) { return BigInt(a) | BigInt(b); },
|
bignum_logior(a, b) { return BigInt(a) | BigInt(b); },
|
||||||
bignum_logxor(a, b) { return BigInt(a) ^ BigInt(b); },
|
bignum_logxor(a, b) { return BigInt(a) ^ BigInt(b); },
|
||||||
bignum_logsub(a, b) { return BigInt(a) & (~ BigInt(b)); },
|
|
||||||
|
|
||||||
bignum_lt(a, b) { return a < b; },
|
bignum_lt(a, b) { return a < b; },
|
||||||
bignum_le(a, b) { return a <= b; },
|
bignum_le(a, b) { return a <= b; },
|
||||||
|
@ -477,14 +657,17 @@ class SchemeModule {
|
||||||
|
|
||||||
bignum_to_f64(n) { return Number(n); },
|
bignum_to_f64(n) { return Number(n); },
|
||||||
|
|
||||||
f64_is_nan(n) { return Number.isNaN(n); },
|
|
||||||
f64_is_infinite(n) { return !Number.isFinite(n); },
|
|
||||||
|
|
||||||
flonum_to_string,
|
flonum_to_string,
|
||||||
|
|
||||||
string_upcase: Function.call.bind(String.prototype.toUpperCase),
|
string_upcase: Function.call.bind(String.prototype.toUpperCase),
|
||||||
string_downcase: Function.call.bind(String.prototype.toLowerCase),
|
string_downcase: Function.call.bind(String.prototype.toLowerCase),
|
||||||
|
|
||||||
|
make_weak_ref(x) { return new WeakRef(x); },
|
||||||
|
weak_ref_deref(ref, fail) {
|
||||||
|
const val = ref.deref();
|
||||||
|
return val === undefined ? fail: val;
|
||||||
|
},
|
||||||
|
|
||||||
make_weak_map() { return new WeakMap; },
|
make_weak_map() { return new WeakMap; },
|
||||||
weak_map_get(map, k, fail) {
|
weak_map_get(map, k, fail) {
|
||||||
const val = map.get(k);
|
const val = map.get(k);
|
||||||
|
@ -493,6 +676,14 @@ class SchemeModule {
|
||||||
weak_map_set(map, k, v) { return map.set(k, v); },
|
weak_map_set(map, k, v) { return map.set(k, v); },
|
||||||
weak_map_delete(map, k) { return map.delete(k); },
|
weak_map_delete(map, k) { return map.delete(k); },
|
||||||
|
|
||||||
|
make_finalization_registry(f) { return new FinalizationRegistry(f); },
|
||||||
|
finalization_registry_register(registry, target, heldValue, unregisterToken) {
|
||||||
|
registry.register(target, heldValue, unregisterToken);
|
||||||
|
},
|
||||||
|
finalization_registry_unregister(registry, unregisterToken) {
|
||||||
|
registry.unregister(unregisterToken);
|
||||||
|
},
|
||||||
|
|
||||||
fsqrt: Math.sqrt,
|
fsqrt: Math.sqrt,
|
||||||
fsin: Math.sin,
|
fsin: Math.sin,
|
||||||
fcos: Math.cos,
|
fcos: Math.cos,
|
||||||
|
@ -510,7 +701,15 @@ class SchemeModule {
|
||||||
|
|
||||||
async_invoke,
|
async_invoke,
|
||||||
async_invoke_later,
|
async_invoke_later,
|
||||||
promise_on_completed(p, kt, kf) { p.then(kt, kf); },
|
promise_on_completed(p, kt, kf) {
|
||||||
|
p.then((val) => {
|
||||||
|
if (val === undefined) {
|
||||||
|
kt(false);
|
||||||
|
} else {
|
||||||
|
kt(val);
|
||||||
|
}
|
||||||
|
}, kf);
|
||||||
|
},
|
||||||
promise_complete(callback, val) { callback(val); },
|
promise_complete(callback, val) { callback(val); },
|
||||||
|
|
||||||
// Wrap in functions to allow for lazy loading of the wtf8
|
// Wrap in functions to allow for lazy loading of the wtf8
|
||||||
|
@ -518,11 +717,73 @@ class SchemeModule {
|
||||||
wtf8_to_string(wtf8) { return wtf8_to_string(wtf8); },
|
wtf8_to_string(wtf8) { return wtf8_to_string(wtf8); },
|
||||||
string_to_wtf8(str) { return string_to_wtf8(str); },
|
string_to_wtf8(str) { return string_to_wtf8(str); },
|
||||||
|
|
||||||
die(tag, data) { throw new SchemeTrapError(tag, data); }
|
make_regexp(pattern, flags) { return new RegExp(pattern, flags); },
|
||||||
|
regexp_exec(re, str) { return re.exec(str); },
|
||||||
|
regexp_match_string(m) { return m.input; },
|
||||||
|
regexp_match_start(m) { return m.index; },
|
||||||
|
regexp_match_end(m) { return m.index + m[0].length; },
|
||||||
|
regexp_match_count(m) { return m.length; },
|
||||||
|
regexp_match_substring(m, i) {
|
||||||
|
const str = m[i];
|
||||||
|
if (str === undefined) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
|
||||||
|
die(tag, data) { throw new SchemeTrapError(tag, data); },
|
||||||
|
quit(status) { throw new SchemeQuitError(status); },
|
||||||
|
|
||||||
|
stream_make_chunk(len) { return new Uint8Array(len); },
|
||||||
|
stream_chunk_length(chunk) { return chunk.length; },
|
||||||
|
stream_chunk_ref(chunk, idx) { return chunk[idx]; },
|
||||||
|
stream_chunk_set(chunk, idx, val) { chunk[idx] = val; },
|
||||||
|
stream_get_reader(stream) { return stream.getReader(); },
|
||||||
|
stream_read(reader) { return reader.read(); },
|
||||||
|
stream_result_chunk(result) { return result.value; },
|
||||||
|
stream_result_done(result) { return result.done ? 1 : 0; },
|
||||||
|
stream_get_writer(stream) { return stream.getWriter(); },
|
||||||
|
stream_write(writer, chunk) { return writer.write(chunk); },
|
||||||
|
stream_close_writer(writer) { return writer.close(); },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static #code_origins = new WeakMap;
|
||||||
|
static #all_modules = new IterableWeakSet;
|
||||||
|
static #code_origin(code) {
|
||||||
|
if (SchemeModule.#code_origins.has(code))
|
||||||
|
return SchemeModule.#code_origins.get(code);
|
||||||
|
for (let mod of SchemeModule.#all_modules) {
|
||||||
|
for (let i = 0, x = null; x = mod.instance_code(i); i++) {
|
||||||
|
let origin = [mod, i];
|
||||||
|
if (!SchemeModule.#code_origins.has(x))
|
||||||
|
SchemeModule.#code_origins.set(x, origin);
|
||||||
|
if (x === code)
|
||||||
|
return origin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [null, 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static #code_name(code) {
|
||||||
|
let [mod, idx] = SchemeModule.#code_origin(code);
|
||||||
|
if (mod)
|
||||||
|
return mod.instance_code_name(idx);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static #code_source(code) {
|
||||||
|
let [mod, idx] = SchemeModule.#code_origin(code);
|
||||||
|
if (mod)
|
||||||
|
return mod.instance_code_source(idx);
|
||||||
|
return [null, 0, 0];
|
||||||
|
}
|
||||||
|
|
||||||
constructor(instance) {
|
constructor(instance) {
|
||||||
|
SchemeModule.#all_modules.add(this);
|
||||||
this.#instance = instance;
|
this.#instance = instance;
|
||||||
|
let open_file_error = (filename) => {
|
||||||
|
throw new Error('No file system access');
|
||||||
|
};
|
||||||
if (typeof printErr === 'function') { // v8/sm dev console
|
if (typeof printErr === 'function') { // v8/sm dev console
|
||||||
// On the console, try to use 'write' (v8) or 'putstr' (sm),
|
// On the console, try to use 'write' (v8) or 'putstr' (sm),
|
||||||
// as these don't add an extraneous newline. Unfortunately
|
// as these don't add an extraneous newline. Unfortunately
|
||||||
|
@ -541,14 +802,13 @@ class SchemeModule {
|
||||||
return '\n';
|
return '\n';
|
||||||
}
|
}
|
||||||
}: () => '';
|
}: () => '';
|
||||||
let delete_file = (filename) => false;
|
|
||||||
this.#io_handler = {
|
this.#io_handler = {
|
||||||
write_stdout: write_no_newline,
|
write_stdout: write_no_newline,
|
||||||
write_stderr: printErr,
|
write_stderr: printErr,
|
||||||
read_stdin,
|
read_stdin,
|
||||||
file_exists: (filename) => false,
|
file_exists: (filename) => false,
|
||||||
open_input_file: (filename) => {},
|
open_input_file: open_file_error,
|
||||||
open_output_file: (filename) => {},
|
open_output_file: open_file_error,
|
||||||
close_file: () => undefined,
|
close_file: () => undefined,
|
||||||
read_file: (handle, length) => 0,
|
read_file: (handle, length) => 0,
|
||||||
write_file: (handle, length) => 0,
|
write_file: (handle, length) => 0,
|
||||||
|
@ -557,7 +817,11 @@ class SchemeModule {
|
||||||
file_buffer_size: (handle) => 0,
|
file_buffer_size: (handle) => 0,
|
||||||
file_buffer_ref: (handle, i) => 0,
|
file_buffer_ref: (handle, i) => 0,
|
||||||
file_buffer_set: (handle, i, x) => undefined,
|
file_buffer_set: (handle, i, x) => undefined,
|
||||||
delete_file: (filename) => undefined
|
delete_file: (filename) => undefined,
|
||||||
|
// FIXME: We should polyfill these out.
|
||||||
|
stream_stdin() { throw new Error('stream_stdin not implemented'); },
|
||||||
|
stream_stdout() { throw new Error('stream_stderr not implemented'); },
|
||||||
|
stream_stderr() { throw new Error('stream_stderr not implemented'); },
|
||||||
};
|
};
|
||||||
} else if (typeof window !== 'undefined') { // web browser
|
} else if (typeof window !== 'undefined') { // web browser
|
||||||
this.#io_handler = {
|
this.#io_handler = {
|
||||||
|
@ -565,8 +829,8 @@ class SchemeModule {
|
||||||
write_stderr: console.error,
|
write_stderr: console.error,
|
||||||
read_stdin: () => '',
|
read_stdin: () => '',
|
||||||
file_exists: (filename) => false,
|
file_exists: (filename) => false,
|
||||||
open_input_file: (filename) => {},
|
open_input_file: open_file_error,
|
||||||
open_output_file: (filename) => {},
|
open_output_file: open_file_error,
|
||||||
close_file: () => undefined,
|
close_file: () => undefined,
|
||||||
read_file: (handle, length) => 0,
|
read_file: (handle, length) => 0,
|
||||||
write_file: (handle, length) => 0,
|
write_file: (handle, length) => 0,
|
||||||
|
@ -575,17 +839,26 @@ class SchemeModule {
|
||||||
file_buffer_size: (handle) => 0,
|
file_buffer_size: (handle) => 0,
|
||||||
file_buffer_ref: (handle, i) => 0,
|
file_buffer_ref: (handle, i) => 0,
|
||||||
file_buffer_set: (handle, i, x) => undefined,
|
file_buffer_set: (handle, i, x) => undefined,
|
||||||
delete_file: (filename) => undefined
|
delete_file: (filename) => undefined,
|
||||||
|
stream_stdin() { return new ReadableStream; },
|
||||||
|
stream_stdout() {
|
||||||
|
return make_textual_writable_stream(s => console.log(s));
|
||||||
|
},
|
||||||
|
stream_stderr() {
|
||||||
|
return make_textual_writable_stream(s => console.error(s));
|
||||||
|
},
|
||||||
};
|
};
|
||||||
} else { // nodejs
|
} else { // nodejs
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const process = require('process');
|
const process = require('process');
|
||||||
|
const { ReadableStream, WritableStream } = require('node:stream/web');
|
||||||
|
|
||||||
const bufLength = 1024;
|
const bufLength = 1024;
|
||||||
const stdinBuf = Buffer.alloc(bufLength);
|
const stdinBuf = Buffer.alloc(bufLength);
|
||||||
const SEEK_SET = 0, SEEK_CUR = 1, SEEK_END = 2;
|
const SEEK_SET = 0, SEEK_CUR = 1, SEEK_END = 2;
|
||||||
this.#io_handler = {
|
this.#io_handler = {
|
||||||
write_stdout: console.log,
|
write_stdout: process.stdout.write.bind(process.stdout),
|
||||||
write_stderr: console.error,
|
write_stderr: process.stderr.write.bind(process.stderr),
|
||||||
read_stdin: () => {
|
read_stdin: () => {
|
||||||
let n = fs.readSync(process.stdin.fd, stdinBuf, 0, stdinBuf.length);
|
let n = fs.readSync(process.stdin.fd, stdinBuf, 0, stdinBuf.length);
|
||||||
return stdinBuf.toString('utf8', 0, n);
|
return stdinBuf.toString('utf8', 0, n);
|
||||||
|
@ -646,7 +919,23 @@ class SchemeModule {
|
||||||
file_buffer_set: (handle, i, x) => {
|
file_buffer_set: (handle, i, x) => {
|
||||||
handle.buf[i] = x;
|
handle.buf[i] = x;
|
||||||
},
|
},
|
||||||
delete_file: fs.rmSync.bind(fs)
|
delete_file: fs.rmSync.bind(fs),
|
||||||
|
stream_stdin() {
|
||||||
|
return new ReadableStream({
|
||||||
|
async start(controller) {
|
||||||
|
for await (const chunk of process.stdin) {
|
||||||
|
controller.enqueue(chunk);
|
||||||
|
}
|
||||||
|
controller.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
stream_stdout() {
|
||||||
|
return make_textual_writable_stream(s => process.stdout.write(s));
|
||||||
|
},
|
||||||
|
stream_stderr() {
|
||||||
|
return make_textual_writable_stream(s => process.stderr.write(s));
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
this.#debug_handler = {
|
this.#debug_handler = {
|
||||||
|
@ -673,12 +962,17 @@ class SchemeModule {
|
||||||
file_buffer_size(handle) { return mod.#io_handler.file_buffer_size(handle); },
|
file_buffer_size(handle) { return mod.#io_handler.file_buffer_size(handle); },
|
||||||
file_buffer_ref(handle, i) { return mod.#io_handler.file_buffer_ref(handle, i); },
|
file_buffer_ref(handle, i) { return mod.#io_handler.file_buffer_ref(handle, i); },
|
||||||
file_buffer_set(handle, i, x) { return mod.#io_handler.file_buffer_set(handle, i, x); },
|
file_buffer_set(handle, i, x) { return mod.#io_handler.file_buffer_set(handle, i, x); },
|
||||||
delete_file(filename) { mod.#io_handler.delete_file(filename); }
|
delete_file(filename) { mod.#io_handler.delete_file(filename); },
|
||||||
|
stream_stdin() { return mod.#io_handler.stream_stdin(); },
|
||||||
|
stream_stdout() { return mod.#io_handler.stream_stdout(); },
|
||||||
|
stream_stderr() { return mod.#io_handler.stream_stderr(); },
|
||||||
};
|
};
|
||||||
let debug = {
|
let debug = {
|
||||||
debug_str(x) { mod.#debug_handler.debug_str(x); },
|
debug_str(x) { mod.#debug_handler.debug_str(x); },
|
||||||
debug_str_i32(x, y) { mod.#debug_handler.debug_str_i32(x, y); },
|
debug_str_i32(x, y) { mod.#debug_handler.debug_str_i32(x, y); },
|
||||||
debug_str_scm(x, y) { mod.#debug_handler.debug_str_scm(x, y); },
|
debug_str_scm(x, y) { mod.#debug_handler.debug_str_scm(x, y); },
|
||||||
|
code_name(code) { return SchemeModule.#code_name(code); },
|
||||||
|
code_source(code) { return SchemeModule.#code_source(code); },
|
||||||
}
|
}
|
||||||
let ffi = {
|
let ffi = {
|
||||||
procedure_to_extern(proc) {
|
procedure_to_extern(proc) {
|
||||||
|
@ -718,6 +1012,24 @@ class SchemeModule {
|
||||||
return this.all_exports()[name];
|
return this.all_exports()[name];
|
||||||
throw new Error(`unknown export: ${name}`)
|
throw new Error(`unknown export: ${name}`)
|
||||||
}
|
}
|
||||||
|
instance_code(idx) {
|
||||||
|
if ('%instance-code' in this.all_exports()) {
|
||||||
|
return this.all_exports()['%instance-code'](idx);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
instance_code_name(idx) {
|
||||||
|
if ('%instance-code-name' in this.all_exports()) {
|
||||||
|
return this.all_exports()['%instance-code-name'](idx);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
instance_code_source(idx) {
|
||||||
|
if ('%instance-code-source' in this.all_exports()) {
|
||||||
|
return this.all_exports()['%instance-code-source'](idx);
|
||||||
|
}
|
||||||
|
return [null, 0, 0];
|
||||||
|
}
|
||||||
async reflect(opts = {}) {
|
async reflect(opts = {}) {
|
||||||
return await Scheme.reflect(this.exported_abi(), opts);
|
return await Scheme.reflect(this.exported_abi(), opts);
|
||||||
}
|
}
|
||||||
|
@ -734,3 +1046,10 @@ function repr(obj) {
|
||||||
return string_repr(obj);
|
return string_repr(obj);
|
||||||
return obj + '';
|
return obj + '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Modulize when possible.
|
||||||
|
if (typeof exports !== 'undefined') {
|
||||||
|
exports.Scheme = Scheme;
|
||||||
|
exports.SchemeQuitError = SchemeQuitError;
|
||||||
|
exports.repr = repr;
|
||||||
|
}
|
||||||
|
|
BIN
reflect.wasm
BIN
reflect.wasm
Binary file not shown.
Loading…
Add table
Reference in a new issue