Hoot 0.8.0 released!
Dave Thompson —We are excited to announce the release of Hoot 0.8.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!
This release contains new features and bug fixes and since the 0.7.0 release back in October.
New features
-
New
(hoot repl)module. At long last, there is now a built-in read-eval-print loop implementation! Previous releases added a macroexpander, a Scheme interpreter, and a runtime module system, but now it's possible to do live hacking from a Hoot program inside a WebAssembly runtime!-
To use the REPL, compile your Wasm binary with the necessary debug flag during development:
guild compile-wasm -g runtime-modules. This will include the runtime module system in the resulting binary. Expect compilation time and binary size to increase significantly. The trade-off is that a live hacking workflow should make recompilations fewer and farther between.
-
-
While not shipping in Hoot directly, initial support for using the Hoot REPL from Emacs has been added in the new geiser-hoot library. We expect to release this more formally and package it for easy installation with Guix or Emacs' built-in package manager in the near future.
-
Enhanced
(hoot web-server)module. To support the use of REPLs running within a web browser tab, the most common development use case, the web server doubles as a REPL server, proxying TCP traffic from REPL clients (more about that below) over a WebSocket to the connected browser tab.-
These enhancements introduce two new, optional depedencies to Hoot: Fibers and guile-websocket. If either of these dependencies are not present at build time, the
(hoot web-server)module will not be built.
-
-
New
(hoot web-repl)module. This module can be imported and compiled into the Wasm binary so that it can act as a REPL "server". "Server" is quoted because a browser tab cannot act as a server, it is strictly a client. Instead, it connects to the aforementioned(hoot web-server)which as a proxy for all connected REPL clients. -
New
hootcommand-line tool. This tool will be used as a place to collect handy Hoot development tools. This initial version has two subcommands:-
hoot repl: Open a REPL running in Node. Useful for quickly trying out basic Scheme expressions in Hoot without having to compile a standalone WebAssembly program. -
hoot server: Conveniently launch the development web server in(hoot web-server).
-
-
New
(web request)and(web response)modules that export a sliver of the API defined in Guile's modules of the same names. -
New
(web socket)module that provides a input/output interface to WebSocket client connections. Mimicks the module of the same name in guile-websocket. -
Added customizable module loader interface via new
current-module-loaderparameter. Two concrete loaders are provided: By default, modules are loaded from the file system by searching a load path. This is useful when running in a non-browser runtime such as NodeJS. Whenrun-web-replin(web repl)is used, connected REPLs are configured to use an HTTP-based loader. This loader makes HTTP requests to a special endpoint on the development web server to fetch source code.-
Note that modules loaded at runtime are loaded from source and then interpreted. Unlike Guile, where modules are automatically compiled to bytecode, Hoot cannot compile individual modules to Wasm (which would require compiling the Wasm compiler to Wasm which is an interesting and overwhelming future possibility).
-
Documentation changes
-
Updated
Installationchapter to mention new optional dependencies. -
Added
ModulesandREPLsections to the Scheme reference chapter. -
Added
Developmentchapter. -
Update
Statussection to remove mention of missing R7RS support that we have now. -
Removed docs for obsolete
--emit-namesflag -
Add documentation for
-gflag toguild compile-wasm.
Toolchain changes
-
Split Wasm validation out of
(wasm vm)module and into new(wasm validation)module. -
Keep data computed within the validation pass in
<validated-wasm>records so that data can be used during instantiation rather than redundantly recomputing it. -
Added explicit support for representing a "canonicalization": a world in which structurally equal types are equal.
-
(wasm vm)types<wasm-func>,<wasm-struct>,<wasm-array>now refer to their types by index into a canonicalized set. -
Added untagged
<wasm-array>backing stores to(wasm vm)for all simple scalar numeric types, includingi8andi16packed types. -
Modified
(wasm vm)to look up named heap type references in the instance's canonicalization. -
Added
bytevector->wasm-array,wasm-array->bytevectorto(wasm vm). -
Added support for some of the "none" bottom types.
-
Packed data is stored signed, wrapped from
i32when set, and only unwrapped to unsigned inget_ufunctions.
Miscelanneous changes
-
Made
schedule-task, which is implemented using inline Wasm, a no-op when called at expansion time on the host machine. -
Added support for
vectorandcall-with-valuesprimitives to(hoot primitives)module so they can be used in interpreted code. -
truncateis now exported from(guile). -
Allow exports to clobber each other in
module-declare!to support live hacking of modules wheredefine-moduleforms are often re-evaluated many times. -
Extracted JS
Uint8Arraybindings from internals of(fibers streams)to new(hoot typed-arrays)module. -
Implement subset of Guile's procedural module API for hackable programs (i.e. programs that are built with runtime module support).
-
Added
(hoot config)target-side module for accessing certain build-time constants (currently just the Hoot version string). -
Extracted
(hoot library)module from(hoot library-group)so that the library parser can be used on the target for live hacking purposes. -
Added
define-moduleimplementation to(guile)that simply throws an error if used during compilation. A separate implementation is installed for use by the interpreter in hackable programs. -
Added
#:replace?argument tomodule-export!to allow replacement of exports for live hacking purposes. -
Exported
module-rootfrom(hoot modules). -
Added
module-imported-modulesprocedure to(hoot modules). -
Changed file I/O host functions to return
nullwhen a file cannot be opened so a Scheme exception that can be handled by user code rather than a host exception that cannot. -
Extracted contents of
(scheme file)to new(hoot file)module for use in internal code such as the implementation of the file system module loader in(hoot hackable). -
Moved implementation of
string-join,string-concatenate,string-prefix?, andstring-prefix-ci?from(guile)to(hoot strings). -
Moved case-insensitive string procedures from
(scheme char)to(hoot strings). -
Added
string-dropto(hoot strings). -
Added
everyandfold-rightprocedures to(hoot lists). -
Moved implementation of
and-mapandor-mapfrom(guile)to(hoot lists). -
Added
symbol-appendto(hoot symbols). -
Added less verbose custom printer for
<module>record type. -
Switched from positional to keyword arguments for
make-soft-portin(hoot ports).
Bug fixes
-
Fixed
format-exceptionnot writing all of its output to the current error port. -
Fix
eof-objectexport in(ice-9 binary-ports). -
Fixed off-by-one error for procedures with rest args in
(hoot eval). -
Fixed
min/maxto only accept real numbers, handle NaNs, and normalize exact zeroes. -
Fixed continuation composition leaving an unwind continuation on the stack.
-
Fixed prompt unwinding in certain join continuation situations.
-
Fixed compilation of
unwindprimcalls at join points.
Browser compatibility
-
Compatible with Safari 26 or later.
-
Compatible with Firefox 121 or later.
-
Compatible with Chrome 119 or later.
Get Hoot 0.8.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.8.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 Codeberg.
If you build something cool with Hoot (for the upcoming game jam or otherwise), let us know on our community forum!
Thanks to our supporters
TODO
Until next time, happy hooting! 🦉