hoot.texi 78 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687
  1. \input texinfo @c -*- texinfo -*-
  2. @c %**start of header
  3. @setfilename hoot.info
  4. @settitle Guile Hoot
  5. @documentencoding UTF-8
  6. @documentlanguage en
  7. @syncodeindex pg cp
  8. @c %**end of header
  9. @dircategory The Algorithmic Language Scheme
  10. @direntry
  11. * Hoot: (hoot). Scheme to Wasm compiler backend for Guile and Wasm toolchain.
  12. @end direntry
  13. @finalout
  14. @titlepage
  15. @title Guile Hoot
  16. @author David Thompson (@email{dave@@spritely.institute})
  17. @author The Spritely Institute
  18. @end titlepage
  19. @contents
  20. @ifnottex
  21. @node Top
  22. @top Guile Hoot
  23. This is the manual for Guile Hoot, a Scheme to WebAssembly compiler
  24. backend for @url{https://gnu.org/software/guile,GNU Guile} and general
  25. purpose Wasm toolchain.
  26. Both this manual and Guile Hoot itself are released under Apache v2.
  27. See @ref{License} for more information.
  28. @end ifnottex
  29. @menu
  30. * Introduction:: What's the deal with Wasm, anyway?
  31. * Compiling to Wasm:: Using the compiler and development tools.
  32. * Web deployment:: Scheme in the browser!
  33. * Scheme reference:: Hoot-specific Scheme extensions.
  34. * Toolchain reference:: General purpose Wasm tools.
  35. * Contributing:: Lend a hand!
  36. * License:: Copying, distributing, and using this text.
  37. * Index::
  38. @end menu
  39. @node Introduction
  40. @chapter Introduction
  41. Guile Hoot is a Scheme to WebAssembly (henceforth referred to as
  42. @emph{Wasm}) compiler backend for
  43. @url{https://gnu.org/software/guile,GNU Guile} and a general purpose
  44. Wasm toolchain. Wasm is an abstract but low-level binary compilation
  45. target that can run on all major web browsers, and increasingly in
  46. other, more ``native'' contexts, as well. For over two decades,
  47. JavaScript has been @emph{the} official language of the web, and while
  48. the language has improved a lot over the years, its design leaves much
  49. to be desired. Thus web developers looked for ways to bring their
  50. preferred language to the browser to use instead. In the past, the
  51. only option available was to @emph{compile that language to
  52. JavaScript!} This approach worked in some sense but it was unideal
  53. because many languages do not map cleanly to JavaScript. In the case
  54. of Scheme, for example, the lack of a tail call facility makes
  55. compiling tail-recursive Scheme code unpleasant. At long last, thanks
  56. to Wasm, it has become possible to use an alternative language with
  57. fewer compromises and better performance. Hoot aims to bring Guile's
  58. ``whole self'' to the web, as well as to other Wasm GC runtimes.
  59. Hoot is being developed by the
  60. @url{https://spritely.institute,Spritely Institute} in collaboration
  61. with @url{https://www.igalia.com/,Igalia} to advance Spritely's
  62. mission to build the infrastructure for a completely decentralized
  63. social Internet. And for that mission, what better platform to target
  64. than the web browser?
  65. @url{https://spritely.institute/goblins/,Goblins}, Spritely's
  66. distributed object programming environment, is primarily written in
  67. Guile. So, to meet users where they are at @emph{and} not use
  68. JavaScript at the same time, Spritely needs a Guile to Wasm compiler!
  69. A secondary goal of Hoot is to advocate for all dynamic programming
  70. languages' (Python, Ruby, etc.) rightful place on the client-side web.
  71. The Wasm 1.0 specification was not a habitable environment for
  72. languages that require a garbage collector. The Wasm GC proposal,
  73. among others, has made it possible for dynamic languages to target
  74. Wasm in a real way. However, such advances are not without their
  75. detractors. Without the necessary support, a useful proposal will
  76. never make it into the core specification. For example, strings are a
  77. particularly controversial subject in the WebAssembly Community Group
  78. and proposals that would greatly benefit Hoot and other languages have
  79. not reached consensus. Implementing and targeting emergent and useful
  80. Wasm proposals helps those proposals find their way into the core
  81. specification. A rising tide lifts all boats, as they say, and while
  82. we may be little schemers, we want our work to help advance the Wasm
  83. standard for all dynamic languages.
  84. @menu
  85. * Status:: What works. What doesn't.
  86. * Installation:: Setting up Hoot.
  87. * Tutorial:: Compiling your first Scheme program to Wasm.
  88. @end menu
  89. @node Status
  90. @section Status
  91. Hoot's Wasm output is compatible with Google Chrome starting with
  92. version 119 and Mozilla Firefox starting with version 121. As of
  93. writing, WebKit/Apple Safari is not yet compatible.
  94. Hoot is still in an early phase of active development and its API
  95. should be considered unstable and subject to change in future
  96. releases. Hoot currently supports a subset of the R7RS-small Scheme
  97. specification, along with a small set of Guile-specific functionality
  98. such as @inlinefmtifelse{html,
  99. @url{https://www.gnu.org/software/guile/manual/html_node/Prompts.html,
  100. prompts}, @ref{Prompts,,,Guile Reference}}.
  101. Missing R7RS-small features include:
  102. @enumerate
  103. @item Complex numbers (constants are supported, math procedures are not)
  104. @item Environments and evaluation (@code{environment}, @code{eval}, etc.)
  105. @end enumerate
  106. Future releases will add support for all of R7RS-small and eventually
  107. full Guile-flavored Scheme.
  108. To compile Scheme to Wasm, Hoot takes advantage of several new Wasm
  109. proposals. The most important of these new features are tail calls
  110. and GC reference types. The @code{return_call} family of instructions
  111. has made the implementation of Scheme's tail recursive procedure call
  112. semantics relatively straightforward. GC reference type instructions
  113. allow for heap allocated objects (and immediates via the @code{i31}
  114. type) that are managed by the Wasm runtime. This allows Hoot to take
  115. advantage of production garbage collectors already present in web
  116. browsers, obviating the need to implement and ship our own which would
  117. be both inferior to the host's and a major source of binary bloat.
  118. There's an additional Wasm proposal that Hoot has been built on that
  119. has, unfortunately, not found its way into the core Wasm
  120. specification: stringref. We still emit stringref, but it is reduced
  121. to being an intermediate form. A lowering pass replaces stringref
  122. instructions with something resembling the JS String Builtins
  123. proposal.
  124. @node Installation
  125. @section Installation
  126. The @emph{easiest} way to get up and running with Hoot is by using the
  127. @url{https://guix.gnu.org,GNU Guix} package manager for which we
  128. provide a @file{guix.scm} file ready for use with @command{guix
  129. shell}:
  130. @example
  131. cd guile-hoot/
  132. guix shell
  133. @end example
  134. @command{guix shell} will download/compile all required dependencies
  135. and start an interactive shell that is ready to use for building Hoot.
  136. To use Hoot without Guix requires building Guile from source. Hoot is
  137. currently undergoing a lot of development and requires a bleeding-edge
  138. Guile built against the @code{main} branch. Eventually Hoot will just
  139. require a stable release of Guile.
  140. With a sufficiently fresh Guile, via Guix or otherwise, the build can
  141. begin. If you are building from a Git checkout rather than an
  142. official release tarball, the first step is to bootstrap the build
  143. system:
  144. @example
  145. ./bootstrap.sh
  146. @end example
  147. Release tarballs have a pre-bootstrapped build system and do not
  148. require the above step.
  149. Now, build Hoot:
  150. @example
  151. ./configure
  152. make
  153. @end example
  154. If you'd like to install Hoot onto your system, run:
  155. @example
  156. sudo make install
  157. @end example
  158. The GNU build system defaults to @file{/usr/local} as the installation
  159. prefix. This can be changed by re-running the configure script:
  160. @example
  161. ./configure --prefix=/some/where/else
  162. sudo make install
  163. @end example
  164. To try out Hoot without installing it, use the @file{pre-inst-env}
  165. wrapper to launch Guile in the context of the Hoot build directory:
  166. @example
  167. ./pre-inst-env guile
  168. @end example
  169. If you installed Guile to your system, simply run @command{guile}.
  170. If everything went well, you will be greeted with a Guile REPL prompt.
  171. Regardless of installation status, to verify that Guile can find the
  172. Hoot modules, run:
  173. @lisp
  174. scheme@@(guile-user)> ,use (hoot compile)
  175. @end lisp
  176. If there is no error then congratulations! Your setup is correct.
  177. Proceed to the tutorial for a crash course in how to use Hoot, or see
  178. later chapters for an API reference.
  179. @subsection Running the test suite
  180. This is entirely optional, but if you'd like further verification that
  181. your build is good (or perhaps you're packaging Hoot for
  182. distribution), the test suite can be run via @command{make check}. By
  183. default, the tests are run against two Wasm runtimes: Hoot's own Wasm
  184. interpreter and @url{https://v8.dev/,V8} via the @command{d8} tool.
  185. Getting V8 can be tricky, and will most likely require you to
  186. @url{https://v8.dev/docs/build,compile it from source.} It's a pain!
  187. To skip all of that trouble and just run the tests against the
  188. built-in interpreter, run:
  189. @example
  190. make check Wasm_HOST=hoot
  191. @end example
  192. @node Tutorial
  193. @section Tutorial
  194. Let's compile some simple Scheme programs and learn how to work with
  195. their compiled Wasm forms.
  196. As we all know, the answer to everything is simply 42. So, we should
  197. make sure that we can compile 42 to Wasm. To do so, import the
  198. @code{(hoot compile)} module and call the @code{compile} procedure.
  199. @lisp
  200. @verbatim
  201. scheme@(guile-user)> ,use (hoot compile)
  202. scheme@(guile-user)> (define the-answer (compile 42))
  203. @end verbatim
  204. @end lisp
  205. The result is a Wasm module. There is a lot of stuff inside, but
  206. we're not going to focus on that right now. We should load and run
  207. the module to verify that it outputs 42 like we expect. We can do so
  208. from the comfort of our Guile REPL because Hoot includes a Wasm
  209. interpreter. There's no need to use a web browser or other Wasm
  210. runtime to try out small programs.
  211. First, import the @code{(hoot reflect)} module. Then, instantiate
  212. @code{the-answer} to load it into the Wasm interpreter:
  213. @lisp
  214. @verbatim
  215. scheme@(guile-user)> ,use (hoot reflect)
  216. scheme@(guile-user)> (define instance (hoot-instantiate the-answer))
  217. @end verbatim
  218. @end lisp
  219. All that's left to do now is execute the program with
  220. @code{hoot-load}:
  221. @lisp
  222. @verbatim
  223. scheme@(guile-user)> (hoot-load instance)
  224. $5 = 42
  225. @end verbatim
  226. @end lisp
  227. Ta-da! It feels kind of funny to compile a Scheme program to Wasm
  228. only to load it back into Scheme, but it's a quick and easy way to
  229. test things out.
  230. For cases when you simply want to compile an expression and see the
  231. result immediately, there is a faster method. Just use the
  232. @code{compile-value} procedure instead:
  233. @lisp
  234. @verbatim
  235. scheme@(guile-user)> (compile-value '(list 1 2 3))
  236. $6 = #<hoot (1 2 3)>
  237. @end verbatim
  238. @end lisp
  239. With @code{compile-value}, the compiled Wasm module is thrown away,
  240. which is just fine for testing throwaway code.
  241. Lists are cool and 42 is ultimately the answer to everything, but it
  242. would be a shame if we didn't talk about compiling something a little
  243. more complicated. Let's compile a simple, tail-recursive procedure!
  244. How about good ol' factorial?
  245. @lisp
  246. @verbatim
  247. scheme@(guile-user)> (define hoot-factorial
  248. (compile-value
  249. '(let ()
  250. (define (factorial x result)
  251. (if (= x 1)
  252. result
  253. (factorial (- x 1)
  254. (* result x))))
  255. factorial)))
  256. @end verbatim
  257. @end lisp
  258. A Hoot procedure can be called just like a regular procedure:
  259. @lisp
  260. @verbatim
  261. scheme@(guile-user)> (hoot-factorial 5 1)
  262. $7 = 120
  263. @end verbatim
  264. @end lisp
  265. The Hoot reflection in Guile is great for quickly iterating on code,
  266. but what we really want is to get our programs running in a web
  267. browser. We've compiled a couple of things to Wasm now, but the
  268. resulting modules have stayed within the confines of the Guile
  269. process. To make something that can be loaded by a web browser, we
  270. need to use the assembler to create a Wasm binary:
  271. @lisp
  272. @verbatim
  273. scheme@(guile-user)> (define hello (compile "Hello, world!"))
  274. scheme@(guile-user)> ,use (wasm assemble)
  275. scheme@(guile-user)> (define bin (assemble-wasm hello))
  276. @end verbatim
  277. @end lisp
  278. Now, create a new directory for this tutorial:
  279. @example
  280. mkdir hoot-tutorial
  281. @end example
  282. Write the binary to disk in that directory:
  283. @lisp
  284. @verbatim
  285. scheme@(guile-user)> ,use (ice-9 binary-ports)
  286. scheme@(guile-user)> (call-with-output-file "/path/to/hoot-tutorial/hello.wasm"
  287. (lambda (port)
  288. (put-bytevector port bin)))
  289. @end verbatim
  290. @end lisp
  291. To inspect Scheme values from JavaScript, Hoot provides the
  292. @file{js-runtime/reflect.js} library. Copy that file and its
  293. associated Wasm helper modules, @file{js-runtime/reflect.wasm} and
  294. @file{js-runtime/wtf8.wasm}, to the @file{hoot-tutorial} directory:
  295. @example
  296. cd /path/to/hoot-tutorial
  297. cp /path/to/guile-hoot/js-runtime/reflect.js .
  298. mkdir js-runtime
  299. cp /path/to/guile-hoot/js-runtime/reflect.wasm js-runtime/
  300. cp /path/to/guile-hoot/js-runtime/wtf8.wasm js-runtime/
  301. @end example
  302. To run @file{hello.wasm}, we need a little JavaScript glue code.
  303. Let's call this @file{hello.js}:
  304. @example
  305. @verbatim
  306. async function load() {
  307. const [message] = await Scheme.load_main("hello.wasm", {});
  308. console.log(message);
  309. }
  310. window.addEventListener("load", load);
  311. @end verbatim
  312. @end example
  313. We also need a minimal @file{index.html} web page to bring it all
  314. together:
  315. @example
  316. <!DOCTYPE html>
  317. <html>
  318. <head>
  319. <script type="text/javascript" src="reflect.js"></script>
  320. <script type="text/javascript" src="hello.js"></script>
  321. </head>
  322. <body>
  323. Guile is a hoot!
  324. </body>
  325. </html>
  326. @end example
  327. The file tree in @file{hoot-tutorial} should look like this:
  328. @example
  329. ./js-runtime
  330. ./js-runtime/wtf8.wasm
  331. ./js-runtime/reflect.wasm
  332. ./reflect.js
  333. ./hello.js
  334. ./index.html
  335. ./hello.wasm
  336. @end example
  337. Finally, we need a local web server to serve the files. Fortunately,
  338. Guile includes all the building blocks we need to make a minimal one
  339. for the purposes of this tutorial. Save the following to
  340. @file{web-server.scm}:
  341. @lisp
  342. (use-modules (ice-9 binary-ports) (ice-9 format) (ice-9 match)
  343. (web server) (web request) (web response) (web uri))
  344. (define (extension file)
  345. (match (string-split file #\.)
  346. (() #f)
  347. ((_ ... ext) ext)))
  348. (define (mime-type file-name)
  349. (or (assoc-ref '(("js" . application/javascript)
  350. ("html" . text/html)
  351. ("wasm" . application/wasm))
  352. (extension file-name))
  353. 'text/plain))
  354. (define (render-file file-name)
  355. (values `((content-type . (,(mime-type file-name))))
  356. (call-with-input-file file-name get-bytevector-all)))
  357. (define (not-found path)
  358. (values (build-response #:code 404) (string-append "Not found: " path)))
  359. (define (directory? file-name)
  360. (eq? (stat:type (stat file-name)) 'directory))
  361. (define (serve-file path)
  362. (let ((f (string-append (getcwd) (uri-decode path))))
  363. (if (and (file-exists? f) (not (directory? f)))
  364. (render-file f)
  365. (not-found path))))
  366. (define (handle-request request body)
  367. (let ((method (request-method request))
  368. (path (uri-path (request-uri request))))
  369. (format #t "~a ~a\n" method path)
  370. (serve-file path)))
  371. (run-server handle-request 'http '(#:port 8080))
  372. @end lisp
  373. Start the web server like so:
  374. @example
  375. guile web-server.scm
  376. @end example
  377. Visit @url{http://localhost:8080/index.html} in your web browser, and
  378. if it is new enough to have Wasm GC enabled, you should see the text
  379. ``Hello, world!'' printed in the developer console.
  380. We hope this tutorial has helped you get started with Hoot! Read on
  381. for full API documentation.
  382. @node Compiling to Wasm
  383. @chapter Compiling to Wasm
  384. @menu
  385. * Invoking the compiler:: Compiling a Hoot module.
  386. * High-level development tools:: Using Hoot modules from the host environment.
  387. * Low-level development tools:: Inspecting and debugging Wasm.
  388. @end menu
  389. @node Invoking the compiler
  390. @section Invoking the compiler
  391. In Guile's compiler tower, Scheme code goes through several
  392. transformations before being compiled to VM bytecode. Scheme is
  393. lowered to @ref{Tree-IL,,,Guile Reference}, which is then lowered to
  394. @ref{Continuation Passing Style,,,Guile Reference}(CPS), and then
  395. finally to @ref{Bytecode,,,Guile Reference}. Hoot adds an additional
  396. backend that compiles CPS to Wasm.
  397. Currently, Hoot does not use Guile's module system and instead peforms
  398. whole program compilation using a prelude that provides R7RS-small
  399. features (and also some Guile ones, like prompts.) Support for
  400. modules will be added in a future release.
  401. For hooking the Hoot compiler up to a build system such as GNU Make,
  402. invoke the @command{guild compile-wasm} tool:
  403. @example
  404. guild compile-wasm -o foo.wasm foo.scm
  405. @end example
  406. When writing Scheme intended to be compiled to the Wasm target, a
  407. special form called @code{%inline-wasm} is available for implementing
  408. a section of code in WAT rather than Scheme. For example, here's how
  409. @code{port?} is implemented:
  410. @lisp
  411. (define (port? x)
  412. (%inline-wasm '(func (param $obj (ref eq))
  413. (result (ref eq))
  414. (if (ref eq)
  415. (ref.test $port (local.get $obj))
  416. (then (ref.i31 (i32.const 17)))
  417. (else (ref.i31 (i32.const 1)))))
  418. x))
  419. @end lisp
  420. An inline Wasm form specifies a single function using WAT expressions
  421. whose parameters and result types are all @code{(ref eq)}, as well as
  422. the Scheme variables that map to the parameters. The compiler then
  423. transforms and splices the function body into the procedure.
  424. Like Guile's built-in compiler, the Hoot compiler can also be invoked
  425. within Scheme. The @code{(hoot compile)} module provides the
  426. interface to the Wasm compiler backend.
  427. @deffn {Procedure} compile exp [#:import-abi? #f] [#:export-abi? #t] @
  428. [#:from (current-language)] @
  429. [#:imports %default-program-imports] @
  430. [#:optimization-level (default-optimization-level)] @
  431. [#:warning-level (default-warning-level)] @
  432. [#:dump-cps? #f] [#:dump-wasm? #f] [#:emit-names? #f] @
  433. [#:opts '()]
  434. Compile the Scheme expression @var{exp} to Wasm and return a Wasm
  435. module.
  436. The environment in which @var{exp} is evaluated is defined by
  437. @var{imports}, a list of module names such as @code{(scheme time)} or
  438. @code{(hoot ffi)}.
  439. When @var{import-abi?} is @code{#t}, the Wasm module will be built
  440. such that it needs to import its ABI from another module. When
  441. @var{export-abi?} is @code{#t}, the Wasm module will be built such
  442. that it exports its ABI functions. A typical use of these flags is to
  443. export the ABI from one ``main'' module and then import that ABI into
  444. any additional modules that are being used.
  445. When @var{emit-names?} is @code{#t} then human-readable names will be
  446. embedded in the resulting Wasm object. By default, this is turned off
  447. as it greatly increases binary size.
  448. @xref{Compiling Scheme Code,,,Guile Reference} for more information
  449. about invoking Guile's compiler.
  450. @end deffn
  451. @deffn {Procedure} read-and-compile port [#:import-abi? #f] [#:export-abi? #t] @
  452. [#:from (current-language)] @
  453. [#:optimization-level (default-optimization-level)] @
  454. [#:warning-level (default-warning-level)] @
  455. [#:dump-cps? #f] [#:dump-wasm? #f] [#:emit-names? #f] @
  456. [#:opts '()]
  457. Like @code{compile}, but read Scheme expressions from @var{port}.
  458. If the first expression is an @code{import} form, then only the
  459. bindings from those modules will be imported into the compilation
  460. unit. If the @code{import} form is omitted, a default set of modules
  461. will be imported. It is highly recommended to be explicit and use
  462. @code{import}.
  463. @end deffn
  464. @deffn {Procedure} compile-file input-file [#:import-abi? #f] @
  465. [#:export-abi? #t] @
  466. [#:from (current-language)] @
  467. [#:optimization-level (default-optimization-level)] @
  468. [#:warning-level (default-warning-level)] @
  469. [#:dump-cps? #f] [#:dump-wasm? #f] [#:emit-names? #f] @
  470. [#:opts '()]
  471. Like @code{read-and-compile}, but read the Scheme expression from
  472. @var{input-file}.
  473. @end deffn
  474. @node High-level development tools
  475. @section High-level development tools
  476. The @code{(hoot reflect)} module provides an interface for inspecting
  477. and manipulating Scheme values that live within Wasm modules. This is
  478. the primary interface for testing compiler output directly from Guile.
  479. @deffn {Procedure} hoot-instantiate scheme-wasm [imports '()] [reflector]
  480. Instantiate and return a new Hoot module using the compiled Scheme
  481. Wasm module @var{scheme-wasm} and the reflection module
  482. @var{reflector}. If @var{reflector} is not specified, a new reflector
  483. instance will be created.
  484. Optionally, @var{imports} may contain a 2-tier association list
  485. structure of imported functions, globals, tables, and memories:
  486. @lisp
  487. `(("math" . (("random" . ,(lambda (x) (random x))))))
  488. @end lisp
  489. @end deffn
  490. @deffn {Procedure} hoot-load module
  491. Invoke the load thunk of @var{module} and return the reflected
  492. result values.
  493. @end deffn
  494. @deffn {Procedure} compile-value exp [imports '()]
  495. Compile @var{exp} and return the result.
  496. Optionally, @var{imports} may contain a 2-tier association list
  497. structure of imported functions, globals, tables, and memories. See
  498. @code{hoot-instantiate} for an example of such a structure.
  499. @end deffn
  500. @deffn {Procedure} compile-call proc-exp arg-exps ...
  501. Compile @var{proc-exp} and all @var{arg-exps}, call the procedure with
  502. the arguments, then return the results.
  503. @end deffn
  504. @deffn {Procedure} hoot-module? obj
  505. Return @code{#t} if @var{obj} is a Hoot module.
  506. @end deffn
  507. @deffn {Procedure} hoot-module-reflector module
  508. Return the reflection module for @var{module}.
  509. @end deffn
  510. @deffn {Procedure} hoot-module-instance module
  511. Return the Wasm instance for @var{module}.
  512. @end deffn
  513. @deffn {Procedure} reflector? obj
  514. Return @code{#t} if @var{obj} is a reflector.
  515. @end deffn
  516. @deffn {Procedure} reflector-instance reflector
  517. Return the Wasm instance of @var{reflector}.
  518. @end deffn
  519. @deffn {Procedure} reflector-abi reflector
  520. Return the association list of ABI imports for @var{reflector}.
  521. @end deffn
  522. @deffn {Procedure} hoot-object? obj
  523. Return @code{#t} if @var{obj} is a Hoot object.
  524. @end deffn
  525. @deffn {Procedure} hoot-complex? obj
  526. Return @code{#t} if @var{obj} is a Hoot complex number.
  527. @end deffn
  528. @deffn {Procedure} hoot-complex-real complex
  529. Return the real part of @var{complex}.
  530. @end deffn
  531. @deffn {Procedure} hoot-complex-imag complex
  532. Return the imaginary part of @var{complex}.
  533. @end deffn
  534. @deffn {Procedure} hoot-fraction? obj
  535. Return @code{#t} if @var{obj} is a Hoot fraction.
  536. @end deffn
  537. @deffn {Procedure} hoot-fraction-num fraction
  538. Return the numerator of @var{fraction}
  539. @end deffn
  540. @deffn {Procedure} hoot-fraction-denom fraction
  541. Return the denominator of @var{fraction}.
  542. @end deffn
  543. @deffn {Procedure} hoot-pair? obj
  544. Return @code{#t} if @var{obj} is a Hoot pair.
  545. @end deffn
  546. @deffn {Procedure} mutable-hoot-pair? obj
  547. Return @code{#t} if @var{obj} is a mutable Hoot pair.
  548. @end deffn
  549. @deffn {Procedure} hoot-pair-car pair
  550. Return the first element of @var{pair}.
  551. @end deffn
  552. @deffn {Procedure} hoot-pair-cdr pair
  553. Return the second element of @var{pair}.
  554. @end deffn
  555. @deffn {Procedure} hoot-vector? obj
  556. Return @code{#t} if @var{obj} is a Hoot vector.
  557. @end deffn
  558. @deffn {Procedure} mutable-hoot-vector? obj
  559. Return @code{#t} if @var{obj} is a mutable Hoot vector.
  560. @end deffn
  561. @deffn {Procedure} hoot-vector-length vec
  562. Return the length of @var{vec}.
  563. @end deffn
  564. @deffn {Procedure} hoot-vector-ref vec i
  565. Return the @var{i}th element of @var{vec}.
  566. @end deffn
  567. @deffn {Procedure} hoot-bytevector? obj
  568. Return @code{#t} if @var{obj} is a Hoot bytevector.
  569. @end deffn
  570. @deffn {Procedure} mutable-hoot-bytevector? obj
  571. Return @code{#t} if @var{obj} is a mutable Hoot bytevector.
  572. @end deffn
  573. @deffn {Procedure} hoot-bytevector-length bv
  574. Return the length of @var{bv}.
  575. @end deffn
  576. @deffn {Procedure} hoot-bytevector-ref bv i
  577. Return the @var{i}th byte of @var{bv}.
  578. @end deffn
  579. @deffn {Procedure} hoot-bitvector? obj
  580. Return @code{#t} if @var{obj} is a Hoot bitvector.
  581. @end deffn
  582. @deffn {Procedure} mutable-hoot-bitvector? obj
  583. Return @code{#t} if @var{obj} is a mutable Hoot bitvector.
  584. @end deffn
  585. @deffn {Procedure} hoot-bitvector-length bv
  586. Return the length of @var{bv}.
  587. @end deffn
  588. @deffn {Procedure} hoot-bitvector-ref bv i
  589. Return the @var{i}th bit of @var{bv}.
  590. @end deffn
  591. @deffn {Procedure} hoot-symbol? obj
  592. Return @code{#t} if @var{obj} is a Hoot symbol.
  593. @end deffn
  594. @deffn {Procedure} hoot-symbol-name sym
  595. Return the string name of @var{sym}.
  596. @end deffn
  597. @deffn {Procedure} hoot-keyword? obj
  598. Return @code{#t} if @var{obj} is a Hoot keyword.
  599. @end deffn
  600. @deffn {Procedure} hoot-keyword-name keyword
  601. Return the name string of @var{keyword}.
  602. @end deffn
  603. @deffn {Procedure} mutable-hoot-string? obj
  604. Return @code{#t} if @var{obj} is a mutable Hoot string.
  605. @end deffn
  606. @deffn {Procedure} mutable-hoot-string->string str
  607. Return the underlying string for @var{str}.
  608. @end deffn
  609. @deffn {Procedure} hoot-procedure? obj
  610. Return @code{#t} if @var{obj} is a Hoot procedure.
  611. @end deffn
  612. @deffn {Procedure} hoot-variable? obj
  613. Return @code{#t} if @var{obj} is a Hoot variable.
  614. @end deffn
  615. @deffn {Procedure} hoot-atomic-box? obj
  616. Return @code{#t} if @var{obj} is a Hoot atomic box.
  617. @end deffn
  618. @deffn {Procedure} hoot-hash-table? obj
  619. Return @code{#t} if @var{obj} is a Hoot hash table.
  620. @end deffn
  621. @deffn {Procedure} hoot-weak-table? obj
  622. Return @code{#t} if @var{obj} is a Hoot weak table.
  623. @end deffn
  624. @deffn {Procedure} hoot-fluid? obj
  625. Return @code{#t} if @var{obj} is a Hoot fluid.
  626. @end deffn
  627. @deffn {Procedure} hoot-dynamic-state? obj
  628. Return @code{#t} if @var{obj} is a Hoot dynamic state.
  629. @end deffn
  630. @deffn {Procedure} hoot-syntax? obj
  631. Return @code{#t} if @var{obj} is a Hoot syntax object.
  632. @end deffn
  633. @deffn {Procedure} hoot-port? obj
  634. Return @code{#t} if @var{obj} is a Hoot port.
  635. @end deffn
  636. @deffn {Procedure} hoot-struct? obj
  637. Return @code{#t} if @var{obj} is a Hoot struct.
  638. @end deffn
  639. @node Low-level development tools
  640. @section Low-level development tools
  641. The @code{(hoot repl)} module provides a set of REPL commands to
  642. assist with inspecting and debugging Wasm modules. As a matter of
  643. course, Hoot's Scheme compiler @emph{should not} cause low-level Wasm
  644. runtime errors, but when it does, or when working with the Wasm
  645. toolchain directly, these REPL tools may provide some assistance.
  646. To install the REPL commands, simply import the module:
  647. @lisp
  648. scheme@@(guile-user)> ,use (hoot repl)
  649. @end lisp
  650. To see a list of all the Wasm commands, run:
  651. @lisp
  652. scheme@@(guile-user)> ,help wasm
  653. @end lisp
  654. To demonstrate the debugging features, let's create a trivial module
  655. with a buggy function:
  656. @lisp
  657. @verbatim
  658. scheme@(guile-user)> (define src
  659. '(module
  660. (func (export "main") (param $x i32) (result i32)
  661. (i32.add (local.get $x)
  662. (unreachable)))))
  663. @end verbatim
  664. @end lisp
  665. When called, this function will hit the @code{unreachable} instruction
  666. and throw a runtime error. Let's compile the WAT source, load it into
  667. the VM, and get a reference to the @code{main} function:
  668. @lisp
  669. @verbatim
  670. scheme@(guile-user)> ,use (wasm resolve) (wasm vm) (wasm wat)
  671. scheme@(guile-user)> (define wasm (validate-wasm (resolve-wasm (wat->wasm src))))
  672. scheme@(guile-user)> (define instance (instantiate-wasm wasm))
  673. scheme@(guile-user)> (define main (wasm-instance-export-ref instance "main"))
  674. @end verbatim
  675. @end lisp
  676. To trap the Wasm runtime error and open a Wasm debugging REPL, the
  677. @command{wasm-catch} REPL command can be prefixed before an
  678. expression:
  679. @lisp
  680. @verbatim
  681. scheme@(guile-user)> ,wasm-catch (main 7)
  682. ice-9/boot-9.scm:1674:22: In procedure raise-exception:
  683. ERROR:
  684. 1. &wasm-runtime-error:
  685. instruction: (unreachable)
  686. position: (func 0 1)
  687. instance: #<wasm-instance 140506559041920>
  688. stack: #<<wasm-stack> items: (7)>
  689. blocks: ((wasm-block))
  690. locals: #(7)
  691. 2. &message: "Wasm runtime error: unreachable"
  692. 3. &irritants: ()
  693. Entering Wasm debug prompt. Type `,help wasm' for info or `,q' to continue.
  694. scheme@(guile-user) [1]>
  695. @end verbatim
  696. @end lisp
  697. Once in a Wasm debug context, many of the other REPL commands become
  698. usable. To highlight the instruction where execution has paused, use
  699. @command{wasm-pos}:
  700. @lisp
  701. @verbatim
  702. scheme@(guile-user) [1]> ,wasm-pos
  703. (func 0 (param $x i32) (result i32)
  704. (local.get 0)
  705. <<< (unreachable) >>>
  706. (i32.add))
  707. @end verbatim
  708. @end lisp
  709. To print the contents of the values stack, use @command{wasm-stack}:
  710. @lisp
  711. @verbatim
  712. scheme@(guile-user) [1]> ,wasm-stack
  713. Value stack:
  714. 0: 7
  715. @end verbatim
  716. @end lisp
  717. To print the contents of the function locals, use @command{wasm-locals}:
  718. @lisp
  719. @verbatim
  720. scheme@(guile-user) [1]> ,wasm-locals
  721. Locals:
  722. 0: 7
  723. @end verbatim
  724. @end lisp
  725. To evaluate arbitary Wasm instructions in the current context, either
  726. in an attempt to repair interpreter state or just for fun, use
  727. @command{wasm-eval}:
  728. @lisp
  729. @verbatim
  730. scheme@(guile-user) [1]> ,wasm-eval '(local.get 0)
  731. scheme@(guile-user) [1]> ,wasm-stack
  732. Value stack:
  733. 0: 7
  734. 1: 7
  735. @end verbatim
  736. @end lisp
  737. There are now two i32 values on the stack. If we were to proceed with
  738. execution, the next instruction, @code{i32.add}, should add them
  739. together and return a result of 14. To resume execution, use
  740. @command{wasm-continue}:
  741. @lisp
  742. @verbatim
  743. scheme@(guile-user) [1]> ,wasm-continue
  744. $5 = 14
  745. @end verbatim
  746. @end lisp
  747. Evaluating arbitrary Wasm commands in a debugging context is very
  748. helpful when trying to understand the nature of a bug, but bear in
  749. mind that cursed things may happen during the process as there is no
  750. validation applied. This goes especially for when you try to resume
  751. execution.
  752. See @ref{Interpreter} for detailed information on running Wasm within
  753. Guile and @ref{Toolchain reference} in general for working with Wasm
  754. directly.
  755. @deffn {REPL Command} wasm-trace exp
  756. Evaluate @var{exp} with verbose Wasm tracing enabled. This will print
  757. out every instruction along with the state of the value stack and
  758. function locals at the time of evaluation.
  759. @end deffn
  760. @deffn {REPL Command} wasm-freq exp
  761. Evaluate @var{exp} and print out a table showing how many times each
  762. kind of Wasm instruction was executed as well as a total instruction
  763. count.
  764. @end deffn
  765. @deffn {REPL Command} wasm-catch exp
  766. Catch and debug Wasm runtime errors that are raised by evaluating
  767. @var{exp}.
  768. @end deffn
  769. The following commands are usable only in the context of a Wasm debug
  770. REPL:
  771. @deffn {REPL Command} wasm-stack
  772. Print the state of the Wasm stack.
  773. @end deffn
  774. @deffn {REPL Command} wasm-locals
  775. Print the state of the Wasm function locals.
  776. @end deffn
  777. @deffn {REPL Command} wasm-pos
  778. Print the current function disassembly and highlight the instruction
  779. where Wasm execution has paused.
  780. @end deffn
  781. @deffn {REPL Command} wasm-eval instr
  782. Evaluate the Wasm instruction @var{instr} in the current debug
  783. context. Use this when attempting to fix the state of the Wasm stack
  784. or locals before attempting to resume with @code{,wasm-continue}.
  785. @end deffn
  786. The following commands behave differently depending on if they are run
  787. within a Wasm debug REPL or not.
  788. @deffn {REPL Command} wasm-dump [wasm]
  789. Display information about @var{wasm}, or the current Wasm instance
  790. when debugging.
  791. @end deffn
  792. @deffn {REPL Command} wasm-continue
  793. When in a debugger, exit and resume Wasm execution. In the event that
  794. this is run after trapping a runtime error, your warranty is void and
  795. all bets are off! While it may be dangerous, this does allow one to
  796. manually fix the Wasm interpreter state manually with
  797. @code{,wasm-eval} and attempt to proceed, which can come in handy
  798. sometimes.
  799. When not in a debugger, set the Wasm execution mode to continue
  800. without interruption. In other words, deactive the instruction
  801. stepper if it is active.
  802. @end deffn
  803. @deffn {REPL Command} wasm-step
  804. When in a debugger, resume Wasm execution but pause before the next
  805. instruction is evaluated.
  806. When not in a debugger, set Wasm execution to pause before each
  807. instruction is evaluated.
  808. @end deffn
  809. @node Web deployment
  810. @chapter Web deployment
  811. On the client-side web, JavaScript is the host environment for Wasm
  812. modules and the
  813. @url{https://developer.mozilla.org/en-US/docs/WebAssembly,WebAssembly}
  814. API is used to load and run them. Hoot includes a JavaScript library,
  815. @file{reflect.js} that wraps the @code{WebAssembly} API and
  816. furthermore can inspect Scheme values and call Scheme procedures.
  817. This chapter documents deploying Hoot artifacts and using the
  818. reflection API to run Scheme in the browser.
  819. @menu
  820. * Web server setup:: Prepare a server to run Hoot programs.
  821. * JavaScript API reference:: JavaScript reflection interface.
  822. @end menu
  823. @node Web server setup
  824. @section Web server setup
  825. In order to run Hoot binaries in the browser, a web server needs to
  826. host a copy of the Hoot JavaScript runtime.
  827. The runtime files can be found in the
  828. @file{$prefix/share/guile-hoot/js-runtime} directory, where
  829. @code{$prefix} is the directory where Hoot was installed on your
  830. system. This is typically @file{/usr} or @file{/usr/local} on Linux
  831. distributions such as Debian, Ubuntu, Fedora, etc.
  832. Don't forget to upload the Wasm files for the Scheme programs, too!
  833. A bit of JavaScript code is needed to bootstrap a Scheme program using
  834. the @file{js-runtime/reflect.js} library. For example, here's an
  835. example @file{boot.js} file that runs the Scheme program
  836. @file{hello.wasm} and prints the return values:
  837. @example
  838. @verbatim
  839. window.addEventListener("load", async () => {
  840. const results = await Scheme.load_main("/hello.wasm", {});
  841. console.log(results);
  842. });
  843. @end verbatim
  844. @end example
  845. The @code{Scheme} namespace is defined in @file{reflect.js}.
  846. @xref{JavaScript API reference} for more information.
  847. To run @file{boot.js} on a web page, add @code{<script>} tags for it
  848. and @file{reflect.js}:
  849. @example
  850. <!DOCTYPE html>
  851. <html>
  852. <head>
  853. <script type="text/javascript" src="/js-runtime/reflect.js"></script>
  854. <script type="text/javascript" src="/boot.js"></script>
  855. </head>
  856. <body>
  857. <h1>Hello, Hoot!</h1>
  858. </body>
  859. </html>
  860. @end example
  861. @node JavaScript API reference
  862. @section JavaScript API reference
  863. The @code{Scheme} class is used to load a Hoot binary, start the
  864. program, and initialize reflection.
  865. @deftp {Class} Scheme
  866. A Scheme runtime environment.
  867. @end deftp
  868. @defop {Static method} Scheme load_main path abi [user_imports @code{@{@}}]
  869. Fetch and execute the Hoot Wasm binary at the URL @var{path} and
  870. return an array of Scheme values produced by the program.
  871. The @var{abi} parameter is for more advanced usage where multiple Hoot
  872. binaries share a single application binary interface (ABI). This
  873. should be set to @code{@{@}} when loading the first Scheme binary. It
  874. is better to use the @code{load_extension} method for subsequent
  875. binaries, though.
  876. The @var{user_imports} parameter is for providing concrete
  877. implementations of functions declared using the @ref{Foreign function
  878. interface}. It uses a two-tier nested object structure to map import
  879. names to the functions that implement them.
  880. For example, this Scheme code:
  881. @lisp
  882. (define-foreign make-text-node
  883. "document" "createTextNode"
  884. (ref string) -> (ref null extern))
  885. @end lisp
  886. Could be instantiated like so:
  887. @example
  888. @verbatim
  889. Scheme.load_main("hello.wasm", {}, {
  890. document: {
  891. createTextNode: Document.prototype.createTextNode.bind(document)
  892. }
  893. });
  894. @end verbatim
  895. @end example
  896. @end defop
  897. @defmethod Scheme load_extension path [user_imports @code{@{@}}]
  898. Fetch and load an additional Hoot binary at the URL @var{path} that
  899. shares the ABI of @code{this}. Optionally, a set of user-defined
  900. imported functions can be specified with the @var{user_imports}
  901. parameter.
  902. @end defmethod
  903. All of the fundamental Scheme types have an associated JavaScript
  904. class that can reflect their values. Calling the @code{repr} function
  905. on an instance of a reflected Scheme object will return a Scheme-like
  906. printing of the object.
  907. @example
  908. repr(pair) // => "(1 . 2)"
  909. @end example
  910. @deftp {Class} Char
  911. A Unicode character.
  912. @end deftp
  913. @deftp {Class} Eof
  914. End-of-file object.
  915. @end deftp
  916. @deftp {Class} Null
  917. The empty list.
  918. @end deftp
  919. @deftp {Class} Unspecified
  920. The unspecified value.
  921. @end deftp
  922. @deftp {Class} Complex real imag
  923. Complex number with real part @var{real} and imaginary part
  924. @var{imag}.
  925. @end deftp
  926. @deftp {Class} Fraction num denom
  927. An exact fraction with numerator @var{num} and denominator
  928. @var{denom}.
  929. @end deftp
  930. The @code{HeapObject} class is the parent class of all of the
  931. remaining Scheme types.
  932. @deftp {Class} HeapObject
  933. A Scheme heap object.
  934. @end deftp
  935. @defivar HeapObject reflector
  936. The reflector for @code{this}, an instance of the @code{Scheme} class.
  937. @end defivar
  938. The @code{reflector} property can be used in conjuction with the
  939. @code{load_extension} method to load additional Hoot binaries that
  940. share the same ABI.
  941. @example
  942. heapObject.reflector.load_extension("/helper.wasm")
  943. @end example
  944. @deftp {Class} Procedure
  945. A Scheme procedure.
  946. @end deftp
  947. Procedure instances can be invoked with the @code{call} method to
  948. perform a Javascript to Scheme function call.
  949. @defmethod Procedure call args@dots{}
  950. Call procedure with @var{args} and return an array of result values.
  951. @end defmethod
  952. @deftp {Class} Pair
  953. An immutable cons cell.
  954. @end deftp
  955. @deftp {Class} MutablePair
  956. A mutable cons cell.
  957. @end deftp
  958. @deftp {Class} Vector
  959. An immutable vector.
  960. @end deftp
  961. @deftp {Class} MutableVector
  962. A mutable vector.
  963. @end deftp
  964. @deftp {Class} Bytevector
  965. An immutable bytevector.
  966. @end deftp
  967. @deftp {Class} MutableBytevector
  968. A mutable bytevector.
  969. @end deftp
  970. @deftp {Class} Bitvector
  971. An immutable bitvector.
  972. @end deftp
  973. @deftp {Class} MutableBitvector
  974. A mutable bitvector.
  975. @end deftp
  976. @deftp {Class} MutableString
  977. A mutable string.
  978. @end deftp
  979. @deftp {Class} Sym
  980. A symbol.
  981. @end deftp
  982. @deftp {Class} Keyword
  983. A keyword.
  984. @end deftp
  985. @deftp {Class} Variable
  986. A mutable variable.
  987. @end deftp
  988. @deftp {Class} AtomicBox
  989. A mutable box with atomic updates.
  990. @end deftp
  991. @deftp {Class} HashTable
  992. A hash table.
  993. @end deftp
  994. @deftp {Class} WeakTable
  995. A weak key hash table.
  996. @end deftp
  997. @deftp {Class} Fluid
  998. A dynamic variable.
  999. @end deftp
  1000. @deftp {Class} DynamicState
  1001. A set of fluids.
  1002. @end deftp
  1003. @deftp {Class} Syntax
  1004. A syntax object.
  1005. @end deftp
  1006. @deftp {Class} Port
  1007. An I/O port.
  1008. @end deftp
  1009. @deftp {Class} Struct
  1010. A user-defined structure.
  1011. @end deftp
  1012. @node Scheme reference
  1013. @chapter Scheme reference
  1014. In addition to supporting standard Scheme and Guile-specific features,
  1015. Hoot includes some of its own Scheme extensions. This chapter
  1016. documents the APIs of these extensions.
  1017. @menu
  1018. * Hash tables:: Mutable key/value data structures.
  1019. * Foreign function interface:: Call host functions from Scheme.
  1020. @end menu
  1021. @node Hash tables
  1022. @section Hash tables
  1023. There are many mutable hashtable APIs amongst all the various Scheme
  1024. implementations, standards, and SRFIs. From our point of view, there
  1025. is no clear ``best'' hashtable API that has emerged, but we think the
  1026. R6RS interface is OK. Guile's own hashtable API has design issues
  1027. that are best left in the past. So, the @code{(hoot hashtables)}
  1028. module is R6RS-like.
  1029. Currently, this interface supports keys hashed by object identity
  1030. (@code{eq?}) only. The object equivalence (@code{eqv?}) and deep
  1031. object equality (@code{equal?}) hashing strategies are not yet
  1032. implemented.
  1033. @deffn {Procedure} make-eq-hashtable
  1034. Return a new, empty hash table.
  1035. @end deffn
  1036. @deffn {Procedure} hashtable? obj
  1037. Return @code{#t} if @var{obj}
  1038. @end deffn
  1039. @deffn {Procedure} hashtable-size hashtable
  1040. Return the number of key/value pairs in @var{hashtable}.
  1041. @end deffn
  1042. @deffn {Procedure} hashtable-ref hashtable key default
  1043. Return the value associated with @var{key} in @var{hashtable} or
  1044. @var{default} if there is no such association.
  1045. @end deffn
  1046. @deffn {Procedure} hashtable-set! hashtable key value
  1047. Modify @var{hashtable} to associate @var{key} with @var{value},
  1048. overwriting any previous association that may have existed.
  1049. @end deffn
  1050. @deffn {Procedure} hashtable-delete! hashtable key
  1051. Remove the association with @var{key} in @var{hashtable}, if one
  1052. exists.
  1053. @end deffn
  1054. @deffn {Procedure} hashtable-clear! hashtable
  1055. Remove all of the key/value associations in @var{hashtable}.
  1056. @end deffn
  1057. @deffn {Procedure} hashtable-contains? hashtable key
  1058. Return @code{#t} if @var{key} has an associated value in
  1059. @var{hashtable}.
  1060. @end deffn
  1061. @deffn {Procedure} hashtable-copy hashtable
  1062. Return a copy of @var{hashtable}.
  1063. @end deffn
  1064. @deffn {Procedure} hashtable-keys hashtable
  1065. Return a vector of keys in @var{hashtable}.
  1066. @end deffn
  1067. @deffn {Procedure} hashtable-entries hashtable
  1068. Return a vector of values in @var{hashtable}.
  1069. @end deffn
  1070. @deffn {Procedure} hashtable-for-each proc hashtable
  1071. For each key/value pair in @var{hashtable}, call @var{proc} with two
  1072. arguments: the key and the value.
  1073. @end deffn
  1074. Hoot also includes weak key hash tables that wrap those of the Wasm
  1075. host platform, such as the @code{WeakMap} JavaScript class on the web.
  1076. @deffn {Procedure} make-weak-key-hashtable
  1077. Return a new weak key hashtable.
  1078. @end deffn
  1079. @deffn {Procedure} weak-key-hashtable? obj
  1080. Return @code{#t} if @var{obj} is a weak key hashtable.
  1081. @end deffn
  1082. @deffn {Procedure} weak-key-hashtable-ref hashtable key [default #f]
  1083. Return the value associated with @var{key} in @var{hashtable} or
  1084. @var{default} if there is no such association.
  1085. @end deffn
  1086. @deffn {Procedure} weak-key-hashtable-set! hashtable key value
  1087. Modify @var{hashtable} to associate @var{key} with @var{value},
  1088. overwriting any previous association that may have existed.
  1089. @end deffn
  1090. @deffn {Procedure} weak-key-hashtable-delete! hashtable key
  1091. Remove the association with @var{key} in @var{hashtable}, if one
  1092. exists.
  1093. @end deffn
  1094. @node Foreign function interface
  1095. @section Foreign function interface
  1096. WebAssembly follows the capability security model, which means that
  1097. modules cannot do much on their own. Wasm modules are guests within a
  1098. host. They must be given capabilities by the host in order to
  1099. interact with the outside world. Modules request capabilities by
  1100. declaring imports, which the host then fills out with concrete
  1101. implementations at instantiation time. Hoot provides a foreign
  1102. function interface (FFI) in the @code{(hoot ffi)} module to embed
  1103. these import declarations within Scheme code.
  1104. The @code{define-foreign} form declares an import with a given type
  1105. signature (Wasm is statically typed) and defines a procedure for
  1106. calling it. The FFI takes care of converting Scheme values to Wasm
  1107. values and vice versa. For example, declaring an import for creating
  1108. text nodes in a web browser could look like this:
  1109. @lisp
  1110. (define-foreign make-text-node
  1111. "document" "createTextNode"
  1112. (ref string) -> (ref null extern))
  1113. @end lisp
  1114. In the above example, the procedure is bound to the variable
  1115. @code{make-text-node}. In the Wasm binary, this import is named
  1116. ``createTextNode'' and resides in the ``document'' namespace of the
  1117. import table. A Wasm host is expected to satisfy this import by
  1118. providing a function that accepts one argument, a string, and returns
  1119. an arbitary host value which may be null.
  1120. Note that declaring an import @emph{does not} do anything to bind that
  1121. import to an implementation on the host. The Wasm guest cannot grant
  1122. capabilities unto itself. Furthermore, the host could be any Wasm
  1123. runtime, so the actual implementation will vary. In the context of a
  1124. web browser, the JavaScript code that instantiates a module with this
  1125. import could look like this:
  1126. @example
  1127. @verbatim
  1128. Scheme.load_main("hello.wasm", {}, {
  1129. document: {
  1130. createTextNode: Document.prototype.createTextNode.bind(document)
  1131. }
  1132. });
  1133. @end verbatim
  1134. @end example
  1135. And here's what it might look like when using the Hoot interpreter:
  1136. @lisp
  1137. (use-modules (hoot reflect))
  1138. (hoot-instantiate (call-with-input-file "hello.wasm" parse-wasm)
  1139. `(("document" .
  1140. (("createTextNode" . ,(lambda (str) `(text ,str)))))))
  1141. @end lisp
  1142. Once defined, @code{make-text-node} can be called like any other
  1143. procedure:
  1144. @lisp
  1145. (define text-node (make-text-node "Hello, world!"))
  1146. @end lisp
  1147. Since the return type of @code{make-text-node} is @code{(ref null
  1148. extern}), the value of @code{text-node} is an @emph{external
  1149. reference}. To check if a value is an external reference, use the
  1150. @code{external?} predicate:
  1151. @lisp
  1152. (external? text-node) ; => #t
  1153. @end lisp
  1154. External references may be null, which could indicate failure, a cache
  1155. miss, etc. To check if an external value is null, use the
  1156. @code{external-null?} predicate:
  1157. @lisp
  1158. (if (external-null? text-node) 'yay 'uh-oh)
  1159. @end lisp
  1160. @deffn {Syntax} define-foreign scheme-name namespace import-name param-types ... -> result-type
  1161. Define @var{scheme-name}, a procedure wrapping the Wasm import
  1162. @var{import-name} in the namespace @var{namespace}.
  1163. The signature of the function is specified by @var{param-types} and
  1164. @var{result-type}, which are all Wasm types expressed in WAT form.
  1165. Valid parameter types are:
  1166. @itemize
  1167. @item i32: 32-bit integer
  1168. @item i64: 64-bit integer
  1169. @item f32: 32-bit float
  1170. @item f64: 64-bit float
  1171. @item (ref string): a string
  1172. @item (ref extern): a non-null external value
  1173. @item (ref null extern): a possible null external value
  1174. @item (ref eq): any Scheme value
  1175. @end itemize
  1176. Valid result types are:
  1177. @itemize
  1178. @item none: no return value
  1179. @item i32: 32-bit integer
  1180. @item i64: 64-bit integer
  1181. @item f32: 32-bit float
  1182. @item f64: 64-bit float
  1183. @item (ref string): a string
  1184. @item (ref extern): a non-null external value
  1185. @item (ref null extern): a possibly null external value
  1186. @item (ref eq): a Scheme value
  1187. @end itemize
  1188. @end deffn
  1189. @deffn {Procedure} external? obj
  1190. Return @code{#t} if @var{obj} is an external reference.
  1191. @end deffn
  1192. @deffn {Procedure} external-null? extern
  1193. Return @code{#t} if @var{extern} is null.
  1194. @end deffn
  1195. @deffn {Procedure} external-non-null? extern
  1196. Return @code{#t} if @var{extern} is not null.
  1197. @end deffn
  1198. @node Toolchain reference
  1199. @chapter Toolchain reference
  1200. Hoot is not just a Scheme to Wasm compiler. It's also a
  1201. self-contained and general purpose Wasm toolchain. Hoot does not use
  1202. binaryen, wabt, emscripten, etc. in order to assemble and disassemble
  1203. Wasm. The entire toolchain is implemented as a set of Scheme modules
  1204. that can be used to automate other Wasm targeted build workflows.
  1205. Since everything is implemented in one place, in a single language,
  1206. and because Guile encourages a REPL-driven development workflow, Hoot
  1207. makes a great platform for learning Wasm in a hands-on, interactive
  1208. way!
  1209. @menu
  1210. * Data types:: Core Wasm module data types.
  1211. * GWAT:: Guile-flavored WebAssembly Text format.
  1212. * Resolver:: Lower human-readable identifiers to index values.
  1213. * Linker:: Add a standard library to a Wasm module.
  1214. * Assembler:: Create Wasm binaries.
  1215. * Binary Parser:: Parse Wasm binaries.
  1216. * Printer:: Print the contents of a Wasm module.
  1217. * Interpreter:: Execute Wasm within Guile.
  1218. @end menu
  1219. @node Data types
  1220. @section Data types
  1221. The @code{(wasm types)} module contains all the core data types that
  1222. comprise a Wasm module.
  1223. @subsection Modules
  1224. The Wasm module type is the top type, incorporating values of all the
  1225. types that are to follow.
  1226. @deffn {Procedure} wasm? obj
  1227. Return @code{#t} if @var{obj} is a Wasm module.
  1228. @end deffn
  1229. @deffn {Procedure} wasm-id wasm
  1230. Return the symbolic ID of @var{wasm}.
  1231. @end deffn
  1232. @deffn {Procedure} wasm-types wasm
  1233. Return the list of types in @var{wasm}.
  1234. @end deffn
  1235. @deffn {Procedure} wasm-imports wasm
  1236. Return the list of imports in @var{wasm}.
  1237. @end deffn
  1238. @deffn {Procedure} wasm-funcs wasm
  1239. Return the list of functions in @var{wasm}.
  1240. @end deffn
  1241. @deffn {Procedure} wasm-tables wasm
  1242. Return the list of tables in @var{wasm}.
  1243. @end deffn
  1244. @deffn {Procedure} wasm-memories wasm
  1245. Return the list of memories in @var{wasm}.
  1246. @end deffn
  1247. @deffn {Procedure} wasm-globals wasm
  1248. Return the list of globals in @var{wasm}.
  1249. @end deffn
  1250. @deffn {Procedure} wasm-exports wasm
  1251. Return the list of exports in @var{wasm}.
  1252. @end deffn
  1253. @deffn {Procedure} wasm-elems wasm
  1254. Return the list of element segments in @var{wasm}.
  1255. @end deffn
  1256. @deffn {Procedure} wasm-datas wasm
  1257. Return the list of data segments in @var{wasm}.
  1258. @end deffn
  1259. @deffn {Procedure} wasm-tags wasm
  1260. Return the list of tags in @var{wasm}.
  1261. @end deffn
  1262. @deffn {Procedure} wasm-strings wasm
  1263. Return the list of strings in @var{wasm}.
  1264. @end deffn
  1265. @deffn {Procedure} wasm-custom wasm
  1266. Return the list of custom segments in @var{wasm}.
  1267. @end deffn
  1268. @deffn {Procedure} wasm-start wasm
  1269. Return the start function index for @var{wasm}.
  1270. @end deffn
  1271. @subsection Types
  1272. Wasm has four numeric types:
  1273. @enumerate
  1274. @item @code{i32}:
  1275. 32-bit integer (signed or unsigned)
  1276. @item @code{i64}:
  1277. 64-bit integer (signed or unsigned)
  1278. @item @code{f32}:
  1279. 32-bit single precision IEEE floating point number.
  1280. @item @code{f64}:
  1281. 64-bit double precision IEEE floating point number.
  1282. @end enumerate
  1283. There is also the @code{v128} vector type, but it is currently
  1284. unsupported.
  1285. Then there are a number of reference types that fall into 3
  1286. categories: function, external, and internal.
  1287. Function reference types:
  1288. @enumerate
  1289. @item @code{func}:
  1290. Function reference.
  1291. @item @code{nofunc}:
  1292. Bottom type for functions. No function is of type @code{nofunc}.
  1293. @end enumerate
  1294. External reference types:
  1295. @enumerate
  1296. @item @code{extern}:
  1297. External reference introduced by the host.
  1298. @item @code{noextern}:
  1299. Bottom type for external references. No external reference is of type
  1300. @code{noextern}.
  1301. @end enumerate
  1302. Internal reference types:
  1303. @enumerate
  1304. @item @code{any}:
  1305. The top type of all internal reference types.
  1306. @item @code{eq}:
  1307. Structural equivalence type. Subtype of @code{all}.
  1308. @item @code{i31}:
  1309. Used for immediate references (such as the empty list or fixnums in
  1310. Scheme.) Subtype of @code{eq}.
  1311. @item @code{array}:
  1312. Super type of all array types. Subtype of @code{eq}.
  1313. @item @code{struct}:
  1314. Super type of all struct types. Subtype of @code{eq}.
  1315. @item @code{none}:
  1316. The bottom type for internal references. No internal reference is of
  1317. type @code{none}.
  1318. @end enumerate
  1319. Of course, modules may specify their own compound types assembled from
  1320. these primitives.
  1321. The type hierarchy looks like this:
  1322. @verbatim
  1323. .-----. .-------. .---------.
  1324. .--------- | any | ------------. | func | | extern |
  1325. | `-----' | `-------' `---------'
  1326. ↓ ↓ ↓ ↓ ↓
  1327. .-----. .-----. .---------. .-----------. .-----------.
  1328. | i31 | | eq | | struct | | all funcs | | noextern |
  1329. `-----' `-----' `---------' `-----------' `-----------'
  1330. ↓ ↓ ↓
  1331. .-------------. .-------------. .---------.
  1332. | all arrays | | all structs | | nofunc |
  1333. `-------------' `-------------' `---------'
  1334. .-----.
  1335. | any |
  1336. `-----'
  1337. @end verbatim
  1338. A collection of type descriptor objects form a type table that
  1339. describes all non-primitive types used within a module. Type objects
  1340. associate an identifier with a function signature or reference type
  1341. descriptor.
  1342. @deffn {Procedure} type? obj
  1343. Return @code{#t} if @var{obj} is a type.
  1344. @end deffn
  1345. @deffn {Procedure} type-id type
  1346. Return the symbolic ID of @var{type}.
  1347. @end deffn
  1348. @deffn {Procedure} type-val type
  1349. Return the type descriptor of @var{type}.
  1350. @end deffn
  1351. Types may also be nested within recursive type groups that allow for
  1352. circular and self references to the types within the group. Types
  1353. @emph{not} within a group can be thought of as belonging to a group of
  1354. one.
  1355. @deffn {Procedure} rec-group? obj
  1356. Return @code{#t} if @var{obj} is a recursive type group.
  1357. @end deffn
  1358. @deffn {Procedure} rec-group-types rec-group
  1359. Return the types within @var{rec-group}.
  1360. @end deffn
  1361. Note that while each Wasm module contains a full inventory of its
  1362. types, structurally identical type groups across Wasm modules are
  1363. canonicalized at runtime and are considered to be identical
  1364. (@code{eq?} in Scheme terms.) This allows for passing references
  1365. between modules.
  1366. Type uses refer to function signatures and are used for specifying the
  1367. type of a @code{block}, @code{loop}, or @code{if} expression.
  1368. @deffn {Procedure} type-use? obj
  1369. Return @code{#t} if @var{obj} is a type use.
  1370. @end deffn
  1371. @deffn {Procedure} type-use-idx type-use
  1372. Return the type index of @var{type-use}.
  1373. @end deffn
  1374. @deffn {Procedure} type-use-sig type-use
  1375. Return the function signature of @var{type-use}.
  1376. @end deffn
  1377. @deffn {Procedure} ref-type? obj
  1378. Return @code{#t} if @var{obj} is a reference type.
  1379. @end deffn
  1380. @deffn {Procedure} ref-type-nullable? ref-type
  1381. Return @var{#t} if @var{ref-type} is nullable.
  1382. @end deffn
  1383. @deffn {Procedure} ref-type-heap-type ref-type
  1384. Return the heap type of @var{ref-type}.
  1385. @end deffn
  1386. As mentioned above, reference types support structural subtyping.
  1387. @deffn {Procedure} sub-type? obj
  1388. Return @code{#t} if @var{obj} is a sub type.
  1389. @end deffn
  1390. @deffn {Procedure} sub-type-final? sub-type
  1391. Return @code{#t} if @var{sub-type} is marked as final.
  1392. @end deffn
  1393. @deffn {Procedure} sub-type-supers sub-type
  1394. Return super types of @var{sub-type}.
  1395. @end deffn
  1396. @deffn {Procedure} sub-type-type sub-type
  1397. Return the concrete type descriptor of @var{sub-type}.
  1398. @end deffn
  1399. Compound types take the form of arrays and structs.
  1400. @deffn {Procedure} array-type? obj
  1401. Return @code{#t} if @var{obj} is an array type.
  1402. @end deffn
  1403. @deffn {Procedure} array-type-mutable? array-type
  1404. Return @code{#t} if @var{array-type} is mutable.
  1405. @end deffn
  1406. @deffn {Procedure} array-type-type array-type
  1407. Retun the element type descriptor of @var{array-type}.
  1408. @end deffn
  1409. @deffn {Procedure} struct-type? obj
  1410. Return @code{#t} if @var{obj} is a struct type.
  1411. @end deffn
  1412. @deffn {Procedure} struct-type-fields struct-type
  1413. Return the field descriptors of @var{struct-type}.
  1414. @end deffn
  1415. Struct types are composed of several fields.
  1416. @deffn {Procedure} field? obj
  1417. Return @code{#t} if @var{obj} is a struct field.
  1418. @end deffn
  1419. @deffn {Procedure} field-id field
  1420. Return the symbolic ID of @var{field}.
  1421. @end deffn
  1422. @deffn {Procedure} field-mutable? field
  1423. Return @code{#t} if @var{field} is mutable.
  1424. @end deffn
  1425. @deffn {Procedure} field-type field
  1426. Return the type descriptor of @var{field}.
  1427. @end deffn
  1428. Both arrays and struct fields allow for packed data using the special
  1429. @code{i8} and @code{i16} data types.
  1430. @subsection Globals
  1431. Wasm supports both mutable and immutable global variables.
  1432. @deffn {Procedure} global? obj
  1433. Return @code{#t} if @var{obj} is a global.
  1434. @end deffn
  1435. @deffn {Procedure} global-id global
  1436. Return the symbloc ID of @var{global}.
  1437. @end deffn
  1438. @deffn {Procedure} global-type global
  1439. Return the type of @var{global}.
  1440. @end deffn
  1441. @deffn {Procedure} global-init global
  1442. Return the initialization instructions of @var{global}. Only constant
  1443. instructions are allowed.
  1444. @end deffn
  1445. @deffn {Procedure} global-type? obj
  1446. Return @code{#t} if @var{obj} is a global type.
  1447. @end deffn
  1448. @deffn {Procedure} global-type-mutable? global-type
  1449. Return @code{#t} if @var{global-type} is mutable.
  1450. @end deffn
  1451. @deffn {Procedure} global-type-type global-type
  1452. Return the type descriptor of @var{global-type}.
  1453. @end deffn
  1454. @subsection Functions
  1455. @deffn {Procedure} func? obj
  1456. Return @code{#t} if @var{obj} is a function.
  1457. @end deffn
  1458. @deffn {Procedure} func-id func
  1459. Return the symbolic ID of @var{func}.
  1460. @end deffn
  1461. @deffn {Procedure} func-type func
  1462. Return the signature of @var{func}.
  1463. @end deffn
  1464. @deffn {Procedure} func-locals func
  1465. Return the locals of @var{func}.
  1466. @end deffn
  1467. @deffn {Procedure} func-body func
  1468. Return the body instructions of @var{func}.
  1469. @end deffn
  1470. The type of a function is its signature. Notably, Wasm supports
  1471. multiple return values, just like Scheme.
  1472. @deffn {Procedure} func-sig? obj
  1473. Return @code{#t} if @var{obj} is a function signature.
  1474. @end deffn
  1475. @deffn {Procedure} func-sig-params func
  1476. Return the parameters of @var{func}.
  1477. @end deffn
  1478. @deffn {Procedure} func-sig-results func
  1479. Return the result types of @var{func}.
  1480. @end deffn
  1481. Function parameters pair a local identifier with its type.
  1482. @deffn {Procedure} param? obj
  1483. Return @code{#t} if @var{obj} is a param.
  1484. @end deffn
  1485. @deffn {Procedure} param-id param
  1486. Return the symbolic ID of @var{param}.
  1487. @end deffn
  1488. @deffn {Procedure} param-type param
  1489. Return the type descriptor of @var{param}.
  1490. @end deffn
  1491. Locals provide additional mutable variables scoped to the body of a
  1492. function.
  1493. @deffn {Procedure} local? obj
  1494. Return @code{#t} if @var{obj} is a function local.
  1495. @end deffn
  1496. @deffn {Procedure} local-id local
  1497. Return the symbolic ID of @var{local}.
  1498. @end deffn
  1499. @deffn {Procedure} local-type local
  1500. Return the type descriptor of @var{local}.
  1501. @end deffn
  1502. @subsection Imports/exports
  1503. Functions, globals, memories, and tables can be imported from the host
  1504. or another Wasm module. They are organized into a two layer
  1505. hierarchy. An import module groups many imports under an umbrella
  1506. name, and then the individual item names distinguish imported data
  1507. within a module.
  1508. @deffn {Procedure} import? obj
  1509. Return @code{#t} if @var{obj} is an import.
  1510. @end deffn
  1511. @deffn {Procedure} import-mod import
  1512. Return the module name string of @var{import}.
  1513. @end deffn
  1514. @deffn {Procedure} import-name import
  1515. Return the name string of @var{import}.
  1516. @end deffn
  1517. @deffn {Procedure} import-kind import
  1518. Return the kind of @var{import}. Either @code{func}, @code{global},
  1519. @code{memory}, or @code{table}.
  1520. @end deffn
  1521. @deffn {Procedure} import-id import
  1522. Return the symbolic ID of @var{import}.
  1523. @end deffn
  1524. @deffn {Procedure} import-type import
  1525. Return the type descriptor of @var{import}.
  1526. @end deffn
  1527. Likewise, functions, globals, memories, and tables can be exported
  1528. from a module to be used by the host or by other modules.
  1529. @deffn {Procedure} export? obj
  1530. Return @code{#t} if @var{obj} is an export.
  1531. @end deffn
  1532. @deffn {Procedure} export-name export
  1533. Return the name string of @var{export}.
  1534. @end deffn
  1535. @deffn {Procedure} export-kind export
  1536. Return the kind of @var{export}. Either @code{func}, @code{global},
  1537. @code{memory}, or @code{table}.
  1538. @end deffn
  1539. @deffn {Procedure} export-idx export
  1540. Return the index of @var{export}.
  1541. @end deffn
  1542. @subsection Linear memory
  1543. Memory objects specify linear chunks of bytes that a module can write
  1544. to/read from at runtime. The size of a memory is specified in terms
  1545. of 64KiB pages. While many memory objects coud be included in a
  1546. module, the Wasm specification currently only allows the use of a
  1547. single memory at index 0.
  1548. @deffn {Procedure} memory? obj
  1549. Return @code{#t} if @var{obj} is a memory.
  1550. @end deffn
  1551. @deffn {Procedure} memory-id memory
  1552. Return the symbolic ID of @var{memory}.
  1553. @end deffn
  1554. The type of a memory currently just specifies the size limitations.
  1555. @deffn {Procedure} memory-type memory
  1556. Return the type of @var{memory}.
  1557. @end deffn
  1558. @deffn {Procedure} mem-type? obj
  1559. Return @code{#t} if @var{obj} is a memory type.
  1560. @end deffn
  1561. @deffn {Procedure} mem-type-limits mem-type
  1562. Return the limits of @var{mem-type}.
  1563. @end deffn
  1564. Instructions that manipulate linear memory use the memory argument
  1565. type to point to a specific offset within a memory.
  1566. @deffn {Procedure} mem-arg? obj
  1567. Return @code{#t} if @var{obj} is a memory argument.
  1568. @end deffn
  1569. @deffn {Procedure} mem-arg-id mem-arg
  1570. Return the symbolic ID of @var{mem-arg}.
  1571. @end deffn
  1572. @deffn {Procedure} mem-arg-offset mem-arg
  1573. Return the offset of @var{mem-arg}.
  1574. @end deffn
  1575. @deffn {Procedure} mem-arg-align mem-arg
  1576. Return the alignment of @var{mem-arg}.
  1577. @end deffn
  1578. @subsection Data segments
  1579. Data segments are static chunks of data used to initialize regions of
  1580. memory. They have two possible modes of use:
  1581. @enumerate
  1582. @item @strong{Active:}
  1583. The data segment is copied into memory during instantiation.
  1584. @item @strong{Passive:}
  1585. The data segment is copied into memory using the @code{memory.init}
  1586. instruction.
  1587. @end enumerate
  1588. @deffn {Procedure} data? obj
  1589. Return @code{#t} if @var{obj} is a data segment.
  1590. @end deffn
  1591. @deffn {Procedure} data-id data
  1592. Return the symbolic ID of @var{data}.
  1593. @end deffn
  1594. @deffn {Procedure} data-mode data
  1595. Return the mode of @var{data}. Either @code{passive} or
  1596. @code{active}.
  1597. @end deffn
  1598. @deffn {Procedure} data-mem data
  1599. Return the memory associated with @var{data}.
  1600. @end deffn
  1601. @deffn {Procedure} data-offset data
  1602. Return the instructions that compute the offset of @var{data}. Only
  1603. constant instructions are allowed.
  1604. @end deffn
  1605. @deffn {Procedure} data-init data
  1606. Return a bytevector containing the initialization data of @var{data}.
  1607. @end deffn
  1608. @subsection Tables
  1609. Tables specify a vector of heap object references of a particular
  1610. reference type.
  1611. @deffn {Procedure} table? obj
  1612. Return @code{#t} if @var{obj} is a reference table.
  1613. @end deffn
  1614. @deffn {Procedure} table-id table
  1615. Return the symbolic ID of @var{table}.
  1616. @end deffn
  1617. @deffn {Procedure} table-type table
  1618. Return the type of @var{table}.
  1619. @end deffn
  1620. Table types specify the reference type of the elements as well as the
  1621. size limitations.
  1622. @deffn {Procedure} table-type? obj
  1623. Return @code{#t} if @var{obj} is a table type.
  1624. @end deffn
  1625. @deffn {Procedure} table-type-limits table-type
  1626. Return the limts of @var{table-type}.
  1627. @end deffn
  1628. @deffn {Procedure} table-type-elem-type table-type
  1629. Return the element type of @var{table-type}.
  1630. @end deffn
  1631. @subsection Element segments
  1632. Element segments are static vectors of references used to initialize
  1633. regions of tables (well, mostly.) They have three possible modes of
  1634. use:
  1635. @enumerate
  1636. @item @strong{Active:}
  1637. The element segment is copied into its associated table during
  1638. instantiation.
  1639. @item @strong{Passive:}
  1640. The element segment is copied into its associated table using the
  1641. @code{table.init} instruction.
  1642. @item @strong{Declarative:}
  1643. The element segment is unavailable at runtime and is instead used for
  1644. forward declarations of types that are used elsewhere in the code.
  1645. @end enumerate
  1646. @deffn {Procedure} elem? obj
  1647. Return @code{#t} if @var{obj} is an element segment.
  1648. @end deffn
  1649. @deffn {Procedure} elem-id elem
  1650. Return the symoblic ID of @var{elem}.
  1651. @end deffn
  1652. @deffn {Procedure} elem-mode elem
  1653. Return the mode of @var{elem}.
  1654. @end deffn
  1655. @deffn {Procedure} elem-table elem
  1656. Return the table associated with @var{elem}.
  1657. @end deffn
  1658. @deffn {Procedure} elem-type elem
  1659. Return the type of @var{elem}.
  1660. @end deffn
  1661. @deffn {Procedure} elem-offset elem
  1662. Return the instructions that compute the offset of @var{elem}. Only
  1663. constant instructions are allowed.
  1664. @end deffn
  1665. @deffn {Procedure} elem-inits elem
  1666. Return a list of initializer instructions for the items of @var{elem}.
  1667. Only constant instructions are allowed.
  1668. @end deffn
  1669. @subsection Limits
  1670. Both memories and tables use limits to constrain their minimum and
  1671. maximum size. A valid limit must have a minimum of at least 1, but
  1672. the maximum may be @code{#f} if unbounded growth is allowed.
  1673. @deffn {Procedure} limits? obj
  1674. Return @code{#t} if @var{obj} is a limits.
  1675. @end deffn
  1676. @deffn {Procedure} limits-min limits
  1677. Return the minimum value of @var{limits}.
  1678. @end deffn
  1679. @deffn {Procedure} limits-max limits
  1680. Return the maximum value of @var{limits} or @code{#f} if there is no
  1681. maximum.
  1682. @end deffn
  1683. @subsection Tags
  1684. Tag segments specify types of runtime errors that may be raised.
  1685. @deffn {Procedure} tag? obj
  1686. Return @code{#t} if @var{obj} is a tag.
  1687. @end deffn
  1688. @deffn {Procedure} tag-id tag
  1689. Return the symbolic ID of @var{tag}.
  1690. @end deffn
  1691. @deffn {Procedure} tag-type tag
  1692. Return the type of @var{tag}.
  1693. @end deffn
  1694. @subsection Custom sections
  1695. Custom sections specify arbitrary data that is not covered by the Wasm
  1696. specification.
  1697. @deffn {Procedure} custom? obj
  1698. Return @code{#t} if @var{obj} is a custom segment.
  1699. @end deffn
  1700. @deffn {Procedure} custom-name custom
  1701. Return the name of @var{custom}.
  1702. @end deffn
  1703. @deffn {Procedure} custom-bytes custom
  1704. Return the bytevector of @var{custom}.
  1705. @end deffn
  1706. There is, however, one custom section that @emph{is} specified: the
  1707. name section. This section contains various ``name maps'' that can be
  1708. used to translate integer identifiers to (hopefully) human-readable
  1709. names for the purposes of debugging.
  1710. Hoot supports the name subsections described in the Wasm core
  1711. specification, the Wasm GC specification, and the extended names
  1712. proposal:
  1713. @enumerate
  1714. @item Module name
  1715. @item Function name map
  1716. @item Function local indirect name map
  1717. @item Block label indirect name map
  1718. @item Type name map
  1719. @item Table name map
  1720. @item Memory name map
  1721. @item Global name map
  1722. @item Element name map
  1723. @item Data name map
  1724. @item Struct field indirect name map
  1725. @item Tag name map
  1726. @end enumerate
  1727. Name maps are represented as association lists mapping integers to
  1728. strings. Indirect name maps are represented as association lists
  1729. mapping integers to name maps.
  1730. @deffn {Procedure} names? obj
  1731. Return @code{#t} if @var{obj} is a name section object.
  1732. @end deffn
  1733. @deffn {Procedure} names-module names
  1734. Return the module name of @var{names}.
  1735. @end deffn
  1736. @deffn {Procedure} names-func names
  1737. Return the function name map of @var{names}.
  1738. @end deffn
  1739. @deffn {Procedure} names-local names
  1740. Return the function local indirect name map of @var{names}.
  1741. @end deffn
  1742. @deffn {Procedure} names-label names
  1743. Return the block label indirect name map of @var{names}.
  1744. @end deffn
  1745. @deffn {Procedure} names-type names
  1746. Return the type name map of @var{names}.
  1747. @end deffn
  1748. @deffn {Procedure} names-table names
  1749. Return the table name map of @var{names}.
  1750. @end deffn
  1751. @deffn {Procedure} names-memory names
  1752. Return the memory name map of @var{names}.
  1753. @end deffn
  1754. @deffn {Procedure} names-global names
  1755. Return the global name map of @var{names}.
  1756. @end deffn
  1757. @deffn {Procedure} names-elem names
  1758. Return the element name map of @var{names}.
  1759. @end deffn
  1760. @deffn {Procedure} names-data names
  1761. Return the data name map of @var{names}.
  1762. @end deffn
  1763. @deffn {Procedure} names-fields names
  1764. Return the struct field indirect name map of @var{names}.
  1765. @end deffn
  1766. @deffn {Procedure} names-tag names
  1767. Return the tag name map of @var{names}.
  1768. @end deffn
  1769. @node GWAT
  1770. @section GWAT
  1771. The @code{(wasm wat)} module provides a parser for a variant of
  1772. WebAssembly Text (WAT) format. Since the WAT uses an s-expression
  1773. syntax that resembles but is distinct from Scheme syntax, Hoot opts to
  1774. represent WAT code as Scheme expressions. This allows for embedding
  1775. WAT directly into Scheme code and programmatically generating WAT code
  1776. via quasiquote templating or other means. We call this variant GWAT
  1777. where the ``G'' stands for ``Guile'', of course.
  1778. The GWAT form has some additional expressive power such as allowing
  1779. string constants, bytevectors for data segments, and i32/i64 constants
  1780. in either the signed or unsigned range.
  1781. WAT has two variants: unfolded and folded. In the unfolded form,
  1782. instruction sequences are linear, as they would be in the resulting
  1783. binary:
  1784. @lisp
  1785. '(module
  1786. (func (export "add") (param $a i32) (param $b i32) (result i32)
  1787. (local.get $a)
  1788. (local.get $b)
  1789. (i32.add)))
  1790. @end lisp
  1791. The folded form allows instructions to be nested within each other:
  1792. @lisp
  1793. '(module
  1794. (func (export "add") (param $a i32) (param $b i32) (result i32)
  1795. (i32.add (local.get $a)
  1796. (local.get $b))))
  1797. @end lisp
  1798. This form looks more like Scheme procedure calls and is generally
  1799. easier to write and reason about.
  1800. @deffn {Procedure} wat->wasm expr
  1801. Parse @var{expr}, a Wasm module expressed as WAT code, and return a
  1802. Wasm module.
  1803. @lisp
  1804. (parse-wat
  1805. '(module
  1806. (func (export "add") (param $a i32) (param $b i32) (result i32)
  1807. (i32.add (local.get $a)
  1808. (local.get $b)))))
  1809. @end lisp
  1810. The returned Wasm module preserves named references, among other
  1811. things, and is thus unsuitable as input to the assembler or
  1812. interpreter. To lower the module into a usable form, see
  1813. @code{resolve-wasm} in @ref{Resolver}.
  1814. @end deffn
  1815. @deffn {Procedure} wasm->wat wasm
  1816. Disassemble @var{wasm} and return its symbolic WAT form.
  1817. @end deffn
  1818. @node Resolver
  1819. @section Resolver
  1820. The @code{(wasm resolve)} module provides the @code{resolve-wasm}
  1821. procedure which lowers Wasm modules into a form that can be used by
  1822. the assembler or interpreter. The resolver replaces named references
  1823. with their respective integer identifiers, fills out the type table,
  1824. and adjusts i32 and i64 constants into their canonical form.
  1825. @deffn {Procedure} resolve-wasm mod [#:name-section? #f]
  1826. Lower the Wasm module @var{mod} into a form that can be assembled or
  1827. interpreted. Returns a new Wasm module and does not modify @var{mod}.
  1828. When @var{name-section?} is @code{#t}, the returned Wasm module will
  1829. include a name map that maps the original, human-readable names to the
  1830. resolved integer identifiers.
  1831. @end deffn
  1832. @node Linker
  1833. @section Linker
  1834. The @code{(wasm link)} module provides a means for extending a Wasm
  1835. module with the standard library that it needs at runtime. Hoot uses
  1836. the linker to add the Scheme runtime to the compiled form of user
  1837. code. The linker uses a form of tree-shaking to remove anything that
  1838. is not used by the base module.
  1839. @deffn {Procedure} add-stdlib wasm stdlib
  1840. Return a new Wasm module that is the combination of the Wasm module
  1841. @var{wasm} with the Wasm module @var{stdlib}.
  1842. @end deffn
  1843. @node Assembler
  1844. @section Assembler
  1845. The @code{(wasm assemble)} module is used to lower Wasm modules into
  1846. the Wasm binary format.
  1847. @deffn {Procedure} assemble-wasm wasm
  1848. Return a bytevector containing the assembled binary form of the Wasm
  1849. module @var{wasm}.
  1850. @end deffn
  1851. @node Binary Parser
  1852. @section Binary Parser
  1853. The @code{(wasm parse)} module parses the Wasm binary format.
  1854. @deffn {Procedure} parse-wasm port
  1855. Parse the Wasm binary data from @var{port} and return a Wasm module.
  1856. @end deffn
  1857. @node Printer
  1858. @section Printer
  1859. The @code{(wasm dump)} module provides the @code{dump-wasm} procedure
  1860. for generating a detailed print-out of a Wasm module's contents. See
  1861. also @ref{Low-level development tools} for the @code{wasm-dump} REPL
  1862. command.
  1863. @deffn {Procedure} dump-wasm mod [#:port] [#:dump-func-defs? #t]
  1864. Write a detailed inventory of the Wasm module @var{mod} to @var{port}
  1865. or the current output port if @var{port} is not specified. If
  1866. @var{dump-func-defs?} is @code{#t}, which is the default, all function
  1867. definitions are printed, including the instructions in the body of
  1868. each. Depending on the size of the module, this may be an
  1869. overwhelming amount of data, thus it is made optional.
  1870. @end deffn
  1871. @node Interpreter
  1872. @section Interpreter
  1873. The @code{(wasm vm)} module provides a virtual machine for
  1874. interpreting Wasm functions. To use the interpreter, a Wasm module is
  1875. first validated for type safety (among other things) and then
  1876. instantiated, at which point exported functions become callable from
  1877. Scheme.
  1878. The interpreter only accepts validated Wasm. The @code{validate-wasm}
  1879. procedure validates and wraps a Wasm module to indicate successful
  1880. validation:
  1881. @lisp
  1882. (use-modules (wasm vm) (wasm resolve))
  1883. (define validated-wasm
  1884. (validate-wasm
  1885. (wat->wasm
  1886. '(module
  1887. (func (export "main") (result i32)
  1888. (i32.const 42))))))
  1889. @end lisp
  1890. When starting with a Wasm binary, the convenient
  1891. @code{load-and-validate-wasm} procedure parses the binary and then
  1892. performs validation:
  1893. @lisp
  1894. (call-with-input-file "hello.wasm" load-and-validate-wasm)
  1895. @end lisp
  1896. Once the Wasm module has been validated, the runtime data needed for
  1897. interpretation can be created by instantiating the module:
  1898. @lisp
  1899. (define instance (instantiate-wasm validated-wasm))
  1900. @end lisp
  1901. Exported Wasm functions then become usable as Scheme procedures:
  1902. @lisp
  1903. (define wasm-main (wasm-instance-export-ref instance "main"))
  1904. (wasm-main) ;; => 42
  1905. @end lisp
  1906. Wasm functions are statically typed, which means that calls from
  1907. Scheme to Wasm require runtime type checking for each call.
  1908. @subsection Validation
  1909. @deffn {Procedure} validate-wasm wasm
  1910. Validate the Wasm module @var{wasm} and return a validated Wasm
  1911. object.
  1912. @end deffn
  1913. @deffn {Procedure} load-and-validate-wasm obj
  1914. Load and validate the Wasm module within @var{obj} then return a
  1915. validated Wasm object. @var{obj} may be a @code{<wasm>} record as
  1916. produced by @code{resolve-wasm}(@pxref{Resolver}), a bytevector
  1917. containing a Wasm binary, or an input port from which to read a Wasm
  1918. binary.
  1919. @end deffn
  1920. @deffn {Procedure} validated-wasm? obj
  1921. Return @code{#t} if @var{obj} is a validated Wasm object.
  1922. @end deffn
  1923. @deffn {Procedure} validated-wasm-ref validated-wasm
  1924. Unbox and return the Wasm module within @var{validated-wasm}.
  1925. @end deffn
  1926. @subsection Instantiation
  1927. @deffn {Procedure} instantiate-wasm wasm [#:imports '()]
  1928. Return a new Wasm instance for the validated Wasm module @var{wasm}.
  1929. @var{imports} is a nested association list of imported functions,
  1930. globals, memories, and tables. Wasm imports are identified by a
  1931. module name and an object name. Consider the following Wasm module
  1932. that computes 2D polar coordinates and prints them to a log:
  1933. @lisp
  1934. (use-modules (wasm resolve) (wasm vm) (wasm wat))
  1935. (define the-module
  1936. (resolve-wasm
  1937. (wat->wasm
  1938. '(module
  1939. (func $logf64 (import "debug" "logf64") (param f64))
  1940. (func $cos (import "math" "cos") (param f64) (result f64))
  1941. (func $sin (import "math" "sin") (param f64) (result f64))
  1942. (func (export "polar") (param $r f64) (param $theta f64)
  1943. (call $logf64 (f64.mul (local.get $r)
  1944. (call $cos (local.get $theta))))
  1945. (call $logf64 (f64.mul (local.get $r)
  1946. (call $sin (local.get $theta)))))))))
  1947. @end lisp
  1948. This module requires three imported functions from two modules. Thus
  1949. the module instantiation code would look like this:
  1950. @lisp
  1951. (define (logf64 x)
  1952. (format #t "f64: ~a\n" x))
  1953. (define the-instance
  1954. (instantiate-wasm (validate-wasm the-module)
  1955. #:imports `(("debug" . (("logf64" . ,logf64)))
  1956. ("math" . (("cos" . ,cos)
  1957. ("sin" . ,sin))))))
  1958. @end lisp
  1959. @end deffn
  1960. @subsection Globals
  1961. @deffn {Procedure} make-wasm-global value mutable?
  1962. Return a new Wasm global containing @var{value}. When @var{mutable?}
  1963. is @code{#f}, the value cannot be modified later.
  1964. @end deffn
  1965. @deffn {Procedure} wasm-global? obj
  1966. Return @code{#t} if @var{obj} is a Wasm global.
  1967. @end deffn
  1968. @deffn {Procedure} wasm-global-ref global
  1969. Return the current value within @var{global}.
  1970. @end deffn
  1971. @deffn {Procedure} wasm-global-set! global val
  1972. Set the value within @var{global} to @var{val}. An exception is
  1973. raised if @var{global} is immutable.
  1974. @end deffn
  1975. @deffn {Procedure} wasm-global-mutable? global
  1976. Return @code{#t} if @var{global} is mutable.
  1977. @end deffn
  1978. @subsection Memories
  1979. @deffn {Procedure} make-wasm-memory size [#:limits (make-limits 1 #f)]
  1980. Return a new Wasm linear memory containing @var{size} 64KiB pages.
  1981. @var{limits} determines the lower and upper bounds of how many pages
  1982. this memory can store. The default limits are a minimum of 1 page and
  1983. no maximum page limit. @xref{Data types} for more information on
  1984. limit objects.
  1985. @end deffn
  1986. @deffn {Procedure} wasm-memory? obj
  1987. Return @code{#t} if @var{obj} is a Wasm memory.
  1988. @end deffn
  1989. @deffn {Procedure} wasm-memory-bytes memory
  1990. Return the current bytevector representing the pages of @var{memory}.
  1991. @end deffn
  1992. @deffn {Procedure} wasm-memory-size memory
  1993. Return the size of @var{memory} in 64KiB pages.
  1994. @end deffn
  1995. @deffn {Procedure} wasm-memory-limits memory
  1996. Return the limits of @var{memory}
  1997. @end deffn
  1998. @deffn {Procedure} wasm-memory-grow! memory n
  1999. Increase the size of @var{memory} by @var{n} pages. An exception is
  2000. raised if growing by @var{n} exceeds the limits of @var{memory}.
  2001. @end deffn
  2002. @subsection Tables
  2003. @deffn {Procedure} make-wasm-table size [#:limits (make-limits 1 #f)]
  2004. Return a new Wasm reference table containing @var{size} element slots.
  2005. @var{limits} determines the lower and upper bounds of how many
  2006. elements this table can store. The default limits are a minimum of 1
  2007. element and no maximum element limit. @xref{Data types} for more
  2008. information on limit objects.
  2009. @end deffn
  2010. @deffn {Procedure} wasm-table?
  2011. Return @code{#t} if @var{obj} is a Wasm table.
  2012. @end deffn
  2013. @deffn {Procedure} wasm-table-size table
  2014. Return the size of @var{table}.
  2015. @end deffn
  2016. @deffn {Procedure} wasm-table-ref table i
  2017. Return the reference at the @var{i}th index in @var{table}.
  2018. @end deffn
  2019. @deffn {Procedure} wasm-table-set! table i x
  2020. Set the @var{i}th element of @var{table} to @var{x}, a Wasm reference
  2021. type.
  2022. @end deffn
  2023. @deffn {Procedure} wasm-table-fill! table start fill length
  2024. Fill the elements of @var{table} from @var{start} to @var{start} +
  2025. @var{length}, exclusive, with the value @var{fill}.
  2026. @end deffn
  2027. @deffn {Procedure} wasm-table-copy! table at elems start length
  2028. Copy the block of elements from vector @var{elems}, from @var{start}
  2029. to @var{start} + @var{length}, exclusive, to @var{table}, starting at
  2030. @var{at}.
  2031. @end deffn
  2032. @deffn {Procedure} wasm-table-grow! table n init
  2033. Increase the size of @var{table} by @var{n} elements. An exception is
  2034. raised if growing by @var{n} exceeds the limits of @var{table}.
  2035. @end deffn
  2036. @subsection Observation
  2037. Every Wasm instruction evaluated by interpreter can be observed via
  2038. the @code{current-instruction-listener} parameter. Use this hook to
  2039. instrument Wasm modules.
  2040. The following instruction listener would print every instruction's
  2041. name on a separate line:
  2042. @lisp
  2043. (define (log-instr instr path instance stack blocks locals)
  2044. (display (car instr))
  2045. (newline))
  2046. (parameterize ((current-instruction-listener log-instr))
  2047. ...)
  2048. @end lisp
  2049. @defvar {Variable} current-instruction-listener
  2050. The current instruction observation hook which is invoked
  2051. @emph{before} each instruction evaluation. Must be a procedure that
  2052. accepts the following arguments:
  2053. @enumerate
  2054. @item @strong{Instruction:}
  2055. The symbolic Wasm instruction to be evaluated.
  2056. @item @strong{Path:}
  2057. The symbolic location of the instruction within the Wasm module.
  2058. @item @strong{Instance:}
  2059. The instance that is evaluating the instruction.
  2060. @item @strong{Stack:}
  2061. The Wasm value stack.
  2062. @item @strong{Blocks:}
  2063. The Wasm block stack, which is just a list of prompt tags.
  2064. @item @strong{Locals:}
  2065. The Wasm function locals.
  2066. @end enumerate
  2067. @end defvar
  2068. The Wasm value stack is a special data type with the following API:
  2069. @deffn {Procedure} wasm-stack? obj
  2070. Return @code{#t} if @var{obj} is a Wasm value stack.
  2071. @end deffn
  2072. @deffn {Procedure} wasm-stack-items stack
  2073. Return the values on @var{stack} as a list.
  2074. @end deffn
  2075. @node Contributing
  2076. @chapter Contributing
  2077. Found a bug? Let us know! Made an improvement? Show us! Issues can
  2078. be filed and pull requests can be submitted on
  2079. @url{https://gitlab.com/spritely/guile-hoot,GitLab}.
  2080. @node License
  2081. @chapter License
  2082. @emph{(C) 2023 David Thompson}
  2083. @emph{Both Guile Hoot and this manual are released under the terms of
  2084. the following license:}
  2085. @include apache-2.0.texi
  2086. @node Index
  2087. @unnumbered Index
  2088. @printindex fn
  2089. @bye