hoot.texi 101 KB

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