Use latest hoot.

This commit is contained in:
David Thompson 2024-05-17 15:39:29 -04:00
parent 0279623e2a
commit 7d728559d0
5 changed files with 74 additions and 27 deletions

View file

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="js-runtime/reflect.js"></script>
<script type="text/javascript" src="reflect.js"></script>
<script type="text/javascript" src="game.js"></script>
<link rel="stylesheet" href="game.css" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

View file

@ -1,7 +1,28 @@
(use-modules (guix packages)
(use-modules (guix git-download)
(guix packages)
(gnu packages autotools)
(gnu packages base)
(gnu packages compression)
(gnu packages guile)
(gnu packages guile-xyz))
(gnu packages guile-xyz)
(gnu packages pkg-config)
(gnu packages texinfo))
(packages->manifest (list guile-next guile-hoot gnu-make zip))
(define guile-hoot-next
(let ((commit "bdc355d97a88b1337c14d3155ce83fe699b405ac")
(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 "0p18zy505flacvqi4r2xp42gljnpq86fydvw2k154aw89chhkc32"))))
(native-inputs
(list autoconf automake pkg-config texinfo)))))
(packages->manifest (list guile-next guile-hoot-next gnu-make zip))

View file

@ -115,6 +115,9 @@ class Procedure extends HeapObject {
call(...arg) {
return this.reflector.call(this, ...arg);
}
async call_async(...arg) {
return await this.reflector.call_async(this, ...arg);
}
}
class Sym extends HeapObject {
@ -160,7 +163,7 @@ class Scheme {
this.#abi = abi;
}
static async reflect(abi) {
static async reflect(abi, {reflect_wasm_dir = '.'}) {
let debug = {
debug_str(x) { console.log(`reflect debug: ${x}`); },
debug_str_i32(x, y) { console.log(`reflect debug: ${x}: ${y}`); },
@ -168,16 +171,14 @@ class Scheme {
console.log(`reflect debug: ${x}: #<scm>`);
},
};
let reflect_wasm = reflect_wasm_dir + '/reflect.wasm';
let rt = {
die(tag, data) { throw new SchemeTrapError(tag, data); },
wtf8_to_string(wtf8) { return wtf8_to_string(wtf8); },
string_to_wtf8(str) { return string_to_wtf8(str); },
};
let { module, instance } =
await instantiate_streaming('js-runtime/reflect.wasm', {
abi,
debug,
rt: {
die(tag, data) { throw new SchemeTrapError(tag, data); },
wtf8_to_string(wtf8) { return wtf8_to_string(wtf8); },
string_to_wtf8(str) { return string_to_wtf8(str); },
}
});
await instantiate_streaming(reflect_wasm, { abi, debug, rt });
return new Scheme(instance, abi);
}
@ -200,13 +201,14 @@ class Scheme {
let proc = new Procedure(this, mod.get_export('$load').value);
return proc.call();
}
static async load_main(path, abi, user_imports = {}) {
let mod = await SchemeModule.fetch_and_instantiate(path, abi, user_imports);
let reflect = await mod.reflect();
static async load_main(path, opts = {}) {
let mod = await SchemeModule.fetch_and_instantiate(path, opts);
let reflect = await mod.reflect(opts);
return reflect.#init_module(mod);
}
async load_extension(path, user_imports = {}) {
let mod = await SchemeModule.fetch_and_instantiate(path, this.#abi, user_imports);
async load_extension(path, opts = {}) {
opts = Object.assign({ abi: this.#abi }, opts);
let mod = await SchemeModule.fetch_and_instantiate(path, opts);
return this.#init_module(mod);
}
@ -236,6 +238,8 @@ class Scheme {
if (js instanceof Complex)
return api.scm_from_complex(js.real, js.imag);
return api.scm_from_extern(js);
} else if (typeof(js) == 'function') {
return api.scm_from_extern(js);
} else {
throw new Error(`unexpected; ${typeof(js)}`);
}
@ -301,6 +305,15 @@ class Scheme {
return results;
}
call_async(func, ...args) {
return new Promise((resolve, reject) => {
this.call(func,
val => resolve(this.#to_js(val)),
err => reject(this.#to_js(err)),
...args);
})
}
car(x) { return this.#to_js(this.#instance.exports.car(x.obj)); }
cdr(x) { return this.#to_js(this.#instance.exports.cdr(x.obj)); }
@ -353,6 +366,13 @@ function flonum_to_string(f64) {
}
}
let async_invoke = typeof queueMicrotask !== 'undefined'
? queueMicrotask
: thunk => setTimeout(thunk, 0);
function async_invoke_later(thunk, jiffies) {
setTimeout(thunk, jiffies / 1000);
}
let wtf8_helper;
function wtf8_to_string(wtf8) {
@ -388,9 +408,10 @@ function string_to_wtf8(str) {
return finish_builder(builder);
}
async function load_wtf8_helper_module() {
async function load_wtf8_helper_module(reflect_wasm_dir = '') {
if (wtf8_helper) return;
let { module, instance } = await instantiate_streaming("js-runtime/wtf8.wasm");
let wtf8_wasm = reflect_wasm_dir + "/wtf8.wasm";
let { module, instance } = await instantiate_streaming(wtf8_wasm);
wtf8_helper = instance;
}
@ -487,6 +508,11 @@ class SchemeModule {
current_jiffy() { return performance.now() * 1000; },
current_second() { return Date.now() / 1000; },
async_invoke,
async_invoke_later,
promise_on_completed(p, kt, kf) { p.then(kt, kf); },
promise_complete(callback, val) { callback(val); },
// Wrap in functions to allow for lazy loading of the wtf8
// module.
wtf8_to_string(wtf8) { return wtf8_to_string(wtf8); },
@ -629,8 +655,9 @@ class SchemeModule {
debug_str_scm(x, y) { console.log(`debug: ${x}: #<scm>`); },
};
}
static async fetch_and_instantiate(path, imported_abi, user_imports = {}) {
await load_wtf8_helper_module();
static async fetch_and_instantiate(path, { abi, reflect_wasm_dir = '.',
user_imports = {} }) {
await load_wtf8_helper_module(reflect_wasm_dir);
let io = {
write_stdout(str) { mod.#io_handler.write_stdout(str); },
write_stderr(str) { mod.#io_handler.write_stderr(str); },
@ -660,8 +687,7 @@ class SchemeModule {
};
let imports = {
rt: SchemeModule.#rt,
abi: imported_abi,
debug, io, ffi, ...user_imports
abi, debug, io, ffi, ...user_imports
};
let { module, instance } = await instantiate_streaming(path, imports);
let mod = new SchemeModule(instance);
@ -692,8 +718,8 @@ class SchemeModule {
return this.all_exports()[name];
throw new Error(`unknown export: ${name}`)
}
async reflect() {
return await Scheme.reflect(this.exported_abi());
async reflect(opts = {}) {
return await Scheme.reflect(this.exported_abi(), opts);
}
}