hoot.texi 126 KB

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