<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title>Spritely Networked Communities Institute</title><id>https://spritely.institute/feed.xml</id><subtitle>Recent Posts</subtitle><updated>2024-02-29T14:55:49Z</updated><link href="spritely.institute/feed.xml" rel="self" /><link href="spritely.institute" /><entry><title>LWN on Spritely</title><id>https://spritely.institute/news/lwn-on-spritely.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2024-02-29T12:00:00Z</updated><link href="https://spritely.institute/news/lwn-on-spritely.html" rel="alternate" /><summary type="html">&lt;p&gt;Daroc Alden over at &lt;a href=&quot;https://lwn.net&quot;&gt;LWN.net&lt;/a&gt; has &lt;a href=&quot;https://lwn.net/Articles/960912&quot;&gt;penned a piece&lt;/a&gt; on the Institute's long-term goal of developing a new paradigm for distributed computing, our progress so far, and the role OCapN will play in supporting our work.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://lwn.net/Articles/960912&quot;&gt;Full writeup&lt;/a&gt;&lt;/p&gt;</summary></entry><entry><title>[Contract] Goblins (Scheme/Wasm) Integrations Engineer</title><id>https://spritely.institute/news/contract-goblins-schemewasm-integrations-engineer.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2024-02-26T09:00:00Z</updated><link href="https://spritely.institute/news/contract-goblins-schemewasm-integrations-engineer.html" rel="alternate" /><summary type="html">&lt;p&gt;We're recruiting for a remote, 20hrs/wk contract as a &lt;a href=&quot;/jobs/Contract-WASM-integration.html&quot;&gt;Goblins (Scheme/Wasm) Integration Engineer&lt;/a&gt;. Come help us bring secure decentralized infrastructure to everyone!&lt;/p&gt;</summary></entry><entry><title>Developer Community Forum open for everyone!</title><id>https://spritely.institute/news/developer-community-forum-open-for-everyone.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2024-02-02T10:00:00Z</updated><link href="https://spritely.institute/news/developer-community-forum-open-for-everyone.html" rel="alternate" /><summary type="html">&lt;p&gt;The &lt;a href=&quot;https://community.spritely.institute&quot;&gt;Spritely Institute developer community forum&lt;/a&gt; is now public and free for all to join and paricipate!&lt;/p&gt;&lt;p&gt;Our forum is the place to talk about all Spritely Institute projects and technolgies - the OCapn protocol, the Spritely Goblins secure distributed programming environment, and Guile HOOT bringing Scheme to WebAssembly (and browsers!).&lt;/p&gt;&lt;h2&gt;How to get help with  technical issues for Spritely Institute technologies&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;If you are running into an issue with the codebase or would like to report a bug, please check the issues on the relevant repo and/or the docs, and file an issue on the appropriate repo as necessary:
&lt;a href=&quot;http://spritely.institute/goblins&quot;&gt;Goblins&lt;/a&gt; &lt;a href=&quot;http://spritely.institute/hoot&quot;&gt;Hoot&lt;/a&gt; &lt;a href=&quot;http://ocapn.org&quot;&gt;OCapN&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Use the &lt;a href=&quot;https://community.spritely.institute&quot;&gt;forum search function&lt;/a&gt; to check if anyone has asked a similar question before. The responses may point you in a helpful direction! If there are no related threads, please sign up, review the community guidelines and post a new topic with your question.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If you do choose to join this community, please &lt;a href=&quot;https://community.spritely.institute/t/welcome-to-the-spritely-institute-discourse-introduce-yourself-here/&quot;&gt;introduce yourself&lt;/a&gt;  and tell us about your project!&lt;/p&gt;</summary></entry><entry><title>Guile Hoot v0.3.0 released!</title><id>https://spritely.institute/news/guile-hoot-v030-released.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2024-01-30T11:30:00Z</updated><link href="https://spritely.institute/news/guile-hoot-v030-released.html" rel="alternate" /><summary type="html">&lt;p&gt;&lt;img src=&quot;/static/images/blog/hoot-0.3.0.png&quot; alt=&quot;Hoot version 0.3.0&quot; /&gt;&lt;/p&gt;&lt;p&gt;We are excited to announce the release of &lt;a href=&quot;/hoot&quot;&gt;Guile Hoot&lt;/a&gt; v0.3.0!
Hoot is a Scheme to WebAssembly compiler backend for
&lt;a href=&quot;https://gnu.org/software/guile&quot;&gt;Guile&lt;/a&gt;, as well as a general purpose
WebAssembly toolchain.  In other words, &lt;em&gt;Scheme in the browser!&lt;/em&gt;&lt;/p&gt;&lt;h3&gt;Highlights&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Partial implementation of the Scheme module system!  In past
releases, programs were compiled by combining user code with a large
Scheme prelude that contained the entire standard library.  In this
release, we've extracted all of the R7RS interface to their
appropriate &lt;code&gt;(scheme ...)&lt;/code&gt; modules and some Hoot-specific interfaces
to &lt;code&gt;(hoot ...)&lt;/code&gt; modules.  Users can now use the &lt;code&gt;import&lt;/code&gt; syntax to
import these modules at the beginning of their programs.  If no
&lt;code&gt;import&lt;/code&gt; form appears, a default set of modules is imported.
User-defined modules are not yet supported.  We plan to address this
in the next release.&lt;/p&gt;&lt;p&gt;Supporting the Scheme module system in a whole-program compiler like
Hoot is no easy task due to procedural macros (&lt;code&gt;syntax-case&lt;/code&gt;).  If
you're interested in the details, check out Hoot lead engineer Andy
Wingo's &lt;a href=&quot;https://wingolog.org/archives/2024/01/05/scheme-modules-vs-whole-program-compilation-fight&quot;&gt;blog
post&lt;/a&gt;
on the subject.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;More of R7RS-small has been implemented and Hoot can now run over
half of the &lt;a href=&quot;https://ecraven.github.io/r7rs-benchmarks/&quot;&gt;Scheme
benchmarks&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The toolchain can now emit and parse binaries with a &lt;code&gt;name&lt;/code&gt; custom
section.  This optional feature makes binaries larger and is
intended for debugging.  By default, name sections are not emitted.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;New hash table and weak key hashtable interfaces.  Hoot's hashtable
interface is inspired by, but does not conform to, R6RS.  Hash keys
are currently limited to identity (&lt;code&gt;eq&lt;/code&gt;) based hashing.  &lt;code&gt;eqv&lt;/code&gt; and
&lt;code&gt;equal&lt;/code&gt; hashing will come in a future release.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The &lt;code&gt;(hoot reflect)&lt;/code&gt; module now automatically loads &lt;code&gt;reflect.wasm&lt;/code&gt;.
In past releases, users would have to locate and load this binary on
their own.  It quickly became the most common source of confusion
for new users.  We hope it is easier than ever to get started with
Hoot!&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Read on for the full change log.&lt;/p&gt;&lt;h3&gt;R7RS-small&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Added &lt;code&gt;import&lt;/code&gt; syntax.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added &lt;code&gt;truncate&lt;/code&gt; and &lt;code&gt;exact-integer-sqrt&lt;/code&gt; procedures.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added &lt;code&gt;guard&lt;/code&gt; exception handling syntax.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added &lt;code&gt;call-with-port&lt;/code&gt; procedure.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added complex number procedures &lt;code&gt;make-polar&lt;/code&gt;, &lt;code&gt;make-rectangular&lt;/code&gt;,
&lt;code&gt;magnitude&lt;/code&gt;, and &lt;code&gt;angle&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added &lt;code&gt;string-map&lt;/code&gt; and &lt;code&gt;substring&lt;/code&gt; procedures.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added support for two list arguments in &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;for-each&lt;/code&gt; (3+
lists still not implemented.)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Enhanced &lt;code&gt;string-&amp;gt;number&lt;/code&gt; to parse all types of numbers.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed names of string comparison procedures. &lt;code&gt;string-=?&lt;/code&gt; is now
&lt;code&gt;string=?&lt;/code&gt;, etc.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed eta expansion of &lt;code&gt;-&lt;/code&gt; and &lt;code&gt;/&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Non-standard interfaces&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Added hash tables and weak key hash tables.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added &lt;code&gt;external-non-null?&lt;/code&gt; procedure.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added support for &lt;code&gt;(ref extern)&lt;/code&gt; params/results to &lt;code&gt;define-foreign&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added support for &lt;code&gt;(ref eq)&lt;/code&gt; results to &lt;code&gt;define-foreign&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed port seeking.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Compiler&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Added &lt;code&gt;library-group&lt;/code&gt; form which encapsulates the entire compilation
unit based on &lt;a href=&quot;https://www.andykeep.com/pubs/scheme-10.pdf&quot;&gt;Enabling cross-library optimization and compile-time
error checking in the presence of procedural
macros&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added &lt;code&gt;#:emit-names?&lt;/code&gt; and &lt;code&gt;#:imports&lt;/code&gt; compiler flags.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Removed &lt;code&gt;#:env&lt;/code&gt; compiler flag.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;read-and-compile&lt;/code&gt; now looks for an &lt;code&gt;import&lt;/code&gt; form and includes only
those modules in the compilation unit when specified.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added support for &lt;code&gt;f64&lt;/code&gt; named temporaries to &lt;code&gt;%inline-wasm&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed fast path check for &lt;code&gt;quo&lt;/code&gt; primcall.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed fast path code for &lt;code&gt;rsh/immediate&lt;/code&gt; primcall.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Runtime&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Uncaught exception details are now printed.  True Scheme backtraces
are not yet possible, however.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed &lt;code&gt;$argv&lt;/code&gt; table initialization to fit the maximum number of
procedure arguments that can be known at compile time.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed &lt;code&gt;$apply&lt;/code&gt; to dynamically grow the &lt;code&gt;$argv&lt;/code&gt; table when the number
of arguments exceeds the current size.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed &lt;code&gt;$add-fracnum-fracnum&lt;/code&gt; when GCD is a bignum.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed &lt;code&gt;$quo&lt;/code&gt; when most negative fixnum is divided by -1.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed stack pointer arithmetic in &lt;code&gt;$fluid-ref*&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Toolchain&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Added support for generating &lt;code&gt;name&lt;/code&gt; custom section to &lt;code&gt;resolve-wasm&lt;/code&gt;
in &lt;code&gt;(wasm-resolve)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added support for &lt;code&gt;name&lt;/code&gt; custom section to &lt;code&gt;assemble-wasm&lt;/code&gt; in &lt;code&gt;(wasm assemble)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added support for &lt;code&gt;name&lt;/code&gt; custom section to &lt;code&gt;parse-wasm&lt;/code&gt; in &lt;code&gt;(wasm parse)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added &lt;code&gt;id&lt;/code&gt; field to &lt;code&gt;&amp;lt;wasm&amp;gt;&lt;/code&gt; type along with &lt;code&gt;wasm-id&lt;/code&gt; accessor.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added &lt;code&gt;&amp;lt;names&amp;gt;&lt;/code&gt; type for name custom section.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Changed &lt;code&gt;hoot-instantiate&lt;/code&gt; in &lt;code&gt;(hoot reflect)&lt;/code&gt; to automatically load
&lt;code&gt;reflect.wasm&lt;/code&gt; from Hoot's installation directory or &lt;code&gt;$HOOT_DATADIR&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;reflect.js&lt;/code&gt; is now partially documented, though we hope to
automatically generate all necessary JavaScript in the future so
users need not concern themselves with this.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Browser compatibility&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;At last, Firefox 121, released in December, enables Wasm tail calls
by default!  This is the minimum Firefox version needed to run Hoot
binaries without messing around in &lt;code&gt;about:config&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Compatible with Google Chrome 119 or later.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Safari/WebKit is still unsupported.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Get Hoot 0.3.0!&lt;/h3&gt;&lt;p&gt;Hoot is already available in GNU Guix:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;$ guix pull
$ guix install guile-next guile-hoot&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(Hoot currently requires a bleeding-edge version of Guile, hence
&lt;code&gt;guile-next&lt;/code&gt; above.)&lt;/p&gt;&lt;p&gt;Otherwise, Hoot can be built from source via our release tarball.  See
the &lt;a href=&quot;/hoot&quot;&gt;Hoot homepage&lt;/a&gt; for a download link and GPG signature.&lt;/p&gt;&lt;p&gt;Documentation for Hoot 0.3.0, including build instructions, can be
found &lt;a href=&quot;/files/docs/guile-hoot/0.3.0/index.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;FOSDEM 2024&lt;/h3&gt;&lt;p&gt;Several of us at Spritely will be attending both
&lt;a href=&quot;https://fosdem.org/2024/&quot;&gt;FOSDEM&lt;/a&gt; and the &lt;a href=&quot;https://libreplanet.org/wiki/Group:Guix/FOSDEM2024&quot;&gt;Guix
days&lt;/a&gt; which
precede them.  Robin Templeton will be presenting &lt;a href=&quot;https://fosdem.org/2024/schedule/event/fosdem-2024-2339-scheme-in-the-browser-with-guile-hoot-and-webassembly/&quot;&gt;Scheme in the
Browser with Guile Hoot and
WebAssembly&lt;/a&gt;
in the &lt;a href=&quot;https://fosdem.org/2024/schedule/track/declarative-and-minimalistic-computing/&quot;&gt;Declarative and Minimalistic Computing
devroom&lt;/a&gt;
on Sunday, February 4th.&lt;/p&gt;&lt;p&gt;If you're planning to attend, please come say hi!&lt;/p&gt;&lt;h3&gt;Get in touch!&lt;/h3&gt;&lt;p&gt;For bug reports, pull requests, or just to follow along with
development, check out the &lt;a href=&quot;https://gitlab.com/spritely/guile-hoot&quot;&gt;Hoot project on
GitLab&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;If you build something cool with Hoot, let us know on our &lt;a href=&quot;https://community.spritely.institute&quot;&gt;community
forum&lt;/a&gt;!&lt;/p&gt;&lt;p&gt;The code in this release was brought to you by Andy Wingo, Robin
Templeton, David Thompson.  The lovely Hoot art is by tessa.  Special
thanks to the &lt;a href=&quot;https://metamask.io/news/developers/meta-mask-grants-dao-funds-spritely-foundation/&quot;&gt;MetaMask
folks&lt;/a&gt;
for &lt;a href=&quot;https://spritely.institute/news/guile-on-web-assembly-project-underway.html&quot;&gt;funding this
work&lt;/a&gt;!&lt;/p&gt;&lt;p&gt;Until next time, happy hooting! 🦉&lt;/p&gt;</summary></entry><entry><title>Meet us at GuixDays &amp; FOSDEM!</title><id>https://spritely.institute/news/fosdem2024.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2024-01-23T09:00:00Z</updated><link href="https://spritely.institute/news/fosdem2024.html" rel="alternate" /><summary type="html">&lt;p&gt;&lt;img src=&quot;/static/images/blog/fosdem-gear.png&quot; alt=&quot;FOSDEM 2024&quot; /&gt;&lt;/p&gt;&lt;p&gt;We will be presenting and attending &lt;a href=&quot;https://fosdem.org/2024/&quot;&gt;FOSDEM 2024&lt;/a&gt; and the &lt;a href=&quot;https://libreplanet.org/wiki/Group:Guix/FOSDEM2024&quot;&gt;Guix Days&lt;/a&gt; unconference in Belgium the first week of February.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://fosdem.org/2024/schedule/event/fosdem-2024-2339-scheme-in-the-browser-with-guile-hoot-and-webassembly/&quot;&gt;&lt;strong&gt;&amp;quot;Scheme in the Browser with Guile Hoot and WebAssembly&amp;quot;&lt;/strong&gt;&lt;/a&gt; by Robin Templeton (Feb 4, 11:00 CET). Guile Hoot is a free and open source WebAssembly toolchain and Scheme compiler that is opening doors for all programming languages to run within Wasm environments.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://fosdem.org/2024/schedule/event/fosdem-2024-2331-spritely-guile-guix-a-unified-vision-for-user-security/&quot;&gt;&lt;strong&gt;&amp;quot;Spritely, Guile, Guix: a unified vision for user security&amp;quot;&lt;/strong&gt;&lt;/a&gt; by Christine Lemmer-Webber (Feb 4, 12:00 CET). Spritely's goal is to create networked communities that puts people in control of their own identity and security. This talk will present a unified vision of how Spritely, Guile, and Guix can work together to bring user freedom and security to everyone!&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;We'll also be attending as many related dinner events as we can.&lt;/p&gt;&lt;h1&gt;Let's talk about partnering&lt;/h1&gt;&lt;p&gt;Spritely Institute is non-profit, and we are excited about partnering to unlock the power of secure decentralized applications. Those partnerships could take many forms, including possible joint-applications for project funding development of interoperable applications and infrastructure. Talk to us about how we might work together!&lt;/p&gt;&lt;h1&gt;Request a f2f meeting in Brussels&lt;/h1&gt;&lt;p&gt;Meet in-person with &lt;a href=&quot;/about&quot;&gt;CTO Christine Lemmer-Webber, Goblins Engineer Jessica Talon, or Hoot Compiler Engineer Robin Templeton&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;To request a meeting, join our &lt;a href=&quot;https://community.spritely.institute&quot;&gt;developer community message board&lt;/a&gt; and see &lt;a href=&quot;https://community.spritely.institute/t/request-a-meeting-in-Brussels/398&quot;&gt;this topic&lt;/a&gt; to let us know in advance about the cool project you're interested in collaborating on. We'd love to schedule some time to meet with you.&lt;/p&gt;&lt;p&gt;Hope to see you there!&lt;/p&gt;</summary></entry><entry><title>Spritely Goblins v0.12.0 Released: Two new netlayers join the OCapN family and more!</title><id>https://spritely.institute/news/spritely-goblins-v0120-released-two-new-netlayers-join-the-ocapn-family-and-more.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2024-01-22T10:30:00Z</updated><link href="https://spritely.institute/news/spritely-goblins-v0120-released-two-new-netlayers-join-the-ocapn-family-and-more.html" rel="alternate" /><summary type="html">&lt;p&gt;&lt;img src=&quot;/static/images/blog/2024_01_11-goblins_0.12.0.jpg&quot; alt=&quot;Goblins version 0.12.0&quot; /&gt;&lt;/p&gt;&lt;p&gt;We're excited to announce the v0.12.0 release of &lt;a href=&quot;https://spritely.institute/goblins/&quot;&gt;Spritely
Goblins&lt;/a&gt;!&lt;/p&gt;&lt;p&gt;The highlights of this release:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;New Prelay netlayer&lt;/li&gt;&lt;li&gt;New TCP-TLS netlayer&lt;/li&gt;&lt;li&gt;Various fixes and enhancements to CapTP support&lt;/li&gt;&lt;li&gt;A new Queue (FIFO) actor in our actor-lib library&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Goblins is Spritely's distributed object programming environment with
implementations for both &lt;a href=&quot;https://www.gnu.org/software/guile/&quot;&gt;Guile&lt;/a&gt; and
&lt;a href=&quot;https://racket-lang.org/&quot;&gt;Racket&lt;/a&gt; Scheme. Goblins provides an intuitive
security model, automatic local transactions for locally synchronous operations,
and an easy to use and efficient asynchronous programming interface for
encapsulated objects which can live anywhere on the network.&lt;/p&gt;&lt;p&gt;(While both versions of Spritely Goblins are fully network compatible
over the &lt;a href=&quot;https://ocapn.org/&quot;&gt;OCapN&lt;/a&gt; protocol, most new features are
aimed at Guile Goblins.)&lt;/p&gt;&lt;h2&gt;Prelay Netlayer&lt;/h2&gt;&lt;p&gt;The Prelay netlayer (the &amp;quot;preview of relay&amp;quot; netlayer) is a new netlayer that
sits on top of our existing netlayers and uses a client/server model. This works
especially well with our new TCP-TLS netlayer, as users will often be behind
firewalls and routers which require special configuration to allow for
peer-to-peer connections.&lt;/p&gt;&lt;p&gt;This new netlayer hopefully will help connect more nodes who otherwise couldn't
have connected to each other. It's currently a technology preview with some
limitations, those being that traffic is unencrypted and unauthenticated,
something akin to IRC or vanilla ActivityPub. It currently requires trusting the
relay server, however in the near future we will be looking to address those
limitations.&lt;/p&gt;&lt;h2&gt;TCP-TLS Netlayer&lt;/h2&gt;&lt;p&gt;This is a new netlayer which supports connections over TCP sockets with
encryption built in with TLS. Eager readers of the our news blog might already
familiar with this netlayer, as we built it last year and used it with the
&lt;a href=&quot;https://spritely.institute/news/lisp-game-jam---fantasary---prototyping-an-object-world--tcp-netlayer.html&quot;&gt;Fantasary Game Jam&lt;/a&gt;.
This netlayer has now made its way into this release of Goblins.&lt;/p&gt;&lt;p&gt;Unlike the Tor netlayer, which requires extra software (the Tor daemon) and
configuration, this allows for both simpler and quicker communication between
two nodes. Encryption occurs with self-signed certificates. This netlayer works
particularly well with the new Prelay netlayer as making peer-to-peer
connections is often difficult due to firewall or router configurations.&lt;/p&gt;&lt;h2&gt;A new Queue actor&lt;/h2&gt;&lt;p&gt;This new queue actor exists &lt;code&gt;(goblins actor-lib queue)&lt;/code&gt; and represents a queue
(i.e. FIFO) where new items can be queued or removed. Please refer to the new
documentation to see how to use this.&lt;/p&gt;&lt;h2&gt;Improved CapTP support&lt;/h2&gt;&lt;p&gt;CapTP is part of &lt;a href=&quot;https://ocapn.org&quot;&gt;OCapN&lt;/a&gt;, the network protocol that Goblins
uses to communicate securely over the network. Specifically CapTP is the bigger
of the three specifications which make up OCapN, being that which supports
object communication, promises, Third Party Handoffs and more. Since CapTP
working the same across both of the two Goblins implementations, these changes
come to both Racket &amp;amp; Guile Goblins.&lt;/p&gt;&lt;p&gt;The improvements we've made to CapTP are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Added crossed hellos mitigation (when two nodes try to connect to each other
at the same time)&lt;/li&gt;&lt;li&gt;Removal of the now deprecated &lt;code&gt;op:bootstrap&lt;/code&gt; operation (this is now done by
always exporting the bootstrap object at position `0``).&lt;/li&gt;&lt;li&gt;More robust verification on third party handoff certificates.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In addition to ensure both our implementations and other OCapN implementations
work according to the specifications we're helping to develop in the OCapN
group, we added the test suite code to each repository to make it easier to test
them against the &lt;a href=&quot;https://github.com/ocapn/ocapn-test-suite&quot;&gt;OCapN test suite&lt;/a&gt;.&lt;/p&gt;&lt;h1&gt;Getting the releases&lt;/h1&gt;&lt;p&gt;You can test the latest Guile Goblins release using, Guix:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;$ guix pull
$ guix install guile-goblins&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you'd prefer to try out the Racket version:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;raco pkg install goblins&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can also read the documentation for this release here:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://spritely.institute/files/docs/guile-goblins/0.12.0/index.html&quot;&gt;Guile Goblins Documentation&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://docs.racket-lang.org/goblins/index.html&quot;&gt;Racket Goblins Documentation&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1&gt;FOSDEM 2024&lt;/h1&gt;&lt;p&gt;Finally, while not directly related to the Spritely Goblins release, several of
us at Spritely will be attending both &lt;a href=&quot;https://fosdem.org/2024/&quot;&gt;FOSDEM&lt;/a&gt; and the
&lt;a href=&quot;https://libreplanet.org/wiki/Group:Guix/FOSDEM2024&quot;&gt;Guix days&lt;/a&gt; which precede
them. So, if you're planning to attend and would like to speak to us or tell us
about the cool things you're building with Goblins, let us know by joining
our &lt;a href=&quot;https://community.spritely.institute&quot;&gt;community&lt;/a&gt;,  we'd love to
chat with you!&lt;/p&gt;</summary></entry><entry><title>[EFF] Spritely and Veilid: Exciting Projects Building the Peer-to-Peer Web</title><id>https://spritely.institute/news/eff-spritely-and-veilid-exciting-projects-building-the-peer-to-peer-web.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2023-12-15T12:30:00Z</updated><link href="https://spritely.institute/news/eff-spritely-and-veilid-exciting-projects-building-the-peer-to-peer-web.html" rel="alternate" /><summary type="html">&lt;p&gt;The EFF (Electric Frontier Foundation) blog gives a great overview of our work in their latest post
&lt;a href=&quot;https://www.eff.org/deeplinks/2023/12/meet-spritely-and-veilid&quot;&gt;Spritely and Veilid: Exciting Projects Building the Peer-to-Peer Web&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&amp;quot;Spritely is worth keeping an eye on. Being developed by the Institute of the same name, Spritely is a framework for building distributed apps that don’t even have to know that they’re distributed...&amp;quot;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.eff.org/deeplinks/2023/12/meet-spritely-and-veilid&quot;&gt;[Read more @ EFF.org]&lt;/a&gt;&lt;/p&gt;</summary></entry><entry><title>Scheme in Scheme on Wasm in the browser</title><id>https://spritely.institute/news/scheme-in-scheme-on-wasm-in-the-browser.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2023-12-15T12:00:00Z</updated><link href="https://spritely.institute/news/scheme-in-scheme-on-wasm-in-the-browser.html" rel="alternate" /><summary type="html">&lt;p&gt;&lt;img src=&quot;/static/images/blog/hoot-meta-repl.gif&quot; alt=&quot;Hoot metacircular evaluator demo recording&quot; /&gt;&lt;/p&gt;&lt;p&gt;Hey, folks!  Today we want to talk about the wonderful
&lt;a href=&quot;https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop&quot;&gt;read-eval-print-loop
(REPL)&lt;/a&gt;.
Thanks to WebAssembly (Wasm), it's becoming increasingly common for
programming language websites to embed a REPL in which passersby can
easily evaluate code and get a feel for the language without having to
install anything on their computer.  We'd like to do the same thing
for our language of choice, &lt;a href=&quot;https://gnu.org/software/guile&quot;&gt;Guile
Scheme&lt;/a&gt;, using &lt;a href=&quot;/hoot&quot;&gt;Guile Hoot&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Guile Hoot is a Scheme-to-Wasm compiler that leverages the &lt;a href=&quot;https://developer.chrome.com/blog/wasmgc&quot;&gt;Wasm
garbage collection (GC)
extension&lt;/a&gt; that has been
rolling out to major browsers recently.  Wasm GC has finally made it
possible to use &lt;a href=&quot;https://en.wikipedia.org/wiki/Dynamic_programming_language&quot;&gt;dynamic
languages&lt;/a&gt;
&lt;em&gt;besides JavaScript&lt;/em&gt; on the client-side web, but it will still take
some additional effort to bring our favorite tools along for the ride.
In this post, we'll walk through building a tiny Scheme interpreter
with a simple user interface and explain what's in store for the
future.&lt;/p&gt;&lt;p&gt;To learn more about Hoot, check out the &lt;a href=&quot;/news/guile-hoot-v020-released.html&quot;&gt;0.2.0 release
announcement&lt;/a&gt; from a couple of
weeks ago!&lt;/p&gt;&lt;h3&gt;The case of the missing REPL&lt;/h3&gt;&lt;p&gt;For Scheme programmers (and Lisp programmers in general), the REPL is
at the core of our development workflow.  We modify some code in our
text editor, evaluate it in the REPL, inspect the output or enter a
debugger, and repeat the process until the program behaves the way we
want.&lt;/p&gt;&lt;p&gt;We're used to having a native REPL process running directly on our
operating system, but since Hoot is putting Scheme on the web, we'd
really like a REPL available in the browser, too.  A web REPL would be
convenient for seasoned Schemers and newcomers alike.  However, at
this early stage in Hoot's development, a fully-featured Scheme REPL
is not yet possible.  We don't have access to the macro expander,
interpreter, etc. from the comfort of our Wasm runtime... yet.&lt;/p&gt;&lt;p&gt;We'll have these things eventually, but what can we have now?&lt;/p&gt;&lt;p&gt;Well, we could implement an interpreter for a small subset of
Scheme... in Scheme!  Sounds pretty recursive, and if you know
anything about Schemers you know we love recursion (and also, that we
love recursion), so let's give it a shot!&lt;/p&gt;&lt;h3&gt;Scheme in Scheme&lt;/h3&gt;&lt;p&gt;In Chapter 4 of the classic computer science textbook &lt;a href=&quot;https://mitp-content-server.mit.edu/books/content/sectbyfn/books_pres_0/6515/sicp.zip/full-text/book/book-Z-H-25.html#%_chap_4&quot;&gt;Structure and
Interpretation of Computer
Programs&lt;/a&gt;
(SICP), Gerald Sussman and Hal Abelson walk through building a small
Scheme interpreter embedded in Scheme.  They called this the
&amp;quot;metacircular evaluator&amp;quot;, meaning that it's an interpreter written in
the language that it is interpreting.&lt;/p&gt;&lt;p&gt;This sounds pretty fancy — the kind of task reserved for MIT
professors that write iconic textbooks — but implementing a Scheme
interpreter is simpler than one might think!  For one thing, since
Scheme can manipulate its own syntax by design, we don't need to spend
any time parsing, a notoriously complex subject in its own right.  We
can skip directly to the fun part instead: evaluation!&lt;/p&gt;&lt;p&gt;Spritely's own &lt;a href=&quot;https://spritely.institute/static/papers/scheme-primer.html&quot;&gt;Scheme
Primer&lt;/a&gt;
distills SICP's interpreter into a much simpler form intended for
people who are brand new to Scheme.  The code examples in the rest of
this post are derived from the &amp;quot;Scheme in Scheme&amp;quot; section of the
Primer.  If you're completely new to Scheme and want to better
understand the code in this post, consider working through our Primer
sometime!&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;/static/images/blog/eval-apply.png&quot; alt=&quot;eval/apply diagram from Andres Raba's unofficial SICP, licensedunder Creative Commons Attribution-ShareAlike 4.0 InternationalLicense&quot; /&gt;&lt;/p&gt;&lt;p&gt;The metacircular evaluator is composed of two main components: &lt;code&gt;eval&lt;/code&gt;
and &lt;code&gt;apply&lt;/code&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;eval&lt;/code&gt; processes an expression in the context of an environment.&lt;/li&gt;&lt;li&gt;&lt;code&gt;apply&lt;/code&gt; calls a procedure (function) with a list of arguments.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The output of &lt;code&gt;eval&lt;/code&gt; is fed to &lt;code&gt;apply&lt;/code&gt;, which may feed more input to
&lt;code&gt;eval&lt;/code&gt;, and this mutually recursive cycle continues until the program
runs out of expressions to evaluate.&lt;/p&gt;&lt;p&gt;In order to implement &lt;code&gt;eval&lt;/code&gt;, we first need a way to represent
environments.  An environment maps variable names to their bound
values.  We'll use &lt;a href=&quot;https://en.wikipedia.org/wiki/Association_list&quot;&gt;association
lists&lt;/a&gt; for our
environments.&lt;/p&gt;&lt;p&gt;An empty environment with no variable bindings is represented by the
empty list &lt;code&gt;'()&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;The first bit of code from the metacircular evaluator we'll cover is
the &lt;code&gt;extend-env&lt;/code&gt; procedure, which creates a new environment by
extending an existing one:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;extend-env&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;names&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vals&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; If there are no more variables to add to env, return env.
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;null?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-symbol&quot;&gt;env&lt;/span&gt;
      &lt;span class=&quot;syntax-comment&quot;&gt;;; Otherwise, add the first binding to the recursive
&lt;/span&gt;      &lt;span class=&quot;syntax-comment&quot;&gt;;; extension of env with the rest of the bindings.
&lt;/span&gt;      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;cons&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;cons&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vals&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;extend-env&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;cdr&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;cdr&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vals&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can extend the empty environment to make a new environment that
includes the variable &lt;code&gt;foo&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;extend-env&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;; =&amp;gt; ((foo . 1))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can further extend that environment to make a new environment that
includes the variable &lt;code&gt;bar&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;extend-env&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;; =&amp;gt; ((bar . 2) (foo . 1))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note that environment manipulation is implemented in a
&lt;a href=&quot;https://en.wikipedia.org/wiki/Functional_programming&quot;&gt;functional&lt;/a&gt;
style.  Extending an environment does not mutate the original one.
This is because mutating the original environment would propagate the
new bindings to other evaluation contexts, potentially breaking
Scheme's &lt;a href=&quot;https://en.wikipedia.org/wiki/Scope_(computer_science)&quot;&gt;lexical scoping
rules&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;We can look up a variable's value using the &lt;code&gt;env-lookup&lt;/code&gt; procedure:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;env-lookup&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; Lookup name in association list.
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;assq&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Success: return the bound value.
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Failure: throw an error.
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Variable unbound:&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Example:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;env-lookup&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'foo&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;; =&amp;gt; 1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And now for the rest of the owl.  Our toy &lt;code&gt;eval&lt;/code&gt; supports:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;booleans&lt;/li&gt;&lt;li&gt;numbers&lt;/li&gt;&lt;li&gt;strings&lt;/li&gt;&lt;li&gt;quoted expressions&lt;/li&gt;&lt;li&gt;conditionals&lt;/li&gt;&lt;li&gt;procedures as values&lt;/li&gt;&lt;li&gt;procedure calls&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;expr&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;expr&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Booleans, numbers, strings
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;boolean?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;number?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-symbol&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Quoted expressions
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;'quote&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;quoted-expr&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-symbol&quot;&gt;quoted-expr&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Variable lookup
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;symbol?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;env-lookup&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Conditionals
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;'if&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;consequent&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;alternate&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;consequent&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;alternate&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Procedures
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;'lambda&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vals&lt;/span&gt;
       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;extend-env&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vals&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Procedure application
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;proc-expr&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;arg-exprs&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-comment&quot;&gt;;; Recursively evaluate the procedure expression and all
&lt;/span&gt;     &lt;span class=&quot;syntax-comment&quot;&gt;;; argument expressions, then apply the procedure with the
&lt;/span&gt;     &lt;span class=&quot;syntax-comment&quot;&gt;;; arguments.
&lt;/span&gt;     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;proc-expr&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;syntax-comment&quot;&gt;;; Recursively evaluate the arguments.
&lt;/span&gt;            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;arg-expr&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;arg-expr&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                 &lt;span class=&quot;syntax-symbol&quot;&gt;arg-exprs&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Fortunately, we don't need to implement &lt;code&gt;apply&lt;/code&gt; ourselves.  Since
&lt;code&gt;lambda&lt;/code&gt; forms in our interpreter evaluate to regular Scheme
procedures, we can just use Scheme's built-in &lt;code&gt;apply&lt;/code&gt; to pass
arguments to them.  Calling a procedure will recursively call &lt;code&gt;eval&lt;/code&gt;
on the procedure's body expression.&lt;/p&gt;&lt;p&gt;Example:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,+&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;; =&amp;gt; 6&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Incidentally, we've created a
&lt;a href=&quot;https://en.wikipedia.org/wiki/Capability-based_security&quot;&gt;capability-secure&lt;/a&gt;
system reminiscent of &lt;a href=&quot;https://webassembly.github.io/spec/core/intro/introduction.html#security-considerations&quot;&gt;Wasm's security
model&lt;/a&gt;!
The program &lt;code&gt;(+ 1 2 3)&lt;/code&gt; only has access to the &lt;code&gt;+&lt;/code&gt; procedure from our
Scheme runtime.  Aside from creating unbounded loops, a devious
developer can't do any harm if their code is evaluated in this
restricted environment.  Neat!&lt;/p&gt;&lt;h3&gt;Scheme in Scheme on Wasm&lt;/h3&gt;&lt;p&gt;Now that we have a simple evaluator, we can compile it with Hoot to
run it inside a web browser.  But to actually use it, we need a user
interface.  To make one, we can borrow the React-like rendering code
we walked through in our previous tutorial on rendering web pages with
Wasm, &lt;a href=&quot;/news/building-interactive-web-pages-with-guile-hoot.html&quot;&gt;&amp;quot;Building interactive web pages with Guile
Hoot&amp;quot;&lt;/a&gt;!&lt;/p&gt;&lt;p&gt;For simplicity, we'll go for a minimalist design reminiscent of a
terminal.  As for the REPL output log, we can store it as a list of
strings.  Let's pre-populate it with a friendly welcome message:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*log*&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Welcome to the Hoot metacircular evaluator demo!

This is a miniature Scheme interpreter written in Scheme that's been
compiled to WebAssembly, and is running directly in the browser!  Its
UI is also written in Scheme, and uses the Hoot FFI to render itself
to the DOM.

&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;log-append!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;set!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*log*&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*log*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here's the rendering template, which prints all the log lines, and
appends the classic &lt;code&gt;&amp;gt;&lt;/code&gt; prompt and a &lt;code&gt;textarea&lt;/code&gt; to the bottom so the
user can write some Scheme code:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;prompt&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;&amp;gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;container&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Hoot REPL&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;repl&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;repl repl-text&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;log&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,@*log*&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;prompt&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;syntax-symbol&quot;&gt;,prompt&lt;/span&gt;
                  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;textarea&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;expression&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                               &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;repl-text&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                               &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;placeholder&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;(+ 1 2 3)&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                               &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;keyup&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,maybe-eval&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Every time the user presses a key while focused on the &lt;code&gt;textarea&lt;/code&gt;, we
call the &lt;code&gt;maybe-eval&lt;/code&gt; procedure shown below.  When the user presses
the Enter key, the REPL&lt;/p&gt;&lt;ul&gt;&lt;li&gt;evaluates their code&lt;/li&gt;&lt;li&gt;clears the &lt;code&gt;textarea&lt;/code&gt;&lt;/li&gt;&lt;li&gt;appends any new output&lt;/li&gt;&lt;li&gt;scrolls to the bottom of the log to keep the terminal screen up to
date&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;maybe-eval&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; Get the event's key.
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;keyboard-event-key&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Evaluate user code when Enter is pressed, but not when
&lt;/span&gt;    &lt;span class=&quot;syntax-comment&quot;&gt;;; Shift is being held so the user can edit across multiple
&lt;/span&gt;    &lt;span class=&quot;syntax-comment&quot;&gt;;; lines.
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;string-=?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Enter&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;keyboard-event-shift?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-comment&quot;&gt;;; Get the text within the expression textarea.
&lt;/span&gt;      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let*&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;get-element-by-id&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;expression&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;exp&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;element-value&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-comment&quot;&gt;;; If the textarea is empty, do nothing.
&lt;/span&gt;        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;string-=?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;exp&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-comment&quot;&gt;;; Clear the textarea.
&lt;/span&gt;          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;set-element-value!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-comment&quot;&gt;;; Evaluate and append output to log.
&lt;/span&gt;          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;eval!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-comment&quot;&gt;;; Update UI.
&lt;/span&gt;          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;refresh!&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-comment&quot;&gt;;; Scroll the log to show the next output.
&lt;/span&gt;          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;scroll-to-bottom!&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At the bottom, you'll notice &lt;code&gt;maybe-eval&lt;/code&gt; uses a new procedure we've
called &lt;code&gt;eval!&lt;/code&gt; (how exciting).  &lt;code&gt;eval!&lt;/code&gt; is &lt;code&gt;eval&lt;/code&gt; + &lt;code&gt;read&lt;/code&gt; — it parses
the user's text using Scheme's built-in &lt;code&gt;read&lt;/code&gt; procedure, calls
&lt;code&gt;eval&lt;/code&gt;, and prints the output to the log:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;eval!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; Parse user input.
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;exp&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;open-input-string&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-comment&quot;&gt;;; Open output port.
&lt;/span&gt;        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;open-output-string&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Redirect all output to our output port.
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;parameterize&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;current-output-port&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-comment&quot;&gt;;; Echo the prompt and user code.
&lt;/span&gt;      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;display&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;prompt&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;display&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-comment&quot;&gt;;; Invoke the interpreter.
&lt;/span&gt;      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;call-with-values&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;exp&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;init-env&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-comment&quot;&gt;;; Display each returned value on its own line.
&lt;/span&gt;        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vals&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;null?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vals&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;display&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;for-each&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;unspecified?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;display&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;=&amp;gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;newline&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;syntax-symbol&quot;&gt;vals&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Append output to log.
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;log-append!&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;get-output-string&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(Note how, thanks to &lt;code&gt;read&lt;/code&gt;, we've elided the messy work of parsing.)&lt;/p&gt;&lt;p&gt;Expressions are evaluated within the context of the following
environment that provides capabilities for basic arithmetic, lists,
multiple value return, and printing:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;init-env&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,+&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,-&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,*&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,/&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,=&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;cons&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,cons&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,car&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;cdr&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,cdr&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,list&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;pair?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,pair?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;null?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,null?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,values&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;display&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,display&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;newline&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,newline&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The initial environment describes the primitive functionality of our
interpreter.  Primitives are simple things that the programmer can
take for granted.  This environment doesn't provide much, but it's
enough to have a bit of fun.&lt;/p&gt;&lt;p&gt;And...&lt;/p&gt;&lt;p&gt;🥁&lt;/p&gt;&lt;p&gt;🥁&lt;/p&gt;&lt;p&gt;🥁&lt;/p&gt;&lt;p&gt;...here's the finished program!&lt;/p&gt;&lt;p&gt;&lt;iframe src=&quot;https://spritely.institute/files/embeds/hoot-meta-repl/index.html&quot; frameborder=&quot;0&quot; sandbox=&quot;allow-scripts&quot; alt=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;p&gt;Some expressions you could try:&lt;/p&gt;&lt;p&gt;Greet the world:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;display&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Make a list of the veggies you want on your sandwich:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;lettuce&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;tomato&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;onion&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;pepper&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;pickles&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Display all your favorite pets as multiple return values:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'cat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'dog&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'chicken&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Apply a procedure that squares numbers:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Recursively apply a procedure to compute the nth Fibonacci number:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;fib&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;
       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;
           &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;fib&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fib&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;fib&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fib&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;syntax-symbol&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Whoa, that last one was kinda wild, huh?  That's because our little
interpreter lacks even the ability to bind variables outside of
&lt;code&gt;lambda&lt;/code&gt;.  There is no &lt;code&gt;let&lt;/code&gt; nor &lt;code&gt;define&lt;/code&gt;, so recursive code gets
weird fast!  Talk about minimalism...&lt;/p&gt;&lt;h3&gt;Scheming ahead&lt;/h3&gt;&lt;p&gt;The interpreter we've shown here is just a toy, but in the coming
months we expect to add support for the &lt;a href=&quot;https://small.r7rs.org/attachment/r7rs.pdf&quot;&gt;R7RS-small
standard&lt;/a&gt;'s &lt;code&gt;eval&lt;/code&gt;, taking
our REPL from toy to full Scheme interpreter.&lt;/p&gt;&lt;p&gt;Once we do so, we could embed Scheme REPLs directly into documents
like the &lt;em&gt;Scheme Primer&lt;/em&gt;, further reducing the activation energy
required to get started with Scheme.  And who knows what exciting
integrations our community will come up with?&lt;/p&gt;&lt;p&gt;In the meantime, if you'd like to start immediately hacking on the
REPL demo, you can find the complete source code on
&lt;a href=&quot;https://gitlab.com/spritely/guile-hoot-meta-repl&quot;&gt;GitLab&lt;/a&gt;.  If you're
into homework assignments, try adding support for more Scheme syntax
such as &lt;code&gt;let&lt;/code&gt;, or adding more procedures to the environment to grant
more power to the interpreter.&lt;/p&gt;&lt;p&gt;And be sure to show off what you build with Hoot in our &lt;a href=&quot;https://community.spritely.institute&quot;&gt;community
forum&lt;/a&gt;!  (Use OCAPN2023 for the
invite code when you join.)&lt;/p&gt;&lt;p&gt;Happy hooting! 🦉&lt;/p&gt;</summary></entry><entry><title>Having a Hoot at the Lisp Game Jam: A Tale of Two Daves</title><id>https://spritely.institute/news/having-a-hoot-at-the-lisp-game-jam-a-tale-of-two-daves.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2023-12-07T12:00:00Z</updated><link href="https://spritely.institute/news/having-a-hoot-at-the-lisp-game-jam-a-tale-of-two-daves.html" rel="alternate" /><summary type="html">&lt;p&gt;&lt;img src=&quot;/static/images/blog/2023_12_07-autumn_game_jam-space_hooter.png&quot; alt=&quot;Hoot-themed Space Invaders&quot; title=&quot;Owlet Storm: a space hooter&quot; /&gt;&lt;/p&gt;&lt;p&gt;This October, several teams and individuals gathered online to create sixteen games over the course of ten days for the biannual &lt;a href=&quot;https://en.wikipedia.org/wiki/Game_jam&quot;&gt;Lisp Game Jam&lt;/a&gt;. The &lt;a href=&quot;https://github.com/lispgames/lispgames.github.io/wiki/Lisp-Game-Jams&quot;&gt;earliest recorded instance of the jam&lt;/a&gt; took place in 2010, then intermittently in the years that followed, before landing on a more semi-annual basis starting in 2016.&lt;/p&gt;&lt;p&gt;This year, two of the entries, &lt;em&gt;Cybersol&lt;/em&gt; by &lt;a href=&quot;https://daviwil.com&quot;&gt;David Wilson&lt;/a&gt; and &lt;em&gt;Strigoform&lt;/em&gt; by Spritely's own &lt;a href=&quot;https://dthompson.us&quot;&gt;Dave Thompson&lt;/a&gt;, &lt;a href=&quot;https://itch.io/jam/autumn-lisp-game-jam-2023/topic/3229219/hacking-a-browser-game-in-scheme-with-guile-hoot&quot;&gt;leveraged Hoot&lt;/a&gt;, our &lt;a href=&quot;https://spritely.institute/hoot&quot;&gt;open-source Wasm toolkit&lt;/a&gt; to enable &lt;a href=&quot;https://www.scheme.org&quot;&gt;Scheme&lt;/a&gt; in the browser. What follows is an interview with the two devs on how it felt to participate in the jam this year, as well as their experiences with Hoot.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Note: Interviews have been lightly formatted&lt;/em&gt;&lt;/p&gt;&lt;h3&gt;How did you come to learn about the jam?&lt;/h3&gt;&lt;h4&gt;David Wilson&lt;/h4&gt;&lt;p&gt;I've known about the Lisp Game Jam for years now and have tried participating a couple of other times but never submitted an entry.  Since &lt;a href=&quot;https://spritely.institute/news/guile-hoot-v010-released.html&quot;&gt;Hoot released 0.1.0&lt;/a&gt; practically a week before the jam, it seemed like an excellent opportunity to participate and experiment with the toolchain.&lt;/p&gt;&lt;h4&gt;Dave Thompson&lt;/h4&gt;&lt;p&gt;I had become friends with one of the former jam hosts, David O'Toole (dto), via the #lispgames IRC channel. It turned out that dto and I live very close to each other and even went to the same college (though not concurrently), and through that connection I got more involved in hobby game development with Lisp, using Guile Scheme as my Lisp of choice. I submitted my first game to the jam that happened soon after:
&lt;a href=&quot;https://itch.io/jam/spring-2016-lisp-game-jam/rate/66627&quot;&gt;Spring 2016 Lisp Game Jam&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I try to participate in every jam, but most of the time I don't submit anything. Finishing stuff is hard!&lt;/p&gt;&lt;h3&gt;How long have you been participating in this or other jams?&lt;/h3&gt;&lt;h4&gt;David Wilson&lt;/h4&gt;&lt;p&gt;I've been participating in game jams like &lt;a href=&quot;https://ludumdare.com&quot;&gt;Ludum Dare&lt;/a&gt;, &lt;a href=&quot;https://github.blog/2023-11-01-github-game-off-2023-theme-announcement&quot;&gt;GitHub Game Off&lt;/a&gt;, and the Lisp Game Jam for around 10 years.  They're a great way to try out new languages, libraries, and programming techniques!  I usually live stream the work on my jam entries on the YouTube channel &lt;a href=&quot;https://youtube.com/@FluxHarmonicLive&quot;&gt;Flux Harmonic&lt;/a&gt;.&lt;/p&gt;&lt;h4&gt;Dave Thompson&lt;/h4&gt;&lt;p&gt;I started participating in &lt;a href=&quot;https://itch.io/jam/january-2016-lisp-game-jam&quot;&gt;2016&lt;/a&gt;, when the jams started being hosted on &lt;a href=&quot;https://itch.io&quot;&gt;itch.io&lt;/a&gt;, a hosting platform and digital store for independent games.&lt;/p&gt;&lt;h3&gt;How did you start running the jam?&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Note: Dave Thompson is a co-organizer of the game jam&lt;/em&gt;&lt;/p&gt;&lt;h4&gt;Dave Thompson&lt;/h4&gt;&lt;p&gt;In 2022, Michael Fiano (mfiano), who had been hosting the jam since late 2016, decided it was time for someone else to take over. Phil Hagelberg (technomancy), who maintains &lt;a href=&quot;https://fennel-lang.org&quot;&gt;Fennel&lt;/a&gt;, among other things, volunteered. Phil felt it would be best to have some redundancy with a second person available to moderate, so I volunteered to co-host. You'll see my name in the &amp;quot;Hosted by&amp;quot; line starting with &lt;a href=&quot;https://itch.io/jam/lisp-game-jam-2022&quot;&gt;Lisp Game Jam 2022&lt;/a&gt;, but really Phil does all the work organizing the dates and setting up the jam page. The jams do not have strict rules, and there is no money involved, so there isn't much to moderate. Phil does kindly check in with me to see if his proposed dates for the next jam sound good to me. I always say &amp;quot;yes.&amp;quot; :)&lt;/p&gt;&lt;h3&gt;Can you tell us a bit about this year's entry?&lt;/h3&gt;&lt;h4&gt;David Wilson&lt;/h4&gt;&lt;p&gt;I have a recurring idea to make keyboard-friendly versions of classic games like Solitaire, so this time I decided to do just that and worked on a &lt;a href=&quot;https://fluxharmonic.itch.io/cybersol&quot;&gt;cyberpunk-themed Solitaire game&lt;/a&gt;.  Instead of clicking on the cards to move them around, you use keyboard keys that are mapped to the various card stacks so that you can be a lot more efficient with your movements.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;/static/images/blog/2023_12_07-2023_autumn_game_jam-Cybersol.gif&quot; alt=&quot;Animated gif of Cybersol gameplay&quot; title=&quot;Cybersol&quot; /&gt;&lt;/p&gt;&lt;h4&gt;Dave Thompson&lt;/h4&gt;&lt;p&gt;I made a vertical scrolling space shooter with a retro arcade style called &lt;a href=&quot;https://davexunit.itch.io/strigoform&quot;&gt;Strigoform&lt;/a&gt;. I wrote all of the code, &lt;a href=&quot;https://dustycloud.org&quot;&gt;Christine Lemmer-Webber&lt;/a&gt; came up with the name, the owl theme, and did all of the pixel art, and my wife Andrea Parthemore wrote the music.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;/static/images/blog/2023_12_07-2023_autumn_game_jam-Strigoform.gif&quot; alt=&quot;Animated gif of Strigoform gameplay&quot; title=&quot;Strigoform&quot; /&gt;&lt;/p&gt;&lt;h3&gt;What inspired your game?&lt;/h3&gt;&lt;h4&gt;David Wilson&lt;/h4&gt;&lt;p&gt;The world needs more keyboard-driven games because using the mouse is boring :)&lt;/p&gt;&lt;h4&gt;Dave Thompson&lt;/h4&gt;&lt;p&gt;Fear! Hoot 0.1.0 had just been released, and since it was the very
first release there were a lot of limitations and some bugs waiting to
be discovered. I knew I'd be pushing my technical skills to get the
game done in time, so I decided to play it safe otherwise and make
something that was familiar to me. I have made several similar games
for past jams, so a space shooter became the obvious safe choice.
Also, Christine thought it would be cool if I made a space shooter and
offered to make pixel art.&lt;/p&gt;&lt;h3&gt;What tools did you use to make your game and why?&lt;/h3&gt;&lt;h4&gt;David Wilson&lt;/h4&gt;&lt;p&gt;I used &lt;a href=&quot;https://www.gnu.org/software/emacs&quot;&gt;Emacs&lt;/a&gt; for development because it is the ultimate work environment, &lt;a href=&quot;https://inkscape.org&quot;&gt;Inkscape&lt;/a&gt; for creating vector graphics, &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API&quot;&gt;HTML5 canvas APIs&lt;/a&gt; for rendering the game, and &lt;a href=&quot;https://www.google.com/chrome/canary&quot;&gt;Google Chrome Unstable&lt;/a&gt; for testing the game because it had all the bleeding-edge WebAssembly features needed by Hoot.&lt;/p&gt;&lt;h4&gt;Dave Thompson&lt;/h4&gt;&lt;p&gt;The game was made completely with FOSS. The code was written in &lt;a href=&quot;https://www.gnu.org/software/emacs&quot;&gt;Emacs&lt;/a&gt; because it's the best editor for Lisp out there. The art was made in &lt;a href=&quot;https://libresprite.github.io&quot;&gt;LibreSprite&lt;/a&gt; because it is built for pixel artists. The level was made in &lt;a href=&quot;https://www.mapeditor.org&quot;&gt;Tiled&lt;/a&gt; because it's a flexible 2D map editor and I already had a parser for its TMX format written in Scheme. The music was made in &lt;a href=&quot;https://milkytracker.org&quot;&gt;MilkyTracker&lt;/a&gt; because it's good for retro chiptune music.&lt;/p&gt;&lt;p&gt;Most importantly, the source code was compiled with Guile Hoot because it builds Wasm binaries that can run in web browsers. I've done game jams long enough to know that browser games will be tried and rated by more people than games with only native builds because it is much less work for the user. Browser games are also more likely to work on other people's computers. Providing native builds for all major operating systems that work reliably is difficult as an independent developer.&lt;/p&gt;&lt;h3&gt;What challenges did you encounter in development?&lt;/h3&gt;&lt;h4&gt;David Wilson&lt;/h4&gt;&lt;p&gt;Because Hoot did not have a &lt;a href=&quot;https://en.wikipedia.org/wiki/Foreign_function_interface&quot;&gt;foreign function interface&lt;/a&gt; as of the 0.1.0 release, I had to write a decent portion of the game in JavaScript because Hoot could not call the JS functions needed for rendering the screen handling input, etc.&lt;/p&gt;&lt;p&gt;The biggest challenge there was designing the Scheme code to be purely focused on the game logic and to create a simple protocol for communicating the game state between the JavaScript and Scheme code so that the JS code can render the game and Scheme can process the user's actions.  It was a lot of extra work to get around a temporary limitation of Hoot!&lt;/p&gt;&lt;p&gt;This problem has now disappeared as of &lt;a href=&quot;https://spritely.institute/news/guile-hoot-v020-released.html&quot;&gt;Hoot 0.2.0&lt;/a&gt;.  I've already started rewriting the game to &lt;a href=&quot;https://spritely.institute/news/building-interactive-web-pages-with-guile-hoot.html&quot;&gt;make use of the new FFI capabilities&lt;/a&gt;.&lt;/p&gt;&lt;h4&gt;Dave Thompson&lt;/h4&gt;&lt;p&gt;Hoot's in an early stage of development, so challenges caused by bugs and missing features were to be expected. I ran into bugs with some floating point operations and hacked around them with some inline Wasm. There was a particularly gnarly compiler bug that caused the Scheme stack to get into an invalid state sometimes and throw a Wasm runtime exception. User defined record types, which Schemers know as &lt;code&gt;define-record-type&lt;/code&gt;, wasn't implemented yet so I resorted to tagged vectors to describe all my data types for the player, enemies, etc. All of these issues and more have since been fixed!&lt;/p&gt;&lt;p&gt;It was also challenging to not be able to use &lt;a href=&quot;https://dthompson.us/projects/chickadee.html&quot;&gt;Chickadee&lt;/a&gt;, the game programming library for Guile that I maintain. Chickadee uses the &lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/Foreign-Function-Interface.html&quot;&gt;C FFI&lt;/a&gt; to interact with native libraries like &lt;a href=&quot;https://dri.freedesktop.org/wiki/libGL&quot;&gt;libGL&lt;/a&gt;, &lt;a href=&quot;http://www.libpng.org/pub/png/libpng.html&quot;&gt;libpng&lt;/a&gt; and &lt;a href=&quot;https://freetype.org&quot;&gt;libfreetype&lt;/a&gt;, so it needs extensive work to add a new backend that uses web APIs instead via the Hoot FFI.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Note: Check out Dave's &lt;a href=&quot;https://itch.io/jam/autumn-lisp-game-jam-2023/topic/3213364/chickadee-guile-scheme-game-template&quot;&gt;Chickadee template here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;&lt;h3&gt;What about successes or wins?&lt;/h3&gt;&lt;h4&gt;David Wilson&lt;/h4&gt;&lt;p&gt;The main success was that I was able to implement basic working game logic and rendering in the time of the jam!  The biggest win, though, was that, thanks to Hoot, I was able to write working Scheme code to run in a browser.&lt;/p&gt;&lt;h4&gt;Dave Thompson&lt;/h4&gt;&lt;p&gt;The biggest win is that the prototype FFI for Hoot that I was hacking on before the jam started worked well enough to access the
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API&quot;&gt;HTML5 Canvas API&lt;/a&gt;. I wasn't sure if performance would be good
enough without using WebGL, which I definitely did not have time to use, but it worked out great!&lt;/p&gt;&lt;p&gt;Another small success story happened a few days into the jam. When the jam started, I was writing the level data by hand, tile by tile, in the Scheme source. I thought that since it was just a jam game I could deal with how annoying it was to edit the level, but it quickly became a productivity destroyer. I decided I should use a proper map editor like Tiled. However, writing the code to fetch, parse, and transform a Tiled map in the browser was going to be too difficult to implement in the time I had. I thought I was stuck, but then I remembered: this is Scheme! &lt;a href=&quot;https://en.wikipedia.org/wiki/Code_as_data&quot;&gt;Code is data&lt;/a&gt;! I could compile the map file to Scheme code at build time. That auto-generated Scheme code could then be composed with the Scheme code that I wrote for the rest of the game and then the level would be baked into the final binary. So, that's what I did and it worked great! No need to use an XML parser at runtime!&lt;/p&gt;&lt;h3&gt;What do you hope to see from Hoot going forward?&lt;/h3&gt;&lt;h4&gt;David Wilson&lt;/h4&gt;&lt;p&gt;Since Hoot is quickly reaching compatibility with &lt;a href=&quot;https://small.r7rs.org&quot;&gt;R7RS-small&lt;/a&gt;, it will be a fully functional Scheme for basic application and game development.  What I'm more excited about is new libraries written for Hoot which add APIs for graphics programming, UI development, and networking support via HTTP requests or WebSockets.  I imagine that is an area where the Hoot community could help out significantly!&lt;/p&gt;&lt;h4&gt;Dave Thompson&lt;/h4&gt;&lt;p&gt;I'd like to see a lot of useful browser APIs get wrapped into ready-to-use Guile libraries. Hoot still lacks a module system, but that's on the way and it will enable the community that's growing around Hoot to start making cool and reusable things. Besides the DOM, the most important APIs for games are HTML5 Canvas, WebGL, WebGPU, and Web Audio. Porting Chickadee to the web will make it much easier to build games with Hoot.&lt;/p&gt;&lt;h3&gt;Do you have any advice or favorite resources you'd like to share with future participants?&lt;/h3&gt;&lt;h4&gt;David Wilson&lt;/h4&gt;&lt;p&gt;My advice for anyone participating in a game jam is to limit the scope of your ideas as much as possible so that you can actually complete the game! You'll have a lot more fun if you make a &amp;quot;simpler&amp;quot; game that you can finish and then spend the rest of the time polishing it to make it more fun.&lt;/p&gt;&lt;h4&gt;Dave Thompson&lt;/h4&gt;&lt;p&gt;This is common jam advice but it's so true that it's worth repeating: Scope your ambitions down. Way down. Whatever your brain is telling you is a reasonable goal, try to reduce it even further. This takes practice, and I've failed at it more times than I've succeeded. The Lisp Game Jam is great because of its relaxed rules and how it always takes place across 2 full weekends for a total of 10 days, which makes it accessible to busy people.&lt;/p&gt;&lt;p&gt;Come into the jam with your tools ready and don't wait until the last day to figure out how you're going to distribute your game. Toolchain issues are no fun, and jams are supposed to be fun!&lt;/p&gt;&lt;p&gt;To learn more about what the options are for making games with Lisp, check out the source code for the entries in &lt;a href=&quot;https://github.com/lispgames/lispgames.github.io/wiki/Lisp-Game-Jams&quot;&gt;past Lisp Game Jams&lt;/a&gt;. Every game is required to publish source code so there's a lot of good code to learn from! The Strigoform source code is available on my &lt;a href=&quot;https://git.dthompson.us/autumn-lisp-game-jam-2023&quot;&gt;personal website&lt;/a&gt;. I think Hoot is great for building web games and I'm going to try using it for the next jam, too.&lt;/p&gt;&lt;h3&gt;Are there any other questions you wish you'd been asked about the jam?&lt;/h3&gt;&lt;h4&gt;David Wilson&lt;/h4&gt;&lt;p&gt;Maybe &amp;quot;What was your favorite game from the jam?&amp;quot;  My answer would be Dave Thompson's Strigoform because it's much better than mine and a &lt;em&gt;real&lt;/em&gt; example of what you can do with a fully-Scheme browser game using Hoot :)&lt;/p&gt;&lt;h4&gt;Dave Thompson&lt;/h4&gt;&lt;p&gt;I think you covered all the important stuff. Thanks! :)&lt;/p&gt;&lt;h3&gt;Further reading&lt;/h3&gt;&lt;p&gt;All good things come to an end and so too must this interview. If you'd like to participate in the next Lisp Game Jam, here are some resources you might find useful:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;📒 &lt;a href=&quot;https://itch.io/jam/autumn-lisp-game-jam-2023&quot;&gt;Autumn Lisp Game Jam 2023&lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;📣 (Keep an eye out for the Spring Game Jam 2024 announcement on the &lt;a href=&quot;https://itch.io/jam/autumn-lisp-game-jam-2023/community&quot;&gt;Community tab&lt;/a&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;📒 &lt;a href=&quot;https://github.com/kobitoko/Game-Jam-Tools-Resources&quot;&gt;Game Jam Tools &amp;amp; Resources&lt;/a&gt;, kobitoko (GitHub)&lt;/li&gt;&lt;li&gt;📖 &lt;a href=&quot;https://en.wikipedia.org/wiki/Game_jam&quot;&gt;Game jam&lt;/a&gt;, Wikipedia&lt;/li&gt;&lt;li&gt;📖 &lt;a href=&quot;https://github.com/lispgames/lispgames.github.io/wiki&quot;&gt;Lisp Game Wiki&lt;/a&gt;&lt;/li&gt;&lt;li&gt;📰 &lt;a href=&quot;https://www.gamedeveloper.com/design/7-tips-to-7-day-game-jams&quot;&gt;7 Tips to 7-Day Game Jams&lt;/a&gt;, John Cooney (&lt;em&gt;Game Developer&lt;/em&gt;)&lt;/li&gt;&lt;li&gt;📺 &lt;a href=&quot;https://www.youtube.com/watch?v=BZr1KHa89Ew&amp;amp;list=PLwranTcItp8se9p-01UtzXopS-wAjeEJf&quot;&gt;Live Coding a 2D Platformer with Lisp&lt;/a&gt;, David Wilson (YouTube)&lt;/li&gt;&lt;li&gt;📺 &lt;a href=&quot;https://www.youtube.com/live/fp9J6sIYAMA?si=zxoi_EONeonwBwci&quot;&gt;Live Coding a Solitaire Game with Scheme&lt;/a&gt;, David Wilson (YouTube)&lt;/li&gt;&lt;li&gt;📓 &lt;a href=&quot;https://dthompson.us/spring-lisp-game-jam-2023-summary.html&quot;&gt;Spring Lisp Game Jam 2023 Summary&lt;/a&gt;, David Thompson (blog)&lt;/li&gt;&lt;li&gt;📓 &lt;a href=&quot;https://log.schemescape.com/posts/game-development/lisp-game-jam-2.html&quot;&gt;Retrospective: Lisp Game Jam (Spring 2023)&lt;/a&gt;, Jared Krinke (Schemescape)&lt;/li&gt;&lt;li&gt;🎮 &lt;a href=&quot;https://fluxharmonic.itch.io/cybersol&quot;&gt;Cybersol&lt;/a&gt;&lt;/li&gt;&lt;li&gt;🎮 &lt;a href=&quot;https://davexunit.itch.io/strigoform&quot;&gt;Strigoform&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;And if you'd like to learn more about and contribute to Hoot, be sure to check out our &lt;a href=&quot;/hoot&quot;&gt;webpage&lt;/a&gt; and the &lt;a href=&quot;https://gitlab.com/spritely/guile-hoot&quot;&gt;GitLab repo&lt;/a&gt;!&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;/static/images/blog/2023_12_07-2023_autumn_game_jam-itch_submissions.png&quot; alt=&quot;All 16 game jam submissions&quot; title=&quot;itch.io submissions&quot; /&gt;&lt;/p&gt;&lt;p&gt;Thanks for reading! 🌟&lt;/p&gt;</summary></entry><entry><title>Building interactive web pages with Guile Hoot</title><id>https://spritely.institute/news/building-interactive-web-pages-with-guile-hoot.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2023-11-30T13:30:00Z</updated><link href="https://spritely.institute/news/building-interactive-web-pages-with-guile-hoot.html" rel="alternate" /><summary type="html">&lt;p&gt;&lt;img src=&quot;/static/images/blog/hoot-todo.jpg&quot; alt=&quot;Hoot owl with a to-do list scroll&quot; /&gt;&lt;/p&gt;&lt;p&gt;A question we frequently hear in discussions about WebAssembly (Wasm)
is:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&amp;quot;Can Wasm call the DOM (Document Object Model) API?&amp;quot;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The answer is: &lt;strong&gt;Yes, thanks to &lt;a href=&quot;https://v8.dev/blog/wasm-gc-porting&quot;&gt;Wasm Garbage
Collection&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;In this post, we will use &lt;a href=&quot;/hoot&quot;&gt;Guile Hoot&lt;/a&gt; (our Scheme to Wasm
compiler) to demonstrate how a language that compiles to Wasm GC can
be used to implement the kind of interactivity we're used to
implementing with JavaScript.  We'll start very simple and build up to
something that resembles a &lt;a href=&quot;https://react.dev/&quot;&gt;React&lt;/a&gt;-like
application.&lt;/p&gt;&lt;p&gt;In our &lt;a href=&quot;/news/scheme-wireworld-in-browser.html&quot;&gt;previous post about running Scheme in the
browser&lt;/a&gt;, we had to use quite
a lot of JavaScript code to call Scheme procedures (functions), render
the user interface, and handle user input. However, today we're
pleased to announce that those days are behind us; Hoot 0.2.0,
&lt;a href=&quot;/news/guile-hoot-v020-released.html&quot;&gt;released today&lt;/a&gt;, now includes a
foreign function interface (FFI) for calling JavaScript from Scheme.
In other words, the vast majority of code in a Hoot application can
now be written directly in Scheme!&lt;/p&gt;&lt;h3&gt;Hello, world!&lt;/h3&gt;&lt;p&gt;Let's start with a &amp;quot;Hello, world&amp;quot; application that simply adds a text
node to the document body.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;document-body&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;document&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;body&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; Parameters: none
&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;;; Result: an external reference which may be null
&lt;/span&gt;  &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;make-text-node&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;document&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;createTextNode&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; Parameters: a string
&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;;; Result: an external reference which may be null
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;append-child!&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;element&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;appendChild&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; Parameters: two external references which may be null
&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;;; Result: an external reference which may be null
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;append-child!&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;document-body&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-text-node&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;define-foreign&lt;/code&gt; syntax declares a Wasm import with a given
signature that is bound to a Scheme variable.  In this example, we'd
like access to &lt;code&gt;document.body&lt;/code&gt;, &lt;code&gt;document.createTextNode&lt;/code&gt;, and
&lt;code&gt;element.appendChild&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Each import has a two-part name, which correspond to the strings in
the &lt;code&gt;define-foreign&lt;/code&gt; expressions above.  Imported functions have a
signature specifying the parameter and result types.&lt;/p&gt;&lt;p&gt;WebAssembly follows the &lt;a href=&quot;https://en.wikipedia.org/wiki/Capability-based_security&quot;&gt;&lt;em&gt;capability security&lt;/em&gt;
model&lt;/a&gt; (and
if you know us, you know &lt;a href=&quot;/goblins&quot;&gt;we're big fans&lt;/a&gt;).  Wasm modules
act as guests within a host environment — in our case, the host is the
browser.  By default, a Wasm module has no access to functions that
interact with its host.  The Wasm guest must be granted explicit
permission by its host to be able to, for example, add DOM elements to
a web page.&lt;/p&gt;&lt;p&gt;The way capabilities work in Wasm is as follows:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The Wasm module declares a set of imports.&lt;/li&gt;&lt;li&gt;When the Wasm module is
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/instantiateStreaming&quot;&gt;instantiated&lt;/a&gt;,
the host maps the import names to concrete implementations.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So, &lt;code&gt;define-foreign&lt;/code&gt; merely &lt;em&gt;declares&lt;/em&gt; the module's need for a
particular function import; it does &lt;em&gt;not&lt;/em&gt; bind to a particular
function on the host.  The Wasm guest cannot grant capabilities unto
itself.&lt;/p&gt;&lt;p&gt;The host environment in the browser is the JavaScript engine, so we
must use JavaScript to bootstrap our Wasm program.  To do so, we
instantiate the Wasm module and pass along the implementations for the
declared imports.  The import names in JavaScript match up to the
import names in the Wasm module.  For our &amp;quot;Hello, world&amp;quot; example, that
code looks like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;load&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;Scheme&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;load_main&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;hello.wasm&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;syntax-symbol&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;syntax-symbol&quot;&gt;createTextNode&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Document&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;createTextNode&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;syntax-symbol&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;child&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;child&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;Scheme&lt;/code&gt; class is provided by our JavaScript integration library,
&lt;a href=&quot;https://gitlab.com/spritely/guile-hoot/-/blob/main/js-runtime/reflect.js&quot;&gt;reflect.js&lt;/a&gt;.
This library provides a Scheme abstraction layer on top of the
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface&quot;&gt;&lt;code&gt;WebAssembly&lt;/code&gt;
API&lt;/a&gt;
and is used to load Hoot binaries and manipulate Scheme values from
JavaScript.&lt;/p&gt;&lt;p&gt;The result:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;/static/images/blog/hoot-ffi-hello-world.png&quot; alt=&quot;The text &amp;quot;Hello, world!&amp;quot; rendered in a web browser.&quot; /&gt;&lt;/p&gt;&lt;h3&gt;HTML as Scheme data&lt;/h3&gt;&lt;p&gt;Now that we've explained the basics, let's move on to something more
interesting.  How about rendering an entire tree of DOM elements?  For
that, we'll need to declare imports for &lt;code&gt;document.createElement&lt;/code&gt; and
&lt;code&gt;element.setAttribute&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;make-element&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;document&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;createElement&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;set-attribute!&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;element&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;setAttribute&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And here's the additional JavaScript wrapper code:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-comment&quot;&gt;// These are added to the existing bindings from the previous section.
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Document&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;// ... the previously defined document functions
&lt;/span&gt;  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;// ... the previously defined element functions
&lt;/span&gt;  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we need some markup to render.  Thanks to the symbolic
manipulation powers of Scheme, we have no need for an additional
language like React's
&lt;a href=&quot;https://react.dev/learn/writing-markup-with-jsx&quot;&gt;JSX&lt;/a&gt; to cleanly mix
markup with code.  Scheme has &lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/Expression-Syntax.html#index-quote&quot;&gt;a lovely little thing called
&lt;code&gt;quote&lt;/code&gt;&lt;/a&gt;
which we can use to represent arbitrary data as Scheme expressions.
We'll use this to embed HTML within our Scheme code.&lt;/p&gt;&lt;p&gt;We use &lt;code&gt;quote&lt;/code&gt; by prepending a single quote (&lt;code&gt;'&lt;/code&gt;) to an expression.
For example, the expression &lt;code&gt;(+ 1 2 3)&lt;/code&gt; calls &lt;code&gt;+&lt;/code&gt; with the numbers
&lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;, and &lt;code&gt;3&lt;/code&gt; and returns &lt;code&gt;6&lt;/code&gt;.  However, the expression &lt;code&gt;'(+ 1 2 3)&lt;/code&gt; (note the &lt;code&gt;'&lt;/code&gt;) does not call &lt;code&gt;+&lt;/code&gt; but instead returns a list of 4
elements: the symbol &lt;code&gt;+&lt;/code&gt;, followed by the numbers &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;, and &lt;code&gt;3&lt;/code&gt;.
In other words, &lt;code&gt;quote&lt;/code&gt; turns code into data.&lt;/p&gt;&lt;p&gt;Now, to write HTML from within Scheme, we can leverage a format called
&lt;a href=&quot;https://okmij.org/ftp/Scheme/SXML.html&quot;&gt;SXML&lt;/a&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;sxml&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;section&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Scheme rocks!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;With Scheme, data is code and code is data.&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;small&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Made with &amp;quot;&lt;/span&gt;
           &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;href&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;https://spritely.institute/hoot&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Guile Hoot&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;section&lt;/code&gt;, &lt;code&gt;h1&lt;/code&gt;, etc. are not procedure calls, they are literal
symbolic data.&lt;/p&gt;&lt;p&gt;To transform this Scheme data into a rendered document, we need to
walk the SXML tree and make the necessary DOM API calls, like so:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;sxml-&amp;gt;dom&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;exp&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; The simple case: a string representing a text node.
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-text-node&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; An element tree.  The first item is the HTML tag.
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;symbol?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-comment&quot;&gt;;; Create a new element with the given tag.
&lt;/span&gt;     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-element&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;symbol-&amp;gt;string&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;add-children&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;syntax-comment&quot;&gt;;; Recursively call sxml-&amp;gt;dom for each child node and
&lt;/span&gt;         &lt;span class=&quot;syntax-comment&quot;&gt;;; append it to elem.
&lt;/span&gt;         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;for-each&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;child&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;append-child!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;sxml-&amp;gt;dom&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;child&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;syntax-symbol&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;body&lt;/span&gt;
         &lt;span class=&quot;syntax-comment&quot;&gt;;; '@' denotes an attribute list.  Child nodes follow.
&lt;/span&gt;         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;'@&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;attrs&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-comment&quot;&gt;;; Set attributes.
&lt;/span&gt;          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;for-each&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;attr&lt;/span&gt;
                        &lt;span class=&quot;syntax-comment&quot;&gt;;; Attributes are (symbol string) tuples.
&lt;/span&gt;                        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;symbol?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;set-attribute!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;
                                         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;symbol-&amp;gt;string&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                                         &lt;span class=&quot;syntax-symbol&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;syntax-symbol&quot;&gt;attrs&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;add-children&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;syntax-comment&quot;&gt;;; No attributes, just a list of child nodes.
&lt;/span&gt;         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;children&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;add-children&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then we can use our newly defined &lt;code&gt;sxml-&amp;gt;dom&lt;/code&gt; procedure to generate
the element tree and add it to the document body:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;append-child!&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;document-body&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;sxml-&amp;gt;dom&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;sxml&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The result:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;/static/images/blog/hoot-ffi-sxml.png&quot; alt=&quot;SXML rendered to DOM elements.&quot; /&gt;&lt;/p&gt;&lt;h3&gt;HTML templating with Scheme&lt;/h3&gt;&lt;p&gt;That was pretty neat, but we don't need JavaScript, let alone
WebAssembly, to render a simple static document!  In other words,
we're far from done here.  Let's introduce some interactivity by
adding a button and a counter that displays how many times the button
was clicked.  We could take an
&lt;a href=&quot;https://en.wikipedia.org/wiki/Imperative_programming&quot;&gt;imperative&lt;/a&gt;
approach and modify the element by mutating the counter value every
time the button is clicked.  Indeed, for something this simple that
would be fine.  But just for fun, let's take a look at a more
functional approach that uses a template to create the entire document
body.&lt;/p&gt;&lt;p&gt;Scheme provides support for structured templating via
&lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/Expression-Syntax.html#index-quasiquote&quot;&gt;&lt;code&gt;quasiquote&lt;/code&gt;&lt;/a&gt;,
which uses backticks (&lt;code&gt;`&lt;/code&gt;) instead of single-quotes (&lt;code&gt;'&lt;/code&gt;).
Arbitrary code can be evaluated in the template by using &lt;code&gt;unquote&lt;/code&gt;,
represented by a comma (&lt;code&gt;,&lt;/code&gt;).  The expression &lt;code&gt;`(+ 1 2 ,(+ 1 2))&lt;/code&gt;
produces the list &lt;code&gt;(+ 1 2 3)&lt;/code&gt;.  The first &lt;code&gt;(+ ...)&lt;/code&gt; expression is
quoted, but the second is not, and thus &lt;code&gt;(+ 1 2)&lt;/code&gt; is evaluated as code
and the value &lt;code&gt;3&lt;/code&gt; is placed into the final list element.&lt;/p&gt;&lt;p&gt;Scheme's &lt;code&gt;quasiquote&lt;/code&gt; stands in stark contrast to the limited string
templating available in most other languages.  In JavaScript, we could
do &lt;code&gt;`1 + 2 + ${1 + 2}`&lt;/code&gt;, but this form of templating lacks
structure.  The result is just a flat string, which makes it clumsy to
work with and vulnerable to &lt;a href=&quot;https://www.more-magic.net/posts/structurally-fixing-injection-bugs.html&quot;&gt;injection
bugs&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Below is an SXML template. It is a procedure which generates a
document based on the current value of &lt;code&gt;*clicks*&lt;/code&gt;, a global mutable
variable that stores how many times the button was clicked:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-comment&quot;&gt;;; It is a Scheme/Lisp naming convention to use asterisks, AKA
&lt;/span&gt;&lt;span class=&quot;syntax-comment&quot;&gt;;; earmuffs, to mark global mutable variables.
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*clicks*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;container&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;number-&amp;gt;string&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*clicks*&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot; clicks&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Increment click counter when button is clicked.
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;click&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;set!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*clicks*&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*clicks*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Click me&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To handle interactive elements, we've added a new feature on top of
SXML. Notice that the button has a &lt;code&gt;click&lt;/code&gt; property with a procedure
as its value.  To get some interactivity, we need event handlers, and
we've chosen to encode the click handler into the template much like
how you could use the &lt;code&gt;onclick&lt;/code&gt; attribute in plain HTML.&lt;/p&gt;&lt;p&gt;To make this work, we need imports for &lt;code&gt;document.getElementById&lt;/code&gt;,
&lt;code&gt;element.addEventListener&lt;/code&gt; and &lt;code&gt;element.remove&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;get-element-by-id&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;document&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;getElementById&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;add-event-listener!&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;element&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;addEventListener&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;remove!&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;element&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;remove&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And the JavaScript bindings:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Document&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;// ...
&lt;/span&gt;  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;// ...
&lt;/span&gt;  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here is what the attribute handling code in the &lt;code&gt;sxml-&amp;gt;dom&lt;/code&gt; procedure
looks like now:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;body&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;'@&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;attrs&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;for-each&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;attr&lt;/span&gt;
                 &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;symbol?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;set-attribute!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;
                                  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;symbol-&amp;gt;string&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                                  &lt;span class=&quot;syntax-symbol&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                 &lt;span class=&quot;syntax-comment&quot;&gt;;; THIS IS THE NEW BIT!
&lt;/span&gt;                 &lt;span class=&quot;syntax-comment&quot;&gt;;;
&lt;/span&gt;                 &lt;span class=&quot;syntax-comment&quot;&gt;;; If the attribute's value is a procedure, add an
&lt;/span&gt;                 &lt;span class=&quot;syntax-comment&quot;&gt;;; event listener.
&lt;/span&gt;                 &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;symbol?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;procedure?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;add-event-listener!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;
                                       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;symbol-&amp;gt;string&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                                       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;procedure-&amp;gt;external&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;syntax-symbol&quot;&gt;attrs&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;add-children&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;children&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;add-children&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To keep things simple (for now), every time the button is clicked
we'll delete what's in the document and re-render the template:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;old&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;get-element-by-id&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;container&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;external-null?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;remove!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;append-child!&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;document-body&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;sxml-&amp;gt;dom&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The result:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;/static/images/blog/hoot-ffi-counter.png&quot; alt=&quot;Button click counter screenshot.&quot; /&gt;&lt;/p&gt;&lt;h3&gt;Building a virtual DOM&lt;/h3&gt;&lt;p&gt;Wouldn't it be &lt;em&gt;even cooler&lt;/em&gt; if we could apply some kind of React-like
diffing algorithm that only updates the parts of the document that
have changed when we need to re-render?  Why yes, that would be cool!
Let's do that now.&lt;/p&gt;&lt;p&gt;We'll add bindings for the
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker&quot;&gt;TreeWalker&lt;/a&gt;
interface to traverse the document, as well as some additional element
methods to get/set the &lt;code&gt;value&lt;/code&gt; and &lt;code&gt;checked&lt;/code&gt; properties, remove event
listeners, replace elements, remove attributes, and get event targets:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-comment&quot;&gt;;; TreeWalker constructor:
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;make-tree-walker&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;document&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;createTreeWalker&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-comment&quot;&gt;;; TreeWalker API:
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;current-node&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;treeWalker&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;currentNode&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;set-current-node!&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;treeWalker&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;setCurrentNode&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;next-node!&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;treeWalker&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;nextNode&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;first-child!&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;treeWalker&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;firstChild&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;next-sibling!&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;treeWalker&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;nextSibling&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-comment&quot;&gt;;; More element API:
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;element-value&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;element&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;value&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;set-element-value!&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;element&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;setValue&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;remove-event-listener!&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;element&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;removeEventListener&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;replace-with!&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;element&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;replaceWith&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;remove-attribute!&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;element&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;removeAttribute&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-comment&quot;&gt;;; Event API:
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-foreign&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;event-target&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;event&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;target&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And the JavaScript bindings:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;createTreeWalker&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Document&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;createTreeWalker&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;// ...
&lt;/span&gt;  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;setValue&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;checked&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;checked&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;setChecked&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;checked&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;checked&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;checked&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;removeAttribute&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;removeAttribute&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;removeEventListener&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;removeEventListener&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;// ...
&lt;/span&gt;  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;treeWalker&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;currentNode&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;currentNode&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;setCurrentNode&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;currentNode&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;nextNode&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;nextNode&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;firstChild&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;firstChild&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;nextSibling&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;nextSibling&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we can implement the diffing algorithm.  Below is an abridged
version, but you can see the beautiful, fully-fledged source code on
&lt;a href=&quot;https://gitlab.com/spritely/guile-hoot-ffi-demo/-/blob/main/todo.scm&quot;&gt;GitLab&lt;/a&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;virtual-dom-render&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; &amp;lt;nested helper procedures have been omitted&amp;gt;
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-tree-walker&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;first-child!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;old&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt;
         &lt;span class=&quot;syntax-comment&quot;&gt;;; It's the first render, so clear out whatever might be
&lt;/span&gt;         &lt;span class=&quot;syntax-comment&quot;&gt;;; in the actual DOM and render the entire tree.  No
&lt;/span&gt;         &lt;span class=&quot;syntax-comment&quot;&gt;;; diffing necessary.
&lt;/span&gt;         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;current-node&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;external-null?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;next-sibling!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;remove!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;append-child!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;sxml-&amp;gt;dom&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;syntax-comment&quot;&gt;;; Replace text node with either a new text node if the
&lt;/span&gt;         &lt;span class=&quot;syntax-comment&quot;&gt;;; text has changed, or an element subtree if the text
&lt;/span&gt;         &lt;span class=&quot;syntax-comment&quot;&gt;;; has been replaced by an element.
&lt;/span&gt;         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;string?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;string-=?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;new-node&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;sxml-&amp;gt;dom&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;replace-with!&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;current-node&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-node&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;set-current-node!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-node&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;symbol?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old-tag&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old-rest&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let-values&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;old-attrs&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old-children&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;attrs+children&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old-rest&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt;
             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;string?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;syntax-comment&quot;&gt;;; Old node was an element, but the new node is a
&lt;/span&gt;              &lt;span class=&quot;syntax-comment&quot;&gt;;; string, so replace the element subtree with a
&lt;/span&gt;              &lt;span class=&quot;syntax-comment&quot;&gt;;; text node.
&lt;/span&gt;              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;new-text&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-text-node&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;replace-with!&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;current-node&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-text&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;set-current-node!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-text&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;symbol?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-tag&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-rest&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let-values&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;new-attrs&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-children&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;attrs+children&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-rest&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;cond&lt;/span&gt;
                 &lt;span class=&quot;syntax-comment&quot;&gt;;; The element tag is the same, so modify the
&lt;/span&gt;                 &lt;span class=&quot;syntax-comment&quot;&gt;;; inner contents of the element if necessary.
&lt;/span&gt;                 &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;eq?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old-tag&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-tag&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;current-node&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;update-attrs&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old-attrs&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-attrs&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;first-child!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;child-loop&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;old&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old-children&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                                     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-children&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old&lt;/span&gt;
                        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                         &lt;span class=&quot;syntax-comment&quot;&gt;;; The old child list is empty, so
&lt;/span&gt;                         &lt;span class=&quot;syntax-comment&quot;&gt;;; diffing stops here.  All remaining
&lt;/span&gt;                         &lt;span class=&quot;syntax-comment&quot;&gt;;; children in the new list are fresh
&lt;/span&gt;                         &lt;span class=&quot;syntax-comment&quot;&gt;;; elements that need to be added.
&lt;/span&gt;                         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;for-each&lt;/span&gt;
                          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;append-child!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;sxml-&amp;gt;dom&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                          &lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;old-child&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old-rest&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt;
                           &lt;span class=&quot;syntax-comment&quot;&gt;;; The new child list is empty, so any
&lt;/span&gt;                           &lt;span class=&quot;syntax-comment&quot;&gt;;; remaining children in the old child
&lt;/span&gt;                           &lt;span class=&quot;syntax-comment&quot;&gt;;; list need to be removed, including
&lt;/span&gt;                           &lt;span class=&quot;syntax-comment&quot;&gt;;; the current one.
&lt;/span&gt;                           &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;rem-loop&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;current-node&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;external-null?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                                &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;next-sibling!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                                  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;remove!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                                  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;rem-loop&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                           &lt;span class=&quot;syntax-comment&quot;&gt;;; Recursively diff old and new child
&lt;/span&gt;                           &lt;span class=&quot;syntax-comment&quot;&gt;;; elements.
&lt;/span&gt;                           &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;new-child&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-rest&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old-child&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-child&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;next-sibling!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;child-loop&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;old-rest&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-rest&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;set-current-node!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                 &lt;span class=&quot;syntax-comment&quot;&gt;;; New element tag is different than the old
&lt;/span&gt;                 &lt;span class=&quot;syntax-comment&quot;&gt;;; one, so replace the entire element subtree.
&lt;/span&gt;                 &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;else&lt;/span&gt;
                  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;replace-with!&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;current-node&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                                 &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;sxml-&amp;gt;dom&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, instead of deleting and recreating every single element on the
DOM tree to update the text for the counter, we can call the
&lt;code&gt;virtual-dom-render&lt;/code&gt; procedure and it will replace just one text node
instead.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-comment&quot;&gt;;; We'll diff the new vdom against the current one.
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*current-vdom*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;new-vdom&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;virtual-dom-render&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;document-body&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*current-vdom*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-vdom&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;set!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*current-vdom*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new-vdom&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;To-do app&lt;/h3&gt;&lt;p&gt;Let's wrap things up with our take on a classic: the to-do list.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;/static/images/blog/hoot-ffi-todo.png&quot; alt=&quot;A to-do list application inside a web browser.&quot; /&gt;&lt;/p&gt;&lt;p&gt;The humble to-do list is often used as a &amp;quot;Hello, world&amp;quot; of sorts for
client-side UI libraries (there's even &lt;a href=&quot;https://todomvc.com/&quot;&gt;an entire
website&lt;/a&gt; dedicated to them).&lt;/p&gt;&lt;p&gt;A to-do list has many tasks.  Tasks have a name and a flag indicating
if the task has been completed.  We'll use Scheme's
&lt;code&gt;define-record-type&lt;/code&gt; to encapsulate a task:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-record-type&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;&amp;lt;task&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-task&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;done?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;task?&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;task-name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;done?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;task-done?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;set-task-done!&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Tasks can be created and deleted.  We'll use a bit of global state for
managing the task list as a substitute for actual persistent storage:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*tasks*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;add-task!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;set!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*tasks*&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;cons&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*tasks*&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;remove-task!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;set!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*tasks*&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;delq&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*tasks*&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we can define a template for rendering the UI:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;task-template&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;checkbox&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;syntax-comment&quot;&gt;;; Toggle done? flag on click.
&lt;/span&gt;                   &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;change&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let*&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;checkbox&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event-target&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                                     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;checked?&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;element-checked?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;checkbox&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                                &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;set-task-done!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;checked?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                                &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;syntax-comment&quot;&gt;;; Check the box if task is done.
&lt;/span&gt;                   &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;checked&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;task-done?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;span&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;padding: 0 1em 0 1em;&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;syntax-comment&quot;&gt;;; Strikethrough if task is done.
&lt;/span&gt;               &lt;span class=&quot;syntax-symbol&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;task-done?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;syntax-symbol&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;task-name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;task-name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;href&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;#&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;syntax-comment&quot;&gt;;; Remove task on click.
&lt;/span&gt;               &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;click&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;remove-task!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;remove&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;div&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;h2&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Tasks&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Tasks are stored in reverse order.
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ul&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;task-template&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;reverse&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;*tasks*&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;new-task&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;placeholder&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Write more Scheme&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Add new task on click
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;click&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                         &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let*&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;get-element-by-id&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;new-task&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                                &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;element-value&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                           &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;string-=?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;add-task!&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-task&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;set-element-value!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Add task&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For this final example, we've embedded the result in an iframe below.
This requires a browser capable of Wasm GC and tail calls, such as
Chrome 119 or Firefox 121:&lt;/p&gt;&lt;p&gt;&lt;iframe src=&quot;https://spritely.institute/files/embeds/hoot-ffi-demo/todo.html&quot; frameborder=&quot;0&quot; sandbox=&quot;allow-scripts&quot; alt=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;p&gt;It should be said that a React-like virtual DOM isn't necessarily the
best way to implement a UI layer.  We like how the abstraction turns
the state of the UI into a function mapping application state to HTML
elements, as it avoids an entire class of synchronization bugs that
impact more imperative approaches.  That said, the overhead introduced
by a virtual DOM is not always acceptable.  Simple web pages are
better off with little to no client-side code so that they are more
usable on low power devices.  Still, a to-do application with a
virtual DOM diffing algorithm is a neat yet familiar way to show off
the expressive power of Hoot and its FFI.&lt;/p&gt;&lt;h3&gt;Looking forward&lt;/h3&gt;&lt;p&gt;With the introduction of an FFI, you can now implement nearly your
entire web frontend in Scheme; the examples we've looked at today are
but a glimpse of what's now possible!&lt;/p&gt;&lt;p&gt;In the future, we hope the Guile community will join us in developing
a colorful variety of wrapper libraries for commonly-used web APIs, so
that building with Hoot becomes increasingly fun and easy.&lt;/p&gt;&lt;p&gt;If you'd like to start playing around with the demos today, you can
find the complete source code &lt;a href=&quot;https://gitlab.com/spritely/guile-hoot-ffi-demo&quot;&gt;on
GitLab&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;To see everything that's new in Hoot 0.2.0, be sure to check out our
&lt;a href=&quot;/news/guile-hoot-v020-released.html&quot;&gt;release announcement post&lt;/a&gt;!&lt;/p&gt;</summary></entry><entry><title>Guile Hoot v0.2.0 released!</title><id>https://spritely.institute/news/guile-hoot-v020-released.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2023-11-30T12:00:00Z</updated><link href="https://spritely.institute/news/guile-hoot-v020-released.html" rel="alternate" /><summary type="html">&lt;p&gt;&lt;img src=&quot;/static/images/blog/hoot-0.2.0.jpg&quot; alt=&quot;Hoot version 0.2.0&quot; /&gt;&lt;/p&gt;&lt;p&gt;We are excited to announce the release of &lt;a href=&quot;/hoot&quot;&gt;Guile Hoot&lt;/a&gt; v0.2.0!
Hoot is a Scheme to WebAssembly compiler backend for
&lt;a href=&quot;https://gnu.org/software/guile&quot;&gt;Guile&lt;/a&gt;, as well as a general purpose
WebAssembly toolchain.  In other words, &lt;em&gt;Scheme in the browser!&lt;/em&gt;  It
has been a busy two months since 0.1.0, and we've got a lot of goodies
to share.&lt;/p&gt;&lt;h3&gt;Highlights&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Nearly all of &lt;a href=&quot;https://small.r7rs.org/&quot;&gt;R7RS-small&lt;/a&gt; is now
implemented!  Hoot 0.2.0 is now capable of running many more
standard Scheme programs than 0.1.0.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;A foreign function interface (FFI) has been added to make it easy to
declare imported host functions and call them from Scheme.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;User-defined record types, sorely missing from 0.1.0, have been
added.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Read on for a detailed list of changes.&lt;/p&gt;&lt;h3&gt;R7RS-small&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Added record types and &lt;code&gt;define-record-type&lt;/code&gt; syntax.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added &lt;code&gt;read&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added &lt;code&gt;case-lambda&lt;/code&gt; and &lt;code&gt;case-lambda*&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added system timer procedures &lt;code&gt;current-second&lt;/code&gt;, &lt;code&gt;current-jiffy&lt;/code&gt;, and
&lt;code&gt;jiffies-per-second&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added promise procedures &lt;code&gt;make-promise&lt;/code&gt;, &lt;code&gt;promise&lt;/code&gt;, ``delay&lt;code&gt;,&lt;/code&gt;force&lt;code&gt;, and&lt;/code&gt;delay-force`.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added &lt;code&gt;string-&amp;gt;symbol&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added partial &lt;code&gt;string-&amp;gt;number&lt;/code&gt; implementation.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added character procedures &lt;code&gt;char-upcase&lt;/code&gt;, &lt;code&gt;char-downcase&lt;/code&gt;,
&lt;code&gt;char-titlecase&lt;/code&gt;, &lt;code&gt;char-upper-case?&lt;/code&gt;, &lt;code&gt;char-lower-case?&lt;/code&gt;,
&lt;code&gt;char-alphabetic?&lt;/code&gt;, &lt;code&gt;char-whitespace?&lt;/code&gt;, &lt;code&gt;char-numeric?&lt;/code&gt;,
&lt;code&gt;digit-value&lt;/code&gt;, &lt;code&gt;char-ci&amp;lt;?&lt;/code&gt;, &lt;code&gt;char-ci&amp;lt;=?&lt;/code&gt;, &lt;code&gt;char-ci=?&lt;/code&gt;, &lt;code&gt;char-ci&amp;gt;=?&lt;/code&gt;,
and &lt;code&gt;char-ci&amp;gt;?&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added mutable string procedures &lt;code&gt;string-set!&lt;/code&gt;, &lt;code&gt;string-copy!&lt;/code&gt;, and
&lt;code&gt;string-fill!&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added stubs for &lt;code&gt;command-line&lt;/code&gt;, &lt;code&gt;get-environment-variable&lt;/code&gt;, and
&lt;code&gt;get-environment-variables&lt;/code&gt; procedures that do not make much sense
in a web context.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added integer flonum support for &lt;code&gt;quotient&lt;/code&gt;, &lt;code&gt;remainder&lt;/code&gt;, and
&lt;code&gt;modulo&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed &lt;code&gt;string-&amp;gt;?&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed &lt;code&gt;assq&lt;/code&gt;, &lt;code&gt;assv&lt;/code&gt;, and &lt;code&gt;assoc&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed &lt;code&gt;memq&lt;/code&gt;, &lt;code&gt;memv&lt;/code&gt;, and &lt;code&gt;member&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed &lt;code&gt;gcd&lt;/code&gt;, &lt;code&gt;expt&lt;/code&gt;, and &lt;code&gt;exact&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed &lt;code&gt;finite?&lt;/code&gt;, &lt;code&gt;infinite?&lt;/code&gt;, and &lt;code&gt;nan?&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed &lt;code&gt;peek-char&lt;/code&gt; and &lt;code&gt;read-char&lt;/code&gt; for multibyte chars.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Non-standard interfaces&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Added &lt;a href=&quot;https://spritely.institute/files/docs/guile-hoot/0.2.0/Foreign-function-interface.html&quot;&gt;foreign function
interface&lt;/a&gt;
via &lt;code&gt;define-foreign&lt;/code&gt; syntax.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added support for unboxed parameters and results to &lt;code&gt;%inline-wasm&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added &lt;code&gt;%wasm-import&lt;/code&gt; form for use by the FFI.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added Guile's structured exception system.  All errors raised in the
Scheme prelude are now structured.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Toolchain&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Added global lowering pass to more easily emit Scheme constants that
are not Wasm constants.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Added support for symbols/keywords in secondary Wasm modules that
import the ABI from a primary module.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Improved compiler tree shaker to reduce overall Wasm binary size.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Reduced the size of bytevector literals in Wasm binaries.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed lowering of &lt;code&gt;stringview_iter.slice&lt;/code&gt; instruction.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed flonum constants sometimes being treated as fixnums.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed printing of mutable strings in both JS and Scheme reflection
libraries.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed &lt;code&gt;scm_from_char&lt;/code&gt; in &lt;code&gt;reflect.wasm&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed &lt;code&gt;br_table&lt;/code&gt; implementation in Wasm interpreter.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed mis-compilation of &lt;code&gt;rational?&lt;/code&gt; and &lt;code&gt;integer?&lt;/code&gt; primcalls.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fixed switch optimization for repeated symbol comparisons.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Browser compatibility&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Google Chrome 119 was released about a month ago and comes with
&lt;a href=&quot;https://developer.chrome.com/blog/wasmgc/&quot;&gt;Wasm GC and tail calls enabled by
default&lt;/a&gt;.  Hoot binaries
now work in Chrome without fiddling with any experimental settings!&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Firefox 120 was released with Wasm GC enabled, but tail calls will
not be enabled until December 19th when Firefox 121 is released.
For the time being, Firefox users can either install a &lt;a href=&quot;https://www.mozilla.org/en-US/firefox/channel/desktop/&quot;&gt;Nightly
build&lt;/a&gt; or
enable &lt;code&gt;javascript.options.wasm_tail_calls&lt;/code&gt; in &lt;code&gt;about:config&lt;/code&gt; on
Firefox 120.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Safari/WebKit is still unsupported.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Get Hoot 0.2.0!&lt;/h3&gt;&lt;p&gt;Hoot is already available in GNU Guix:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;$ guix pull
$ guix install guile-next guile-hoot&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(Hoot currently requires a bleeding-edge version of Guile, hence
&lt;code&gt;guile-next&lt;/code&gt; above.)&lt;/p&gt;&lt;p&gt;Otherwise, Hoot can be built from source via our release tarball.  See
the &lt;a href=&quot;/hoot&quot;&gt;Hoot landing page&lt;/a&gt; for a download link and GPG signature.&lt;/p&gt;&lt;p&gt;Documentation for Hoot 0.2.0, including build instructions, can be
found &lt;a href=&quot;/files/docs/guile-hoot/0.2.0/index.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;Check out our greatest hoots!&lt;/h3&gt;&lt;p&gt;&lt;img src=&quot;/static/images/blog/greatest-hoots.jpg&quot; alt=&quot;A &amp;quot;Greatest Hoots&amp;quot; album CD cover&quot; /&gt;&lt;/p&gt;&lt;p&gt;For a detailed walkthrough of using the new foreign function
interface, check out &lt;a href=&quot;/news/building-interactive-web-pages-with-guile-hoot.html&quot;&gt;our cool new blog post about building
interactive web pages with
Hoot&lt;/a&gt;!&lt;/p&gt;&lt;p&gt;Robin Templeton and David Thompson recently presented about Hoot at
the &lt;a href=&quot;https://seagl.org&quot;&gt;SeaGL&lt;/a&gt; conference in Seattle, WA.  The talk
was livestreamed and you can catch the replay on
&lt;a href=&quot;https://www.youtube.com/live/CxQOhCVFVdk?feature=shared&amp;amp;t=23030&quot;&gt;YouTube&lt;/a&gt;!&lt;/p&gt;&lt;p&gt;For bug reports, pull requests, or just to follow along with
development, check out the &lt;a href=&quot;https://gitlab.com/spritely/guile-hoot&quot;&gt;Hoot project on
GitLab&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;If you build something cool with Hoot, let us know on our &lt;a href=&quot;https://community.spritely.institute&quot;&gt;community
forum&lt;/a&gt;!  (Use OCAPN2023 for the
Invite Code when you join.)&lt;/p&gt;&lt;p&gt;The code in this release was brought to you by Andy Wingo, Robin
Templeton, David Thompson, and Christine Lemmer-Webber.  The lovely
Hoot art is by tessa.  Special thanks to the &lt;a href=&quot;https://metamask.io/news/developers/meta-mask-grants-dao-funds-spritely-foundation/&quot;&gt;MetaMask
folks&lt;/a&gt;
for &lt;a href=&quot;https://spritely.institute/news/guile-on-web-assembly-project-underway.html&quot;&gt;funding this
work&lt;/a&gt;!&lt;/p&gt;&lt;p&gt;Happy hooting! 🦉&lt;/p&gt;</summary></entry><entry><title>Introducing OCapN, interoperable capabilities over the network</title><id>https://spritely.institute/news/introducing-ocapn-interoperable-capabilities-over-the-network.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2023-11-16T13:45:00Z</updated><link href="https://spritely.institute/news/introducing-ocapn-interoperable-capabilities-over-the-network.html" rel="alternate" /><summary type="html">&lt;p&gt;&lt;img src=&quot;https://spritely.institute/files/talks/static/ocapn-handoff-wip1.gif&quot; alt=&quot;Step-by-step walkthrough to perform a OCapN Third Party Handoff&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://ocapn.org/&quot;&gt;OCapN (&lt;strong&gt;O&lt;/strong&gt;bject &lt;strong&gt;Cap&lt;/strong&gt;ability &lt;strong&gt;N&lt;/strong&gt;etwork)&lt;/a&gt; is a new
protocol to add support for secure, seamless, and distributed (often
peer-to-peer) communication for networked applications.&lt;/p&gt;&lt;p&gt;OCapN was originally developed as part of
&lt;a href=&quot;https://spritely.institute/goblins/&quot;&gt;Goblins&lt;/a&gt;, our distributed object
programming environment. But OCapN is no longer just for Goblins! Thanks to the
support of a grant from &lt;a href=&quot;https://nlnet.nl/&quot;&gt;NLnet&lt;/a&gt;, we have documented OCapN's
functionality as a set of specifications so that OCapN's technology can be
incorporated into any programming language environment. We have been working
with colleagues across several partner projects and organizations to shape
these documents following a consensus-based review process.&lt;/p&gt;&lt;p&gt;Without OCapN, building networked applications such as social networks, chat
rooms and online virtual worlds otherwise would have to manually solve many
problems which OCapN handles automatically as part of its design. OCapN
simplifies building otherwise complicated peer-to-peer systems and has many
useful features:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Intuitive distributed programming:&lt;/strong&gt; allows for networked programming
such that it doesn't matter where objects live: they can be fully local or
distributed over the network.  Performing asynchronous operations against
networked objects is the same as asynchronous programming against local
ones.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Object capability security:&lt;/strong&gt; makes complicated secure systems simpler to
reason about following the principle of &amp;quot;if you don't have it, you can't
use it.&amp;quot;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Promise Pipelining:&lt;/strong&gt; enables sending messages to a promise's potentially
settled output. This streamlines reasoning about promises, and cuts down on
round trips across the network.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Distributed Garbage Collection:&lt;/strong&gt; powers garbage collection across
multiple devices. While programming languages may sufficiently handle garbage
collection within a local machine, when references to objects are scattered
across a network, the network itself must also explicitly support garbage
collection of obsolete objects.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Certificate-Based Third-Party Handoffs:&lt;/strong&gt; provide a mechanism by which two
machines can securely reference objects on a third. Connections between
machines that potentially span across networks necessitate the free sharing
of object references, even those which exist on machines outside that
connection. Third-party handoffs enable such references to be intuitively
and securely shared within Goblins, without needing to consider the network.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;NLnet Grant&lt;/h2&gt;&lt;p&gt;Jessica Tallon has been working with Spritely on an
&lt;a href=&quot;https://nlnet.nl/project/SpritelyOCapN&quot;&gt;NLnet grant-funded initiative&lt;/a&gt; for the
past year, with a focus on improving OCapN support in both Goblins
implementations and initiating the standardization push for OCapN. Below,
Jessica delivers her personal account of her efforts to develop, grow, and
refine open standards for the protocol to ensure solid foundations and
interoperability across the OCapN ecosystem over the course of the grant.&lt;/p&gt;&lt;h3&gt;Milestone 1: Racket Goblins &amp;lt;-&amp;gt; Guile Goblins Interoperability&lt;/h3&gt;&lt;p&gt;When I started on this grant work in late 2022, Racket Goblins had a mature OCapN
implementation, but Guile Goblins had none. This meant the two implementations
couldn't interoperate (send messages to each other) at all.&lt;/p&gt;&lt;p&gt;At the start of 2023, I completed this milestone, adding comprehensive OCapN
support to Guile Goblins and a protocol to enable streamlined communication with
its Racket counterpart.&lt;/p&gt;&lt;p&gt;To assess the boundaries of OCapN coverage, the team and I ported a simple and
minimalist chat application used internally for testing from Racket Goblins to
Guile Goblins.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://spritely.institute/files/talks/static/goblin-chat-interop.gif&quot; alt=&quot;Step-by-step walkthrough to perform a OCapN Third Party Handoff&quot; /&gt;&lt;/p&gt;&lt;p&gt;The evaluation was successful, meaning that Goblins objects written in Guile
scheme can send messages with those written in Racket scheme and vice versa
over OCapN.&lt;/p&gt;&lt;h3&gt;Milestone 2: Start the OCapN Pre-standardization Group&lt;/h3&gt;&lt;p&gt;Although we've made significant additions to the OCapN standard — such as
certificate-based third-party handoffs — through our work on its Goblins
implementation, it's important to note that the protocol wasn't invented at
Spritely; we've drawn from and built upon the contributions of many others
(&lt;a href=&quot;https://erights.org&quot;&gt;the E programming language&lt;/a&gt;,
&lt;a href=&quot;https://agoric.com&quot;&gt;Agoric&lt;/a&gt;, and &lt;a href=&quot;https://capnproto.org&quot;&gt;Cap'n Proto&lt;/a&gt; to name
a few) and is actively being shaped by input from many developers of those
projects.&lt;/p&gt;&lt;p&gt;The OCapN group is comprised of many organizations such as Spritely and Agoric
as well as many independent experts and interested parties. The group's goal is
to come to consensus on draft documents which define the protocols within
OCapN.&lt;/p&gt;&lt;p&gt;If you're interested in joining the group and helping the standardization
effort, or you just want to take a look at our work, please find more info at
&lt;a href=&quot;https://ocapn.org&quot;&gt;ocapn.org&lt;/a&gt;&lt;/p&gt;&lt;h3&gt;Milestone 3: Three draft specifications&lt;/h3&gt;&lt;p&gt;Part of the standardization effort is to have documents the OCapN group can
develop as the group meets consensus. The initial draft specifications are based
on the Goblins' implementations of OCapN, The OCapN protocol is split into three
documents:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/ocapn/ocapn/blob/main/draft-specifications/CapTP%20Specification.md&quot;&gt;CapTP&lt;/a&gt;:
covers the majority of the protocol including message sending, promises, promise
pipelining, third-party handoffs.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/ocapn/ocapn/blob/main/draft-specifications/Netlayers.md&quot;&gt;Netlayers&lt;/a&gt;:
describes how new netlayer types should be defined and documents the ones
currently in use, such as the Tor Onion Services Netlayer. Netlayers are an
abstraction for different transport protocols which CapTP uses to
communicate on, this is because OCapN is designed to be agnostic to the
specific protocol CapTP runs on. While Goblins so far has largely used Tor,
as it provides strong anonymity, other protocols, such as
&lt;a href=&quot;https://libp2p.io/&quot;&gt;libp2p&lt;/a&gt;, &lt;a href=&quot;https://ibcprotocol.org/&quot;&gt;IBC&lt;/a&gt; or carrier
pigeons with little flash drives could be used.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/ocapn/ocapn/blob/main/draft-specifications/Locators.md&quot;&gt;Locators&lt;/a&gt;:
defines how representations of nodes (machines) on the network and specific
objects are encoded. The node identity specifications include both in-band
and out-of-band, string-like representations, both of which are needed in
order to bootstrap new connections and to share references within
established connections.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;As the OCapN group progresses these standardization efforts, we'll continue to
update these documents; and on Spritely's end, our Goblins OCapN implementation.&lt;/p&gt;&lt;h3&gt;Milestone 4: Test suite&lt;/h3&gt;&lt;p&gt;One of the main goals of the OCapN standardization effort is to develop an
&lt;a href=&quot;http://en.wikipedia.org/wiki/Open_standard&quot;&gt;open standard&lt;/a&gt; with many
implementations. To ensure all of them interoperate as expected, the
&lt;a href=&quot;https://github.com/ocapn/ocapn-test-suite&quot;&gt;OCapN test suite&lt;/a&gt; verifies that a given
implementation has correctly implemented the protocol according to spec.&lt;/p&gt;&lt;p&gt;Excitingly, this test suite has already been put to use:
&lt;a href=&quot;https://dpwiz.gitlab.io/actors-guild&quot;&gt;Alexander Bondarenko's Haskell implementation of OCapN&lt;/a&gt;
has been built against and passes the OCapN test suite!&lt;/p&gt;&lt;h3&gt;Milestone 5: Both goblins implementations pass test suite&lt;/h3&gt;&lt;p&gt;Perhaps it goes without saying, but Spritely's Racket and Guile Goblins' OCapN
implementations should also both pass the test suite. This may seem simple
because the specification documents, and therefore the test suite itself, were
written based on our Goblins' OCapN implementations. However the standard drafts
continued to change, and the test suite along with it, necessitating appropriate
updates to Goblins in the process. In addition, we found and fixed a few bugs
thanks to the new suite.&lt;/p&gt;&lt;p&gt;As of today, both implementations pass the test suite! 🎉&lt;/p&gt;&lt;h1&gt;Where next?&lt;/h1&gt;&lt;p&gt;While we've gotten a lot done during the last 12 months, we still have a ways to
go on the road to having an OCapN standard. The higher level work of solidifying
a shared set of definitions for OCapN will be done as a community as the OCapN
group refines the documents until we reach a foundational consensus.&lt;/p&gt;&lt;p&gt;Once we've agreed upon the first version of the specification documents, with
the test suite and Goblins implementations following in lockstep, we plan
to bring these documents to a standards body such as
&lt;a href=&quot;https://www.ietf.org&quot;&gt;IETF&lt;/a&gt; or &lt;a href=&quot;https://www.w3.org&quot;&gt;W3C&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;We also hope these documents and tools will empower more people to develop OCapN
libraries, tools, and implementations, and grow a rich ecosystem so that more
secure, distributed applications and games can be easily developed which put the
users freedom and privacy first.&lt;/p&gt;&lt;h1&gt;Acknowledgments&lt;/h1&gt;&lt;p&gt;This work was funded through the &lt;a href=&quot;https://nlnet.nl/assure&quot;&gt;NGI Assure Fund&lt;/a&gt;, a
fund established by &lt;a href=&quot;https://nlnet.nl/&quot;&gt;NLnet&lt;/a&gt; with financial support from the
European Commission's &lt;a href=&quot;https://www.ngi.eu/&quot;&gt;Next Generation Internet&lt;/a&gt; program.
We want to say a big thanks for supporting this work and enabling us to do this
important work.&lt;/p&gt;</summary></entry><entry><title>Guile Hoot v0.1.0 released!</title><id>https://spritely.institute/news/guile-hoot-v010-released.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2023-10-16T16:00:00Z</updated><link href="https://spritely.institute/news/guile-hoot-v010-released.html" rel="alternate" /><summary type="html">&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=8LuQtoy9NLs&quot;&gt;&lt;img src=&quot;/static/images/blog/hoot-future-of-scheme-hacking.png&quot; alt=&quot;Hoot version 0.1.0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;We are excited to announce the first official release of &lt;a href=&quot;/hoot&quot;&gt;Guile
Hoot&lt;/a&gt;, v0.1.0!  Hoot is a Scheme to WebAssembly compiler
backend for &lt;a href=&quot;https://gnu.org/software/guile&quot;&gt;GNU Guile&lt;/a&gt;, as well as a
general purpose WebAssembly toolchain.  In other words, &lt;em&gt;Scheme in the
browser!&lt;/em&gt;  At long last, thanks to WASM GC, it’s finally possible for
other dynamic languages to be first-class citizens on the web.  Make
room, JavaScript, you’re no longer the only game in town!&lt;/p&gt;&lt;p&gt;This initial v0.1.0 release features support for a subset of
R7RS-small Scheme, a JavaScript library providing an interface to
Scheme, and a full WASM toolchain implemented as a set of Scheme
libraries.&lt;/p&gt;&lt;h2&gt;Features&lt;/h2&gt;&lt;p&gt;Hoot has a number of notable features that distinguish it from many
other WASM tools out there:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Self-contained toolchain&lt;/strong&gt;: No emscripten, binaryen, wabt, etc.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;GC reference type usage&lt;/strong&gt;: The host provides the garbage
collector.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Small programs produce small binaries&lt;/strong&gt;: Kilobytes, not megabytes.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Full development environment&lt;/strong&gt;: Compile and run WASM binaries
without leaving Guile.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Hoot’s WASM toolchain includes:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;WAT parser&lt;/strong&gt;: Converts WAT to WASM.  Both folded and unfolded
forms are supported.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Assembler&lt;/strong&gt;: Generates WASM binaries.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Binary parser&lt;/strong&gt;: Converts WASM binaries to an internal WASM data
structure.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Disassembler&lt;/strong&gt;: Converts WASM to WAT.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Linker&lt;/strong&gt;: Composes WASM modules with a standard libary, adding in
only what is actually used.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Interpreter&lt;/strong&gt;: Validates and evaluates WASM without having to jump
into the web browser.&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Limitations&lt;/h2&gt;&lt;p&gt;Hoot is still in an early phase of active development and there are
many missing features, including:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Module system&lt;/li&gt;&lt;li&gt;Record types&lt;/li&gt;&lt;li&gt;Environments and evaluation&lt;/li&gt;&lt;li&gt;Foreign function interface&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;For our next release, we intend to provide full R7RS-small support as
we work towards the larger goal of supporting all of Guile.&lt;/p&gt;&lt;h2&gt;Get Hoot v0.1.0!&lt;/h2&gt;&lt;p&gt;Hoot is already available in GNU Guix:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;$ guix pull
$ guix install guile-next guile-hoot&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(Hoot currently requires a bleeding-edge version of Guile, hence
&lt;code&gt;guile-next&lt;/code&gt; above.)&lt;/p&gt;&lt;p&gt;Otherwise, Hoot can be built from source via our release tarball.  See
the &lt;a href=&quot;/hoot&quot;&gt;Hoot landing page&lt;/a&gt; for a download link and GPG signature.&lt;/p&gt;&lt;h2&gt;Learn more!&lt;/h2&gt;&lt;p&gt;Documentation for Hoot v0.1.0, including build instructions, can be
found &lt;a href=&quot;/files/docs/guile-hoot/0.1.0/index.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;For code samples and a live demo of Hoot, check out &lt;a href=&quot;/news/scheme-wireworld-in-browser.html&quot;&gt;last week’s blog
post&lt;/a&gt; about implementing
Wireworld in Scheme and running it inside a web browser.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;BONUS:&lt;/strong&gt; Three members of the Spritely team recently appeared on the
&lt;a href=&quot;https://www.youtube.com/@SystemCrafters&quot;&gt;System Crafters&lt;/a&gt; live stream
to talk with David Wilson in detail about Hoot.  If this interests
you, check out the &lt;a href=&quot;https://www.youtube.com/watch?v=8LuQtoy9NLs&quot;&gt;recording of the
stream&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;For bug reports, pull requests, or just to follow along with
development, check out the &lt;a href=&quot;https://gitlab.com/spritely/guile-hoot&quot;&gt;Hoot project on
GitLab&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;If you build something cool with Hoot, let us know on our &lt;a href=&quot;https://community.spritely.institute&quot;&gt;community
forum&lt;/a&gt;!  (Use OCAPN2023 for the
Invite Code when you join.)&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;/static/images/blog/hoot.png&quot; alt=&quot;Hoot logo&quot; /&gt;&lt;/p&gt;&lt;p&gt;This release was brought to you by Andy Wingo, Christine
Lemmer-Webber, Robin Templeton, and David Thompson.
Special thanks to the
&lt;a href=&quot;https://metamask.io/news/developers/meta-mask-grants-dao-funds-spritely-foundation/&quot;&gt;MetaMask folks&lt;/a&gt;
for &lt;a href=&quot;https://spritely.institute/news/guile-on-web-assembly-project-underway.html&quot;&gt;funding this work&lt;/a&gt;!&lt;/p&gt;&lt;p&gt;Happy hooting! 🦉&lt;/p&gt;</summary></entry><entry><title>Scheme in the browser: A Hoot of a tale</title><id>https://spritely.institute/news/scheme-wireworld-in-browser.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2023-10-10T11:00:00Z</updated><link href="https://spritely.institute/news/scheme-wireworld-in-browser.html" rel="alternate" /><summary type="html">&lt;p&gt;&lt;img src=&quot;/static/images/blog/scheme-wireworld.gif&quot; alt=&quot;XOR gate in Scheme Wireworld&quot; /&gt;&lt;/p&gt;&lt;p&gt;Hey there, it’s been awhile!  We’re back to share some more exciting
news about &lt;a href=&quot;https://gitlab.com/spritely/guile-hoot&quot;&gt;Guile Hoot&lt;/a&gt;, a
WebAssembly toolchain and Scheme→WASM compiler.  In &lt;a href=&quot;/news/hoot-wireworld-live-in-browser.html&quot;&gt;our last
post&lt;/a&gt; we demonstrated that
the Guile Hoot toolchain can be used to assemble programs written in
WebAssembly Text (WAT) format, which allowed us to develop for the
WASM-4 fantasy console.  That was pretty cool, of course, but our goal
is to compile Scheme programs (of the
&lt;a href=&quot;https://small.r7rs.org/attachment/r7rs.pdf&quot;&gt;R7RS-small&lt;/a&gt; dialect, for
now) to WASM.  We are getting ready for our first release, and we’re
happy to report that we’ve made excellent progress!  We can now
demonstrate the Hoot compiler working end-to-end.&lt;/p&gt;&lt;p&gt;Before we get to the demo, let’s go over what makes Hoot special.
Hoot differs from most WASM compiler projects in some notable ways:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Self-contained toolchain&lt;/strong&gt;: No emscripten, binaryen, wabt, etc.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;GC reference type usage&lt;/strong&gt;: The host provides the garbage
collector.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Small programs produce small binaries&lt;/strong&gt;: Kilobytes, not megabytes.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Full development environment&lt;/strong&gt;: Compile and run WASM binaries
without leaving Guile.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Self-contained toolchain&lt;/h3&gt;&lt;p&gt;The Hoot toolchain has been written from the ground up to be
self-contained with no external dependencies required (aside from
Guile, of course.)  This gives us a lot of flexibility and control
over the entire compilation process.  The toolchain includes:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;WAT parser&lt;/strong&gt;: Converts WAT to WASM.  Both folded and unfolded
forms are supported.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Assembler&lt;/strong&gt;: Generates WASM binaries.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Binary parser&lt;/strong&gt;: Converts WASM binaries to an internal WASM data
structure.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Disassembler&lt;/strong&gt;: Converts WASM to WAT.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Linker&lt;/strong&gt;: Composes WASM modules with a standard libary (for
example), adding in only what is actually used.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Interpreter&lt;/strong&gt;: Validates and evaluates WASM without having to jump
into the web browser.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;All of these tools are available as a Scheme library that could be
used to automate other WASM targeted build workflows.&lt;/p&gt;&lt;h3&gt;GC reference types&lt;/h3&gt;&lt;p&gt;In WASM 1.0, if a language implementation needed a garbage collector
then it had to bring its own built on top of linear memory.  There are
many drawbacks to this approach:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Large binaries&lt;/strong&gt;: A whole GC needs to be shipped along with the
program.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Stop the world&lt;/strong&gt;: Parallelism and concurrency are limited in WASM
right now, so GC performance suffers.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Collectable confusion&lt;/strong&gt;: How do you know when references to your
heap objects are collectable if they’ve been passed to JavaScript or
other WASM modules?  It’s a heap of trouble.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In other words, you had to ship a &lt;em&gt;bad&lt;/em&gt; garbage collector when there
is a battle tested, high performance, production garbage collector
sitting right there in the browser.  Check out Andy Wingo’s excellent
BOB 2023 talk (in
&lt;a href=&quot;https://wingolog.org/archives/2023/03/20/a-world-to-win-webassembly-for-the-rest-of-us&quot;&gt;text&lt;/a&gt;
or &lt;a href=&quot;https://www.youtube.com/watch?v=lUCegCa7A08&quot;&gt;video&lt;/a&gt; form) for more
detailed information about the problems with GC in WASM 1.0.  (Andy is
the &lt;a href=&quot;/news/andy-wingo-leads-g2W.html&quot;&gt;lead engineer&lt;/a&gt; for the Hoot
project.)&lt;/p&gt;&lt;p&gt;Thankfully, WASM GC has added the ability to allocate heap values that
are managed by the host.  Hoot is currently one of the few dynamic
language implementations that makes use of GC reference types.  We
hope that by sharing our work and our experience we can help other
dynamic languages find their way into web browsers, too.&lt;/p&gt;&lt;p&gt;Hoot is also taking advantage of another recent addition to WASM: tail
calls.  Loops are expressed as recursive function calls in Scheme, so
having a tail call feature available simplifies our implementation
effort.  We don’t have to wait long to use these features, either.
Production versions of WASM GC and tail calls are already shipping in
bleeding edge versions of browsers and will become available to all
users of the web soon.&lt;/p&gt;&lt;h3&gt;Small programs produce small binaries&lt;/h3&gt;&lt;p&gt;We made the choice when starting this project &lt;em&gt;not to&lt;/em&gt; compile Guile’s
C runtime to WASM using emscripten.  While it would have been
feasible, the resulting binaries would have been quite large, among
other things.  We did not want the end result of this project to be a
multiple megabyte binary for “Hello, world.”  Instead, we’ve taken the
approach of writing a dedicated compiler backend for Guile with some
handwritten WASM providing primitive functionality and calling out to
imported host functions when necessary.  Programs compiled with Hoot
include only the parts of the standard library that they rely upon.
As mentioned earlier, WASM GC obviates the need to link in an entire
garbage collector.  For these reasons, Hoot binaries tend to be much
smaller than the output of most other compilers.  Small programs
produce binaries measured in kilobytes, not megabytes.&lt;/p&gt;&lt;h3&gt;Full development environment&lt;/h3&gt;&lt;p&gt;Hoot includes an embedded WASM interpreter that makes it possible to
run WASM directly within the Guile process being used for development.
Since the toolchain is also readily available as a set of Scheme
modules, you can compile and test out programs (either Scheme programs
or hand-crafted WAT) from the comfort of the Guile REPL.  There is
also a set of REPL tools to make inspecting and debugging WASM easier.
Keep reading for a practical demonstration of the development
workflow.&lt;/p&gt;&lt;p&gt;OK, onto Wireworld!&lt;/p&gt;&lt;h3&gt;Wireworld part 1: Scheme&lt;/h3&gt;&lt;p&gt;To show off the compiler, we decided to revisit our favorite cellular
automaton: Wireworld. Check out &lt;a href=&quot;/news/hoot-wireworld-live-in-browser.html&quot;&gt;our last
post&lt;/a&gt; to learn more about
what Wireworld is and how we used Hoot to build a pure WASM version of
it.  This time, instead of writing several hundred lines of WAT, we
wrote about 70 lines of Scheme:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-size&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;cu&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;syntax-comment&quot;&gt;; copper
&lt;/span&gt;      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ehead&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;; electron head
&lt;/span&gt;      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;etail&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;; electron tail
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-grid&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-bytevector&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-size&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-size&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;bytevector-u8-ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-size&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-ref/wrap&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;bytevector-u8-ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;modulo&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-size&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-size&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                               &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;modulo&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-size&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-set!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;bytevector-u8-set!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-size&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;neighbors&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-ref/wrap&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;ehead&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-size&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-size&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let*&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;t*&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;cond&lt;/span&gt;
                    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;cu&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;neighbors&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;ehead&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;cu&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;ehead&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;etail&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;etail&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;cu&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-set!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;t*&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;copy&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;bytevector-length&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;bytevector-u8-set!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;bytevector-u8-ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-a&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-grid&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-b&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-grid&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;update-and-swap&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-a&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-b&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;copy&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-b&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-a&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-a&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-set!&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-a&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;cycle&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;modulo&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-size&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;cycle&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;update-and-swap&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After compiling and gzipping the resulting binary, we’re looking at a
28KiB download.  Not too shabby!  (And we’re anticipating adding a
size optimization pass resembling binaryen’s &lt;code&gt;wasm-opt -Oz&lt;/code&gt; in the
future to reduce binary size even further.)&lt;/p&gt;&lt;p&gt;Before we get to the browser, let’s take a quick detour and talk about
development workflow.  It took several iterations to arrive at the
code above.  In true Scheme fashion, the program was developed
incrementally in an interactive REPL session.  By using Hoot’s WASM
interpreter, we repeatedly compiled and tested the program without
having to load it into a web browser or shell out to V8’s &lt;code&gt;d8&lt;/code&gt; tool.
We think it’s pretty neat!  Below is an annotated excerpt of a REPL
session that shows the values of 3 cells before and after an update.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-comment&quot;&gt;;; Import necessary Guile modules.
&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,use&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;hoot&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;reflect&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;wasm&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-comment&quot;&gt;;; Load reflection WASM module.
&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;reflect-wasm&lt;/span&gt;
                       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;call-with-input-file&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;js-runtime/reflect.wasm&amp;quot;&lt;/span&gt;
                                             &lt;span class=&quot;syntax-symbol&quot;&gt;parse-wasm&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-comment&quot;&gt;;; Compile and evaluate Wireworld source.
&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-values&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-size&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-set&lt;/span&gt;
                                     &lt;span class=&quot;syntax-symbol&quot;&gt;grid-cycle&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grid-update&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;compile-value&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;reflect-wasm&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;wireworld-src&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;; electron tail at (0, 0)
&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$10&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;; electron head at (1, 0)
&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$11&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;; copper at (2, 0)
&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$12&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-update&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;syntax-comment&quot;&gt;; step the simulation
&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;; copper at (0, 0)
&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$13&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;; electron tail at (1, 0)
&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$14&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;grid-ref&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;; electron head at (2, 0)
&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$15&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The electron has moved to the right one cell, exactly as it should.
With some amount of confidence that the program is working, we proceed
to the web browser.&lt;/p&gt;&lt;h3&gt;Wireworld part 2: JavaScript&lt;/h3&gt;&lt;p&gt;To get this version of Wireworld running in the browser, an additional
~100 lines of JavaScript were used to glue the Scheme program to
various browser APIs.  Since we aren’t targeting WASM-4 this time, we
needed a new rendering method.  We chose HTML5 canvas to keep things
simple.  The code below updates the simulation at some regular
interval, renders to the canvas, and handles keyboard/mouse input.
Hoot’s &lt;code&gt;reflect.js&lt;/code&gt; library allows us to call Scheme procedures from
JS.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-special&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;syntax-special&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;canvas&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;canvas&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-special&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;canvas&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;getContext&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;2d&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-special&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;_gridSize&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;gridRef&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;gridSet&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;gridCycle&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;gridUpdate&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt;
        &lt;span class=&quot;syntax-special&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Scheme&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;load_main&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;scheme-wireworld.wasm&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-special&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;gridSize&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Number&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;_gridSize&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;tileSize&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-special&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;canvasSize&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;gridSize&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;tileSize&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-special&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;cu&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;ehead&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;etail&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;paused&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;mouseX&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;mouseY&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;syntax-special&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;requestAnimationFrame&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;syntax-special&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;gridSize&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;syntax-special&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;gridSize&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;syntax-special&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Number&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;gridRef&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;BigInt&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;BigInt&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;syntax-special&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;syntax-special&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;syntax-symbol&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;fillStyle&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;#fff6d3&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;syntax-special&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;syntax-special&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;cu&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;syntax-symbol&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;fillStyle&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;#f9a875&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;syntax-special&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;syntax-special&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;ehead&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;syntax-symbol&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;fillStyle&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;#7c3f58&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;syntax-special&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;syntax-special&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;etail&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;syntax-symbol&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;fillStyle&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;#eb6b6f&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;syntax-special&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;syntax-symbol&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;fillRect&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;tileSize&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;tileSize&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;tileSize&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;tileSize&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;mouseX&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;mouseY&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;syntax-symbol&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;fillStyle&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;#00000020&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;syntax-symbol&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;fillRect&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;tileSize&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;tileSize&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;tileSize&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;tileSize&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;syntax-special&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;paused&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;syntax-symbol&quot;&gt;gridUpdate&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;syntax-symbol&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;syntax-special&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;pixelToTile&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-special&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;floor&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;tileSize&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;gridSize&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;syntax-special&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;cycleTile&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;gridCycle&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;BigInt&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;BigInt&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;syntax-special&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;setTile&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;gridSet&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;BigInt&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;BigInt&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;BigInt&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;syntax-special&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;clearTile&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;setTile&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;syntax-special&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;togglePause&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;paused&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;paused&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;syntax-symbol&quot;&gt;canvas&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;canvasSize&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;canvas&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;canvasSize&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;canvas&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;mousemove&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;mouseX&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;pixelToTile&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;offsetX&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;mouseY&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;pixelToTile&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;offsetY&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;buttons&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;// left
&lt;/span&gt;      &lt;span class=&quot;syntax-symbol&quot;&gt;setTile&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;mouseX&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;mouseY&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;cu&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;buttons&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;//right
&lt;/span&gt;      &lt;span class=&quot;syntax-symbol&quot;&gt;clearTile&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;mouseX&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;mouseY&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;canvas&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;mousedown&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-special&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;pixelToTile&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;offsetX&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-special&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;pixelToTile&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;offsetY&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;// left
&lt;/span&gt;      &lt;span class=&quot;syntax-symbol&quot;&gt;cycleTile&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;// right
&lt;/span&gt;      &lt;span class=&quot;syntax-symbol&quot;&gt;clearTile&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;canvas&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;contextmenu&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;keydown&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Space&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;togglePause&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;syntax-close&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;load&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-operator&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note the use of &lt;code&gt;BigInt&lt;/code&gt; in several places.  This is a consequence of
how JavaScript’s &lt;code&gt;Number&lt;/code&gt; type works.  JS numbers are floating point
values, but Scheme has a much richer set of numeric types including
exact integers.  So, values of type &lt;code&gt;Number&lt;/code&gt; are treated as Scheme
floats, and the &lt;code&gt;BigInt&lt;/code&gt; type is used to box all integer values that
traverse the JS⇄Scheme bridge.&lt;/p&gt;&lt;p&gt;As Hoot matures and we implement a foreign function interface (FFI)
for calling into JS (or other hosts) from Scheme, we expect to see the
amount of glue code shrink considerably.&lt;/p&gt;&lt;h3&gt;Live demo&lt;/h3&gt;&lt;p&gt;OK, now it’s time to see Scheme Wireworld in action!  But first, a
disclaimer: As of publishing, major web browsers are just beginning to
ship WASM GC support.  Starting with Firefox 120 and Chrome 119, GC is
enabled by default.  Neither version is stable yet, so use either
&lt;a href=&quot;https://www.mozilla.org/en-US/firefox/channel/desktop/&quot;&gt;Firefox
Nightly&lt;/a&gt; or
&lt;a href=&quot;https://www.google.com/chrome/dev/&quot;&gt;Chrome Dev&lt;/a&gt; if you’d like to run
the demo.  If you’re reading this further into the future then
congratulations!  The browser you are using should have everything you
need.&lt;/p&gt;&lt;p&gt;How to use:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Press the left mouse button and move the cursor to draw copper.&lt;/li&gt;&lt;li&gt;Press the right mouse button and move the cursor to erase.&lt;/li&gt;&lt;li&gt;Left click on a cell to cycle its type (copper becomes electron
head, etc.)&lt;/li&gt;&lt;li&gt;Right click on a cell to clear it.&lt;/li&gt;&lt;li&gt;Press the space bar to pause or resume the simulation.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;iframe src=&quot;/static/embed/scheme-wireworld.html&quot; frameborder=&quot;0&quot; sandbox=&quot;allow-scripts&quot; alt=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;h3&gt;Now you try!&lt;/h3&gt;&lt;p&gt;If you’d like to compile and run this yourself, check out our &lt;a href=&quot;https://gitlab.com/spritely/scheme-wireworld&quot;&gt;GitLab
repo&lt;/a&gt; for this demo.
Like most of our projects, it uses &lt;a href=&quot;https://guix.gnu.org&quot;&gt;Guix&lt;/a&gt; to
setup the development environment.  The environment requires an
unreleased version of Guile compiled from source, so be prepared to
wait awhile for it to build.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git clone https://gitlab.com/spritely/scheme-wireworld.git
cd scheme-wireworld
guix shell
# The following commands are evaluated *within* the Guix shell
guile wireworld.scm
guile web-server.scm&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once the web server is up and running, visit
&lt;a href=&quot;http://localhost:8080&quot;&gt;http://localhost:8080&lt;/a&gt; in your web browser.
Feel free to modify the code and have some fun!&lt;/p&gt;&lt;p&gt;We look forward to sharing more when we release Hoot 0.1.0!&lt;/p&gt;</summary></entry><entry><title>[Hiring] Open Source Developer Relations Manager</title><id>https://spritely.institute/news/hiring-open-source-developer-relations-manager.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2023-09-29T15:00:00Z</updated><link href="https://spritely.institute/news/hiring-open-source-developer-relations-manager.html" rel="alternate" /><summary type="html">&lt;p&gt;We're hiring an &lt;a href=&quot;/jobs/developer-relations.html&quot;&gt;Open Source Developer Relations Manager&lt;/a&gt; - come help us support the Goblins ecosystem!&lt;/p&gt;&lt;p&gt;We will be posting full-time, part-time, and contract openings shortly for Engineers, UI/UX Design/Research, and (Funding) Development as funding permits. If you would like to be notified of job openings, email &lt;a href=&quot;mailto:jobs@spritely.institute&quot;&gt;jobs@spritely.institute&lt;/a&gt;, and we'll contact you the moment they are listed.&lt;/p&gt;&lt;p&gt;Spritely Networked Communities Institute is an Equal Opportunity Employer and is committed to ensuring that all employees and applicants receive equal consideration and treatment, regardless of race, color, creed, gender (including gender identity or gender expression), religion, marital or domestic partner status, age, body size, national origin or ancestry, physical, mental or medical disability, sex, sexual orientation, citizenship, military service status, veteran status, or any other characteristic protected by state or federal law or local ordinance.&lt;/p&gt;</summary></entry><entry><title>Lisp Game Jam - &quot;Wireworld&quot; - Hoot's low level WASM tooling in action</title><id>https://spritely.institute/news/hoot-wireworld-live-in-browser.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2023-06-12T14:00:00Z</updated><link href="https://spritely.institute/news/hoot-wireworld-live-in-browser.html" rel="alternate" /><summary type="html">&lt;p&gt;&lt;img src=&quot;/static/images/blog/wireworld-splash.gif&quot; alt=&quot;Wireworld + splash screen&quot; /&gt;&lt;/p&gt;&lt;p&gt;This blogpost focuses on our second &lt;a href=&quot;https://itch.io/jam/spring-lisp-game-jam-2023&quot;&gt;Spring Lisp Game Jam 2023&lt;/a&gt; entry,
&lt;a href=&quot;https://gitlab.com/spritely/wasm4-wireworld/&quot;&gt;wasm4-wireworld&lt;/a&gt;,
an implementation of
&lt;a href=&quot;https://en.wikipedia.org/wiki/Wireworld&quot;&gt;Wireworld&lt;/a&gt; on top of
&lt;a href=&quot;https://gitlab.com/spritely/guile-hoot&quot;&gt;Hoot&lt;/a&gt;'s lower-level assembly
tools which are a part of our &lt;a href=&quot;https://spritely.institute/news/guile-on-web-assembly-project-underway.html&quot;&gt;Guile → WASM&lt;/a&gt; project to bring &lt;a href=&quot;https://spritely.institute/goblins/&quot;&gt;Spritely Goblins&lt;/a&gt;-powered distributed applications to the common web browser.&lt;/p&gt;&lt;p&gt;For our entry, we targeted &lt;a href=&quot;https://wasm4.org/&quot;&gt;WASM-4&lt;/a&gt;, a &amp;quot;fantasy console&amp;quot; which uses low-level WebAssembly constructs.&lt;/p&gt;&lt;p&gt;In fact, if you see the animated &amp;quot;wireworld&amp;quot; splash screen at the top
of this article, that's running wasm-wireworld itself... you can even
&lt;a href=&quot;/static/embed/wireworld-splash.wasm4.html&quot;&gt;run it live in your browser&lt;/a&gt;!&lt;/p&gt;&lt;h2&gt;A brief intro to Wireworld&lt;/h2&gt;&lt;p&gt;The real point of this blogpost isn't Wireworld itself, but how
Hoot enabled making this Wireworld demo.
So we're going to walk into how Hoot turned out to be an incredible
toolkit to build this game jam entry, but first let's talk about
Wireworld to give some more context!&lt;/p&gt;&lt;p&gt;Wireworld is a powerful cellular automata, categorically similar to
&lt;a href=&quot;https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life&quot;&gt;Conway's Game of Life&lt;/a&gt;.
Unlike Life, Wireworld's paths are fixed: &amp;quot;electrons&amp;quot; flow upon copper
wires.
The rules of Wireworld are very simple:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Blank tiles remain blank&lt;/li&gt;&lt;li&gt;Electron heads always become electron tails&lt;/li&gt;&lt;li&gt;Electron tails always become copper&lt;/li&gt;&lt;li&gt;Copper stays copper, &lt;em&gt;unless&lt;/em&gt; there are one or two electron heads in any neighboring cells, in which case it becomes an electron head&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;That's it!  Despite that simplicity, this leads to powerful emergent
behavior.
Electron head and tail pairs appear to &amp;quot;flow&amp;quot; fluidly upon copper
wires and can branch easily.
But we can also make &amp;quot;generators&amp;quot; and diodes that only permit
electrons to flow in one direction and not another:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;/static/images/blog/wireworld-intro.gif&quot; alt=&quot;Wireworld + intro&quot; /&gt;&lt;/p&gt;&lt;p&gt;(&lt;a href=&quot;/static/embed/wireworld-intro.wasm4.html&quot;&gt;Try it live!&lt;/a&gt;)&lt;/p&gt;&lt;p&gt;These rules result in behavior which permits visually stunning examples,
many of which even &lt;em&gt;look&lt;/em&gt; like computational circuitry.&lt;/p&gt;&lt;p&gt;Below is a
&lt;a href=&quot;https://www.quinapalus.com/wires8.html&quot;&gt;&amp;quot;binary adder&amp;quot; circuit&lt;/a&gt;
running our implementation of Wireworld.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;/static/images/blog/wireworld-adder.gif&quot; alt=&quot;Wireworld + binary adder&quot; /&gt;&lt;/p&gt;&lt;p&gt;Encoded in little endian, 3 (011) + 6 (110) = 9 (1001)!
(And here's the &lt;a href=&quot;/static/embed/wireworld-adder.wasm4.html&quot;&gt;live version&lt;/a&gt;...
press the &amp;quot;x&amp;quot; button to start the simulation when you're ready!)&lt;/p&gt;&lt;p&gt;If you find this kind of thing delightful, see
&lt;a href=&quot;https://www.quinapalus.com/wi-index.html&quot;&gt;The Wireworld Computer&lt;/a&gt;
for a tutorial that uses Wireworld to build from the simplest elements
all the way up to a computer that can calculate prime numbers.&lt;/p&gt;&lt;h3&gt;Try Wireworld yourself!&lt;/h3&gt;&lt;p&gt;While building a cool version of Wireworld wasn't the &lt;em&gt;real&lt;/em&gt; goal
of our participation in the game jam, it was a lot of fun to build...
and we hope it's fun to use and play with, too!
And since you're reading this in a web browser and we're using
Webassembly anyway, why not try playing with Wireworld right here
in the browser?&lt;/p&gt;&lt;p&gt;&lt;iframe src=&quot;/static/embed/wireworld-blank.wasm4.html&quot; class=&quot;wasm4&quot; frameborder=&quot;0&quot; sandbox=&quot;allow-scripts&quot; alt=&quot;Wireworld with a blank canvas&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;p&gt;You can click to place wires and electron heads/tails and press X
to start/stop the emulation.  Enjoy!&lt;/p&gt;&lt;h2&gt;Insights from using Hoot to build WASM-4 Wireworld&lt;/h2&gt;&lt;p&gt;Our intent in this game jam was to show off how the &amp;quot;lower level layers&amp;quot;
of Hoot (i.e. the assembler, disassembler, etc) are themselves useful
and powerful and could be used to compile something interactive and
compelling.
WASM-4's minimalist homage to 80s video game consoles helped us deliver
on this focus by encouraging &amp;quot;coding towards the bare metal&amp;quot;.&lt;/p&gt;&lt;p&gt;As usual, game jams force you to pare down features.  For instance,
4-colored sprites were planned from the beginning, and we considered
some unusual additions to wireworld, such as tiles which could make
noise, which we thought maybe would allow Wireworld to be used as a
custom music synthesizer.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;/static/images/blog/wireworld-sprites-mockup.png&quot;&gt;&lt;img src=&quot;/static/images/blog/wireworld-sprites-mockup-scaled.png&quot; alt=&quot;Mockup sprites for wireworld&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;We were happy to be able to
&lt;a href=&quot;https://terpri.itch.io/wireworld&quot;&gt;deliver a completed and working Wireworld demo&lt;/a&gt;
by the end of the game jam, but most of these features were
removed, and notably we did not yet even have time to properly get
in the sprites we had designed... instead we shipped with placeholder
graphics using the &amp;quot;hello world&amp;quot; smiley from the WASM-4 tutorial!&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;/static/images/blog/wireworld-release.gif&quot; alt=&quot;Release artwork for wireworld&quot; /&gt;&lt;/p&gt;&lt;p&gt;We were surprised to wake up the next morning to find that Spritely
community member &lt;a href=&quot;https://vvv.gay/&quot;&gt;Vivi&lt;/a&gt; had taken our program and
not only made a cool world with it, but had modified the program
itself:&lt;/p&gt;&lt;p&gt;&lt;video src=&quot;/static/images/blog/wireworld-vivi-binary-adder.webm&quot; controls=&quot;true&quot; alt=&quot;Vivi's binary adder&quot;&gt;&lt;/video&gt;&lt;/p&gt;&lt;p&gt;Thus it was Vivi who first put a version of the binary adder (the
&lt;a href=&quot;https://www.quinapalus.com/wires8.html&quot;&gt;general design&lt;/a&gt; taken from
&lt;a href=&quot;https://www.quinapalus.com/wi-index.html&quot;&gt;the wireworld computer&lt;/a&gt;)
inside of wasm4-wireworld.
With no assistance from Spritely's internal team, Vivi changed the
grid size to render at 40x40 to have sufficient space to represent
the binary adder (the sprite data was not changed for this grid
redesign in Vivi's initial hack, leading to an entertaining effect
resembling renderings from a corrupted Gameboy cartridge).
The game jam submitted entry had a 20x20 grid size, but once we saw
the binary adder, we knew we had to have it, so we resized the
official implementation to 40x40 and redrew the sprites accordingly.&lt;/p&gt;&lt;p&gt;But the biggest takeaways from the jam were that Hoot, while still in
early development, is already a very promising and powerful
environment for doing low-level Webassembly programming.
This merits some further explanation!&lt;/p&gt;&lt;h2&gt;How we used Hoot to build wasm4-wireworld&lt;/h2&gt;&lt;p&gt;The last time we talked about &lt;a href=&quot;https://gitlab.com/spritely/guile-hoot&quot;&gt;Hoot&lt;/a&gt;
(our &lt;a href=&quot;https://spritely.institute/news/guile-on-web-assembly-project-underway.html&quot;&gt;Scheme-&amp;gt;WASM&lt;/a&gt; project)
we talked about
&lt;a href=&quot;https://spritely.institute/news/scheme-to-wasm-lambdas-recursion.html&quot;&gt;directly compiling Scheme to WebAssembly&lt;/a&gt;.
This is of course the higher level goal of Hoot:
since Spritely's tooling is written in
&lt;a href=&quot;https://www.gnu.org/software/guile/&quot;&gt;Guile Scheme&lt;/a&gt;,
we want Spritely to be in the browser, and compiling Scheme programs
themselves to WebAssembly is a great way to accomplish that goal.&lt;/p&gt;&lt;p&gt;But what if we wanted to play with WebAssembly on a lower level?
It turns out Hoot is a great choice for this: since Hoot uses Guile's
&lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/Compiler-Tower.html&quot;&gt;compiler tower&lt;/a&gt;
and has multiple steps of transformation, the lower level assembler,
disassembler, etc tools of WebAssembly are also available to the
inspired Guile hacker.&lt;/p&gt;&lt;p&gt;Though Hoot will be a complete Scheme→WebAssembly compiler... it
already contains a nascent powerful and general WebAssembly toolkit!&lt;/p&gt;&lt;hr /&gt;&lt;h3&gt;Getting Technical: Making a minimal WASM-4 cart using Hoot&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://wasm4.org/&quot;&gt;WASM-4&lt;/a&gt; is intentionally minimal and sparse.
No garbage collector extension, and no room for higher level constructs.
You've got 64kb of memory, 4 colors, and individual instructions count.&lt;/p&gt;&lt;p&gt;WASM-4 runs fully compiled WebAssembly programs called &amp;quot;carts&amp;quot;.
A very minimal WASM-4 cart (in fact a cut down version of WASM-4's
&amp;quot;hello world&amp;quot; cart) could be defined like so:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;$smiley$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#x19a0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;syntax-comment&quot;&gt;; location of the smiley
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;smiley-data&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;#vu8&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;#b11000011&lt;/span&gt;      &lt;span class=&quot;syntax-comment&quot;&gt;; 1bpp (1 bit per pixel) sprite!
&lt;/span&gt;       &lt;span class=&quot;syntax-symbol&quot;&gt;#b10000001&lt;/span&gt;      &lt;span class=&quot;syntax-comment&quot;&gt;; We have two colors represented by 0 and 1
&lt;/span&gt;       &lt;span class=&quot;syntax-symbol&quot;&gt;#b00100100&lt;/span&gt;      &lt;span class=&quot;syntax-comment&quot;&gt;; which means if you squint
&lt;/span&gt;       &lt;span class=&quot;syntax-symbol&quot;&gt;#b00100100&lt;/span&gt;      &lt;span class=&quot;syntax-comment&quot;&gt;; you can kinda see the smiley!
&lt;/span&gt;       &lt;span class=&quot;syntax-symbol&quot;&gt;#b00000000&lt;/span&gt;
       &lt;span class=&quot;syntax-symbol&quot;&gt;#b00100100&lt;/span&gt;
       &lt;span class=&quot;syntax-symbol&quot;&gt;#b10011001&lt;/span&gt;
       &lt;span class=&quot;syntax-symbol&quot;&gt;#b11000011&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;our-game&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;module&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Copies pixels to the framebuffer.
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;env&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;blit&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;$blit&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;param&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;syntax-comment&quot;&gt;;; Define the smiley sprite in memory
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,$smiley$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,smiley-data&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;update&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;$blit&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,$smiley$&lt;/span&gt;
            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;76&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;76&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;; draw at 76, 76
&lt;/span&gt;            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;syntax-comment&quot;&gt;; 8x8 sprite
&lt;/span&gt;            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;              &lt;span class=&quot;syntax-comment&quot;&gt;; 1bpp sprite&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here we are using a special lisp/scheme feature called &amp;quot;quasiquote&amp;quot;.
Quasiquote is enabled with the &amp;quot;back-tick&amp;quot; character appearing before
&lt;code&gt;module&lt;/code&gt;, switching into read-only data.
In this way, inside of &lt;code&gt;our-game&lt;/code&gt;, in the places we have written
&lt;code&gt;,$smiley$&lt;/code&gt; we are actually substituting in the &lt;code&gt;$smiley$&lt;/code&gt; definition
from the top of the program, and where we say &lt;code&gt;,smiley-data&lt;/code&gt; we are
inserting the bytevector describing the smiley sprite.
This turns out to be a powerful templating system for producing
WebAssembly, and we will use it in greater detail later.&lt;/p&gt;&lt;p&gt;Now let's say we want to try this cart.
Since we're in a lisp and lisp culture encourages &amp;quot;live development&amp;quot;,
let's make a helper utility to compile and run our game:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;use-modules&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;wasm&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;assemble&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define*&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;try-game&lt;/span&gt; &lt;span class=&quot;syntax-keyword&quot;&gt;#:optional&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;game&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;our-game&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;call-with-output-file&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;our-game.wasm&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;put-bytevector&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;wat-&amp;gt;wasm&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;game&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;system*&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;wasm4&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;our-game.wasm&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now giving the game a try is as simple as running &lt;code&gt;try-game&lt;/code&gt; at the REPL:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;try-game&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here's a version of the cart we just built above running live:&lt;/p&gt;&lt;p&gt;&lt;iframe src=&quot;/static/embed/hello-wasm4-v0.wasm4.html&quot; class=&quot;wasm4&quot; frameborder=&quot;0&quot; sandbox=&quot;allow-scripts&quot; alt=&quot;Hello world WASM cart&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;h3&gt;Programmatically generating WebAssembly&lt;/h3&gt;&lt;p&gt;Unfortunately, WebAssembly is very verbose.
Consider how messy our &amp;quot;update&amp;quot; procedure was already looking:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  &lt;span class=&quot;syntax-symbol&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;update&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;$blit&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,$smiley$&lt;/span&gt;
           &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;76&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;76&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;; draw at 76, 76
&lt;/span&gt;           &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;syntax-comment&quot;&gt;; 8x8 sprite
&lt;/span&gt;           &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;                &lt;span class=&quot;syntax-comment&quot;&gt;; 1bpp sprite&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is very noisy!  All of those &lt;code&gt;i32.const&lt;/code&gt; operations are
getting in the way of us placing our smiley and defining its width
and height.
Not to mention that the final argument defines various flags specified
by individual bits which are very hard to remember.
If we were writing many of these, this would get very hard to read indeed.
Time for an abstraction!&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;maybe-i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;number?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-symbol&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,x&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define*&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;call-blit&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;sprite-ptr&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;height&lt;/span&gt;
                    &lt;span class=&quot;syntax-keyword&quot;&gt;#:key&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2bpp?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;rotate?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;flip-x?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;flip-y?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;flags&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;logior&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#b0&lt;/span&gt;                            &lt;span class=&quot;syntax-comment&quot;&gt;; start with empty byte
&lt;/span&gt;            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2bpp?&lt;/span&gt;   &lt;span class=&quot;syntax-symbol&quot;&gt;#b00000001&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#b0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;syntax-comment&quot;&gt;; rightmost bit for 2-bits-per-pixel
&lt;/span&gt;            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;flip-x?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#b00000010&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#b0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;syntax-comment&quot;&gt;; second bit for flipping x axis
&lt;/span&gt;            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;flip-y?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#b00000100&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#b0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;syntax-comment&quot;&gt;; third bit for flipping y axis
&lt;/span&gt;            &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;rotate?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#b00001000&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#b0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;; fourth bit for rotating 90 degrees
&lt;/span&gt;  &lt;span class=&quot;syntax-symbol&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;$blit&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,sprite-ptr&lt;/span&gt;
         &lt;span class=&quot;syntax-symbol&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;maybe-i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;maybe-i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;syntax-symbol&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;maybe-i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;maybe-i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;syntax-symbol&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;maybe-i32.const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we can update our update procedure to rotate and place
the smiley multiple times:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;update&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;call-blit&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;$smiley$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;76&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;76&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;call-blit&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;$smiley$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;8&lt;/span&gt;
              &lt;span class=&quot;syntax-keyword&quot;&gt;#:flip-y?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt; &lt;span class=&quot;syntax-keyword&quot;&gt;#:rotate?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;iframe src=&quot;/static/embed/hello-wasm4-v1.wasm4.html&quot; class=&quot;wasm4&quot; frameborder=&quot;0&quot; sandbox=&quot;allow-scripts&quot; alt=&quot;Hello world WASM cart&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;p&gt;Despite now blitting the smiley twice, and rotating and flipping it
on the second version, this is now dramatically easier to read than
the first version.&lt;/p&gt;&lt;h3&gt;Scheme procedures to generate data and whole programs&lt;/h3&gt;&lt;p&gt;While we're not translating Scheme to WebAssembly directly in this
particular usage of Hoot, we are &lt;em&gt;using&lt;/em&gt; Scheme to &lt;em&gt;generate&lt;/em&gt;
WebAssembly... and that means we have the full power of Scheme at our
fingertips!&lt;/p&gt;&lt;p&gt;This turned out to be hugely useful during the game jam.  For
instance, while the &amp;quot;smiley&amp;quot; sprite we showed earlier was defined in 1
bit per pixel (&amp;quot;1BPP&amp;quot;) and thus could be &amp;quot;seen while squinting&amp;quot; in
its binary representation:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;smiley-data&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;#vu8&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;#b11000011&lt;/span&gt;      &lt;span class=&quot;syntax-comment&quot;&gt;; 1bpp (1 bit per pixel) sprite!
&lt;/span&gt;       &lt;span class=&quot;syntax-symbol&quot;&gt;#b10000001&lt;/span&gt;      &lt;span class=&quot;syntax-comment&quot;&gt;; We have two colors represented by 0 and 1
&lt;/span&gt;       &lt;span class=&quot;syntax-symbol&quot;&gt;#b00100100&lt;/span&gt;      &lt;span class=&quot;syntax-comment&quot;&gt;; which means if you squint
&lt;/span&gt;       &lt;span class=&quot;syntax-symbol&quot;&gt;#b00100100&lt;/span&gt;      &lt;span class=&quot;syntax-comment&quot;&gt;; you can kinda see the smiley!
&lt;/span&gt;       &lt;span class=&quot;syntax-symbol&quot;&gt;#b00000000&lt;/span&gt;
       &lt;span class=&quot;syntax-symbol&quot;&gt;#b00100100&lt;/span&gt;
       &lt;span class=&quot;syntax-symbol&quot;&gt;#b10011001&lt;/span&gt;
       &lt;span class=&quot;syntax-symbol&quot;&gt;#b11000011&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;However, for Wireworld we wanted to take advantage of WASM-4's support
for a 4-color palette to draw prettier sprites.
These are not readable as text in pure binary data in the same way.
However, for the sake of fast iteration and easy ability to &amp;quot;play with&amp;quot;
sprite appearance, we wanted to get back the defined-in-ascii-art
approach.&lt;/p&gt;&lt;p&gt;So we did just that.  Here are the head and tail sprite definitions:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;head-text&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;\
X##X
#~.#
#~~#
X##X&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;tail-text&lt;/span&gt;
  &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;\
XXXX
X#~X
X##X
XXXX&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here &lt;code&gt;X&lt;/code&gt; represents a dark blue pixel, &lt;code&gt;#&lt;/code&gt; is dark purple,
&lt;code&gt;~&lt;/code&gt; is light purple, and &lt;code&gt;.&lt;/code&gt; is off-white.
These sprites are compiled into their binary representation from
within Scheme itself:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;text-&amp;gt;2bpp-sprite-bv&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;head-text&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;$7&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#vu8&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;235&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;146&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;150&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;235&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can then directly insert the binary representation into the
assembly of the program!
(Understanding how
&lt;a href=&quot;https://gitlab.com/spritely/wasm4-wireworld/-/blob/46a39eb6e0b9f690e8d53cd372d6d3faac71725a/data-utils.scm#L41&quot;&gt;text-&amp;gt;2bpp-sprite-bv&lt;/a&gt;
works is left as an exercise for the reader.)&lt;/p&gt;&lt;p&gt;When constructing this blogpost, we also wanted a way to generate
multiple Wireworld WASM-4 carts which each started with an
&lt;a href=&quot;https://gitlab.com/spritely/wasm4-wireworld/-/tree/main/worlds&quot;&gt;initial world state&lt;/a&gt;.
Once again, we wanted to define these in plaintext for fast
iteration and experimentation while preserving readability:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  *#                                #@
 @  ################################  *
  #                                  #
 #                                    #
  #                                  #
 #                                    #
  ######     ####### ####   ####     #
 #     #     #   #   #   # #          #
  #    #  #  #   #   ####   ###      #
 #     #  #  #   #   #  #  #          #
  #    #  #  #   #   #   # #         #
 #      ## ##  #######   ## ####      #
  #                             ######
 #                                    #
  #                                  #
 #                                    #
  #  #     #   ##   ####  #    ###   #
 #   #     #  #  #  #   # #    #  #   #
  #  #  #  # *    @ ####  #    #  #  #
 #   #  #  # @    * #  #  #    #  #   #
  #  #  #  #  #  #  #   # #    #  #  #
 #    ## ##    ##   #   # #### ###    #
  #                                  #
 #                                    #
  #                                  #
 #                                    #
  #                                  #
 *  ################################  @
  @#                                #*&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Writing a text parser interpreted by a WASM program for reading
textual wireworld descriptions would have been too much work
(both for us and for the spirit of an old-school fantasy console).
We took the same technique as with the textual representation of
sprites: our Scheme program
&lt;a href=&quot;https://gitlab.com/spritely/wasm4-wireworld/-/blob/main/load-world.scm&quot;&gt;loaded and translated worlds&lt;/a&gt;
from the textual representation to the very in-memory representation
our WASM-4 game would use, then thanks to the power of quasiquote,
we simply inserted the game into the generated program.&lt;/p&gt;&lt;p&gt;The really cool thing here is that
&lt;em&gt;the generation of carts is itself a procedure&lt;/em&gt;.
Generating a custom cart is as simple as:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;wat-&amp;gt;wasm&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-wireworld-game&lt;/span&gt;
            &lt;span class=&quot;syntax-keyword&quot;&gt;#:world&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;load-world-file&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;world-filename&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Thus our make file could simply spit out custom files with custom
initial world states, &amp;quot;baking&amp;quot; the initial level descriptions into
memory:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;$ make
Built build/wireworld-adder.wasm
Built build/wireworld-splash.wasm
Built build/wireworld-intro.wasm
Built build/wireworld-blank.wasm&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you've ever heard lisp programmers talk about &amp;quot;programs that write
programs&amp;quot;, consider this a nice example!&lt;/p&gt;&lt;h2&gt;Lessons learned and meta-observations&lt;/h2&gt;&lt;p&gt;Our biggest successes were when we began embracing the abstraction powers
provided by Hoot.
Initially we simply hand-coded using WebAssembly's textual format and
compiled such files.
Once we moved to the scheme-as-code-generator abstractions shown in
this article there was a marked uptick in productivity and
correctness.
Code became easier to write and understand and iteration became faster.
Tools such as the textual representations of sprites and levels became
easy to directly integrate.
And significantly, by embracing the &amp;quot;programs that write programs&amp;quot;
philosophy, generating the custom carts shown off in this article became
as simple as passing in the relevant arguments to the procedure which
&amp;quot;baked&amp;quot; the carts with the relevant levels.
This latter part was particularly satisfying but was simply a natural
outgrowth of the style of programming we took.&lt;/p&gt;&lt;p&gt;Hoot's primary goal is to get Spritely's tooling available in the
browser by
&lt;a href=&quot;https://spritely.institute/news/scheme-to-wasm-lambdas-recursion.html&quot;&gt;directly compiling Scheme to WebAssembly&lt;/a&gt;.
However it turns out that Hoot's lower level layers of abstractions
are powerful tooling in their own right!
Game jams are a great opportunity to put your tooling
to the test, and we're delighted with the outcome.&lt;/p&gt;</summary></entry><entry><title>Lisp Game Jam - &quot;Fantasary&quot; - prototyping an object world (&amp; TCP netlayer)</title><id>https://spritely.institute/news/lisp-game-jam---fantasary---prototyping-an-object-world--tcp-netlayer.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2023-06-07T16:30:00Z</updated><link href="https://spritely.institute/news/lisp-game-jam---fantasary---prototyping-an-object-world--tcp-netlayer.html" rel="alternate" /><summary type="html">&lt;p&gt;&lt;img src=&quot;/static/images/blog/fantasary.png&quot; alt=&quot;Fantasary screenshot in cool-retro-term&quot; /&gt;&lt;/p&gt;&lt;p&gt;Spritely participated in the &lt;a href=&quot;https://itch.io/jam/spring-lisp-game-jam-2023&quot;&gt;Spring Lisp Game Jam
2023&lt;/a&gt; last week.  We
submitted not one, but two, entries.  This post is about one of them:
&lt;a href=&quot;https://cwebber.itch.io/fantasary&quot;&gt;Fantasary&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Fantasary is a prototype textual virtual world with interactive
objects.  Users can move between multiple virtual rooms and interact
with the objects (other humans and bots) in those rooms.  We used an
ncurses-based user interface and
&lt;a href=&quot;https://github.com/Swordfish90/cool-retro-term&quot;&gt;cool-retro-term&lt;/a&gt; to
make it look pretty.  The result resembles an IRC chat application but
under the hood it is built using object capabilities.  Building this
prototype under the time constraints of a game jam served multiple
purposes:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Testing out a new, prototype TCP+TLS netlayer for OCapN.&lt;/li&gt;&lt;li&gt;Experimenting with &lt;a href=&quot;https://spritely.institute/static/papers/petnames.html&quot;&gt;petnames&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Experimenting with the &lt;a href=&quot;http://habitatchronicles.com/2019/08/the-unum-pattern/&quot;&gt;unum
pattern&lt;/a&gt; to
model objects in a distributed virtual world.&lt;/li&gt;&lt;li&gt;Getting more experience building and releasing applications with
&lt;a href=&quot;https://spritely.institute/goblins&quot;&gt;Goblins&lt;/a&gt; AKA dogfooding.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;A new, prototype netlayer&lt;/h3&gt;&lt;p&gt;Test driving a new OCapN netlayer was the primary motivation for
working on Fantasary.  As of today, Goblins ships with a Tor Onion
services netlayer.  This netlayer has its uses and was relatively
simple to implement, but there are significant downsides:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;It requires running a Tor daemon configured in a particular way.&lt;/li&gt;&lt;li&gt;Connecting to a Tor onion service for the first time tends to be
slow.&lt;/li&gt;&lt;li&gt;There's a lot of lag due to the overhead inherent in onion routing.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;It's great to have Tor as an available option, but we'd also like to
provide something simpler and faster.  To that end, we've written a
prototype netlayer, internally called the &amp;quot;Simple TCP&amp;quot; netlayer, that
operates over standard TCP sockets and uses TLS to encrypt the data
that passes through.  The &amp;quot;simple&amp;quot; part refers to using widespread
networking protocols to achieve peer-to-peer connections to the extent
possible, without being part of a true peer-to-peer network such as
one built with libp2p.  This prototype seems to be working pretty well
so far.  The 3-day game jam rating period is still ongoing at the time
of writing and people who have never used Goblins before are able to
connect to our Fantasary server and play around, and our server hasn't
crashed.  That said, there are several caveats to using this netlayer
at the moment, and we had to build Fantasary carefully to avoid those
shortcomings.&lt;/p&gt;&lt;p&gt;For starters, most people who try Fantasary will be behind a NAT
gateway and a firewall on their home network, which makes establishing
peer-to-peer connections very difficult.  We did not solve this
problem before writing Fantasary, so we made sure that all network
communication was between a client and our public server, never
peer-to-peer.  In OCapN terms, this meant &lt;em&gt;no third-party handoffs&lt;/em&gt; of
object references.  Looking ahead, we are exploring using public STUN
servers to do the necessary NAT hole punching so that clients can be
connected directly, much like WebRTC-based chat systems (among
others.)&lt;/p&gt;&lt;p&gt;Another major problem is bootstrapping clients onto OCapN.  In order
to connect to an application using OCapN from the outside world, you
need a sturdyref URI.  At the moment, we are doing the simplest
possible thing and using an encoded form of the X.509 certificate as
the host identifier, and rely upon hints to point a client towards the
machine that owns that certificate.  Here's an abridged example:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ocapn://&amp;lt;encoded-cert&amp;gt;.simple-tcp/s/&amp;lt;swiss-num&amp;gt;?host=example.com&amp;amp;port=8888&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It would be unreasonable to print a real world example is because the
encoded cert is a huge number of characters.  The &lt;a href=&quot;https://gitlab.com/spritely/fantasary/-/blob/main/sturdyref&quot;&gt;sturdyref shipped
in
Fantasary&lt;/a&gt;
is 4124 characters long!  This makes the URIs difficult to share and
thus poses a usability problem.  We are looking to fix this by using a
&lt;em&gt;hash&lt;/em&gt; of the certificate as the host identifier and introducing a
step prior to the TLS handshake where the server sends over the
certificate and the client confirms that it hashes to the expected
value.&lt;/p&gt;&lt;p&gt;As an aside, the URI above may seem inverted from typical URIs you are
used to because the host name appears in the query string.  In OCapN,
the essential identifier of a machine is its public key, not its name
or location.  We reserve the query string as a place for &amp;quot;hints&amp;quot; that
can help clients establish a connection to the machine with the given
identity.  Here we are using a hint that relies upon DNS, but there
could be other ways to point a client towards the machine's location.&lt;/p&gt;&lt;p&gt;The last major problem is the X.509 certificate system being a poor
fit for the distributed world we are building.  We are using TLS
because of its ubiquity, not because we love it.  X.509 certificates
include all sorts of data that is for the centralized certificate
authority system.  All we care about in Goblins is that we have a
public/private key pair that we can use to establish an encrypted
channel.  In fact, the netlayer &lt;em&gt;does not&lt;/em&gt; rely on CA certificate
chains (the stuff you'd typically find in &lt;code&gt;/etc/ssl&lt;/code&gt;) at all.  Because
the OCapN URI has the certificate for the remote machine encoded in
it, the associated TLS session inserts that certificate into its trust
store and &lt;em&gt;nothing else&lt;/em&gt;.  Also, we didn't want to make users figure
out how to generate their own certificates as that would be a major
barrier to entry.  Instead, we shelled out to OpenSSL to automatically
generate one, filling in all text fields with hardcoded values to
satisfy the generator.  Moving forward, we'd like to preserve
automatic certificate generation but want to generate them through
library calls within the program rather than spawning a subprocess.&lt;/p&gt;&lt;h3&gt;Petnames&lt;/h3&gt;&lt;p&gt;A distributed world doesn't rely upon centralized naming authoritities
like domain name registrars, so we pushed ourselves to keep the server
code free of name registration behavior.  Instead, users say what
their self-proclaimed name is, and other users are free to replace
that name with a &amp;quot;petname&amp;quot;, a name local to their client that only
they will see.  It works much like how a contact list on a cell phone
associates local names to phone numbers.  To distinguish
self-proclaimed names from petnames, we introduced a little bit of new
syntax into the client interface.  A self-proclaimed name appears
prefixed with &lt;code&gt;?&lt;/code&gt; like &lt;code&gt;?Alice&lt;/code&gt;.  A local petname appears prefixed
with &lt;code&gt;@&lt;/code&gt; like &lt;code&gt;@AuntAlice&lt;/code&gt;.  Because there's no central registry of
names, self-proclaimed name collisions are both possible and not a big
deal.  When clients see many objects with the same self-proclaimed
name, they add an integer prefix to distinguish them.  If there were
three users named &lt;code&gt;Goblin&lt;/code&gt; in the room, they would show up as
&lt;code&gt;?Goblin&lt;/code&gt;, &lt;code&gt;?Goblin+1&lt;/code&gt;, and &lt;code&gt;?Goblin+2&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Fun fact: Fantasary started out with centralized names, and when we
decided to expand scope to incorporate petnames it actually
&lt;em&gt;simplified&lt;/em&gt; the code for the objects on the server because they no
longer needed to care about names at all, only object identity.&lt;/p&gt;&lt;p&gt;If you'd like to read more about petnames, check out &lt;a href=&quot;https://spritely.institute/news/two-petnames-papers-are-released.html&quot;&gt;our blog post
from last
year&lt;/a&gt;
about two papers we wrote on the subject.&lt;/p&gt;&lt;h3&gt;The unum pattern&lt;/h3&gt;&lt;p&gt;The unum pattern, diagramed in the &lt;a href=&quot;http://www.erights.org/elib/distrib/unum/index.html&quot;&gt;E
literature&lt;/a&gt; and
&lt;a href=&quot;http://habitatchronicles.com/2019/08/the-unum-pattern/&quot;&gt;explained in greater detail by Chip
Morningstar&lt;/a&gt;,
is a way of representing an object in a virtual world that has a
presence across many machines.  The owner of an object views/interacts
with that object in one way, a server may have yet another view, the
users in the same room may have yet another view, etc., yet they all
refer to the same conceptual &amp;quot;thing.&amp;quot;  For Fantasary, we tried to
understand and implement a simple version of this pattern.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;/static/images/blog/fantasary-unum.png&quot; alt=&quot;Diagram of unum pattern in Fantasary&quot; /&gt;&lt;/p&gt;&lt;p&gt;Our game objects, the things that can exist inside a room, are called
&amp;quot;entities.&amp;quot;  The owner of an entity has the capability to do whatever
it would like.  Fantasary is very simple, and the only things to be
done are setting a name and an event handler.  When an entity enters a
room, the room is given a &amp;quot;puppet&amp;quot; of that entity.  A puppet is a
proxy for the entity with limited capabilities.  The room has
read-only access to the entity's identity and can invoke the event
handler to notify the entity of activity within the room.  When an
entity leaves a room, it cuts the metaphorical puppet strings
(represented as dashed lines in the diagram above) to revoke the
capability for the room to send messages to it.  Other entities in the
room see puppets of their roommates, as well, but puppets of a
different sort.  These puppets are constructed by the room
specifically for use by a single roommate.  If either entity leaves
the room, the puppet strings are cut and they can no longer talk via
that puppet.  This proxying strategy provides both security (an entity
&lt;em&gt;never&lt;/em&gt; gets a direct reference to another entity, nor does a room)
and a means to layer on context-specific behavior.  This initial
experiment with the unum pattern suggests to us that it's a pattern
worth exploring more in future projects.&lt;/p&gt;&lt;h3&gt;Packaging&lt;/h3&gt;&lt;p&gt;In order to make Fantasary something that people could actually run
without too much time investment, we utilized &lt;a href=&quot;https://guix.gnu.org&quot;&gt;GNU
Guix&lt;/a&gt;.  We use Guix internally for development
and server administration, but this was our first time using it to
ship software.  We used the &lt;code&gt;guix pack&lt;/code&gt; program to produce a
redistributable binary bundle that contains &lt;em&gt;all&lt;/em&gt; of the dependencies
required to run Fantasary, all the way down to glibc.  There a couple
of caveats:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The bundle is &lt;em&gt;big&lt;/em&gt;.  Nearly 1G uncompressed, ~250M gzipped.&lt;/li&gt;&lt;li&gt;The bundle works on Linux only, but that's OK for now.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The trade-off for making minimal assumptions about the Linux host
running the game is that the bundle is quite large.  It could be made
smaller, as there are things included that are not needed at runtime,
but that requires optimizing Guix package builds upstream.  From what
we've seen, the bundle has worked for most people that have tried
Fantasary, and some of the failures are due to assumptions made in our
own code (I didn't expect &lt;code&gt;(getprotobyname &amp;quot;tcp&amp;quot;)&lt;/code&gt; to fail on some
systems) and are not the fault of Guix.&lt;/p&gt;&lt;p&gt;Guix also made it to easy to write a wrapper script that automatically
launches Fantasary in cool-retro-term for that extra coolness factor.
This fancy version doesn't work for all users, however, so we also
included a fallback script that simply runs in the user's regular
terminal.&lt;/p&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;p&gt;Participating in the Lisp Game Jam gave us a great opportunity to
dedicate a fixed amount of time to develop a prototype that will be
important to us moving forward.  Fantasary is not without its share of
bugs and missing features (like cleaning up users that have
disconnected without sending a quit message), but that's part of what
a game jam is all about: Ruthlessly reducing scope to just the things
that matter the most and trying to sprint to the finish line with
something that mostly works.  We look forward to shipping the Simple
TCP netlayer in a future release of Goblins.&lt;/p&gt;</summary></entry><entry><title>Directly compiling Scheme to WebAssembly: lambdas, recursion, iteration!</title><id>https://spritely.institute/news/scheme-to-wasm-lambdas-recursion.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2023-05-30T14:00:00Z</updated><link href="https://spritely.institute/news/scheme-to-wasm-lambdas-recursion.html" rel="alternate" /><summary type="html">&lt;p&gt;&lt;img src=&quot;/static/images/blog/hoot-fib.png&quot; alt=&quot;Hoot logo in recursive fib style&quot; /&gt;&lt;/p&gt;&lt;p&gt;It's been just over three months since we
&lt;a href=&quot;https://spritely.institute/news/guile-on-web-assembly-project-underway.html&quot;&gt;announced the Guile on WebAssembly project&lt;/a&gt;
(codenamed &lt;a href=&quot;https://gitlab.com/spritely/guile-hoot&quot;&gt;Hoot&lt;/a&gt;).
Since then we've brought on two
&lt;a href=&quot;https://spritely.institute/news/andy-wingo-leads-g2W.html&quot;&gt;fantastic&lt;/a&gt;
&lt;a href=&quot;https://spritely.institute/news/robin-templeton-joins.html&quot;&gt;hackers&lt;/a&gt;
to develop the project and progress has been quick.&lt;/p&gt;&lt;p&gt;We now are at the point where we have things to show: we can now
compile various Scheme procedures &lt;em&gt;directly to WebAssembly.&lt;/em&gt;
Let's clarify that: by compiling directly to WebAssembly, we mean they
compile and run &lt;em&gt;without any intermediate virtual machine.&lt;/em&gt;
No C, no Rust, no Zig: Hoot outputs pure WebAssembly.
It's early, but Hoot compiled programs are starting to work...
and they're fast!&lt;/p&gt;&lt;h2&gt;Hoot by familiar Scheme examples&lt;/h2&gt;&lt;p&gt;The Hoot test suite
&lt;a href=&quot;https://gitlab.com/spritely/guile-hoot/-/blob/main/test/test-constants.scm&quot;&gt;includes some examples&lt;/a&gt;
of fairly standard scheme procedures, compiled directly to WebAssembly
and executed against V8.
Let's take a look at some of those examples to contextualize what Hoot
provides.
(If you're not familiar with Scheme, you can focus on the text of this
blogpost rather than the code.
Or, you can read our &lt;a href=&quot;https://spritely.institute/static/papers/scheme-primer.html&quot;&gt;Scheme Primer&lt;/a&gt;
as a way to get started on following along!)&lt;/p&gt;&lt;p&gt;Here's an all time favorite intro-to-Scheme example
(one of the &lt;a href=&quot;https://sarabander.github.io/sicp/html/1_002e2.xhtml#g_t1_002e2_002e1&quot;&gt;first examples in SICP&lt;/a&gt;):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-comment&quot;&gt;;; Your intro-to-CS factorial function
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;test-call&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;120&amp;quot;&lt;/span&gt;                         &lt;span class=&quot;syntax-comment&quot;&gt;; expected value
&lt;/span&gt;           &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;                   &lt;span class=&quot;syntax-comment&quot;&gt;; factorial function which takes `n`
&lt;/span&gt;             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fac&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;            &lt;span class=&quot;syntax-comment&quot;&gt;; start recursing at `n`
&lt;/span&gt;               &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;eq?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;             &lt;span class=&quot;syntax-comment&quot;&gt;; are we at zero?
&lt;/span&gt;                   &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;                     &lt;span class=&quot;syntax-comment&quot;&gt;; if so, return 1, otherwise...
&lt;/span&gt;                   &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;fac&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;1-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;; `n` times factorial of `n` minus one
&lt;/span&gt;           &lt;span class=&quot;syntax-symbol&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;                            &lt;span class=&quot;syntax-comment&quot;&gt;; run `factorial(5)`&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;test-call&lt;/code&gt; takes two or more arguments: the value we expect to see V8
spit out from running the compiled WebAssembly code, a procedure we
want to test, and any more arguments are arguments to the function.&lt;/p&gt;&lt;p&gt;Hoot is compiling this program to WebAssembly directly.    Astoundingly, at the time of writing, the
size of the compiled WebAssembly program is &lt;em&gt;only 970 bytes&lt;/em&gt;... less
than a kilobyte!  (Did you gasp?)&lt;/p&gt;&lt;p&gt;Other familiar intro-to-computer-science friends are also now available.
Who doesn't love the Fibonacci function?&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-comment&quot;&gt;;; Fibonacci, everyone's favorite
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;test-call&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;9227465&amp;quot;&lt;/span&gt;                     &lt;span class=&quot;syntax-comment&quot;&gt;; expected value
&lt;/span&gt;           &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;                   &lt;span class=&quot;syntax-comment&quot;&gt;; fibonacci function which takes `n`
&lt;/span&gt;             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fib&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;            &lt;span class=&quot;syntax-comment&quot;&gt;; start recursing at `n`
&lt;/span&gt;               &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;              &lt;span class=&quot;syntax-comment&quot;&gt;; is `n` 1 or less?
&lt;/span&gt;                   &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;                     &lt;span class=&quot;syntax-comment&quot;&gt;; if so, return 1, otherwise...
&lt;/span&gt;                   &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;fib&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;      &lt;span class=&quot;syntax-comment&quot;&gt;; add `fib(n - 1)` to
&lt;/span&gt;                      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;fib&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;;     `fib(n - 2)`
&lt;/span&gt;           &lt;span class=&quot;syntax-symbol&quot;&gt;34&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;                           &lt;span class=&quot;syntax-comment&quot;&gt;; run `fibonacci(34)`&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now the astute reader may be looking at the above two functions and
observing that these are &lt;em&gt;recursive procedures!&lt;/em&gt;
Yes, recursion is all fine and well in the land of Scheme, and it's
all fine and well in the land of Hoot, too.&lt;/p&gt;&lt;p&gt;Of course, the astute reader will &lt;em&gt;also&lt;/em&gt; recognize that neither of
these is the most efficient way to implement either of these
functions: both grow more memory than necessary.
It's great that we &lt;em&gt;can&lt;/em&gt; recurse, but &lt;em&gt;should we&lt;/em&gt; recurse?&lt;/p&gt;&lt;p&gt;Well, it turns out that iteration can be defined in terms of recursion.
If a procedure doesn't need to do any more work, there's no need to
keep it on the stack anymore.
And if a procedure doesn't need to do any more work &lt;em&gt;and&lt;/em&gt; it's just
calling itself, Scheme implementations are historically especially
smart about this, because we can just reuse the same procedure where
it was!&lt;/p&gt;&lt;p&gt;Which means, here's a very terse looking loop which &lt;em&gt;looks&lt;/em&gt; kinda
recursive but in terms of computational work is merely iterative:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-comment&quot;&gt;;; Let's get loopin!
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;test-call&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;500000000&amp;quot;&lt;/span&gt;                   &lt;span class=&quot;syntax-comment&quot;&gt;; expected value
&lt;/span&gt;           &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;           &lt;span class=&quot;syntax-comment&quot;&gt;; start loop at 0
&lt;/span&gt;               &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;500000000&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;       &lt;span class=&quot;syntax-comment&quot;&gt;; if we're less than 500 million...
&lt;/span&gt;                   &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;1+&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;         &lt;span class=&quot;syntax-comment&quot;&gt;; keep looping and increment n
&lt;/span&gt;                   &lt;span class=&quot;syntax-symbol&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;                 &lt;span class=&quot;syntax-comment&quot;&gt;; otherwise we're done, return n&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once again, this program is less than 1 kilobyte when compiled, and
carries with it everything a Hoot-compiled program needs to execute.
That's cheap in terms of file size.
But how fast is it?&lt;/p&gt;&lt;p&gt;Well consider that Guile is
&lt;a href=&quot;https://ecraven.github.io/r7rs-benchmarks/&quot;&gt;actually fairly speedy&lt;/a&gt;.
It's not the fastest Scheme out there (their role in programming
language research means that Schemes are a well trodden territory for
optimizing languages), but it's quite fast.
Shockingly then, the Hoot-compiled WebAssembly for the above executes,
on local tests, is &lt;em&gt;five times faster than native Guile!&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Of course, looping over addition is a very limited benchmark.
Still, we're happy for this early indicator that Scheme to WebAssembly
is likely to be very performant.&lt;/p&gt;&lt;h2&gt;Hoot is also a mini WebAssembly toolkit!&lt;/h2&gt;&lt;p&gt;One of the interesting aspects of Hoot is that it takes advantage of
&lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/Compiler-Tower.html&quot;&gt;Guile's compiler tower&lt;/a&gt;.
Hoot is able to use all the optimizations that Guile already provides,
because &lt;a href=&quot;https://gitlab.com/spritely/guile-hoot/-/blob/main/module/hoot/compile.scm&quot;&gt;Hoot's compiler&lt;/a&gt;
transforms Scheme code from Guile's
&lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/CPS-Soup.html&quot;&gt;CPS Soup&lt;/a&gt;
intermediate language directly to WebAssembly.&lt;/p&gt;&lt;p&gt;(Guile's compiler tower has some limited support for other toplevel languages
which are not Scheme; this also means that those too can compile directly
to WebAssembly.)&lt;/p&gt;&lt;p&gt;One nice aspect of WebAssembly is that its textual representation is
already very lispy, using parenthetical s-expression notation.
This means that WebAssembly is already ripe territory for lispers to
embrace, and Hoot has done just that.&lt;/p&gt;&lt;p&gt;Rather than use external tooling like
&lt;a href=&quot;https://github.com/WebAssembly/binaryen&quot;&gt;binaryen&lt;/a&gt;
or &lt;a href=&quot;https://github.com/WebAssembly/wabt&quot;&gt;wabt&lt;/a&gt;, Hoot provides its own suite
of tools for
&lt;a href=&quot;https://gitlab.com/spritely/guile-hoot/-/blob/main/module/wasm/parse.scm&quot;&gt;parsing&lt;/a&gt;,
&lt;a href=&quot;https://gitlab.com/spritely/guile-hoot/-/blob/main/module/wasm/assemble.scm&quot;&gt;assembling&lt;/a&gt;,
&lt;a href=&quot;https://gitlab.com/spritely/guile-hoot/-/blob/main/module/wasm/disassemble.scm&quot;&gt;disassembling&lt;/a&gt;,
and &lt;a href=&quot;https://gitlab.com/spritely/guile-hoot/-/blob/main/module/wasm/dump.scm&quot;&gt;dumping&lt;/a&gt;
WebAssembly directly.
This means Hoot isn't just useful as a way of compiling Scheme to WebAssembly,
it's a useful WebAssembly toolkit in and of itself!&lt;/p&gt;&lt;h2&gt;What Hoot means for other languages&lt;/h2&gt;&lt;p&gt;For a long time, programmers were given one real option to program in web
browsers: Javascript.
WebAssembly's initial introduction has provided a ripe ground for several
other non-garbage-collected languages to enter the space, such as C, C++, Rust,
and Zig.&lt;/p&gt;&lt;p&gt;But there is a large and beautiful array of programming languages available
to programmers in the world.
Many of those languages have been given less than ideal paths to
participating on the web.
Compiling an entire language environment or virtual machine to WebAssembly
is perhaps better than transpiling to Javascript, but it is still an
expensive operation.&lt;/p&gt;&lt;p&gt;This blogpost has primarily been centered around Scheme
(Spritely's core tooling is written in Guile Scheme, and Hoot is a project
to compile Scheme to WebAssembly, so this isn't too surprising).
But the Spritely Institute is just that, a research institution.
Hoot is breaking ground in some new spaces in WebAssembly land (and we are
participating in the WebAssembly standards processes accordingly).&lt;/p&gt;&lt;p&gt;The web should be for everyone.
We hope Hoot paves a path so that more languages may enter the web, including
Python, Lua, Haskell, ML, and friends.&lt;/p&gt;&lt;h2&gt;What Hoot means for Spritely&lt;/h2&gt;&lt;p&gt;We showed some exciting demos in this blogpost, but it remains true that
Hoot is still early.
Some Scheme simple procedures can compile, but we have a ways to go.
But we are on track, and the future looks bright.
Hoot has been made possible due to a generous grant from
&lt;a href=&quot;https://consensys.net/&quot;&gt;Consensys&lt;/a&gt;/&lt;a href=&quot;https://metamask.io/&quot;&gt;Metamask&lt;/a&gt;.
This grant was given was a knowingly ambitious project; we are grateful
for their support and are excited to be delivering towards those goals.&lt;/p&gt;&lt;p&gt;On the immediate roadmap is the compilation of the Scheme standard
&lt;a href=&quot;https://small.r7rs.org/&quot;&gt;r7rs-small&lt;/a&gt;, with the goal to get Hoot compiled
programs to appear on the &lt;a href=&quot;https://ecraven.github.io/r7rs-benchmarks/&quot;&gt;r7rs benchmarks&lt;/a&gt;
page.
After that, it's onto getting &lt;a href=&quot;https://spritely.institute/goblins/&quot;&gt;Goblins itself&lt;/a&gt;
to run in the browser and in the (increasingly) many places WebAssembly
is supported.
We are excited to have an optimistic path to get Spritely's tooling in the
hands of as many users as possible.&lt;/p&gt;&lt;p&gt;We look forward to delivering more updates about Hoot as the project
progresses.
The future of WebAssembly (and Spritely) is bright!&lt;/p&gt;</summary></entry><entry><title>Spritely Goblins v0.11.0 released: time travel distributed debugging and more!</title><id>https://spritely.institute/news/spritely-goblins-v0110-released-time-travel-distributed-debugging-and-more.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2023-05-08T08:00:00Z</updated><link href="https://spritely.institute/news/spritely-goblins-v0110-released-time-travel-distributed-debugging-and-more.html" rel="alternate" /><summary type="html">&lt;p&gt;&lt;img src=&quot;/static/images/blog/goblins-v0.11.0.png&quot; alt=&quot;Goblins version 0.11.0&quot; /&gt;&lt;/p&gt;&lt;p&gt;We are delighted to announce the v0.11.0 release of our distributed programming
environment, &lt;a href=&quot;/goblins/&quot;&gt;Spritely Goblins&lt;/a&gt;!&lt;/p&gt;&lt;p&gt;Highlights from this release:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A new &lt;a href=&quot;https://spritely.institute/news/introducing-a-distributed-debugger-for-goblins-with-time-travel.html&quot;&gt;time-traveling distributed debugger&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Substantially improved documentation and docstrings&lt;/li&gt;&lt;li&gt;Several more actor-lib modules ported from Racket to Guile&lt;/li&gt;&lt;li&gt;Updates to OCapN code&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Goblins is Spritely's distributed object programming environment, providing an
intuitive security model, automatic local transactions for synchronous programming,
and asynchronous programming allowing collaboration over the network with the
same level of ease as local asynchronous programming.
Goblins takes the pain out of reasoning about distributed and secure
peer-to-peer programming: with Goblins, that's the default mode of
operation!&lt;/p&gt;&lt;p&gt;(Releases of Goblins v0.11.0 are available for both
&lt;a href=&quot;https://www.gnu.org/software/guile/&quot;&gt;Guile&lt;/a&gt; and &lt;a href=&quot;https://racket-lang.org/&quot;&gt;Racket&lt;/a&gt;
alike, but new features are aimed at the Guile version of Goblins.
More about the Racket version at the end!)&lt;/p&gt;&lt;h1&gt;A time traveling distributed debugger for Goblins!&lt;/h1&gt;&lt;p&gt;&lt;video src=&quot;https://spritely.institute/files/videos/Causeway-Live-Demo.webm&quot; controls=&quot;true&quot; alt=&quot;distributed debugger demo video&quot;&gt;&lt;/video&gt;&lt;/p&gt;&lt;p&gt;Goblins now includes a
&lt;a href=&quot;https://spritely.institute/news/introducing-a-distributed-debugger-for-goblins-with-time-travel.html&quot;&gt;time traveling distributed debugger&lt;/a&gt;!
Yeah, you heard that right!&lt;/p&gt;&lt;p&gt;The new Goblins debugger allows programmers to inspect and debug
distributed computations that happen across many vats (communicating
event loops.) The time travel feature allows for visiting past events
and inspecting program state at the time the event happened.&lt;/p&gt;&lt;p&gt;These tools are implemented as “meta-commands” for Guile's REPL,
complementing the tools that Guile already provides for sequential
debugging. In true Scheme fashion, this means that debugging happens
live, while the program is running, allowing programmers to fix bugs
and try again without having to stop and recompile/reboot their
program.&lt;/p&gt;&lt;h1&gt;Documentation overhaul&lt;/h1&gt;&lt;p&gt;Documentation has received a major overhaul in this release:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;All key procedures now have docstrings, allowing for easier
discovery of API usage during development&lt;/li&gt;&lt;li&gt;The manual's tutorial has been cleaned up for clarity and
correctness&lt;/li&gt;&lt;li&gt;All core API procedures are now documented in the manual&lt;/li&gt;&lt;li&gt;All modules in the actor-lib are now documented in the manual&lt;/li&gt;&lt;li&gt;The manual now has an index, so finding procedures is much
easier&lt;/li&gt;&lt;/ul&gt;&lt;h1&gt;OCapN / CapTP updates&lt;/h1&gt;&lt;p&gt;Work has continued on Goblins' implementation of OCapN, the Object
Capability Network, the set of network abstractions which provide
the fluid experience of distributed networked programming.&lt;/p&gt;&lt;p&gt;Goblins' network architecture is still in active development; this
release breaks compatibility with the &lt;code&gt;0.10&lt;/code&gt; release of Goblins.&lt;/p&gt;&lt;h2&gt;Semantics closer to CapTP draft specification&lt;/h2&gt;&lt;p&gt;Goblins' implementation of the OCapN version of CapTP (the Capability
Transfer Protocol) is aimed to be used as the starting point for
revisions for the OCapN group.  We have submitted a
&lt;a href=&quot;https://github.com/ocapn/ocapn/pull/42&quot;&gt;draft version of the protocol&lt;/a&gt; to the OCapN group.  Goblins 0.11.0 gets
us closer to the aims of that draft; we are hoping within the next few
releases to get full alignment and group consensus towards a unified
OCapN protocol, and the &lt;code&gt;0.11.0-goblins&lt;/code&gt; release of OCapN and CapTP
shipped with Goblins gets us closer to that goal.&lt;/p&gt;&lt;h2&gt;Add acyclic distributed GC support to CapTP&lt;/h2&gt;&lt;p&gt;Goblins 0.11.0 now ships support for acyclic distributed garbage
collection, meaning that references to cooperative freeing of objects
shared over the network but no longer needed is possible&lt;/p&gt;&lt;h1&gt;More actor-lib modules ported from Racket to Guile&lt;/h1&gt;&lt;p&gt;More of Goblins' &amp;quot;standard library&amp;quot; is now available in the Guile
version of Goblins, ported from Racket:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;(goblins actor-lib pushdown)&lt;/code&gt; is a simple pushdown automata
implementation, useful for various kinds of state machines,
especially in some games&lt;/li&gt;&lt;li&gt;&lt;code&gt;(goblins actor-lib opportunistic)&lt;/code&gt; allows for proxying object
behavior, opportunistically using &lt;code&gt;$&lt;/code&gt; for near objects but using
&lt;code&gt;&amp;lt;-&lt;/code&gt; otherwise (known as select-swear in the Racket version)&lt;/li&gt;&lt;li&gt;&lt;code&gt;(goblins actor-lib simple-mint)&lt;/code&gt; is a very simple example
&amp;quot;bank&amp;quot; of sorts, ported from the example in
&lt;a href=&quot;http://erights.org/elib/capability/ode/index.html&quot;&gt;An Ode to the Granovetter Diagram&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;(goblins actor-lib let-on)&lt;/code&gt; provides convenient code for promise
resolution which strongly resembles &lt;code&gt;let&lt;/code&gt; in Scheme, but with the
behavior of &lt;code&gt;on&lt;/code&gt; in Goblins&lt;/li&gt;&lt;/ul&gt;&lt;h1&gt;Goblins, Racket edition v0.11.0&lt;/h1&gt;&lt;p&gt;The Guile version of Goblins is now the primary version
of Goblins, but we continue to support the
&lt;a href=&quot;https://docs.racket-lang.org/goblins/index.html&quot;&gt;Racket version of Goblins&lt;/a&gt;.
In particular, the Racket version of Goblins has also received a v0.11.0
release, bringing its network code up to the same state as the Guile
version and maintaining compatibility.&lt;/p&gt;&lt;h1&gt;Onward and upward!&lt;/h1&gt;&lt;p&gt;And that's not all!  For more information on Goblins v0.11.0, read the
&lt;a href=&quot;https://gitlab.com/spritely/guile-goblins/-/blob/main/NEWS&quot;&gt;NEWS file&lt;/a&gt;!&lt;/p&gt;&lt;p&gt;This release is brought to you by the following contributors: David
Thompson, Juliana Sims, Christine Lemmer-Webber, Jessica Tallon,
Vivianne Langdon, and Geoffrey J. Teale.  Thank you for your work!&lt;/p&gt;&lt;p&gt;We hope you enjoy this release of Spritely Goblins!
And if you're building something cool with Goblins, let us know on our
&lt;a href=&quot;https://community.spritely.institute&quot;&gt;community forum&lt;/a&gt;.
(Use OCAPN2023 for the Invite Code when you join.)&lt;/p&gt;</summary></entry><entry><title>Introducing: A distributed debugger for Goblins with time travel!</title><id>https://spritely.institute/news/introducing-a-distributed-debugger-for-goblins-with-time-travel.html</id><author><name>Spritely Institute</name><email>contact@spritely.institute</email></author><updated>2023-04-12T12:00:00Z</updated><link href="https://spritely.institute/news/introducing-a-distributed-debugger-for-goblins-with-time-travel.html" rel="alternate" /><summary type="html">&lt;p&gt;&lt;img src=&quot;/static/images/blog/inspector-goblin-400x.png&quot; alt=&quot;Goblins mascot as a &amp;quot;time traveling&amp;quot; inspector&quot; /&gt;&lt;/p&gt;&lt;p&gt;Debugging distributed programs is difficult, but we’ve been hard at
work developing tools to make it easier within the &lt;a href=&quot;/goblins&quot;&gt;Goblins&lt;/a&gt;
object capability system.  While this work is still in its early
stages, we’re excited to share the progress we’ve made so far!&lt;/p&gt;&lt;p&gt;The new Goblins debugger allows programmers to inspect and debug
distributed computations that happen across many vats (&lt;a href=&quot;/static/papers/spritely-core.html#vat-model-of-computation&quot;&gt;communicating
event
loops&lt;/a&gt;.)
The time travel feature allows for visiting past events and inspecting
program state at the time the event happened.&lt;/p&gt;&lt;p&gt;These tools are implemented as “meta-commands” for Guile's REPL,
complementing the tools that Guile already provides for sequential
debugging.  In true Scheme fashion, this means that debugging happens
&lt;em&gt;live&lt;/em&gt;, while the program is running, allowing programmers to fix bugs
and try again without having to stop and recompile/reboot their
program.&lt;/p&gt;&lt;p&gt;Seeing is believing, so let’s walk through building a simple program
and using the new debugger to find and fix a small bug.  We’re going
to make the world’s simplest dungeon crawling RPG.  It will allow a
player to attack a monster to deal damage, and that’s about it.&lt;/p&gt;&lt;p&gt;The first step is to start up a Guile REPL and import the Goblins
modules that we need:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,use&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,use&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;actor-lib&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,use&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;actor-lib&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;let-on&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,use&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;actor-lib&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;methods&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;(goblins)&lt;/code&gt; module provides the core Goblins API.  The other three
modules are part of Goblins’ handy standard library of actor
abstractions.  In Guile's REPL, expressions that start with a comma
invoke a meta-command.  Guile provides a number of these commands,
like &lt;code&gt;,use&lt;/code&gt;.  We’ll be seeing commands specific to Goblins later.&lt;/p&gt;&lt;p&gt;Next, we need to create some vats where our actors can live.  Since
there is overhead in collecting debug data, vat logging is currently
opt-in on a per-vat basis.  The &lt;code&gt;#:log? #t&lt;/code&gt; keyword argument enables
logging.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;p-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn-vat&lt;/span&gt; &lt;span class=&quot;syntax-keyword&quot;&gt;#:name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'Player&lt;/span&gt;  &lt;span class=&quot;syntax-keyword&quot;&gt;#:log?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;m-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn-vat&lt;/span&gt; &lt;span class=&quot;syntax-keyword&quot;&gt;#:name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'Monster&lt;/span&gt; &lt;span class=&quot;syntax-keyword&quot;&gt;#:log?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;c-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn-vat&lt;/span&gt; &lt;span class=&quot;syntax-keyword&quot;&gt;#:name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'Cave&lt;/span&gt;    &lt;span class=&quot;syntax-keyword&quot;&gt;#:log?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we can define some actors to live in our vats.  To do that, we
first need to define constructor procedures.  We only need two kinds
of actors for this demo: Characters and dungeons.  Characters have a
name, some amount of hit points (HP), and a strength value.  They can
be damaged by attacks and die when their HP reaches 0.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;^character&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;_bcom&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;max-hp&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; HP is reduced when the character is attacked, so we use a cell
&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;;; actor to store a counter that can be modified.
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^cell&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;max-hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;methods&lt;/span&gt;
     &lt;span class=&quot;syntax-comment&quot;&gt;;; Getters
&lt;/span&gt;     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-comment&quot;&gt;;; Deal combat damage
&lt;/span&gt;     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;damage&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;; attacks always hit
&lt;/span&gt;     &lt;span class=&quot;syntax-comment&quot;&gt;;; Check if character is dead
&lt;/span&gt;     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;dead?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;zero?&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Dungeons are places where a player character fights a monster
character.  For simplicity, this is going to be a rather one-sided
battle and we’ll only implement the player’s turn.  A player turn
starts by dealing damage to the monster and ends by returning a log
summarizing what happened.  If the monster is killed, the log will say
so.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;^dungeon&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;_bcom&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;player&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;monster&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;methods&lt;/span&gt;
   &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;player-turn&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;let-on&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;player-name&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;player&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;monster-name&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;monster&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;player&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-comment&quot;&gt;;; Deal damage to the monster and check to see if it's dead.
&lt;/span&gt;      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;let*-on&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;hit?&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;monster&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'damage&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;dead?&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;monster&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'dead?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;damage-msg&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;~a deals ~a damage to ~a!&amp;quot;&lt;/span&gt;
                                  &lt;span class=&quot;syntax-symbol&quot;&gt;player-name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;monster-name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-comment&quot;&gt;;; Log a message if the monster is dead.
&lt;/span&gt;          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dead?&lt;/span&gt;
              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;dead-msg&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;~a has been defeated!&amp;quot;&lt;/span&gt;
                                      &lt;span class=&quot;syntax-symbol&quot;&gt;monster-name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;damage-msg&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dead-msg&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;damage-msg&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To show off the “distributed” part of “distributed debugger”, we’ll spawn actors across all three of the vats we defined earlier.  The player character “Alice” will live in the Player vat, p-vat. The monster, a basilisk, will live in the Monster vat, m-vat.  The dungeon will live in the Cave vat, c-vat.  This simulates how, in a real game built using a distributed architecture, different actors in the game world would be hosted on many different computers.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;alice&lt;/span&gt;
                       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;with-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;p-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;basilisk&lt;/span&gt;
                       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;with-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;m-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Basilisk&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dungeon&lt;/span&gt;
                       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;with-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;c-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^dungeon&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;alice&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;basilisk&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With our actors spawned, we are ready to play this trivial game.  But
first, we’ll use a Goblins-specific REPL command to enter a new
context for evaluating code:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,enter-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;c-vat&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;Entering&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'Cave'.&lt;/span&gt;  &lt;span class=&quot;syntax-symbol&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;',q'&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;exit.&lt;/span&gt;  &lt;span class=&quot;syntax-symbol&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;',help&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;goblins'&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;help.&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note the change in the REPL prompt to indicate that we are now in the
Goblins vat named “Cave” and we are in a nested REPL session that is one
level deep.  The &lt;code&gt;,enter-vat&lt;/code&gt; command is provided by Goblins to allow
code (and other Goblins REPL commands) to be evaluated within the
context of a specific vat.  This makes Goblins operators (such as
&lt;code&gt;spawn&lt;/code&gt;, &lt;code&gt;$&lt;/code&gt;, and &lt;code&gt;&amp;lt;-&lt;/code&gt;) “just work” since they require a vat in order
to do their job.&lt;/p&gt;&lt;p&gt;We're now ready to have Alice take a turn.  Alice will attack the
basilisk, dealing 30 damage.  The basilisk only has 20 HP, so it
should die and we should see a log message saying so.  Getting a
result requires communicating with the Player and Monster vats, so we’ll
use the the &lt;code&gt;,vat-resolve&lt;/code&gt; command to wait for the asynchronous operation
to complete and print out the results:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-resolve&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dungeon&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'player-turn&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice deals 30 damage to Basilisk!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hmm, that’s not right!  The log says that Alice dealt 30 damage, but
it should also say that the basilisk was defeated.  Let’s debug and
see if we can spot the error.  For starters, we can run &lt;code&gt;,vat-tail&lt;/code&gt; to
see the most recent messages that the Cave vat has processed:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-tail&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;Churn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;7:&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;36:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-promise&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;Churn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;8:&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;37:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;38:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^on-listener&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;39:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfilled-handler&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;40:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice deals 30 damage to Basilisk!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;41:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice deals 30 damage to Basilisk!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;42:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice deals 30 damage to Basilisk!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;43:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^on-listener&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice deals 30 damage to Basilisk!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;44:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfilled-handler&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice deals 30 damage to Basilisk!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;45:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;finally-handler&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The events have been printed in chronological order.  There is some
useful information in here, but only events in the Cave vat are shown and
there’s nothing that describes how these events relate to one another.
However, we now know that event 45 is the most recent.  This event
represents the terminal point of the &lt;code&gt;,vat-resolve&lt;/code&gt; command we
evaluated above.&lt;/p&gt;&lt;p&gt;To view the events related to another event, across all relevant vats,
we will use the &lt;code&gt;,vat-tree&lt;/code&gt; and &lt;code&gt;,vat-graph&lt;/code&gt; commands. &lt;code&gt;,vat-tree&lt;/code&gt;
outputs a textual representation:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-tree&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;45&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;Vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^call-with-vat&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;├▸&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Player,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;4:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;│&lt;/span&gt;  &lt;span class=&quot;syntax-symbol&quot;&gt;└▸&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;10:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;├▸&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Monster,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;5:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;│&lt;/span&gt;  &lt;span class=&quot;syntax-symbol&quot;&gt;└▸&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;16:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Basilisk&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;│&lt;/span&gt;     &lt;span class=&quot;syntax-symbol&quot;&gt;└▸&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;19:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Basilisk&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;│&lt;/span&gt;        &lt;span class=&quot;syntax-symbol&quot;&gt;└▸&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Monster,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;23:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;damage&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;│&lt;/span&gt;           &lt;span class=&quot;syntax-symbol&quot;&gt;└▸&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;28:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;│&lt;/span&gt;              &lt;span class=&quot;syntax-symbol&quot;&gt;└▸&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Monster,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;32:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dead?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;│&lt;/span&gt;                 &lt;span class=&quot;syntax-symbol&quot;&gt;└▸&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;37:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;│&lt;/span&gt;                    &lt;span class=&quot;syntax-symbol&quot;&gt;└▸&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;40:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice deals 30 damage to Basilisk!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;│&lt;/span&gt;                       &lt;span class=&quot;syntax-symbol&quot;&gt;└▸&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;41:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice deals 30 damage to Basilisk!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;└▸&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Player,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;6:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;syntax-symbol&quot;&gt;└▸&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;13:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And &lt;code&gt;,vat-graph&lt;/code&gt; outputs a graphical Lamport causality diagram (thanks
to &lt;a href=&quot;https://graphviz.org/&quot;&gt;Graphviz&lt;/a&gt;):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-graph&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;45&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;/static/images/blog/questie-lamport-diagram.png&quot; alt=&quot;Lamport diagram of a player turn&quot; /&gt;&lt;/p&gt;&lt;p&gt;In each of these views, we can see that the message &lt;code&gt;(&amp;lt;- monster 'dead?)&lt;/code&gt; (with the debug representation of &lt;code&gt;msg ^character dead?&lt;/code&gt; in
the &lt;code&gt;,vat-graph&lt;/code&gt; output) resolves to &lt;code&gt;#f&lt;/code&gt; when we expected &lt;code&gt;#t&lt;/code&gt;.  Did
you miss it?  Here’s the relevant bit of the &lt;code&gt;,vat-tree&lt;/code&gt; output above:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;│              └▸ Vat Monster, 32: (message #&amp;lt;local-object ^character&amp;gt; dead?)
│                 └▸ Vat Cave, 37: (message #&amp;lt;local-object ^resolver&amp;gt; fulfill #f)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But &lt;em&gt;why&lt;/em&gt; did this happen?  The monster should have been dead.  Let’s
travel back in time and find out.  The first step is to truly enter
the debugger so we can walk backwards in time to when the &lt;code&gt;dead?&lt;/code&gt;
check happened.  To do this, we’ll use the &lt;code&gt;,vat-debug&lt;/code&gt; command, which
takes an event ID argument and starts a new sub-REPL with all the
context we need to debug the problem.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-debug&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;45&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;Entering&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;prompt.&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;`,q'&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;exit.&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note that the &lt;code&gt;[1]&lt;/code&gt; in the prompt became a &lt;code&gt;[2]&lt;/code&gt; because we are in yet
another sub-REPL.  To get our bearings, we’ll use the &lt;code&gt;,vat-trace&lt;/code&gt;
command to get a distributed backtrace showing the direct causes of
event 45:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-trace&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave:&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;Churn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2:&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;2:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^call-with-vat&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;4:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Monster:&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;Churn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;2:&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;6:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Basilisk&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave:&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;Churn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;5:&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;17:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^on-listener&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Basilisk&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;18:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfilled-handler&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Basilisk&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;19:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Basilisk&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;20:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^on-listener&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Basilisk&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;21:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfilled-handler&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Basilisk&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;22:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;damage&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Monster:&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;Churn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;3:&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;24:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave:&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;Churn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;7:&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;29:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^on-listener&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;30:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfilled-handler&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;31:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dead?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Monster:&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;Churn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;4:&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;33:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave:&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;Churn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;8:&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;38:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^on-listener&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;39:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfilled-handler&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;40:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice deals 30 damage to Basilisk!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;41:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice deals 30 damage to Basilisk!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;43:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^on-listener&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice deals 30 damage to Basilisk!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;45:&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;finally-handler&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Much like a regular backtrace in Guile’s sequential debugger, output
is in order from outermost call to innermost.  In other words, the
most recent event is the last event printed.  Our debugging session
starts focused on event 45, but we can shift our focus with the
&lt;code&gt;,vat-up&lt;/code&gt;, &lt;code&gt;,vat-down&lt;/code&gt;, and &lt;code&gt;,vat-jump&lt;/code&gt; commands.&lt;/p&gt;&lt;p&gt;&lt;code&gt;,vat-up&lt;/code&gt; moves up one event, from 45 to 43 in this case:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-up&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;Now&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;43:&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^on-listener&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice deals 30 damage to Basilisk!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;,vat-down&lt;/code&gt; moves down one event, back to event 45 in this case:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-down&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;Now&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;45:&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;finally-handler&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;,vat-jump&lt;/code&gt; moves to a particular event ID, so we can save ourselves
the tedium of typing &lt;code&gt;,vat-up&lt;/code&gt; or &lt;code&gt;,vat-down&lt;/code&gt; a bunch of times if the
event we're trying to inspect is far away from our current position.
In fact, event 31 looks particularly interesting, since that’s when
the &lt;code&gt;dead?&lt;/code&gt; check happened.  Let's jump there now:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-jump&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;31&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;Now&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;31:&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dead?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What &lt;code&gt;,vat-trace&lt;/code&gt; is hiding, for brevity’s sake, is that this “send” event in the Cave vat has a corresponding “receive” event in the Monster vat.  Let’s step down the trace and see where we end up:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-down&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;Now&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Monster,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;32:&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dead?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We’re now focused on an event in vat Monster, where the basilisk lives.
This means that we can travel back in time and send messages to the
basilisk as it existed at event 32.  To do this, we'll use the
&lt;code&gt;,vat-peek&lt;/code&gt; command.  Let's see what its HP looked like at this point:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-peek&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;basilisk&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'hp&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;-10&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hmm, zero should be the lowest HP value.  The &lt;code&gt;dead?&lt;/code&gt; method is
specifically checking if the character’s HP is zero.  It’s a safe bet
that the bug is in the &lt;code&gt;damage&lt;/code&gt; method, which happened around event
22, so let’s confirm our suspicion.  We’ll jump there, move down into
an event in the Monster vat, and check out the basilisk's HP:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-jump&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;22&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;Now&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Cave,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;22:&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;damage&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-down&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;Now&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Monster,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;23:&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;damage&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-peek&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;basilisk&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'hp&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;20&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Thanks to time travel, we can see that the starting HP value is 20,
like it should be.  The basilisk’s health was indeed initialized
correctly.  Moving down one more event, we can see for sure that this
is the point where we entered a problematic state:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-down&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;Now&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;Monster,&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;24:&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#&amp;lt;local-object&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^resolver&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;fulfill&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-peek&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;basilisk&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'hp&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;-10&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A note for the curious: Goblins uses transactional heaps to manage
actor state, enabling us to take snapshots of a vat before each event
is processed.  Querying these snapshots allows users to travel through
time while debugging.  We’re using very simple code for demonstration
purposes, but we believe that this feature will make debugging real
programs, with complex logic and state, much more feasible.&lt;/p&gt;&lt;p&gt;So, what we’re missing is some code to enforce a lower bound on the HP
value.  Let’s update our character constructor to fix that issue
(exiting the nested REPLs and getting back to the top-level Guile
prompt):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,quit&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,quit&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;^character&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;_bcom&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;max-hp&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; HP is reduced when the character is attacked, so we use a cell
&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;;; actor to store a counter that can be modified.
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^cell&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;max-hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;methods&lt;/span&gt;
     &lt;span class=&quot;syntax-comment&quot;&gt;;; Getters
&lt;/span&gt;     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-comment&quot;&gt;;; Deal combat damage
&lt;/span&gt;     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;damage&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-comment&quot;&gt;;; HP can't go below 0.
&lt;/span&gt;      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;max&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;; attacks always hit
&lt;/span&gt;     &lt;span class=&quot;syntax-comment&quot;&gt;;; Check if character is dead
&lt;/span&gt;     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;dead?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;zero?&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A call to &lt;code&gt;max&lt;/code&gt; has been added to the &lt;code&gt;damage&lt;/code&gt; method to ensure that
zero is the lowest HP value.  All that’s left to do now is rebuild the
actors and verify the fix:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;alice&lt;/span&gt;
                       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;with-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;p-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;basilisk&lt;/span&gt;
                       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;with-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;m-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Basilisk&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dungeon&lt;/span&gt;
                       &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;with-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;c-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^dungeon&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;alice&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;basilisk&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,enter-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;c-vat&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;Entering&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'Cave'.&lt;/span&gt;  &lt;span class=&quot;syntax-symbol&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;',q'&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;exit.&lt;/span&gt;  &lt;span class=&quot;syntax-symbol&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;',help&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;goblins'&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;help.&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;goblins/Cave@&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guile-user&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,vat-resolve&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dungeon&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'player-turn&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice deals 30 damage to Basilisk!&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Basilisk has been defeated!&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We see the &lt;code&gt;Basilisk has been defeated&lt;/code&gt; message now.  Problem solved!&lt;/p&gt;&lt;p&gt;We hope this small demo has given you a taste of the exciting things
to come in the next Guile Goblins release.  If you want to use these
tools &lt;em&gt;right now&lt;/em&gt;, all the code used for this demo is available in the
&lt;code&gt;main&lt;/code&gt; branch of the &lt;a href=&quot;https://gitlab.com/spritely/guile-goblins&quot;&gt;Goblins Git
repository&lt;/a&gt;.  While it is
already quite useful, right now the debugger only supports multiple
vats in a &lt;em&gt;single&lt;/em&gt; Guile process.  In the near future, we plan to add
network debugging via CapTP.  We’d also like to take this opportunity
to give credit to &lt;a href=&quot;http://www.erights.org/elang/tools/causeway/index.html&quot;&gt;E’s Causeway
debugger&lt;/a&gt; as a
significant source of inspiration and prior art that was crucial for
this work.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;If you'd like to try this yourself, here's the cut-and-paste text you can use...&lt;/p&gt;&lt;pre&gt;&lt;code&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;,use&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;syntax-symbol&quot;&gt;,use&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;actor-lib&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;syntax-symbol&quot;&gt;,use&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;actor-lib&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;let-on&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;syntax-symbol&quot;&gt;,use&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;goblins&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;actor-lib&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;methods&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

 &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;p-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn-vat&lt;/span&gt; &lt;span class=&quot;syntax-keyword&quot;&gt;#:name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'Player&lt;/span&gt;  &lt;span class=&quot;syntax-keyword&quot;&gt;#:log?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;m-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn-vat&lt;/span&gt; &lt;span class=&quot;syntax-keyword&quot;&gt;#:name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'Monster&lt;/span&gt; &lt;span class=&quot;syntax-keyword&quot;&gt;#:log?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;c-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn-vat&lt;/span&gt; &lt;span class=&quot;syntax-keyword&quot;&gt;#:name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'Cave&lt;/span&gt;    &lt;span class=&quot;syntax-keyword&quot;&gt;#:log?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;^character&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;_bcom&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;max-hp&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; HP is reduced when the character is attacked, so we use a cell
&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;;; actor to store a counter that can be modified.
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^cell&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;max-hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;methods&lt;/span&gt;
     &lt;span class=&quot;syntax-comment&quot;&gt;;; Getters
&lt;/span&gt;     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-comment&quot;&gt;;; Deal combat damage
&lt;/span&gt;     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;damage&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;; attacks always hit
&lt;/span&gt;     &lt;span class=&quot;syntax-comment&quot;&gt;;; Check if character is dead
&lt;/span&gt;     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;dead?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;zero?&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;^dungeon&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;_bcom&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;player&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;monster&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;methods&lt;/span&gt;
   &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;player-turn&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;let-on&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;player-name&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;player&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;monster-name&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;monster&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;player&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-comment&quot;&gt;;; Deal damage to the monster and check to see if it's dead.
&lt;/span&gt;      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;let*-on&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;hit?&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;monster&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'damage&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;dead?&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;monster&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'dead?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;damage-msg&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;~a deals ~a damage to ~a!&amp;quot;&lt;/span&gt;
                                  &lt;span class=&quot;syntax-symbol&quot;&gt;player-name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;monster-name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-comment&quot;&gt;;; Log a message if the monster is dead.
&lt;/span&gt;          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dead?&lt;/span&gt;
              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;dead-msg&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;~a has been defeated!&amp;quot;&lt;/span&gt;
                                      &lt;span class=&quot;syntax-symbol&quot;&gt;monster-name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;damage-msg&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dead-msg&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;damage-msg&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

 &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;alice&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;with-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;p-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;basilisk&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;with-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;m-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Basilisk&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dungeon&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;with-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;c-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^dungeon&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;alice&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;basilisk&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,enter-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;c-vat&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-resolve&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dungeon&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'player-turn&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-tail&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-tree&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;45&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-graph&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;45&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-debug&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;45&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-trace&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-up&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-down&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-jump&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;31&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-down&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-peek&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;basilisk&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'hp&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-jump&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;22&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-down&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-peek&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;basilisk&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'hp&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-down&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-peek&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;basilisk&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'hp&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,quit&lt;/span&gt;
&lt;span class=&quot;syntax-symbol&quot;&gt;,quit&lt;/span&gt;
&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;^character&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;_bcom&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;max-hp&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; HP is reduced when the character is attacked, so we use a cell
&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;;; actor to store a counter that can be modified.
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^cell&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;max-hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;methods&lt;/span&gt;
     &lt;span class=&quot;syntax-comment&quot;&gt;;; Getters
&lt;/span&gt;     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;syntax-comment&quot;&gt;;; Deal combat damage
&lt;/span&gt;     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;damage&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-comment&quot;&gt;;; HP can't go below 0.
&lt;/span&gt;      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;max&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;; attacks always hit
&lt;/span&gt;     &lt;span class=&quot;syntax-comment&quot;&gt;;; Check if character is dead
&lt;/span&gt;     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;dead?&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;zero?&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;hp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;


 &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;alice&lt;/span&gt;     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;with-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;p-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Alice&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;basilisk&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;with-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;m-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^character&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Basilisk&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dungeon&lt;/span&gt;   &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;with-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;c-vat&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;^dungeon&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;alice&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;basilisk&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,enter-vat&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;c-vat&lt;/span&gt;

&lt;span class=&quot;syntax-symbol&quot;&gt;,vat-resolve&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;dungeon&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'player-turn&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</summary></entry></feed>