Thinking through what something like a groveller would look like, except instead helping to automate js<->hoot FFI.
Something like this seems to be totally ok:
await Scheme.load_main("game.wasm", {},
{
...
js: {
setObj: (obj, key, val) => ({
...obj,
key: val
}),
objVal: (obj, key) => obj[key],
emptyObj: () => ({}),
method: (obj, key, ...args) => obj[key](...args),
setter: (obj, key, val) => (obj[key] = val),
constructor: (key, ...args) => new classes[key](...args),
functions: (key, ...args) => new funcs[key](...args),
},
...
})
Where classes
and funcs
is either something you handmake, or generate:
import * as THREE from "three";
const classes = {
Scene: THREE.Scene,
Vector2: THREE.Vector2,
};
After this, we can define anything we want in scheme. I am trying out just organizing things out by function signature, to reduce the amount of define-foreign
s I have to do.
(define-syntax define-foreign-constructor
(syntax-rules ()
((_ name ptype ...)
(define-foreign name "js" "constructor"
(ref string) ptype ... -> (ref extern)))))
(define-syntax define-foreign-method
(syntax-rules (->)
((_ name ptype ... -> rtype)
(define-foreign name "js" "method"
(ref string) ptype ... -> rtype))))
(define-foreign-constructor constructor)
(define-foreign-constructor constructor-f64-f64 f64 f64)
(define-foreign-method method->f64 -> f64)
(define (make-scene) (constructor "Scene"))
(define (make-vector-2 x y) (constructor-f64-f64 "Vector2" x y))
(define (get-angle) (method->f64 "angle"))
;; and so on
This all makes it straightforward I think for a possible code generation. I have made some inroads already just using the Typescript Compiler API and generating files for hoot based off of type declaration files. Just classes/methods right now, but if it seems feasible I am sure this way could be extended to making record types from interfaces and such.
But I suspect this could probably be more flexibly done on the guile side though, where define-foreign
s are only made as needed for their type (method/setter/constructor) and signature. Parsing a full library’s worth of API can produce a lot of guile code and really tick up your compile time. This is true even when any method across classes with the same name and signature is deduplicated. I am still learning about what’s even possible right now with macros in hoot (and also kind of a noob to scheme-type macros).
Hoping we could eventually get something like emscripten’s ccall, but for this wasm->js boundary.