- Scheme 92.9%
- WebAssembly 3.8%
- JavaScript 2.2%
- M4 0.7%
- Makefile 0.4%
The goal is to allow validate-wasm against an explicit canonicalization, and to avoid accidental canonicalization into the main set. |
||
|---|---|---|
| .forgejo/workflows | ||
| bin | ||
| design | ||
| doc | ||
| examples | ||
| js-runner | ||
| lib | ||
| m4 | ||
| module | ||
| reflect-js | ||
| reflect-wasm | ||
| test | ||
| .dir-locals.el | ||
| .gitignore | ||
| bootstrap.sh | ||
| ci-manifest.scm | ||
| configure.ac | ||
| COPYING | ||
| COPYING.LESSERv3 | ||
| guile | ||
| guix.scm | ||
| hoot.ase | ||
| hoot.png | ||
| LICENSE.txt | ||
| Makefile.am | ||
| pre-inst-env.in | ||
| README.md | ||
| size-metrics.scm | ||
Guile Hoot
Hoot is an ahead-of-time, whole-program compiler for Guile Scheme to WebAssembly (aka Wasm) developed by the Spritely Institute. In addition to the compiler, Hoot contains a full WebAssembly toolchain with an assembler, a disassembler, a linker, an interpreter, etc. Hoot produces binaries that conform to the Wasm 3.0 specification which features tail calls and heap-allocated reference types with garbage collection.
Compatibility
Hoot is compatible with the following Wasm runtimes:
- Firefox 121+
- Chrome 119+
- Safari 26+
- NodeJS 22+
Hoot is currently unsupported on WASI runtimes.
Compilation and runtime
A whole-program compilation approach has been chosen in order to create smaller binaries at the expense of increased compilation time. As we implement more of Scheme, we hope to preserve this "small programs compile to small files" property, rather than having every compiled program include the whole of Guile's standard library.
Despite whole-program compilation, it's possible for multiple Hoot modules to be bound together and interoperate. Hoot makes a distinction between main and auxilary modules. Main modules include the full Scheme runtime and export their ABI whereas auxilary modules exclude the runtime and import their ABI from a main module.
To run Hoot binaries on web browsers there is an associated JavaScript module that handles booting the Wasm modules with the necessary host imports and translates Scheme values to/from JavaScript. Some non-web targets are hosted by JavaScript implementations (e.g. NodeJS) and those can make use of the same support module.
Project status
Hoot has not yet achieved maximum Guile compatibility, but R7RS-small Scheme is well supported. Despite gaps in compatibility, Guile libraries such as Spritely Goblins are known to compile and run on Hoot.
All Wasm features that Hoot relies upon are available in all major web browsers and NodeJS.
To build and run Hoot, a bleeding-edge Guile built from the main
branch in Git is required, as several necessary changes that have been
upstreamed to Guile have not made it into a stable release yet.
For a fuller picture of project status, including known limitations, see the "Status" section of our documentation..
But... why the name "Hoot"?
We thought this project deserved a cute project name and mascot, and everyone at the time agreed an owl was nice, and Christine Lemmer-Webber had recently just drawn up this owl pixel art, and so it became the mascot. The name naturally flowed from there.
Installing from a stable release
Note that at the time of writing, Hoot requires a development version of Guile. This may not be the case at your time of reading!
Below are system-specific instructions for installing Hoot.
On Guix
Hoot is already available in Guix:
guix shell --pure guile-next guile-hoot
(The --pure flag is to reduce the likelihood of failure due to
system-specific configuration. You may not need this flag.)
On macOS (Homebrew)
Hoot is available in macOS thanks to to Alex Conchillo Flaqué and the Guile Homebrew repository.
Add the Guile Homebrew tap if you haven't already:
brew tap aconchillo/guile
If Guile is already installed with Homebrew, unlink it since we need a newer version:
brew unlink guile
Now, just install Hoot:
brew install guile-hoot
This will also install guile-next, a bleeding edge version of Guile,
so it might take a while if there's no bottle available.
Building from source
Easy path: Use Guix
This is by far the easiest path because Guix does all the hard work for you.
First, clone the repository:
git clone https://codeberg.org/spritely/hoot
cd hoot
guix shell
./bootstrap.sh && ./configure && make
If everything went okay then you can now run make check:
make check
Did everything pass? Cool! That means Hoot works on your machine!
Advanced path: Build dependencies on your own
Maybe you want to understand better what Hoot is actually doing, or maybe you want to hack on the version of Guile used for Hoot, or etc! This section is for you.
First, you need to build Guile from the main branch.
Then you can clone and build this repo:
git clone https://codeberg.org/spritely/hoot
cd hoot
./bootstrap.sh && ./configure && make
To run the test suite against a production Wasm host, you will need a V8 distribution such as NodeJS 22+ or a standalone V8 build. NodeJS is recommended.
Building V8 is annoying, to say the least. You need to have
depot_tools installed; see https://v8.dev/docs/source-code. Once
you have that see https://v8.dev/docs/build to build. You will end up
with a d8 binary in out/x64.release (if you are on an x86-64
platform). We discourage this route except in the very unlikely case
that you are developing a Hoot feature that requires a fresher V8 than
NodeJS provides.
If all that works you should be able to run the test suite:
make check
By default, the test suite runs against both V8 (either NodeJS or V8's
d8 tool) and Hoot's Wasm interpreter. If you want to run the test
suite with just one or the other, you can use the WASM_HOST
environment variable:
make check WASM_HOST=hoot
# OR
make check WASM_HOST=node
# OR
make check WASM_HOST=d8
Try it out
Hoot is a self-contained system, so the easiest way to try it is from the Guile REPL:
./pre-inst-env guile
From the Guile prompt, enter the following to evaluate the program
42 in Hoot's built-in Wasm interpreter:
scheme@(guile-user)> ,use (hoot reflect)
scheme@(guile-user)> (compile-value 42)
$5 = 42
More interestingly, Scheme procedures that live within the Wasm guest module can be called from Scheme as if they were host procedures:
scheme@(guile-user)> (define hello (compile-value '(lambda (x) (list "hello" x))))
scheme@(guile-user)> hello
$6 = #<hoot #<procedure>>
scheme@(guile-user)> (hello "world")
$7 = #<hoot ("hello" "world")>
Hoot also extends Guile's build tool guild with the guild compile-wasm subcommand which can be used to compile and (optionally)
run a Scheme file:
echo 42 > 42.scm
./pre-inst-env guild compile-wasm --run 42.scm
The above command compiles 42.scm to Wasm and runs the resulting
binary in Hoot's Wasm interpreter. Here's how to run it with NodeJS
instead:
./pre-inst-env guild compile-wasm --run=node 42.scm
The binaries can be saved to disk, too, of course:
./pre-inst-env guild compile-wasm -o 42.wasm 42.scm
To actually load 42.wasm you could use the Hoot VM as mentioned
above or use a production Wasm implementation such as a web browser.
See the manual for further instructions on production deployment and
full API documentation.
Examples
For quickly getting started with a new project, see
examples/project-template/README.md for an explanation of how to use
our project template.
For more examples of using Hoot, check out a some of our other repos:
- https://codeberg.org/spritely/hoot-ffi-demo
- https://codeberg.org/spritely/hoot-repl
- https://codeberg.org/spritely/hoot-game-jam-template
Contributing
Hoot's Git repository is hosted on Codeberg: https://codeberg.org/spritely/hoot
Bug reports and other issues can be filed here: https://codeberg.org/spritely/hoot/issues
Pull requests are very much welcome!
Licenses
Hoot's source code and documentation is licensed under Apache 2.0
unless otherwise noted in a source file. See COPYING for the full
license text and see the license headers in each source file for
individual copyright information.
Several files are licensed under the GNU Lesser General Public License
version 3 or later, see COPYING.LESSERv3.
The owl mascot graphic (hoot.png, hoot.ase) is (C) 2023 Christine
Lemmer-Webber and the Spritely Networked Communities Institute and
released under the Creative Commons Attribution 4.0 International
license