hoot.texi 101 KB

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