We are excited to announce the release of Guile Hoot v0.4.0! Hoot is a Scheme to WebAssembly compiler backend for Guile, as well as a general purpose WebAssembly toolchain. In other words, Scheme in the browser!
Highlights
Hoot now supports user-defined modules. Users no longer have to stuff their entire program into one file! Currently, the R6RS
library
syntax is supported, with R7RSdefine-library
and Guiledefine-module
syntax to come in a future release.The standard library is now available as a collection of importable modules. Hoot supports the standard
(scheme ...)
namespace as specified by R7RS-small. Non-standard interfaces are available under the(hoot ...)
namespace. The see manual for more information about available non-standard interfaces.An example project was added to the source tree in Git,
examples/project-template
, to serve as an easy starting point for new Hoot projects. This example project also ships with our official release tarballs. See the template's README for more information.More of R7RS-small has been implemented and Hoot can now run 54 out of 57 Scheme benchmarks!
Read on for the full change log.
R7RS-small
Improved support for
call-with-current-continuation
.Added support for complex number arithmetic.
Added support for cyclic data structures to
equal?
.Added support for file ports (
call-with-input-file
,call-with-output-file
) with the caveat that they only work in non-browser runtimes such as NodeJS 22+ or Hoot's own Wasm interpreter.Fixed bignum/fraction division.
Fixed missing fraction/flonum arithmetic cases.
Fixed
get-output-bytevector
when total output size is greater than buffer size.Fixed
close-port
to call the port object's close hook.
Non-standard interfaces
- Added support for Guile's keyword argument dispatch syntax
define*
, andlambda*
. To use them, add(only (hoot syntax) define* lambda*)
to your program/module'simport
form.
Compiler
Added
#:load-library
and#:extend-load-library
keyword arguments tocompile
,compile-file
, andread-and-compile
.Improved error messages for unbound variables.
Added new
--load-path
flag toguild compile-wasm
that allows loading user modules from the file system.Added new
--emit-names
flag toguild-compile-wasm
that emits debug names in the resulting Wasm binary.Fixed
guild compile-wasm
passing an invalid keyword argument tocompile
.
Runtime
Errors that occur in standard library functions implemented in Wasm now throw Scheme exceptions rather than crashing. For example, it is now possible to catch the type error thrown by
(+ 1 "two")
.Entry to the Hoot ABI via
reflect.wasm
now pushes the default prompt. Used forcall-with-current-contination
.Fixed issue where sending large strings from Wasm to JS caused a stack overflow.
Toolchain
Added support for the Wasm exceptions proposal (tag objects and
try
,try_delegate
,throw
,rethrow
instructions) as currently shipped in major browsers.The disassembler
wasm->wat
now expects symbolified input (viasymbolify-wasm
) and produces much better output that more closely resembles Wasm disassembly in Chrome dev tools.Fixed multi-value block type handling in
push-block
in(wasm stack)
.
Notable issues
A special combination of branching code involving continuations with known return arity can lead to miscompilations that express themselves as Wasm runtime errors in the form of
table.get
instructions with a negative index or an invalid type cast. GitLab issueUsage of
define-record-type
within the top-level of the main program (not in a module) leads to a compilation error. The workaround for now is to wrap the program body in a(let () ...)
form. GitLab issueSome uses of
dynamic-wind
cause compilation errors due to an unhandledthunk?
primitive. Hoot expects such primitives to be removed. This seems to be caused by Guile's partial evaluator terminating earlier than desired and likely requires a fix to upstream Guile. GitLab issue
Browser compatibility
Compatible with Firefox 121 or later.
Compatible with Google Chrome 119 or later.
Safari/WebKit is unsupported, unfortunately, as Wasm GC and tail calls are still not available.
Get Hoot 0.4.0!
Hoot is already available in GNU Guix:
$ guix pull
$ guix install guile-next guile-hoot
(Hoot currently requires a bleeding-edge version of Guile, hence
guile-next
above.)
Otherwise, Hoot can be built from source via our release tarball. See the Hoot homepage for a download link and GPG signature.
Documentation for Hoot 0.4.0, including build instructions, can be found here.
Get in touch!
For bug reports, pull requests, or just to follow along with development, check out the Hoot project on GitLab.
If you build something cool with Hoot, let us know on our community forum!
The code in this release was brought to you by Andy Wingo and David Thompson. The lovely Hoot art is by tessa. Special thanks to the MetaMask folks for funding this work!
Until next time, happy hooting! 🦉