hoot.texi 78 KB

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