hoot.texi 123 KB

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