stdlib.scm 209 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422
  1. ;;; Standard library for Hoot runtime
  2. ;;; Copyright (C) 2023 Igalia, S.L.
  3. ;;; Copyright (C) 2023 Robin Templeton <robin@spritely.institute>
  4. ;;;
  5. ;;; Licensed under the Apache License, Version 2.0 (the "License");
  6. ;;; you may not use this file except in compliance with the License.
  7. ;;; You may obtain a copy of the License at
  8. ;;;
  9. ;;; http://www.apache.org/licenses/LICENSE-2.0
  10. ;;;
  11. ;;; Unless required by applicable law or agreed to in writing, software
  12. ;;; distributed under the License is distributed on an "AS IS" BASIS,
  13. ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. ;;; See the License for the specific language governing permissions and
  15. ;;; limitations under the License.
  16. ;;; Commentary:
  17. ;;;
  18. ;;; Standard runtime routines for Hoot WebAssembly runtime.
  19. ;;;
  20. ;;; Code:
  21. (define-module (hoot stdlib)
  22. #:use-module (wasm wat)
  23. #:use-module (ice-9 match)
  24. #:use-module (ice-9 receive)
  25. #:export ((compute-stdlib/memoized . compute-stdlib)))
  26. (define (arith-cond . clauses)
  27. (receive (type clauses)
  28. (if (and (pair? clauses) (pair? (car clauses)) (pair? (caar clauses)))
  29. (values '(ref eq) clauses)
  30. (values (car clauses) (cdr clauses)))
  31. (if (null? clauses)
  32. '(unreachable)
  33. (let* ((clause1 (car clauses))
  34. (cond1 (car clause1))
  35. (res1 (cdr clause1)))
  36. (if (eq? cond1 'else)
  37. `(block ,type ,@res1)
  38. `(if ,type ,cond1
  39. (then ,@res1)
  40. (else ,(apply arith-cond type (cdr clauses)))))))))
  41. (define (call-fmath fn . args)
  42. `(struct.new $flonum
  43. (i32.const 0)
  44. (call ,fn
  45. ,@(map (lambda (arg)
  46. `(struct.get $flonum
  47. $val
  48. (call $inexact ,arg)))
  49. args))))
  50. (define (compute-stdlib import-abi?)
  51. (define (maybe-import id)
  52. (if import-abi?
  53. `(,id (import "abi" ,(symbol->string id)))
  54. `(,id)))
  55. (define maybe-init-proc
  56. (if import-abi?
  57. '()
  58. '((struct.new $proc (i32.const 0)
  59. (ref.func $invalid-continuation)))))
  60. (define maybe-init-i31-zero
  61. (if import-abi?
  62. '()
  63. '((ref.i31 (i32.const 0)))))
  64. (define maybe-init-i32-zero
  65. (if import-abi?
  66. '()
  67. '((i32.const 0))))
  68. (define maybe-init-hash-table
  69. (if import-abi?
  70. '()
  71. '((struct.new $hash-table (i32.const 0)
  72. (i32.const 0)
  73. (array.new $raw-scmvector (ref.i31 (i32.const 13))
  74. (i32.const 47))))))
  75. (define (struct-name nfields)
  76. (if (zero? nfields)
  77. '$struct
  78. (string->symbol (format #f "$struct/~a" nfields))))
  79. (define (struct-definition nfields)
  80. (define (field-name i) (string->symbol (format #f "$field~a" i)))
  81. `(struct
  82. (field $hash (mut i32))
  83. (field $vtable (mut (ref null $vtable)))
  84. ,@(map (lambda (i)
  85. `(field ,(field-name i) (mut (ref eq))))
  86. (iota nfields))))
  87. ;; If you change the field count, also update vtable-nfields in
  88. ;; compile.scm.
  89. (define vtable-fields
  90. '((field $nfields (mut (ref eq)))
  91. (field $printer (mut (ref eq)))
  92. (field $name (mut (ref eq)))
  93. (field $constructor (mut (ref eq)))
  94. (field $properties (mut (ref eq)))
  95. (field $parents (mut (ref eq)))
  96. (field $mutable-fields (mut (ref eq)))
  97. (field $compare (mut (ref eq)))))
  98. (define vtable-nfields (length vtable-fields))
  99. (wat->wasm
  100. `((type $kvarargs
  101. (func (param $nargs i32)
  102. (param $arg0 (ref eq))
  103. (param $arg1 (ref eq))
  104. (param $arg2 (ref eq))))
  105. (type $raw-bitvector (array (mut i32)))
  106. (type $raw-bytevector (array (mut i8)))
  107. (type $raw-scmvector (array (mut (ref eq))))
  108. (rec
  109. (type $heap-object
  110. (sub
  111. (struct
  112. (field $hash (mut i32)))))
  113. (type $extern-ref
  114. (sub $heap-object
  115. (struct
  116. (field $hash (mut i32))
  117. (field $val (ref null extern)))))
  118. (type $heap-number
  119. (sub $heap-object
  120. (struct
  121. (field $hash (mut i32)))))
  122. (type $bignum
  123. (sub $heap-number
  124. (struct
  125. (field $hash (mut i32))
  126. (field $val (ref extern)))))
  127. (type $flonum
  128. (sub $heap-number
  129. (struct
  130. (field $hash (mut i32))
  131. (field $val f64))))
  132. (type $complex
  133. (sub $heap-number
  134. (struct
  135. (field $hash (mut i32))
  136. (field $real f64)
  137. (field $imag f64))))
  138. (type $fraction
  139. (sub $heap-number
  140. (struct
  141. (field $hash (mut i32))
  142. (field $num (ref eq))
  143. (field $denom (ref eq)))))
  144. (type $pair
  145. (sub $heap-object
  146. (struct
  147. (field $hash (mut i32))
  148. (field $car (mut (ref eq)))
  149. (field $cdr (mut (ref eq))))))
  150. (type $mutable-pair
  151. (sub $pair
  152. (struct
  153. (field $hash (mut i32))
  154. (field $car (mut (ref eq)))
  155. (field $cdr (mut (ref eq))))))
  156. (type $vector
  157. (sub $heap-object
  158. (struct
  159. (field $hash (mut i32))
  160. (field $vals (ref $raw-scmvector)))))
  161. (type $mutable-vector
  162. (sub $vector
  163. (struct
  164. (field $hash (mut i32))
  165. (field $vals (ref $raw-scmvector)))))
  166. (type $bytevector
  167. (sub $heap-object
  168. (struct
  169. (field $hash (mut i32))
  170. (field $vals (ref $raw-bytevector)))))
  171. (type $mutable-bytevector
  172. (sub $bytevector
  173. (struct
  174. (field $hash (mut i32))
  175. (field $vals (ref $raw-bytevector)))))
  176. (type $bitvector
  177. (sub $heap-object
  178. (struct
  179. (field $hash (mut i32))
  180. (field $len i32)
  181. (field $vals (ref $raw-bitvector)))))
  182. (type $mutable-bitvector
  183. (sub $bitvector
  184. (struct
  185. (field $hash (mut i32))
  186. (field $len i32)
  187. (field $vals (ref $raw-bitvector)))))
  188. (type $string
  189. (sub $heap-object
  190. (struct
  191. (field $hash (mut i32))
  192. (field $str (mut (ref string))))))
  193. (type $mutable-string
  194. (sub $string
  195. (struct
  196. (field $hash (mut i32))
  197. (field $str (mut (ref string))))))
  198. (type $proc
  199. (sub $heap-object
  200. (struct
  201. (field $hash (mut i32))
  202. (field $func (ref $kvarargs)))))
  203. (type $symbol
  204. (sub $heap-object
  205. (struct
  206. (field $hash (mut i32))
  207. (field $name (ref $string)))))
  208. (type $keyword
  209. (sub $heap-object
  210. (struct
  211. (field $hash (mut i32))
  212. (field $name (ref $symbol)))))
  213. (type $variable
  214. (sub $heap-object
  215. (struct
  216. (field $hash (mut i32))
  217. (field $val (mut (ref eq))))))
  218. (type $atomic-box
  219. (sub $heap-object
  220. (struct
  221. (field $hash (mut i32))
  222. (field $val (mut (ref eq))))))
  223. (type $hash-table
  224. (sub $heap-object
  225. (struct
  226. (field $hash (mut i32))
  227. (field $size (mut i32))
  228. (field $buckets (ref $raw-scmvector)))))
  229. (type $weak-table
  230. (sub $heap-object
  231. (struct
  232. (field $hash (mut i32))
  233. (field $val (ref extern)))))
  234. (type $fluid
  235. (sub $heap-object
  236. (struct
  237. (field $hash (mut i32))
  238. (field $init (ref eq)))))
  239. (type $dynamic-state
  240. (sub $heap-object
  241. (struct
  242. (field $hash (mut i32))
  243. (field $fluids (ref $hash-table)))))
  244. (type $syntax
  245. (sub $heap-object
  246. (struct
  247. (field $hash (mut i32))
  248. (field $expr (ref eq))
  249. (field $wrap (ref eq))
  250. (field $module (ref eq))
  251. (field $source (ref eq)))))
  252. (type $port
  253. (sub $heap-object
  254. (struct
  255. (field $hash (mut i32))
  256. (field $open? (mut (ref eq))) ;; #f | #t
  257. (field $read (ref eq)) ;; #f | (bv, start, count) -> size
  258. (field $write (ref eq)) ;; #f | (bv, start, count) -> size
  259. (field $input-waiting? (ref eq)) ;; #f | () -> bool
  260. (field $seek (ref eq)) ;; #f | (offset, whence) -> offset
  261. (field $close (ref eq)) ;; #f | () -> ()
  262. (field $truncate (ref eq)) ;; #f | (length) -> ()
  263. (field $repr (ref $string))
  264. (field $filename (mut (ref eq))) ;; #f | string
  265. (field $position (ref $mutable-pair)) ;; (line . column)
  266. (field $read-buf (mut (ref eq))) ;; #f | #(bv cur end has-eof?)
  267. (field $write-buf (mut (ref eq))) ;; #f | #(bv cur end)
  268. (field $read-buffering (mut (ref eq))) ;; #f | [1,size,1<<29)
  269. (field $r/w-random-access? (ref eq)) ;; #f | #t
  270. (field $fold-case? (mut (ref eq))) ;; #f | #t
  271. (field $private-data (ref eq))))) ;; whatever
  272. (type $struct
  273. (sub $heap-object
  274. (struct
  275. (field $hash (mut i32))
  276. ;; Vtable link is mutable so that we can tie the knot for top
  277. ;; types.
  278. (field $vtable (mut (ref null $vtable))))))
  279. ,@(map (lambda (nfields)
  280. `(type ,(struct-name nfields)
  281. (sub ,(struct-name (1- nfields))
  282. ,(struct-definition nfields))))
  283. (iota vtable-nfields 1))
  284. (type $vtable
  285. (sub ,(struct-name vtable-nfields)
  286. (struct
  287. (field $hash (mut i32))
  288. (field $vtable (mut (ref null $vtable)))
  289. ,@vtable-fields)))
  290. (type $vtable-vtable
  291. (sub $vtable
  292. (struct
  293. (field $hash (mut i32))
  294. (field $vtable (mut (ref null $vtable)))
  295. ,@vtable-fields)))
  296. (type $parameter
  297. (sub $proc
  298. (struct
  299. (field $hash (mut i32))
  300. (field $func (ref $kvarargs))
  301. (field $fluid (ref $fluid))
  302. (field $convert (ref $proc)))))
  303. (type $dyn (sub (struct)))
  304. (type $dynwind
  305. (sub $dyn
  306. (struct
  307. (field $wind (ref $proc))
  308. (field $unwind (ref $proc)))))
  309. (type $dynprompt
  310. (sub $dyn
  311. (struct
  312. (field $raw-sp i32)
  313. (field $scm-sp i32)
  314. (field $ret-sp i32)
  315. (field $unwind-only? i8)
  316. (field $tag (ref eq))
  317. (field $handler (ref $kvarargs)))))
  318. (type $dynfluid
  319. (sub $dyn
  320. (struct
  321. (field $fluid (ref $fluid))
  322. (field $val (mut (ref eq))))))
  323. (type $dynstate
  324. (sub $dyn
  325. (struct
  326. (field $fluids (mut (ref $hash-table)))))))
  327. (type $raw-retvector (array (mut (ref $kvarargs))))
  328. (type $raw-dynvector (array (mut (ref $dyn))))
  329. (type $cont
  330. (sub $proc
  331. (struct
  332. (field $hash (mut i32))
  333. (field $func (ref $kvarargs))
  334. (field $prompt (ref $dynprompt))
  335. (field $raw-stack (ref $raw-bytevector))
  336. (field $scm-stack (ref $raw-scmvector))
  337. (field $ret-stack (ref $raw-retvector))
  338. (field $dyn-stack (ref $raw-dynvector)))))
  339. (global $root-vtable (ref $vtable-vtable) (call $make-root-vtable))
  340. (global $empty-vector (ref $vector)
  341. (struct.new $vector
  342. (i32.const 0) (array.new_fixed $raw-scmvector 0)))
  343. (func $make-root-vtable (result (ref $vtable-vtable))
  344. (local $ret (ref $vtable-vtable))
  345. (local.set $ret
  346. (struct.new $vtable-vtable
  347. (i32.const 0)
  348. (ref.null $vtable)
  349. (ref.i31 (i32.const ,(ash vtable-nfields 1)))
  350. (ref.i31 (i32.const 1)) ; printer
  351. (ref.i31 (i32.const 1)) ; name
  352. (ref.i31 (i32.const 1)) ; constructor
  353. (ref.i31 (i32.const 13)) ; properties
  354. (global.get $empty-vector) ; parents
  355. (ref.i31 (i32.const 0)) ; mutable-fields
  356. (ref.i31 (i32.const 0)))) ; compare
  357. (struct.set $vtable-vtable $vtable (local.get $ret) (local.get $ret))
  358. ;; Rely on Scheme to initialize printer, name, etc...
  359. (local.get $ret))
  360. (func $raise-exception (param $exn (ref eq))
  361. (return_call_ref $kvarargs
  362. (i32.const 2)
  363. (global.get $raise-exception)
  364. (local.get $exn)
  365. (ref.i31 (i32.const 1))
  366. (struct.get $proc $func (global.get $raise-exception))))
  367. (func $raise-returned-value
  368. (param $nargs i32)
  369. (param $arg0 (ref eq)) (param $arg1 (ref eq)) (param $arg2 (ref eq))
  370. (if (i32.ne (local.get $nargs) (i32.const 1))
  371. (then (call $die0
  372. (string.const "unexpected raise-exception return"))))
  373. (return_call $raise-exception (local.get $arg0)))
  374. (func $push-raise-returned-value
  375. (global.set $ret-sp (i32.add (global.get $ret-sp) (i32.const 1)))
  376. (call $maybe-grow-ret-stack)
  377. (table.set $ret-stack
  378. (i32.sub (global.get $ret-sp) (i32.const 1))
  379. (ref.func $raise-returned-value)))
  380. (func $raise-type-error
  381. (param $subr (ref string))
  382. (param $what (ref string))
  383. (param $val (ref eq))
  384. (call $push-raise-returned-value)
  385. (global.set $arg3 (struct.new $string (i32.const 0)
  386. (local.get $what)))
  387. (return_call_ref $kvarargs
  388. (i32.const 4)
  389. (global.get $make-type-error)
  390. (local.get $val)
  391. (struct.new $string (i32.const 0)
  392. (local.get $subr))
  393. (struct.get $proc $func
  394. (global.get $make-type-error))))
  395. (func $raise-range-error
  396. (param $subr (ref string))
  397. (param $val (ref eq))
  398. (call $push-raise-returned-value)
  399. (global.set $arg3 (ref.i31 (i32.const 1)))
  400. (global.set $arg4 (local.get $val))
  401. (return_call_ref $kvarargs
  402. (i32.const 5)
  403. (global.get $make-range-error)
  404. (local.get $val)
  405. (ref.i31 (i32.const 1))
  406. (struct.get $proc $func
  407. (global.get $make-range-error))))
  408. (func $raise-arity-error
  409. (param $subr (ref null string))
  410. (param $val (ref eq))
  411. (call $push-raise-returned-value)
  412. (return_call_ref $kvarargs
  413. (i32.const 3)
  414. (global.get $make-arity-error)
  415. (local.get $val)
  416. (if (ref eq)
  417. (ref.is_null (local.get $subr))
  418. (then (ref.i31 (i32.const 1)))
  419. (else (struct.new $string (i32.const 0)
  420. (ref.as_non_null
  421. (local.get $subr)))))
  422. (struct.get $proc $func
  423. (global.get $make-arity-error))))
  424. (func $string->bignum (import "rt" "bignum_from_string")
  425. (param (ref string))
  426. (result (ref extern)))
  427. (func $bignum-from-i32 (import "rt" "bignum_from_i32")
  428. (param i32)
  429. (result (ref extern)))
  430. (func $bignum-from-i64 (import "rt" "bignum_from_i64")
  431. (param i64)
  432. (result (ref extern)))
  433. (func $bignum-from-u64 (import "rt" "bignum_from_u64")
  434. (param i64)
  435. (result (ref extern)))
  436. (func $bignum-is-i64 (import "rt" "bignum_is_i64")
  437. (param (ref extern))
  438. (result i32))
  439. (func $bignum-is-u64 (import "rt" "bignum_is_u64")
  440. (param (ref extern))
  441. (result i32))
  442. (func $bignum-get-i64 (import "rt" "bignum_get_i64")
  443. (param (ref extern))
  444. (result i64))
  445. (func $bignum-add (import "rt" "bignum_add")
  446. (param (ref extern))
  447. (param (ref extern))
  448. (result (ref extern)))
  449. (func $bignum-add-i32 (import "rt" "bignum_add")
  450. (param (ref extern))
  451. (param i32)
  452. (result (ref extern)))
  453. (func $bignum-sub (import "rt" "bignum_sub")
  454. (param (ref extern))
  455. (param (ref extern))
  456. (result (ref extern)))
  457. (func $bignum-sub-i32 (import "rt" "bignum_sub")
  458. (param (ref extern))
  459. (param i32)
  460. (result (ref extern)))
  461. (func $bignum-sub-i32-i32 (import "rt" "bignum_sub")
  462. (param i32)
  463. (param i32)
  464. (result (ref extern)))
  465. (func $bignum-mul (import "rt" "bignum_mul")
  466. (param (ref extern))
  467. (param (ref extern))
  468. (result (ref extern)))
  469. (func $bignum-mul-i32 (import "rt" "bignum_mul")
  470. (param (ref extern))
  471. (param i32)
  472. (result (ref extern)))
  473. (func $bignum-lsh (import "rt" "bignum_lsh")
  474. (param (ref extern))
  475. (param i64)
  476. (result (ref extern)))
  477. (func $i32-lsh (import "rt" "bignum_lsh")
  478. (param i32)
  479. (param i64)
  480. (result (ref extern)))
  481. (func $bignum-rsh (import "rt" "bignum_rsh")
  482. (param (ref extern))
  483. (param i64)
  484. (result (ref extern)))
  485. (func $bignum-quo (import "rt" "bignum_quo")
  486. (param (ref extern))
  487. (param (ref extern))
  488. (result (ref extern)))
  489. (func $bignum-rem (import "rt" "bignum_rem")
  490. (param (ref extern))
  491. (param (ref extern))
  492. (result (ref extern)))
  493. (func $bignum-mod (import "rt" "bignum_mod")
  494. (param (ref extern))
  495. (param (ref extern))
  496. (result (ref extern)))
  497. (func $bignum-gcd (import "rt" "bignum_gcd")
  498. (param (ref extern))
  499. (param (ref extern))
  500. (result (ref extern)))
  501. (func $bignum-logand-i32 (import "rt" "bignum_logand")
  502. (param (ref extern))
  503. (param i32)
  504. (result (ref extern)))
  505. (func $bignum-logand-bignum (import "rt" "bignum_logand")
  506. (param (ref extern))
  507. (param (ref extern))
  508. (result (ref extern)))
  509. (func $bignum-logior-i32 (import "rt" "bignum_logior")
  510. (param (ref extern))
  511. (param i32)
  512. (result (ref extern)))
  513. (func $bignum-logior-bignum (import "rt" "bignum_logior")
  514. (param (ref extern))
  515. (param (ref extern))
  516. (result (ref extern)))
  517. (func $bignum-logxor-i32 (import "rt" "bignum_logxor")
  518. (param (ref extern))
  519. (param i32)
  520. (result (ref extern)))
  521. (func $bignum-logxor-bignum (import "rt" "bignum_logxor")
  522. (param (ref extern))
  523. (param (ref extern))
  524. (result (ref extern)))
  525. (func $i32-logsub-bignum (import "rt" "bignum_logsub")
  526. (param i32)
  527. (param (ref extern))
  528. (result (ref extern)))
  529. (func $bignum-logsub-i32 (import "rt" "bignum_logsub")
  530. (param (ref extern))
  531. (param i32)
  532. (result (ref extern)))
  533. (func $bignum-logsub-bignum (import "rt" "bignum_logsub")
  534. (param (ref extern))
  535. (param (ref extern))
  536. (result (ref extern)))
  537. (func $lt-fix-big (import "rt" "bignum_lt")
  538. (param i32)
  539. (param (ref extern))
  540. (result i32))
  541. (func $lt-big-fix (import "rt" "bignum_lt")
  542. (param (ref extern))
  543. (param i32)
  544. (result i32))
  545. (func $lt-big-big (import "rt" "bignum_lt")
  546. (param (ref extern))
  547. (param (ref extern))
  548. (result i32))
  549. (func $lt-big-flo (import "rt" "bignum_lt")
  550. (param (ref extern))
  551. (param f64)
  552. (result i32))
  553. (func $lt-flo-big (import "rt" "bignum_lt")
  554. (param f64)
  555. (param (ref extern))
  556. (result i32))
  557. (func $le-fix-big (import "rt" "bignum_le")
  558. (param i32)
  559. (param (ref extern))
  560. (result i32))
  561. (func $le-big-fix (import "rt" "bignum_le")
  562. (param (ref extern))
  563. (param i32)
  564. (result i32))
  565. (func $le-big-big (import "rt" "bignum_le")
  566. (param (ref extern))
  567. (param (ref extern))
  568. (result i32))
  569. (func $le-big-flo (import "rt" "bignum_le")
  570. (param (ref extern))
  571. (param f64)
  572. (result i32))
  573. (func $le-flo-big (import "rt" "bignum_le")
  574. (param f64)
  575. (param (ref extern))
  576. (result i32))
  577. (func $eq-fix-big (import "rt" "bignum_eq")
  578. (param i32)
  579. (param (ref extern))
  580. (result i32))
  581. (func $eq-big-fix (import "rt" "bignum_eq")
  582. (param (ref extern))
  583. (param i32)
  584. (result i32))
  585. (func $eq-big-big (import "rt" "bignum_eq")
  586. (param (ref extern))
  587. (param (ref extern))
  588. (result i32))
  589. (func $eq-big-flo (import "rt" "bignum_eq")
  590. (param (ref extern))
  591. (param f64)
  592. (result i32))
  593. (func $eq-flo-big (import "rt" "bignum_eq")
  594. (param f64)
  595. (param (ref extern))
  596. (result i32))
  597. (func $bignum-to-f64 (import "rt" "bignum_to_f64")
  598. (param (ref extern))
  599. (result f64))
  600. (func $f64-is-nan (import "rt" "f64_is_nan")
  601. (param f64)
  602. (result i32))
  603. (func $f64-is-infinite (import "rt" "f64_is_infinite")
  604. (param f64)
  605. (result i32))
  606. (func $flonum->string (import "rt" "flonum_to_string")
  607. (param f64)
  608. (result (ref string)))
  609. (func $string-upcase (import "rt" "string_upcase")
  610. (param (ref string))
  611. (result (ref string)))
  612. (func $string-downcase (import "rt" "string_downcase")
  613. (param (ref string))
  614. (result (ref string)))
  615. (func $make-weak-map (import "rt" "make_weak_map")
  616. (result (ref extern)))
  617. (func $weak-map-get (import "rt" "weak_map_get")
  618. (param (ref extern) (ref eq) (ref eq))
  619. (result (ref eq)))
  620. (func $weak-map-set (import "rt" "weak_map_set")
  621. (param (ref extern) (ref eq) (ref eq)))
  622. (func $weak-map-delete (import "rt" "weak_map_delete")
  623. (param (ref extern) (ref eq))
  624. (result i32))
  625. ;; FIXME: These are very much temporary.
  626. (func $write-stdout (import "io" "write_stdout") (param (ref string)))
  627. (func $write-stderr (import "io" "write_stderr") (param (ref string)))
  628. (func $read-stdin (import "io" "read_stdin") (result (ref string)))
  629. (func $fsqrt (import "rt" "fsqrt") (param f64) (result f64))
  630. (func $fsin (import "rt" "fsin") (param f64) (result f64))
  631. (func $fcos (import "rt" "fcos") (param f64) (result f64))
  632. (func $ftan (import "rt" "ftan") (param f64) (result f64))
  633. (func $fasin (import "rt" "fasin") (param f64) (result f64))
  634. (func $facos (import "rt" "facos") (param f64) (result f64))
  635. (func $fatan (import "rt" "fatan") (param f64) (result f64))
  636. (func $fatan2 (import "rt" "fatan2") (param f64 f64) (result f64))
  637. (func $flog (import "rt" "flog") (param f64) (result f64))
  638. (func $fexp (import "rt" "fexp") (param f64) (result f64))
  639. (func $jiffies-per-second (import "rt" "jiffies_per_second") (result i32))
  640. (func $current-jiffy (import "rt" "current_jiffy") (result f64))
  641. (func $current-second (import "rt" "current_second") (result f64))
  642. (func $die (import "rt" "die")
  643. (param (ref string) (ref eq)))
  644. (func $debug-str (import "debug" "debug_str")
  645. (param (ref string)))
  646. (func $debug-str-i32 (import "debug" "debug_str_i32")
  647. (param (ref string) i32))
  648. (func $debug-str-scm (import "debug" "debug_str_scm")
  649. (param (ref string) (ref eq)))
  650. (func $procedure->extern (import "ffi" "procedure_to_extern")
  651. (param (ref eq)) (result (ref extern)))
  652. (func $die0 (param $reason (ref string))
  653. (call $die (local.get 0) (ref.i31 (i32.const 1))))
  654. ;; Thomas Wang's integer hasher, from
  655. ;; http://www.cris.com/~Ttwang/tech/inthash.htm.
  656. (func $integer-hash (param $v i32) (result i32)
  657. (local.set $v (i32.xor (i32.xor (local.get $v) (i32.const 61))
  658. (i32.shr_u (local.get $v) (i32.const 16))))
  659. (local.set $v (i32.add (local.get $v)
  660. (i32.shl (local.get $v) (i32.const 3))))
  661. (local.set $v (i32.xor (local.get $v)
  662. (i32.shr_u (local.get $v) (i32.const 4))))
  663. (local.set $v (i32.mul (local.get $v)
  664. (i32.const #x27d4eb2d)))
  665. (i32.xor (local.get $v)
  666. (i32.shr_u (local.get $v) (i32.const 15))))
  667. (func $finish-heap-object-hash (param $hash i32) (result i32)
  668. (local.set $hash (call $integer-hash (local.get $hash)))
  669. (if i32 (local.get $hash)
  670. (then (local.get $hash))
  671. (else (call $integer-hash (i32.const 42)))))
  672. (global $hashq-counter (mut i32) (i32.const 0))
  673. (func $immediate-hashq (param $v (ref i31)) (result i32)
  674. (call $integer-hash (i31.get_u (local.get $v))))
  675. (func $heap-object-hashq (param $v (ref $heap-object)) (result i32)
  676. (local $tag i32)
  677. (local.set $tag (struct.get $heap-object $hash (local.get $v)))
  678. (loop $init-if-zero
  679. (block
  680. $done
  681. (br_if $done (local.get $tag))
  682. (global.set $hashq-counter
  683. (i32.sub (global.get $hashq-counter) (i32.const 1)))
  684. (struct.set $heap-object $hash (local.get $v)
  685. (local.tee $tag (call $integer-hash
  686. (global.get $hashq-counter))))
  687. ;; Check and retry if result is zero.
  688. (br $init-if-zero)))
  689. (local.get $tag))
  690. (func $hashq (param $v (ref eq)) (result i32)
  691. (if i32
  692. (ref.test i31 (local.get $v))
  693. (then
  694. (return_call $immediate-hashq
  695. (ref.cast i31 (local.get $v))))
  696. (else
  697. (return_call $heap-object-hashq
  698. (ref.cast $heap-object (local.get $v))))))
  699. (func $grow-raw-stack
  700. ;; Grow the stack by at least 50% and at least the needed
  701. ;; space. Trap if we fail to grow.
  702. ;; additional_size = (current_size >> 1) | needed_size
  703. (if (i32.eq
  704. (memory.grow
  705. $raw-stack
  706. (i32.or (i32.shr_u (memory.size $raw-stack) (i32.const 1))
  707. ;; Wasm pages are 64 kB.
  708. (i32.sub (i32.add (i32.shr_u (global.get $raw-sp)
  709. (i32.const 16))
  710. (i32.const 1))
  711. (memory.size $raw-stack))))
  712. (i32.const -1))
  713. (then (call $die0 (string.const "$grow-raw-stack")) (unreachable))))
  714. (func $maybe-grow-raw-stack
  715. (if (i32.lt_u (i32.shl (memory.size $raw-stack) (i32.const 16))
  716. (global.get $raw-sp))
  717. (then (call $grow-raw-stack))))
  718. (func $grow-scm-stack
  719. ;; Grow as in $grow-raw-stack.
  720. (if (i32.eq
  721. (table.grow $scm-stack
  722. (ref.i31 (i32.const 0))
  723. (i32.or (i32.shr_u (table.size $scm-stack)
  724. (i32.const 1))
  725. (i32.sub (global.get $scm-sp)
  726. (table.size $scm-stack))))
  727. (i32.const -1))
  728. (then
  729. (call $die0 (string.const "$grow-scm-stack"))
  730. (unreachable))))
  731. (func $maybe-grow-scm-stack
  732. (if (i32.lt_u (table.size $scm-stack) (global.get $scm-sp))
  733. (then (call $grow-scm-stack))))
  734. (func $invalid-continuation (type $kvarargs)
  735. (call $die0 (string.const "$invalid-continuation"))
  736. (unreachable))
  737. (func $grow-ret-stack
  738. ;; Grow as in $grow-raw-stack.
  739. (if (i32.eq (table.grow $ret-stack
  740. (ref.func $invalid-continuation)
  741. (i32.or (i32.shr_u (table.size $ret-stack)
  742. (i32.const 1))
  743. (i32.sub (global.get $ret-sp)
  744. (table.size $ret-stack))))
  745. (i32.const -1))
  746. (then
  747. (call $die0 (string.const "$grow-ret-stack"))
  748. (unreachable))))
  749. (func $maybe-grow-ret-stack
  750. (if (i32.lt_u (table.size $ret-stack) (global.get $ret-sp))
  751. (then (call $grow-ret-stack))))
  752. (func $grow-dyn-stack
  753. ;; Grow as in $grow-ret-stack.
  754. (if (i32.eq (table.grow $dyn-stack
  755. (ref.null $dyn)
  756. (i32.or (i32.shr_u (table.size $dyn-stack)
  757. (i32.const 1))
  758. (i32.sub (global.get $dyn-sp)
  759. (table.size $dyn-stack))))
  760. (i32.const -1))
  761. (then
  762. (call $die0 (string.const "$grow-dyn-stack"))
  763. (unreachable))))
  764. (func $maybe-grow-dyn-stack
  765. (if (i32.lt_u (table.size $dyn-stack) (global.get $dyn-sp))
  766. (then (call $grow-dyn-stack))))
  767. (func $collect-rest-args (param $nargs i32)
  768. (param $arg0 (ref eq)) (param $arg1 (ref eq)) (param $arg2 (ref eq))
  769. (param $npositional i32)
  770. (result (ref eq))
  771. (local $ret (ref eq))
  772. (local.set $ret (ref.i31 (i32.const 13))) ;; null
  773. (block
  774. $done
  775. (block
  776. $nargs1
  777. (block
  778. $nargs2
  779. (block
  780. $nargs3
  781. (block
  782. $nargs4
  783. (block
  784. $nargs5
  785. (block
  786. $nargs6
  787. (block
  788. $nargs7
  789. (block
  790. $nargs8
  791. (block
  792. $nargsN
  793. (br_table $done
  794. $nargs1
  795. $nargs2
  796. $nargs3
  797. $nargs4
  798. $nargs5
  799. $nargs6
  800. $nargs7
  801. $nargs8
  802. $nargsN
  803. (local.get $nargs)))
  804. (loop $lp
  805. (if (i32.gt_u (local.get $nargs) (i32.const 8))
  806. (then
  807. (br_if $done (i32.le_u (local.get $nargs)
  808. (local.get $npositional)))
  809. (local.set
  810. $ret
  811. (struct.new
  812. $pair
  813. (i32.const 0)
  814. (ref.as_non_null
  815. (table.get
  816. $argv
  817. (i32.sub
  818. (local.tee $nargs
  819. (i32.sub (local.get $nargs) (i32.const 1)))
  820. (i32.const 8))))
  821. (local.get $ret)))
  822. (br $lp)))))
  823. (br_if $done (i32.le_u (i32.const 8) (local.get $npositional)))
  824. (local.set $ret
  825. (struct.new $pair (i32.const 0)
  826. (global.get $arg7) (local.get $ret))))
  827. (br_if $done (i32.le_u (i32.const 7) (local.get $npositional)))
  828. (local.set $ret
  829. (struct.new $pair (i32.const 0)
  830. (global.get $arg6) (local.get $ret))))
  831. (br_if $done (i32.le_u (i32.const 6) (local.get $npositional)))
  832. (local.set $ret
  833. (struct.new $pair (i32.const 0)
  834. (global.get $arg5) (local.get $ret))))
  835. (br_if $done (i32.le_u (i32.const 5) (local.get $npositional)))
  836. (local.set $ret
  837. (struct.new $pair (i32.const 0)
  838. (global.get $arg4) (local.get $ret))))
  839. (br_if $done (i32.le_u (i32.const 4) (local.get $npositional)))
  840. (local.set $ret
  841. (struct.new $pair (i32.const 0)
  842. (global.get $arg3) (local.get $ret))))
  843. (br_if $done (i32.le_u (i32.const 3) (local.get $npositional)))
  844. (local.set $ret
  845. (struct.new $pair (i32.const 0)
  846. (local.get $arg2) (local.get $ret))))
  847. (br_if $done (i32.le_u (i32.const 2) (local.get $npositional)))
  848. (local.set $ret
  849. (struct.new $pair (i32.const 0)
  850. (local.get $arg1) (local.get $ret)))
  851. )
  852. (br_if $done (i32.le_u (i32.const 1) (local.get $npositional)))
  853. (local.set $ret
  854. (struct.new $pair (i32.const 0)
  855. (local.get $arg0) (local.get $ret))))
  856. (local.get $ret))
  857. (func $values (param $nargs i32) (param $arg0 (ref eq))
  858. (param $arg1 (ref eq)) (param $arg2 (ref eq))
  859. (block
  860. $done
  861. (local.set $arg0 (local.get $arg1))
  862. (local.set $arg1 (local.get $arg2))
  863. (br_if $done (i32.le_u (local.get $nargs) (i32.const 3)))
  864. (local.set $arg2 (global.get $arg3))
  865. (global.set $arg3 (global.get $arg4))
  866. (global.set $arg4 (global.get $arg5))
  867. (global.set $arg5 (global.get $arg6))
  868. (global.set $arg6 (global.get $arg7))
  869. (br_if $done (i32.le_u (local.get $nargs) (i32.const 8)))
  870. (global.set $arg7 (ref.as_non_null (table.get $argv (i32.const 0))))
  871. (table.copy $argv $argv (i32.const 0) (i32.const 1)
  872. (i32.sub (local.get $nargs) (i32.const 9))))
  873. (i32.sub (local.get $nargs) (i32.const 1))
  874. (local.get $arg0)
  875. (local.get $arg1)
  876. (local.get $arg2)
  877. (global.set $ret-sp (i32.sub (global.get $ret-sp) (i32.const 1)))
  878. (global.get $ret-sp)
  879. (table.get $ret-stack)
  880. (return_call_ref $kvarargs))
  881. (global $values-primitive (ref eq)
  882. (struct.new $proc (i32.const 0) (ref.func $values)))
  883. (global $append-primitive (mut (ref $proc))
  884. (struct.new $proc (i32.const 0) (ref.func $invalid-continuation)))
  885. (func $make-hash-table (result (ref $hash-table))
  886. (struct.new $hash-table (i32.const 0) (i32.const 0)
  887. (array.new $raw-scmvector
  888. (ref.i31 (i32.const 13)) (i32.const 47))))
  889. (func $hashq-lookup (param $tab (ref $hash-table)) (param $k (ref eq))
  890. (result (ref null $pair))
  891. (local $idx i32)
  892. (local $buckets (ref $raw-scmvector))
  893. (local $chain (ref eq))
  894. (local $head (ref $pair))
  895. (local $link (ref $pair))
  896. (local.set $buckets
  897. (struct.get $hash-table $buckets (local.get $tab)))
  898. (local.set $idx
  899. (i32.rem_u (call $hashq (local.get $k))
  900. (array.len (local.get $buckets))))
  901. (local.set $chain
  902. (array.get $raw-scmvector
  903. (local.get $buckets) (local.get $idx)))
  904. (loop $lp
  905. (if (i32.eqz (ref.test $pair (local.get $chain)))
  906. (then (return (ref.null $pair)))
  907. (else
  908. (local.set $link (ref.cast $pair (local.get $chain)))
  909. (local.set $head
  910. (ref.cast $pair
  911. (struct.get $pair $car
  912. (local.get $link))))
  913. (if (ref.eq (struct.get $pair $car (local.get $head))
  914. (local.get $k))
  915. (then
  916. (return (local.get $head)))
  917. (else
  918. (local.set $chain
  919. (struct.get $pair $cdr (local.get $link)))
  920. (br $lp))))))
  921. (unreachable))
  922. (func $hashq-lookup/default
  923. (param $table (ref $hash-table))
  924. (param $key (ref eq))
  925. (param $default (ref eq))
  926. (result (ref eq))
  927. (local $handle (ref null $pair))
  928. (local.set $handle (call $hashq-lookup
  929. (local.get $table)
  930. (local.get $key)))
  931. (if (ref eq)
  932. (ref.is_null (local.get $handle))
  933. (then (local.get $default))
  934. (else (ref.as_non_null (local.get $handle)))))
  935. (func $hashq-insert (param $tab (ref $hash-table)) (param $k (ref eq))
  936. (param $v (ref eq))
  937. (local $idx i32)
  938. (local $buckets (ref $raw-scmvector))
  939. (local.set $buckets (struct.get $hash-table $buckets (local.get $tab)))
  940. (local.set $idx (i32.rem_u (call $hashq (local.get $k))
  941. (array.len (local.get $buckets))))
  942. (array.set
  943. $raw-scmvector
  944. (local.get $buckets) (local.get $idx)
  945. (struct.new
  946. $pair (i32.const 0)
  947. (struct.new $pair (i32.const 0) (local.get $k) (local.get $v))
  948. (array.get $raw-scmvector (local.get $buckets) (local.get $idx))))
  949. (struct.set $hash-table $size
  950. (local.get $tab)
  951. (i32.add (struct.get $hash-table $size (local.get $tab))
  952. (i32.const 1))))
  953. (func $hashq-ref (param $tab (ref $hash-table)) (param $k (ref eq))
  954. (param $default (ref eq))
  955. (result (ref eq))
  956. (local $handle (ref null $pair))
  957. (local.set $handle
  958. (call $hashq-lookup (local.get $tab) (local.get $k)))
  959. (if (ref eq)
  960. (ref.is_null (local.get $handle))
  961. (then (local.get $default))
  962. (else (struct.get $pair $cdr (local.get $handle)))))
  963. (func $hashq-update (param $tab (ref $hash-table)) (param $k (ref eq))
  964. (param $v (ref eq)) (param $default (ref eq))
  965. (result (ref eq))
  966. (local $handle (ref null $pair))
  967. (local.set $handle
  968. (call $hashq-lookup (local.get $tab) (local.get $k)))
  969. (if (ref eq)
  970. (ref.is_null (local.get $handle))
  971. (then
  972. (call $hashq-insert (local.get $tab) (local.get $k)
  973. (local.get $v))
  974. (local.get $default))
  975. (else
  976. (struct.get $pair $cdr (local.get $handle))
  977. (struct.set $pair $cdr (local.get $handle)
  978. (local.get $v)))))
  979. (func $hashq-set! (param $tab (ref $hash-table)) (param $k (ref eq))
  980. (param $v (ref eq))
  981. (call $hashq-update (local.get $tab) (local.get $k)
  982. (local.get $v) (ref.i31 (i32.const 1)))
  983. (drop))
  984. (func $hashq-delete! (param $tab (ref $hash-table)) (param $k (ref eq))
  985. (local $idx i32)
  986. (local $buckets (ref $raw-scmvector))
  987. (local $chain (ref eq))
  988. (local $head (ref $pair))
  989. (local $link (ref $pair))
  990. (local $last (ref null $pair))
  991. (local.set $buckets
  992. (struct.get $hash-table $buckets (local.get $tab)))
  993. (local.set $idx
  994. (i32.rem_u (call $hashq (local.get $k))
  995. (array.len (local.get $buckets))))
  996. (local.set $chain
  997. (array.get $raw-scmvector
  998. (local.get $buckets) (local.get $idx)))
  999. (loop $lp
  1000. (if (i32.eqz (ref.test $pair (local.get $chain)))
  1001. (then (return))
  1002. (else
  1003. (local.set $link (ref.cast $pair (local.get $chain)))
  1004. (local.set $head
  1005. (ref.cast $pair
  1006. (struct.get $pair $car
  1007. (local.get $link))))
  1008. (if (ref.eq (struct.get $pair $car (local.get $head))
  1009. (local.get $k))
  1010. (then
  1011. (struct.set $hash-table $size
  1012. (local.get $tab)
  1013. (i32.sub (struct.get $hash-table $size
  1014. (local.get $tab))
  1015. (i32.const 1)))
  1016. (if (ref.is_null (local.get $last))
  1017. (then
  1018. (array.set $raw-scmvector
  1019. (local.get $buckets)
  1020. (local.get $idx)
  1021. (struct.get $pair $cdr
  1022. (local.get $link)))
  1023. (return))
  1024. (else
  1025. (struct.set $pair $cdr
  1026. (ref.as_non_null (local.get $last))
  1027. (struct.get $pair $cdr
  1028. (local.get $link)))
  1029. (return))))
  1030. (else
  1031. (local.set $chain
  1032. (struct.get $pair $cdr (local.get $link)))
  1033. (local.set $last (local.get $link))
  1034. (br $lp))))))
  1035. (unreachable))
  1036. ;; A specialized hash table, because it's not a hashq lookup.
  1037. (type $symtab-entry
  1038. (struct (field $sym (ref $symbol))
  1039. (field $next (ref null $symtab-entry))))
  1040. (type $symtab (array (mut (ref null $symtab-entry))))
  1041. (global $the-symtab (ref $symtab)
  1042. (array.new $symtab (ref.null $symtab-entry) (i32.const 47)))
  1043. ,(cond
  1044. (import-abi?
  1045. '(func $intern-symbol! (import "abi" "$intern-symbol!")
  1046. (param $sym (ref $symbol)) (result (ref $symbol))))
  1047. (else
  1048. '(func $intern-symbol!
  1049. (param $sym (ref $symbol)) (result (ref $symbol))
  1050. (local $hash i32)
  1051. (local $idx i32)
  1052. (local $entry (ref null $symtab-entry))
  1053. (local.set $hash (struct.get $heap-object $hash (local.get $sym)))
  1054. (local.set $idx (i32.rem_u (local.get $hash)
  1055. (array.len (global.get $the-symtab))))
  1056. (local.set $entry
  1057. (array.get $symtab (global.get $the-symtab)
  1058. (local.get $idx)))
  1059. (block
  1060. $insert
  1061. (loop $lp
  1062. (br_if $insert (ref.is_null (local.get $entry)))
  1063. (block
  1064. $next
  1065. (br_if $next
  1066. (i32.ne (struct.get $symbol $hash
  1067. (struct.get $symtab-entry $sym
  1068. (local.get $entry)))
  1069. (local.get $hash)))
  1070. (br_if $next
  1071. (i32.eqz
  1072. (string.eq
  1073. (struct.get $string $str
  1074. (struct.get $symbol $name
  1075. (struct.get $symtab-entry $sym
  1076. (local.get $entry))))
  1077. (struct.get $string $str
  1078. (struct.get $symbol $name
  1079. (local.get $sym))))))
  1080. (return (struct.get $symtab-entry $sym (local.get $entry))))
  1081. (local.set $entry
  1082. (struct.get $symtab-entry $next (local.get $entry)))
  1083. (br $lp)))
  1084. (array.set $symtab (global.get $the-symtab) (local.get $idx)
  1085. (struct.new $symtab-entry
  1086. (local.get $sym)
  1087. (array.get $symtab (global.get $the-symtab)
  1088. (local.get $idx))))
  1089. (local.get $sym))))
  1090. ;; For now, the Java string hash function, except over codepoints
  1091. ;; rather than WTF-16 code units.
  1092. (func $string-hash (param $str (ref string)) (result i32)
  1093. (local $iter (ref stringview_iter))
  1094. (local $hash i32)
  1095. (local $codepoint i32)
  1096. (local.set $iter (string.as_iter (local.get $str)))
  1097. (block $done
  1098. (loop $lp
  1099. (local.set $codepoint (stringview_iter.next (local.get $iter)))
  1100. (br_if $done (i32.eq (i32.const -1) (local.get $codepoint)))
  1101. (local.set $hash
  1102. (i32.add (i32.mul (local.get $hash) (i32.const 31))
  1103. (local.get $codepoint)))
  1104. (br $lp)))
  1105. (local.get $hash))
  1106. (func $string->symbol (param $str (ref $string)) (result (ref $symbol))
  1107. (call $intern-symbol!
  1108. (struct.new $symbol
  1109. (call $finish-heap-object-hash
  1110. (call $string-hash
  1111. (struct.get $string $str
  1112. (local.get $str))))
  1113. (local.get $str))))
  1114. (global $the-kwtab (ref $hash-table)
  1115. (struct.new $hash-table (i32.const 0) (i32.const 0)
  1116. (array.new $raw-scmvector
  1117. (ref.i31 (i32.const 13)) (i32.const 47))))
  1118. ,(cond
  1119. (import-abi?
  1120. '(func $intern-keyword! (import "abi" "$intern-keyword!")
  1121. (param $sym (ref $keyword)) (result (ref $keyword))))
  1122. (else
  1123. '(func $intern-keyword! (param $kw (ref $keyword)) (result (ref $keyword))
  1124. (local $handle (ref null $pair))
  1125. (local.set $handle
  1126. (call $hashq-lookup (global.get $the-kwtab)
  1127. (struct.get $keyword $name (local.get $kw))))
  1128. (if (ref $keyword)
  1129. (ref.is_null (local.get $handle))
  1130. (then
  1131. (call $hashq-insert (global.get $the-kwtab)
  1132. (struct.get $keyword $name (local.get $kw))
  1133. (local.get $kw))
  1134. (local.get $kw))
  1135. (else
  1136. (ref.cast $keyword
  1137. (struct.get $pair $cdr (local.get $handle))))))))
  1138. (func $symbol->keyword (param $sym (ref $symbol)) (result (ref $keyword))
  1139. (call $intern-keyword!
  1140. (struct.new $keyword
  1141. (call $finish-heap-object-hash
  1142. (struct.get $symbol $hash (local.get $sym)))
  1143. (local.get $sym))))
  1144. (func $push-dyn (param $dyn (ref $dyn))
  1145. (local $dyn-sp i32)
  1146. (global.set $dyn-sp
  1147. (i32.add (local.tee $dyn-sp (global.get $dyn-sp))
  1148. (i32.const 1)))
  1149. (call $maybe-grow-dyn-stack)
  1150. (table.set $dyn-stack (local.get $dyn-sp) (local.get $dyn)))
  1151. (func $wind-dynstate (param $dynstate (ref $dynstate))
  1152. (local $fluids (ref $hash-table))
  1153. (local.set $fluids (global.get $current-fluids))
  1154. (global.set $current-fluids
  1155. (struct.get $dynstate $fluids (local.get $dynstate)))
  1156. (struct.set $dynstate $fluids (local.get $dynstate)
  1157. (local.get $fluids)))
  1158. (func $push-dynamic-state (param $state (ref $dynamic-state))
  1159. (local $dynstate (ref $dynstate))
  1160. (call $push-dyn
  1161. (local.tee $dynstate
  1162. (struct.new $dynstate
  1163. (struct.get $dynamic-state $fluids
  1164. (local.get $state)))))
  1165. (return_call $wind-dynstate (local.get $dynstate)))
  1166. (func $pop-dynamic-state
  1167. (local $sp i32)
  1168. (global.set $dyn-sp
  1169. (local.tee $sp (i32.sub (global.get $dyn-sp)
  1170. (i32.const 1))))
  1171. (return_call $wind-dynstate
  1172. (ref.as_non_null (global) (table.get $dy)) (local.get $dynstate)))
  1173. (func $wind-dynfluid (param $dynfluid (ref $dynfluid))
  1174. (local $fluid (ref $fluid))
  1175. (local.set $fluid
  1176. (struct.get $dynfluid $fluid (local.get $dynfluid)))
  1177. (struct.set
  1178. $dynfluid $val
  1179. (local.get $dynfluid)
  1180. (call $hashq-update (global.get $current-fluids)
  1181. (local.get $fluid)
  1182. (struct.get $dynfluid $val (local.get $dynfluid))
  1183. (struct.get $fluid $init (local.get $fluid)))))
  1184. (func $push-fluid (param $fluid (ref $fluid)) (param $val (ref eq))
  1185. (local $dynfluid (ref $dynfluid))
  1186. (local.set $dynfluid
  1187. (struct.new $dynfluid
  1188. (local.get $fluid) (local.get $val)))
  1189. (call $push-dyn (local.get $dynfluid))
  1190. (call $wind-dynfluid (local.get $dynfluid)))
  1191. (func $pop-fluid
  1192. (local $sp i32)
  1193. (global.set $dyn-sp
  1194. (local.tee $sp (i32.sub (global.get $dyn-sp)
  1195. (i32.const 1))))
  1196. (call $wind-dynfluid
  1197. (ref.cast $dynfluid (table.get $dyn-stack (local.get $sp)))))
  1198. (func $fluid-ref (param $fluid (ref $fluid)) (result (ref eq))
  1199. (call $hashq-ref (global.get $current-fluids)
  1200. (local.get $fluid)
  1201. (struct.get $fluid $init (local.get $fluid))))
  1202. (func $fluid-ref* (param $fluid (ref $fluid)) (param $depth i32)
  1203. (result (ref eq))
  1204. (local $sp i32)
  1205. (local $dyn (ref $dyn))
  1206. (if (local.get $depth)
  1207. (then
  1208. (local.set $sp (global.get $dyn-sp))
  1209. (loop $lp
  1210. (if (local.get $sp)
  1211. (then
  1212. (local.set $sp (i32.sub (local.get $sp) (i32.const 1)))
  1213. (local.set $dyn (ref.as_non_null
  1214. (table.get $dyn-stack (local.get $sp))))
  1215. (br_if $lp (i32.eqz
  1216. (ref.test $dynfluid (local.get $dyn))))
  1217. (local.set $depth
  1218. (i32.sub (local.get $depth) (i32.const 1)))
  1219. (br_if $lp (local.get $depth))
  1220. (return
  1221. (struct.get
  1222. $dynfluid $val
  1223. (ref.cast $dynfluid (local.get $dyn)))))
  1224. (else (return (ref.i31 (i32.const 1)))))))
  1225. (else (return_call $fluid-ref (local.get $fluid))))
  1226. (unreachable))
  1227. (func $fluid-set! (param $fluid (ref $fluid)) (param $val (ref eq))
  1228. (call $hashq-set! (global.get $current-fluids)
  1229. (local.get $fluid)
  1230. (local.get $val)))
  1231. ;; FIXME: Better error handling if prompt not found.
  1232. (func $find-prompt (param $tag (ref eq))
  1233. (result (ref $dynprompt) i32)
  1234. (local $dyn (ref $dyn))
  1235. (local $prompt (ref $dynprompt))
  1236. (local $sp i32)
  1237. (local.set $sp (global.get $dyn-sp))
  1238. (loop $lp
  1239. (if (local.get $sp)
  1240. (then
  1241. (local.set $sp (i32.sub (local.get $sp) (i32.const 1)))
  1242. ;; FIXME: could br_on_cast_fail to $lp; need to fix
  1243. ;; the assembler.
  1244. (local.set $dyn (ref.as_non_null
  1245. (table.get $dyn-stack (local.get $sp))))
  1246. (if (ref.test $dynprompt (local.get $dyn))
  1247. (then
  1248. (local.set $prompt
  1249. (ref.cast $dynprompt (local.get $dyn)))
  1250. (if (ref.eq (struct.get $dynprompt $tag
  1251. (local.get $prompt))
  1252. (local.get $tag))
  1253. (then (return (local.get $prompt)
  1254. (local.get $sp)))
  1255. (else (br $lp)))))
  1256. (br $lp))
  1257. (else
  1258. (call $die (string.const "prompt not found")
  1259. (local.get $tag)))))
  1260. (unreachable))
  1261. (func $rewind
  1262. (param $raw-sp-adjust i32)
  1263. (param $scm-sp-adjust i32)
  1264. (param $ret-sp-adjust i32)
  1265. (param $dyn (ref $raw-dynvector))
  1266. (param $i i32)
  1267. (param $args (ref eq))
  1268. (local $d (ref $dyn))
  1269. (local $dynwind (ref $dynwind))
  1270. (local $dynprompt (ref $dynprompt))
  1271. (local $dynfluid (ref $dynfluid))
  1272. (local $dynstate (ref $dynstate))
  1273. (local $base i32)
  1274. (loop $lp
  1275. (if (i32.eq (local.get $i) (array.len (local.get $dyn)))
  1276. (then
  1277. (return_call $apply (i32.const 3)
  1278. (global.get $apply-primitive)
  1279. (global.get $values-primitive)
  1280. (local.get $args))))
  1281. (local.set $d (array.get $raw-dynvector
  1282. (local.get $dyn)
  1283. (local.get $i)))
  1284. (block
  1285. $next
  1286. (if (ref.test $dynwind (local.get $d))
  1287. (then
  1288. (local.set $dynwind (ref.cast $dynwind (local.get $d)))
  1289. (local.set $base (global.get $raw-sp))
  1290. (global.set $raw-sp (i32.add (local.get $base) (i32.const 16)))
  1291. (global.set $scm-sp (i32.add (global.get $scm-sp) (i32.const 2)))
  1292. (global.set $ret-sp (i32.add (global.get $ret-sp) (i32.const 1)))
  1293. (call $maybe-grow-raw-stack)
  1294. (call $maybe-grow-scm-stack)
  1295. (call $maybe-grow-ret-stack)
  1296. (i32.store $raw-stack offset=0 (local.get $base)
  1297. (local.get $raw-sp-adjust))
  1298. (i32.store $raw-stack offset=4 (local.get $base)
  1299. (local.get $scm-sp-adjust))
  1300. (i32.store $raw-stack offset=8 (local.get $base)
  1301. (local.get $ret-sp-adjust))
  1302. (i32.store $raw-stack offset=12 (local.get $base)
  1303. (local.get $i))
  1304. (table.set $scm-stack
  1305. (i32.sub (global.get $scm-sp) (i32.const 2))
  1306. (local.get $dyn))
  1307. (table.set $scm-stack
  1308. (i32.sub (global.get $scm-sp) (i32.const 1))
  1309. (local.get $args))
  1310. (table.set $ret-stack
  1311. (i32.sub (global.get $ret-sp) (i32.const 1))
  1312. (ref.func $keep-rewinding))
  1313. (return_call_ref $kvarargs
  1314. (i32.const 1)
  1315. (struct.get $dynwind $wind
  1316. (local.get $dynwind))
  1317. (ref.i31 (i32.const 0))
  1318. (ref.i31 (i32.const 0))
  1319. (struct.get
  1320. $proc $func
  1321. (struct.get $dynwind $wind
  1322. (local.get $dynwind))))))
  1323. (if (ref.test $dynprompt (local.get $d))
  1324. (then
  1325. (local.set $dynprompt (ref.cast $dynprompt (local.get $d)))
  1326. (local.set
  1327. $d
  1328. (struct.new
  1329. $dynprompt
  1330. (i32.add
  1331. (struct.get $dynprompt $raw-sp (local.get $dynprompt))
  1332. (local.get $raw-sp-adjust))
  1333. (i32.add
  1334. (struct.get $dynprompt $scm-sp (local.get $dynprompt))
  1335. (local.get $scm-sp-adjust))
  1336. (i32.add
  1337. (struct.get $dynprompt $ret-sp (local.get $dynprompt))
  1338. (local.get $ret-sp-adjust))
  1339. (struct.get_u $dynprompt $unwind-only?
  1340. (local.get $dynprompt))
  1341. (struct.get $dynprompt $tag (local.get $dynprompt))
  1342. (struct.get $dynprompt $handler (local.get $dynprompt))))
  1343. (br $next)))
  1344. (if (ref.test $dynfluid (local.get $d))
  1345. (then
  1346. (local.set $dynfluid (ref.cast $dynfluid (local.get $d)))
  1347. (call $wind-dynfluid (local.get $dynfluid))
  1348. (br $next)))
  1349. (if (ref.test $dynstate (local.get $d))
  1350. (then
  1351. (local.set $dynstate (ref.cast $dynstate (local.get $d)))
  1352. (call $wind-dynstate (local.get $dynstate))
  1353. (br $next))
  1354. (else (unreachable))))
  1355. (call $push-dyn (local.get $d))
  1356. (local.set $i (i32.add (local.get $i) (i32.const 1)))
  1357. (br $lp)))
  1358. (func $restore-raw-stack (param $v (ref $raw-bytevector))
  1359. (local $sp i32)
  1360. (local $i i32)
  1361. (local $len i32)
  1362. (local.set $sp (global.get $raw-sp))
  1363. (local.set $i (i32.const 0))
  1364. (local.set $len (array.len (local.get $v)))
  1365. (global.set $raw-sp (i32.add (local.get $sp) (local.get $len)))
  1366. (call $maybe-grow-raw-stack)
  1367. (loop $lp
  1368. (if (i32.lt_u (local.get $i) (local.get $len))
  1369. (then
  1370. (i32.store8 $raw-stack
  1371. (i32.add (local.get $sp) (local.get $i))
  1372. (array.get_u $raw-bytevector
  1373. (local.get $v)
  1374. (local.get $i)))
  1375. (local.set $i (i32.add (local.get $i) (i32.const 1)))
  1376. (br $lp)))))
  1377. (func $restore-scm-stack (param $v (ref $raw-scmvector))
  1378. (local $sp i32)
  1379. (local $i i32)
  1380. (local $len i32)
  1381. (local.set $sp (global.get $scm-sp))
  1382. (local.set $len (array.len (local.get $v)))
  1383. (global.set $scm-sp (i32.add (local.get $sp) (local.get $len)))
  1384. (call $maybe-grow-scm-stack)
  1385. (loop $lp
  1386. (if (i32.lt_u (local.get $i) (local.get $len))
  1387. (then
  1388. (table.set $scm-stack
  1389. (i32.add (local.get $sp) (local.get $i))
  1390. (array.get $raw-scmvector
  1391. (local.get $v)
  1392. (local.get $i)))
  1393. (local.set $i (i32.add (local.get $i) (i32.const 1)))
  1394. (br $lp)))))
  1395. (func $restore-ret-stack (param $v (ref $raw-retvector))
  1396. (local $sp i32)
  1397. (local $i i32)
  1398. (local $len i32)
  1399. (local.set $sp (global.get $ret-sp))
  1400. (local.set $len (array.len (local.get $v)))
  1401. (global.set $ret-sp (i32.add (local.get $sp) (local.get $len)))
  1402. (call $maybe-grow-ret-stack)
  1403. (loop $lp
  1404. (if (i32.lt_u (local.get $i) (local.get $len))
  1405. (then
  1406. (table.set $ret-stack
  1407. (i32.add (local.get $sp) (local.get $i))
  1408. (array.get $raw-retvector
  1409. (local.get $v)
  1410. (local.get $i)))
  1411. (local.set $i (i32.add (local.get $i) (i32.const 1)))
  1412. (br $lp)))))
  1413. (func $compose-continuation (param $nargs i32)
  1414. (param $arg0 (ref eq)) (param $arg1 (ref eq)) (param $arg2 (ref eq))
  1415. (local $cont (ref $cont))
  1416. (local $prompt (ref $dynprompt))
  1417. (local $raw-sp-adjust i32)
  1418. (local $scm-sp-adjust i32)
  1419. (local $ret-sp-adjust i32)
  1420. (local $args (ref eq))
  1421. (local.set $cont (ref.cast $cont (local.get $arg0)))
  1422. (local.set $prompt (struct.get $cont $prompt (local.get $cont)))
  1423. (local.set $raw-sp-adjust
  1424. (i32.sub (global.get $raw-sp)
  1425. (struct.get $dynprompt $raw-sp
  1426. (local.get $prompt))))
  1427. (local.set $scm-sp-adjust
  1428. (i32.sub (global.get $scm-sp)
  1429. (struct.get $dynprompt $scm-sp
  1430. (local.get $prompt))))
  1431. (local.set $ret-sp-adjust
  1432. (i32.sub (global.get $ret-sp)
  1433. (struct.get $dynprompt $ret-sp
  1434. (local.get $prompt))))
  1435. (local.set $args
  1436. (call $collect-rest-args (local.get $nargs)
  1437. (local.get $arg0)
  1438. (local.get $arg1)
  1439. (local.get $arg2)
  1440. (i32.const 1)))
  1441. (call $restore-raw-stack
  1442. (struct.get $cont $raw-stack (local.get $cont)))
  1443. (call $restore-scm-stack
  1444. (struct.get $cont $scm-stack (local.get $cont)))
  1445. (call $restore-ret-stack
  1446. (struct.get $cont $ret-stack (local.get $cont)))
  1447. ;; Dyn stack is restored incrementally via $rewind.
  1448. (return_call $rewind
  1449. (local.get $raw-sp-adjust)
  1450. (local.get $scm-sp-adjust)
  1451. (local.get $ret-sp-adjust)
  1452. (struct.get $cont $dyn-stack (local.get $cont))
  1453. (i32.const 0)
  1454. (local.get $args)))
  1455. (func $capture-raw-stack (param $base-sp i32)
  1456. (result (ref $raw-bytevector))
  1457. (local $v (ref $raw-bytevector))
  1458. (local $i i32)
  1459. (local $len i32)
  1460. (local.set $len (i32.sub (global.get $raw-sp) (local.get $base-sp)))
  1461. (local.set $v (array.new_default $raw-bytevector
  1462. (local.get $len)))
  1463. (local.set $i (i32.const 0))
  1464. (loop $lp
  1465. (if (i32.lt_u (local.get $i) (local.get $len))
  1466. (then
  1467. (array.set $raw-bytevector
  1468. (local.get $v)
  1469. (local.get $i)
  1470. (i32.load8_u $raw-stack
  1471. (i32.add (local.get $base-sp)
  1472. (local.get $i))))
  1473. (local.set $i (i32.add (local.get $i) (i32.const 1)))
  1474. (br $lp))))
  1475. (local.get $v))
  1476. (func $capture-scm-stack (param $base-sp i32)
  1477. (result (ref $raw-scmvector))
  1478. (local $v (ref $raw-scmvector))
  1479. (local $i i32)
  1480. (local $len i32)
  1481. (local.set $len (i32.sub (global.get $scm-sp) (local.get $base-sp)))
  1482. (local.set $v
  1483. (array.new $raw-scmvector
  1484. (ref.i31 (i32.const 1))
  1485. (local.get $len)))
  1486. (loop $lp
  1487. (if (i32.lt_u (local.get $i) (local.get $len))
  1488. (then
  1489. (array.set $raw-scmvector
  1490. (local.get $v)
  1491. (local.get $i)
  1492. (ref.as_non_null
  1493. (table.get $scm-stack
  1494. (i32.add (local.get $base-sp)
  1495. (local.get $i)))))
  1496. (local.set $i (i32.add (local.get $i) (i32.const 1)))
  1497. (br $lp))))
  1498. (local.get $v))
  1499. (func $capture-ret-stack (param $base-sp i32)
  1500. (result (ref $raw-retvector))
  1501. (local $v (ref $raw-retvector))
  1502. (local $i i32)
  1503. (local $len i32)
  1504. (local.set $len (i32.sub (global.get $ret-sp) (local.get $base-sp)))
  1505. (local.set $v
  1506. (array.new $raw-retvector
  1507. (ref.func $invalid-continuation)
  1508. (local.get $len)))
  1509. (loop $lp
  1510. (if (i32.lt_u (local.get $i) (local.get $len))
  1511. (then
  1512. (array.set $raw-retvector
  1513. (local.get $v)
  1514. (local.get $i)
  1515. (ref.as_non_null
  1516. (table.get $ret-stack
  1517. (i32.add (local.get $base-sp)
  1518. (local.get $i)))))
  1519. (local.set $i (i32.add (local.get $i) (i32.const 1)))
  1520. (br $lp))))
  1521. (local.get $v))
  1522. (func $capture-dyn-stack (param $base-sp i32)
  1523. (result (ref $raw-dynvector))
  1524. (local $v (ref $raw-dynvector))
  1525. (local $i i32)
  1526. (local $len i32)
  1527. (local.set $len (i32.sub (global.get $dyn-sp) (local.get $base-sp)))
  1528. (local.set $v
  1529. (array.new $raw-dynvector
  1530. (struct.new $dyn)
  1531. (local.get $len)))
  1532. (loop $lp
  1533. (if (i32.lt_u (local.get $i) (local.get $len))
  1534. (then
  1535. (array.set $raw-dynvector
  1536. (local.get $v)
  1537. (local.get $i)
  1538. (ref.as_non_null
  1539. (table.get $dyn-stack
  1540. (i32.add (local.get $base-sp)
  1541. (local.get $i)))))
  1542. (local.set $i (i32.add (local.get $i) (i32.const 1)))
  1543. (br $lp))))
  1544. (local.get $v))
  1545. (func $capture-continuation (param $prompt (ref $dynprompt))
  1546. (param $prompt-dyn-sp i32)
  1547. (result (ref eq))
  1548. (if (result (ref eq))
  1549. (struct.get_u $dynprompt $unwind-only? (local.get $prompt))
  1550. (then (ref.i31 (i32.const 1)))
  1551. (else
  1552. (struct.new
  1553. $cont
  1554. (i32.const 0)
  1555. (ref.func $compose-continuation)
  1556. (local.get $prompt)
  1557. (call $capture-raw-stack
  1558. (struct.get $dynprompt $raw-sp (local.get $prompt)))
  1559. (call $capture-scm-stack
  1560. (struct.get $dynprompt $scm-sp (local.get $prompt)))
  1561. (call $capture-ret-stack
  1562. ;; Increment to avoid including the prompt unwind
  1563. ;; continuation. We rely on the compiler
  1564. ;; generating code for non-unwind-only prompt
  1565. ;; bodies that consists of just a closure call.
  1566. (i32.add
  1567. (struct.get $dynprompt $ret-sp (local.get $prompt))
  1568. (i32.const 1)))
  1569. (call $capture-dyn-stack
  1570. ;; Incremented to avoid including the prompt
  1571. ;; itself.
  1572. (i32.add (local.get $prompt-dyn-sp) (i32.const 1)))))))
  1573. (func $keep-unwinding (param $nargs i32)
  1574. (param $arg0 (ref eq)) (param $arg1 (ref eq)) (param $arg2 (ref eq))
  1575. (local $tag (ref eq))
  1576. (local $cont (ref eq))
  1577. (local $args (ref eq))
  1578. (local.set $tag
  1579. (ref.as_non_null
  1580. (table.get $scm-stack
  1581. (i32.sub (global.get $scm-sp) (i32.const 3)))))
  1582. (local.set $cont
  1583. (ref.as_non_null
  1584. (table.get $scm-stack
  1585. (i32.sub (global.get $scm-sp) (i32.const 2)))))
  1586. (local.set $args
  1587. (ref.as_non_null
  1588. (table.get $scm-stack
  1589. (i32.sub (global.get $scm-sp) (i32.const 1)))))
  1590. (global.set $scm-sp (i32.sub (global.get $scm-sp) (i32.const 3)))
  1591. (return_call $unwind-to-prompt
  1592. (local.get $tag) (local.get $cont) (local.get $args)))
  1593. (func $keep-rewinding (param $nargs i32)
  1594. (param $arg0 (ref eq)) (param $arg1 (ref eq)) (param $arg2 (ref eq))
  1595. (local $raw-sp-adjust i32)
  1596. (local $scm-sp-adjust i32)
  1597. (local $ret-sp-adjust i32)
  1598. (local $i i32)
  1599. (local $dyn (ref $raw-dynvector))
  1600. (local $args (ref eq))
  1601. (global.set $raw-sp (i32.sub (global.get $raw-sp) (i32.const 16)))
  1602. (local.set $raw-sp-adjust
  1603. (i32.load $raw-stack offset=0 (global.get $raw-sp)))
  1604. (local.set $scm-sp-adjust
  1605. (i32.load $raw-stack offset=4 (global.get $raw-sp)))
  1606. (local.set $ret-sp-adjust
  1607. (i32.load $raw-stack offset=8 (global.get $raw-sp)))
  1608. (local.set $i
  1609. (i32.load $raw-stack offset=12 (global.get $raw-sp)))
  1610. (global.set $scm-sp (i32.sub (global.get $scm-sp) (i32.const 2)))
  1611. (local.set $dyn (ref.cast
  1612. $raw-dynvector
  1613. (table.get $scm-stack (global.get $scm-sp))))
  1614. (local.set $args (ref.as_non_null
  1615. (table.get $scm-stack
  1616. (i32.add (global.get $scm-sp)
  1617. (i32.const 1)))))
  1618. (return_call $rewind
  1619. (local.get $raw-sp-adjust)
  1620. (local.get $scm-sp-adjust)
  1621. (local.get $ret-sp-adjust)
  1622. (local.get $dyn)
  1623. (local.get $i)
  1624. (local.get $args)))
  1625. (func $unwind-to-prompt
  1626. (param $tag (ref eq)) (param $cont (ref eq)) (param $args (ref eq))
  1627. (local $prompt (ref $dynprompt))
  1628. (local $dynwind (ref $dynwind))
  1629. (local $dyn (ref $dyn))
  1630. ;; During an abort-to-prompt that crosses a dynamic-wind,
  1631. ;; after the dynamic-wind unwinder returns, it could be that
  1632. ;; the dynamic stack is different from where the
  1633. ;; abort-to-prompt started. It could be that the prompt is
  1634. ;; no longer in the continuation; that's why we look it up
  1635. ;; again here. More annoyingly, it could be that the prompt
  1636. ;; becomes not unwind-only! FIXME to check that if $cont is
  1637. ;; #f, that the prompt is indeed still unwind-only.
  1638. (call $find-prompt (local.get $tag))
  1639. (drop) ;; prompt dyn-sp
  1640. (local.set $prompt)
  1641. (loop $lp
  1642. (global.set $dyn-sp
  1643. (i32.sub (global.get $dyn-sp) (i32.const 1)))
  1644. (local.set $dyn (ref.as_non_null
  1645. (table.get $dyn-stack (global.get $dyn-sp))))
  1646. (if (ref.eq (local.get $dyn) (local.get $prompt))
  1647. (then
  1648. ;; Unwind control stacks.
  1649. (global.set $raw-sp (struct.get $dynprompt $raw-sp
  1650. (local.get $prompt)))
  1651. (global.set $scm-sp (struct.get $dynprompt $scm-sp
  1652. (local.get $prompt)))
  1653. (global.set $ret-sp (struct.get $dynprompt $ret-sp
  1654. (local.get $prompt)))
  1655. ;; Use apply + values to pass values to handler.
  1656. (global.set $ret-sp
  1657. (i32.add (global.get $ret-sp) (i32.const 1)))
  1658. (call $maybe-grow-ret-stack)
  1659. (table.set $ret-stack
  1660. (i32.sub (global.get $ret-sp) (i32.const 1))
  1661. (struct.get $dynprompt $handler
  1662. (local.get $prompt)))
  1663. (return_call $apply (i32.const 3)
  1664. (global.get $apply-primitive)
  1665. (global.get $values-primitive)
  1666. (struct.new $pair (i32.const 0)
  1667. (local.get $cont)
  1668. (local.get $args)))))
  1669. ;; Something else is on the stack; what is it?
  1670. (if (ref.test $dynwind (local.get $dyn))
  1671. (then
  1672. (local.set $dynwind (ref.cast $dynwind (local.get $dyn)))
  1673. (global.set $scm-sp (i32.add (global.get $scm-sp) (i32.const 3)))
  1674. (global.set $ret-sp (i32.add (global.get $ret-sp) (i32.const 1)))
  1675. (call $maybe-grow-scm-stack)
  1676. (call $maybe-grow-ret-stack)
  1677. (table.set $scm-stack
  1678. (i32.sub (global.get $scm-sp) (i32.const 3))
  1679. (local.get $tag))
  1680. (table.set $scm-stack
  1681. (i32.sub (global.get $scm-sp) (i32.const 2))
  1682. (local.get $cont))
  1683. (table.set $scm-stack
  1684. (i32.sub (global.get $scm-sp) (i32.const 1))
  1685. (local.get $args))
  1686. (table.set $ret-stack
  1687. (i32.sub (global.get $ret-sp) (i32.const 1))
  1688. (ref.func $keep-unwinding))
  1689. (return_call_ref $kvarargs
  1690. (i32.const 1)
  1691. (struct.get $dynwind $unwind
  1692. (local.get $dynwind))
  1693. (ref.i31 (i32.const 0))
  1694. (ref.i31 (i32.const 0))
  1695. (struct.get
  1696. $proc $func
  1697. (struct.get $dynwind $unwind
  1698. (local.get $dynwind))))))
  1699. (br_if $lp (ref.test $dynprompt (local.get $dyn)))
  1700. (if (ref.test $dynfluid (local.get $dyn))
  1701. (then
  1702. (call $wind-dynfluid (ref.cast $dynfluid (local.get $dyn)))
  1703. (br $lp)))
  1704. (if (ref.test $dynstate (local.get $dyn))
  1705. (then
  1706. (call $wind-dynstate (ref.cast $dynstate (local.get $dyn)))
  1707. (br $lp)))
  1708. (unreachable)))
  1709. (func $abort-to-prompt (param $nargs i32) (param $arg0 (ref eq))
  1710. (param $arg1 (ref eq)) (param $arg2 (ref eq))
  1711. (if (i32.lt_u (local.get $nargs) (i32.const 2))
  1712. (then
  1713. (return_call $raise-arity-error
  1714. (string.const "abort-to-prompt")
  1715. (global.get $abort-to-prompt-primitive))))
  1716. ;; $arg0 is the closure, $arg1 is tag, and the values are in
  1717. ;; $arg2 and up, which we collect to a rest list.
  1718. (return_call $unwind-to-prompt (local.get $arg1)
  1719. (call $capture-continuation
  1720. (call $find-prompt (local.get $arg1)))
  1721. (call $collect-rest-args (local.get $nargs)
  1722. (local.get $arg0)
  1723. (local.get $arg1)
  1724. (local.get $arg2)
  1725. (i32.const 2))))
  1726. (global $abort-to-prompt-primitive (ref eq)
  1727. (struct.new $proc (i32.const 0) (ref.func $abort-to-prompt)))
  1728. (func $maybe-grow-argv (param $size i32)
  1729. (local $diff i32)
  1730. (local.set $diff (i32.sub (local.get $size)
  1731. (table.size $argv)))
  1732. (if (i32.gt_s (local.get $diff) (i32.const 0))
  1733. (then
  1734. (table.grow $argv
  1735. (ref.null eq)
  1736. (local.get $diff))
  1737. (drop))))
  1738. (func $arg-ref (param $n i32)
  1739. (result (ref eq))
  1740. (block
  1741. $arg-in-register
  1742. (block
  1743. $n3
  1744. (block
  1745. $n4
  1746. (block
  1747. $n5
  1748. (block
  1749. $n6
  1750. (block
  1751. $n7
  1752. (block
  1753. $nv
  1754. (br_table $arg-in-register
  1755. $arg-in-register
  1756. $arg-in-register
  1757. $n3
  1758. $n4
  1759. $n5
  1760. $n6
  1761. $n7
  1762. $nv
  1763. (local.get $n)))
  1764. (return (ref.as_non_null
  1765. (table.get $argv (i32.sub (local.get $n) (i32.const 8))))))
  1766. (return (global.get $arg7)))
  1767. (return (global.get $arg6)))
  1768. (return (global.get $arg5)))
  1769. (return (global.get $arg4)))
  1770. (return (global.get $arg3)))
  1771. (unreachable))
  1772. (func $collect-apply-args
  1773. (param $nargs i32) (param $arg2 (ref eq))
  1774. (result (ref eq))
  1775. (local $ret (ref eq))
  1776. (if (i32.le_u (local.get $nargs) (i32.const 3))
  1777. (then
  1778. (call $die0 (string.const "bad collect-apply-args call"))
  1779. (unreachable)))
  1780. (local.set $ret
  1781. (call $arg-ref
  1782. (local.tee $nargs
  1783. (i32.sub (local.get $nargs)
  1784. (i32.const 1)))))
  1785. (loop $lp
  1786. (if (i32.lt_u (i32.const 3) (local.get $nargs))
  1787. (then
  1788. (local.set $ret
  1789. (struct.new
  1790. $pair
  1791. (i32.const 0)
  1792. (call $arg-ref
  1793. (local.tee $nargs
  1794. (i32.sub (local.get $nargs)
  1795. (i32.const 1))))
  1796. (local.get $ret)))
  1797. (br $lp))))
  1798. (struct.new $pair
  1799. (i32.const 0)
  1800. (local.get $arg2)
  1801. (local.get $ret)))
  1802. (func $apply-to-non-list (param $tail (ref eq))
  1803. (call $die (string.const "$apply-to-non-list") (local.get $tail))
  1804. (unreachable))
  1805. (func $get-callee-code (param $callee (ref eq)) (result (ref $kvarargs))
  1806. (call $die (string.const "$get-callee-code") (local.get $callee))
  1807. (unreachable))
  1808. (func $apply (param $nargs i32) (param $arg0 (ref eq))
  1809. (param $arg1 (ref eq)) (param $arg2 (ref eq))
  1810. (local $args (ref eq))
  1811. (if (i32.lt_u (local.get $nargs) (i32.const 3))
  1812. (then
  1813. (return_call $raise-arity-error
  1814. (string.const "apply")
  1815. (global.get $apply-primitive))))
  1816. (local.set $arg0 (local.get $arg1))
  1817. (local.set $args
  1818. (if (ref eq)
  1819. (i32.eq (local.get $nargs) (i32.const 3))
  1820. (then (local.get $arg2))
  1821. (else (call $collect-apply-args
  1822. (local.get $nargs)
  1823. (local.get $arg2)))))
  1824. (if
  1825. (ref.test $pair (local.get $args))
  1826. (then
  1827. (local.set $arg1
  1828. (struct.get $pair $car
  1829. (ref.cast $pair (local.get $args))))
  1830. (if
  1831. (ref.test
  1832. $pair
  1833. (local.tee $args
  1834. (struct.get $pair $cdr
  1835. (ref.cast $pair (local.get $args)))))
  1836. (then
  1837. (local.set $arg2
  1838. (struct.get $pair $car
  1839. (ref.cast $pair (local.get $args))))
  1840. (if
  1841. (ref.test
  1842. $pair
  1843. (local.tee $args
  1844. (struct.get $pair $cdr
  1845. (ref.cast $pair (local.get $args)))))
  1846. (then
  1847. (global.set $arg3
  1848. (struct.get $pair $car
  1849. (ref.cast $pair (local.get $args))))
  1850. (if
  1851. (ref.test
  1852. $pair
  1853. (local.tee $args
  1854. (struct.get $pair $cdr
  1855. (ref.cast $pair (local.get $args)))))
  1856. (then
  1857. (global.set $arg4
  1858. (struct.get $pair $car
  1859. (ref.cast $pair (local.get $args))))
  1860. (if
  1861. (ref.test
  1862. $pair
  1863. (local.tee $args
  1864. (struct.get $pair $cdr
  1865. (ref.cast $pair (local.get $args)))))
  1866. (then
  1867. (global.set $arg5
  1868. (struct.get $pair $car
  1869. (ref.cast $pair (local.get $args))))
  1870. (if
  1871. (ref.test
  1872. $pair
  1873. (local.tee $args
  1874. (struct.get $pair $cdr
  1875. (ref.cast $pair (local.get $args)))))
  1876. (then
  1877. (global.set $arg6
  1878. (struct.get $pair $car
  1879. (ref.cast $pair (local.get $args))))
  1880. (if
  1881. (ref.test
  1882. $pair
  1883. (local.tee $args
  1884. (struct.get $pair $cdr
  1885. (ref.cast $pair (local.get $args)))))
  1886. (then
  1887. (global.set $arg7
  1888. (struct.get $pair $car
  1889. (ref.cast $pair (local.get $args))))
  1890. (local.set $nargs (i32.const 8))
  1891. (loop $lp
  1892. (if
  1893. (ref.test
  1894. $pair
  1895. (local.tee $args
  1896. (struct.get $pair $cdr
  1897. (ref.cast $pair (local.get $args)))))
  1898. (then
  1899. (if (i32.lt_u (table.size $argv)
  1900. (i32.sub (local.get $nargs) (i32.const 7)))
  1901. (then
  1902. (table.grow $argv
  1903. (struct.get $pair $car
  1904. (ref.cast $pair (local.get $args)))
  1905. (i32.const 1))
  1906. (drop))
  1907. (else
  1908. (table.set $argv
  1909. (i32.sub (local.get $nargs) (i32.const 8))
  1910. (struct.get $pair $car
  1911. (ref.cast $pair (local.get $args))))))
  1912. (local.set $nargs (i32.add (local.get $nargs) (i32.const 1)))
  1913. (br $lp)))))
  1914. (else (local.set $nargs (i32.const 7)))))
  1915. (else (local.set $nargs (i32.const 6)))))
  1916. (else (local.set $nargs (i32.const 5)))))
  1917. (else (local.set $nargs (i32.const 4)))))
  1918. (else (local.set $nargs (i32.const 3)))))
  1919. (else (local.set $nargs (i32.const 2)))))
  1920. (else (local.set $nargs (i32.const 1))))
  1921. (if (i32.eqz (ref.eq (local.get $args) (ref.i31 (i32.const 13))))
  1922. (then (return_call $apply-to-non-list (local.get $args))))
  1923. (return_call_ref $kvarargs
  1924. (local.get $nargs)
  1925. (local.get $arg0)
  1926. (local.get $arg1)
  1927. (local.get $arg2)
  1928. (if (ref $kvarargs)
  1929. (ref.test $proc (local.get $arg0))
  1930. (then (struct.get $proc $func
  1931. (ref.cast $proc (local.get $arg0))))
  1932. (else (call $get-callee-code (local.get $arg0))))))
  1933. (global $apply-primitive (ref eq)
  1934. (struct.new $proc (i32.const 0) (ref.func $apply)))
  1935. ;; Helper function for $f64->exact
  1936. (func $decode-f64 (param $frac i64) (param $expt i32) (param $sign i32)
  1937. (result (ref eq))
  1938. (if (i32.eq (local.get $sign) (i32.const 1))
  1939. (then (local.set $frac (i64.mul (local.get $frac) (i64.const -1)))))
  1940. (if (ref eq)
  1941. (i32.lt_s (local.get $expt) (i32.const 0))
  1942. ;; divide $frac by 1/(2**|expt|)
  1943. (then
  1944. (call $div
  1945. (call $s64->bignum (local.get $frac))
  1946. (call $lsh
  1947. (call $i32->fixnum (i32.const 2))
  1948. (i64.mul (i64.const -1)
  1949. (i64.extend_i32_s
  1950. (i32.add
  1951. (local.get $expt)
  1952. (i32.const 1)))))))
  1953. ;; multiply $frac by 2**expt
  1954. (else
  1955. (call $mul
  1956. (call $s64->bignum (local.get $frac))
  1957. (call $lsh
  1958. (call $i32->fixnum (i32.const 2))
  1959. (i64.extend_i32_s
  1960. (i32.add (local.get $expt)
  1961. (i32.const 1))))))))
  1962. ;; Callers must ensure that the argument is a rational float (not
  1963. ;; an infinity or NaN).
  1964. ;; TODO: Optimize for conversion of $X to an integer.
  1965. ;; (at least when it can be represeted with an i32 or i64).
  1966. (func $f64->exact (param $x f64) (result (ref eq))
  1967. (local $bits i64)
  1968. (local $raw-frac i64) ; raw significand
  1969. (local $frac i64) ; decoded significand
  1970. (local $raw-expt i32) ; biased exponent
  1971. (local $expt i32) ; actual exponent
  1972. (local $sign i32)
  1973. ;; Split $X into three parts:
  1974. ;; - the fraction [Knuth] or significand (52 bits, with an
  1975. ;; implicit leading 1 bit),
  1976. ;; - the exponent (with an offset of 1023; here, since we
  1977. ;; represent the significand as an integer, the offset is
  1978. ;; increased by 52 bits to 1075),
  1979. ;; - and a sign bit.
  1980. ;; Special cases:
  1981. ;; (a) E = 0, F = 0 => (signed) zero;
  1982. ;; (b) E = 0, F /= 0 => subnormal: interpret F as
  1983. ;; non-normalized with an exponent of -1074;
  1984. ;; (c) E = #x7FF, F = 0 => (signed) infinity;
  1985. ;; (d) E = #x7FF, F /= 0 => NaN.
  1986. ;; Otherwise, $X represents (1+F)*(2**(E-1023)).
  1987. (local.set $bits (i64.reinterpret_f64 (local.get $x)))
  1988. (local.set $raw-frac
  1989. (i64.and (local.get $bits)
  1990. (i64.const #xFFFFFFFFFFFFF)))
  1991. (local.set $raw-expt
  1992. (i32.wrap_i64
  1993. (i64.and (i64.shr_u (local.get $bits) (i64.const 52))
  1994. (i64.const #x7FF))))
  1995. (local.set $sign (i32.wrap_i64
  1996. (i64.shr_u (local.get $bits) (i64.const 63))))
  1997. (if (ref eq)
  1998. (i32.and (i32.eqz (local.get $raw-expt))
  1999. (i64.eqz (local.get $raw-frac)))
  2000. (then ; zero (E = 0, F = 0)
  2001. (call $i32->fixnum (i32.const 0)))
  2002. (else
  2003. (if (ref eq)
  2004. (i32.eqz (local.get $raw-expt))
  2005. (then ; subnormal (E = 0, F /= 0)
  2006. (local.set $frac (local.get $raw-frac))
  2007. (local.set $expt (i32.const -1074))
  2008. (call $decode-f64
  2009. (local.get $frac)
  2010. (local.get $expt)
  2011. (local.get $sign)))
  2012. (else
  2013. (if (ref eq)
  2014. (i32.eqz (i32.eq (local.get $raw-expt)
  2015. (i32.const #x7FF)))
  2016. (then ; normal (E /= 0, F /= #xFF)
  2017. ;; set "hidden" bit of significand
  2018. (local.set $frac
  2019. (i64.or (local.get $raw-frac)
  2020. (i64.const ,(ash 1 52))))
  2021. (local.set $expt
  2022. (i32.sub (local.get $raw-expt)
  2023. (i32.const 1075)))
  2024. (call $decode-f64
  2025. (local.get $frac)
  2026. (local.get $expt)
  2027. (local.get $sign)))
  2028. (else ; nonrational (inf or NaN)
  2029. (call $die
  2030. (string.const "$decode-float bad arg")
  2031. (struct.new $flonum
  2032. (i32.const 0)
  2033. (local.get $x)))
  2034. (unreachable))))))))
  2035. (func $slow-< (param $a (ref eq)) (param $b (ref eq)) (result i32)
  2036. ,(arith-cond 'i32
  2037. `((call $fixnum? (local.get $a))
  2038. ,(arith-cond 'i32
  2039. `((call $fixnum? (local.get $b))
  2040. (i32.lt_s (i31.get_s (ref.cast i31 (local.get $a)))
  2041. (i31.get_s (ref.cast i31 (local.get $b)))))
  2042. `((ref.test $bignum (local.get $b))
  2043. (call $lt-fix-big
  2044. (call $fixnum->i32 (ref.cast i31 (local.get $a)))
  2045. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
  2046. `((ref.test $flonum (local.get $b))
  2047. (f64.lt (call $fixnum->f64 (ref.cast i31 (local.get $a)))
  2048. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))
  2049. `((ref.test $fraction (local.get $b))
  2050. (call $slow-<
  2051. (call $mul
  2052. (local.get $a)
  2053. (struct.get $fraction $denom
  2054. (ref.cast $fraction (local.get $b))))
  2055. (struct.get $fraction $num
  2056. (ref.cast $fraction (local.get $b)))))
  2057. '(else
  2058. (call $die0 (string.const "$slow-<"))
  2059. (unreachable))))
  2060. `((ref.test $bignum (local.get $a))
  2061. ,(arith-cond 'i32
  2062. `((call $fixnum? (local.get $b))
  2063. (call $lt-big-fix
  2064. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  2065. (call $fixnum->i32 (ref.cast i31 (local.get $b)))))
  2066. `((ref.test $bignum (local.get $b))
  2067. (call $lt-big-big
  2068. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  2069. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
  2070. `((ref.test $flonum (local.get $b))
  2071. (call $lt-big-flo
  2072. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  2073. (struct.get $flonum $val (ref.cast $flonum (local.get $b)))))
  2074. `((ref.test $fraction (local.get $b))
  2075. (call $slow-<
  2076. (call $mul
  2077. (local.get $a)
  2078. (struct.get $fraction $denom
  2079. (ref.cast $fraction (local.get $b))))
  2080. (struct.get $fraction $num
  2081. (ref.cast $fraction (local.get $b)))))
  2082. '(else
  2083. (call $die0 (string.const "$slow-<"))
  2084. (unreachable))))
  2085. `((ref.test $flonum (local.get $a))
  2086. ,(arith-cond 'i32
  2087. `((call $fixnum? (local.get $b))
  2088. (f64.lt (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
  2089. (call $fixnum->f64 (ref.cast i31 (local.get $b)))))
  2090. `((ref.test $bignum (local.get $b))
  2091. (call $lt-flo-big
  2092. (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
  2093. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
  2094. `((ref.test $flonum (local.get $b))
  2095. (f64.lt (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
  2096. (struct.get $flonum $val (ref.cast $flonum (local.get $b)))))
  2097. `((ref.test $fraction (local.get $b))
  2098. ,(arith-cond
  2099. 'i32
  2100. '((call $f64-is-nan
  2101. (call $flonum->f64
  2102. (ref.cast $flonum (local.get $a))))
  2103. (i32.const 0))
  2104. '((call $f64-is-infinite
  2105. (call $flonum->f64
  2106. (ref.cast $flonum (local.get $a))))
  2107. (f64.lt (call $flonum->f64
  2108. (ref.cast $flonum (local.get $a)))
  2109. (f64.const 0)))
  2110. '(else
  2111. (call $slow-<
  2112. (call $f64->exact (call $flonum->f64 (ref.cast $flonum (local.get $a))))
  2113. (local.get $b)))))
  2114. '(else
  2115. (call $die0 (string.const "$slow-<"))
  2116. (unreachable))))
  2117. `((ref.test $fraction (local.get $a))
  2118. ,(arith-cond 'i32
  2119. `((i32.or (call $fixnum? (local.get $b))
  2120. (i32.or (ref.test $bignum (local.get $b))
  2121. (ref.test $fraction (local.get $b))))
  2122. (call $slow-<
  2123. (struct.get $fraction $num
  2124. (ref.cast $fraction (local.get $a)))
  2125. (call $mul
  2126. (local.get $b)
  2127. (struct.get $fraction $denom
  2128. (ref.cast $fraction (local.get $a))))))
  2129. `((ref.test $flonum (local.get $b))
  2130. ,(arith-cond
  2131. 'i32
  2132. '((call $f64-is-nan
  2133. (call $flonum->f64
  2134. (ref.cast $flonum (local.get $b))))
  2135. (i32.const 0))
  2136. '((call $f64-is-infinite
  2137. (call $flonum->f64
  2138. (ref.cast $flonum (local.get $b))))
  2139. (f64.lt (f64.const 0)
  2140. (call $flonum->f64
  2141. (ref.cast $flonum (local.get $b)))))
  2142. '(else
  2143. (call $slow-<
  2144. (local.get $a)
  2145. (call $f64->exact
  2146. (call $flonum->f64
  2147. (ref.cast $flonum (local.get $b))))))))
  2148. '(else
  2149. (call $die0 (string.const "$slow-<"))
  2150. (unreachable))))
  2151. '(else
  2152. (call $die0 (string.const "$slow-<"))
  2153. (unreachable))))
  2154. (func $slow-<= (param $a (ref eq)) (param $b (ref eq)) (result i32)
  2155. ,(arith-cond 'i32
  2156. `((call $fixnum? (local.get $a))
  2157. ,(arith-cond 'i32
  2158. `((call $fixnum? (local.get $b))
  2159. (i32.le_s (i31.get_s (ref.cast i31 (local.get $a)))
  2160. (i31.get_s (ref.cast i31 (local.get $b)))))
  2161. `((ref.test $bignum (local.get $b))
  2162. (call $le-fix-big
  2163. (call $fixnum->i32 (ref.cast i31 (local.get $a)))
  2164. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
  2165. `((ref.test $flonum (local.get $b))
  2166. (f64.le (call $fixnum->f64 (ref.cast i31 (local.get $a)))
  2167. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))
  2168. `((ref.test $fraction (local.get $b))
  2169. (call $slow-<=
  2170. (call $mul
  2171. (local.get $a)
  2172. (struct.get $fraction $denom
  2173. (ref.cast $fraction (local.get $b))))
  2174. (struct.get $fraction $num
  2175. (ref.cast $fraction (local.get $b)))))
  2176. '(else
  2177. (call $die0 (string.const "$slow-<="))
  2178. (unreachable))))
  2179. `((ref.test $bignum (local.get $a))
  2180. ,(arith-cond 'i32
  2181. `((call $fixnum? (local.get $b))
  2182. (call $le-big-fix
  2183. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  2184. (call $fixnum->i32 (ref.cast i31 (local.get $b)))))
  2185. `((ref.test $bignum (local.get $b))
  2186. (call $le-big-big
  2187. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  2188. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
  2189. `((ref.test $flonum (local.get $b))
  2190. (call $le-big-flo
  2191. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  2192. (struct.get $flonum $val (ref.cast $flonum (local.get $b)))))
  2193. `((ref.test $fraction (local.get $b))
  2194. (call $slow-<=
  2195. (call $mul
  2196. (local.get $a)
  2197. (struct.get $fraction $denom
  2198. (ref.cast $fraction (local.get $b))))
  2199. (struct.get $fraction $num
  2200. (ref.cast $fraction (local.get $b)))))
  2201. '(else
  2202. (call $die0 (string.const "$slow-<="))
  2203. (unreachable))))
  2204. `((ref.test $flonum (local.get $a))
  2205. ,(arith-cond 'i32
  2206. `((call $fixnum? (local.get $b))
  2207. (f64.le (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
  2208. (call $fixnum->f64 (ref.cast i31 (local.get $b)))))
  2209. `((ref.test $bignum (local.get $b))
  2210. (call $le-flo-big
  2211. (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
  2212. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
  2213. `((ref.test $flonum (local.get $b))
  2214. (f64.le (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
  2215. (struct.get $flonum $val (ref.cast $flonum (local.get $b)))))
  2216. `((ref.test $fraction (local.get $b))
  2217. ,(arith-cond
  2218. 'i32
  2219. '((call $f64-is-nan
  2220. (call $flonum->f64
  2221. (ref.cast $flonum (local.get $a))))
  2222. (i32.const 0))
  2223. '((call $f64-is-infinite
  2224. (call $flonum->f64
  2225. (ref.cast $flonum (local.get $a))))
  2226. (f64.lt (call $flonum->f64
  2227. (ref.cast $flonum (local.get $a)))
  2228. (f64.const 0)))
  2229. '(else
  2230. (call $slow-<=
  2231. (call $f64->exact (call $flonum->f64 (ref.cast $flonum (local.get $a))))
  2232. (local.get $b)))))
  2233. '(else
  2234. (call $die0 (string.const "$slow-<="))
  2235. (unreachable))))
  2236. `((ref.test $fraction (local.get $a))
  2237. ,(arith-cond 'i32
  2238. `((i32.or (call $fixnum? (local.get $b))
  2239. (i32.or (ref.test $bignum (local.get $b))
  2240. (ref.test $fraction (local.get $b))))
  2241. (call $slow-<=
  2242. (struct.get $fraction $num
  2243. (ref.cast $fraction (local.get $a)))
  2244. (call $mul
  2245. (local.get $b)
  2246. (struct.get $fraction $denom
  2247. (ref.cast $fraction (local.get $a))))))
  2248. `((ref.test $flonum (local.get $b))
  2249. ,(arith-cond
  2250. 'i32
  2251. '((call $f64-is-nan
  2252. (call $flonum->f64
  2253. (ref.cast $flonum (local.get $b))))
  2254. (i32.const 0))
  2255. '((call $f64-is-infinite
  2256. (call $flonum->f64
  2257. (ref.cast $flonum (local.get $b))))
  2258. (f64.le (f64.const 0)
  2259. (call $flonum->f64
  2260. (ref.cast $flonum (local.get $b)))))
  2261. '(else
  2262. (call $slow-<=
  2263. (local.get $a)
  2264. (call $f64->exact (call $flonum->f64 (ref.cast $flonum (local.get $b))))))))
  2265. '(else
  2266. (call $die0 (string.const "$slow-<="))
  2267. (unreachable))))
  2268. '(else
  2269. (call $die0 (string.const "$slow-<="))
  2270. (unreachable))))
  2271. (func $slow-= (param $a (ref eq)) (param $b (ref eq)) (result i32)
  2272. ,(arith-cond 'i32
  2273. `((call $fixnum? (local.get $a))
  2274. ,(arith-cond 'i32
  2275. `((call $fixnum? (local.get $b))
  2276. (i32.eq (i31.get_s (ref.cast i31 (local.get $a)))
  2277. (i31.get_s (ref.cast i31 (local.get $b)))))
  2278. `((ref.test $bignum (local.get $b))
  2279. (call $eq-fix-big
  2280. (call $fixnum->i32 (ref.cast i31 (local.get $a)))
  2281. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
  2282. `((ref.test $flonum (local.get $b))
  2283. (f64.eq (call $fixnum->f64 (ref.cast i31 (local.get $a)))
  2284. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))
  2285. `((ref.test $fraction (local.get $b))
  2286. (call $slow-=
  2287. (call $mul
  2288. (local.get $a)
  2289. (struct.get $fraction $denom
  2290. (ref.cast $fraction (local.get $b))))
  2291. (struct.get $fraction $num
  2292. (ref.cast $fraction (local.get $b)))))
  2293. '(else
  2294. (call $die0 (string.const "$slow-="))
  2295. (unreachable))))
  2296. `((ref.test $bignum (local.get $a))
  2297. ,(arith-cond 'i32
  2298. `((call $fixnum? (local.get $b))
  2299. (call $eq-big-fix
  2300. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  2301. (call $fixnum->i32 (ref.cast i31 (local.get $b)))))
  2302. `((ref.test $bignum (local.get $b))
  2303. (call $eq-big-big
  2304. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  2305. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
  2306. `((ref.test $flonum (local.get $b))
  2307. (call $eq-big-flo
  2308. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  2309. (struct.get $flonum $val (ref.cast $flonum (local.get $b)))))
  2310. `((ref.test $fraction (local.get $b))
  2311. (call $slow-=
  2312. (call $mul
  2313. (local.get $a)
  2314. (struct.get $fraction $denom
  2315. (ref.cast $fraction (local.get $b))))
  2316. (struct.get $fraction $num
  2317. (ref.cast $fraction (local.get $b)))))
  2318. '(else
  2319. (call $die0 (string.const "$slow-="))
  2320. (unreachable))))
  2321. `((ref.test $flonum (local.get $a))
  2322. ,(arith-cond 'i32
  2323. `((call $fixnum? (local.get $b))
  2324. (f64.eq (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
  2325. (call $fixnum->f64 (ref.cast i31 (local.get $b)))))
  2326. `((ref.test $bignum (local.get $b))
  2327. (call $eq-flo-big
  2328. (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
  2329. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
  2330. `((ref.test $flonum (local.get $b))
  2331. (f64.eq (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
  2332. (struct.get $flonum $val (ref.cast $flonum (local.get $b)))))
  2333. `((ref.test $fraction (local.get $b))
  2334. ,(arith-cond
  2335. 'i32
  2336. '((call $f64-is-nan
  2337. (call $flonum->f64
  2338. (ref.cast $flonum (local.get $a))))
  2339. (i32.const 0))
  2340. '((call $f64-is-infinite
  2341. (call $flonum->f64
  2342. (ref.cast $flonum (local.get $a))))
  2343. (f64.eq (call $flonum->f64
  2344. (ref.cast $flonum (local.get $a)))
  2345. (f64.const 0)))
  2346. '(else
  2347. (call $slow-=
  2348. (call $f64->exact (call $flonum->f64 (ref.cast $flonum (local.get $a))))
  2349. (local.get $b)))))
  2350. '(else
  2351. (call $die0 (string.const "$slow-="))
  2352. (unreachable))))
  2353. `((ref.test $fraction (local.get $a))
  2354. ,(arith-cond 'i32
  2355. `((i32.or (call $fixnum? (local.get $b))
  2356. (i32.or (ref.test $bignum (local.get $b))
  2357. (ref.test $fraction (local.get $b))))
  2358. (call $slow-=
  2359. (struct.get $fraction $num
  2360. (ref.cast $fraction (local.get $a)))
  2361. (call $mul
  2362. (local.get $b)
  2363. (struct.get $fraction $denom
  2364. (ref.cast $fraction (local.get $a))))))
  2365. `((ref.test $flonum (local.get $b))
  2366. ,(arith-cond
  2367. 'i32
  2368. '((call $f64-is-nan
  2369. (call $flonum->f64
  2370. (ref.cast $flonum (local.get $b))))
  2371. (i32.const 0))
  2372. '((call $f64-is-infinite
  2373. (call $flonum->f64
  2374. (ref.cast $flonum (local.get $b))))
  2375. (f64.eq (f64.const 0)
  2376. (call $flonum->f64
  2377. (ref.cast $flonum (local.get $b)))))
  2378. '(else
  2379. (call $slow-=
  2380. (local.get $a)
  2381. (call $f64->exact (call $flonum->f64 (ref.cast $flonum (local.get $b))))))))
  2382. '(else
  2383. (call $die0 (string.const "$slow-="))
  2384. (unreachable))))
  2385. '(else
  2386. (call $die0 (string.const "$slow-="))
  2387. (unreachable))))
  2388. (func $heap-numbers-equal? (param $a (ref eq)) (param $b (ref eq))
  2389. (result i32)
  2390. ,(arith-cond
  2391. 'i32
  2392. `((ref.test $bignum (local.get $a))
  2393. ,(arith-cond
  2394. 'i32
  2395. `((ref.test $bignum (local.get $b))
  2396. (call $eq-big-big
  2397. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  2398. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
  2399. '(else
  2400. (i32.const 0))))
  2401. `((ref.test $flonum (local.get $a))
  2402. ,(arith-cond
  2403. 'i32
  2404. `((ref.test $flonum (local.get $b))
  2405. (i32.or
  2406. (i32.and (call $f64-is-nan (struct.get $flonum $val (ref.cast $flonum (local.get $a))))
  2407. (call $f64-is-nan (struct.get $flonum $val (ref.cast $flonum (local.get $a)))))
  2408. (f64.eq (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
  2409. (struct.get $flonum $val (ref.cast $flonum (local.get $b))))))
  2410. '(else
  2411. (i32.const 0))))
  2412. `((ref.test $fraction (local.get $a))
  2413. ,(arith-cond
  2414. 'i32
  2415. `((ref.test $fraction (local.get $b))
  2416. (i32.and
  2417. (call $slow-=
  2418. (struct.get $fraction $num
  2419. (ref.cast $fraction (local.get $a)))
  2420. (struct.get $fraction $num
  2421. (ref.cast $fraction (local.get $b))))
  2422. (call $slow-=
  2423. (struct.get $fraction $denom
  2424. (ref.cast $fraction (local.get $a)))
  2425. (struct.get $fraction $denom
  2426. (ref.cast $fraction (local.get $b))))))
  2427. '(else
  2428. (i32.const 0))))))
  2429. (func $string-set! (param $str (ref $string)) (param $idx i32)
  2430. (param $ch i32)
  2431. (call $die0 (string.const "$string-set!")) (unreachable))
  2432. ;; cf. compile-test in (hoot compile)
  2433. (func $fixnum? (param $a (ref eq)) (result i32)
  2434. (if (result i32)
  2435. (ref.test i31 (local.get $a))
  2436. (then (i32.eqz
  2437. (i32.and (i31.get_s (ref.cast i31 (local.get $a)))
  2438. (i32.const #b1))))
  2439. (else (i32.const 0))))
  2440. (func $fixnum->i32 (param $a (ref i31)) (result i32)
  2441. (i32.shr_s (i31.get_s (local.get $a)) (i32.const 1)))
  2442. (func $fixnum->i64 (param $a (ref i31)) (result i64)
  2443. (i64.extend_i32_s (call $fixnum->i32 (local.get $a))))
  2444. (func $fixnum->f64 (param $a (ref i31)) (result f64)
  2445. (f64.convert_i32_s (call $fixnum->i32 (local.get $a))))
  2446. (func $flonum->f64 (param $a (ref $flonum)) (result f64)
  2447. (struct.get $flonum $val (local.get $a)))
  2448. (func $i32->fixnum (param $a i32) (result (ref i31))
  2449. (ref.i31 (i32.shl (local.get $a) (i32.const 1))))
  2450. (func $i32->bignum (param $a i32) (result (ref eq))
  2451. (struct.new $bignum
  2452. (i32.const 0)
  2453. (call $bignum-from-i64
  2454. (i64.extend_i32_s (local.get $a)))))
  2455. (func $bignum->f64 (param $a (ref $bignum)) (result f64)
  2456. (call $bignum-to-f64 (struct.get $bignum $val (local.get $a))))
  2457. (func $f64-integer? (param $a f64) (result i32)
  2458. ;; Adapted from the f64-int test in (hoot compile). The
  2459. ;; subtraction here detects infinities: (f64.trunc ±inf.0)
  2460. ;; returns an infinity, and the subtraction then produces a
  2461. ;; NaN. (This also detects NaNs correctly, as (f64.trunc
  2462. ;; +nan.0) returns a NaN.)
  2463. (f64.eq
  2464. (f64.sub
  2465. (f64.trunc (local.get $a))
  2466. (local.get $a))
  2467. (f64.const 0)))
  2468. ;; Callers must check that $A is an integer.
  2469. (func $f64->integer (param $a f64) (result (ref eq))
  2470. (call $f64->exact (local.get $a)))
  2471. (func $flonum-integer? (param $a (ref eq)) (result i32)
  2472. (call $f64-integer?
  2473. (struct.get $flonum $val
  2474. (ref.cast $flonum (local.get $a)))))
  2475. ;; Callers must check that $A is an integer.
  2476. (func $flonum->integer (param $a (ref eq)) (result (ref eq))
  2477. (call $f64->integer
  2478. (struct.get $flonum $val
  2479. (ref.cast $flonum (local.get $a)))))
  2480. (func $scm->f64 (param $a (ref eq)) (result f64)
  2481. ,(arith-cond 'f64
  2482. '((call $fixnum? (local.get $a))
  2483. (call $fixnum->f64 (ref.cast i31 (local.get $a))))
  2484. '((ref.test $bignum (local.get $a))
  2485. (call $bignum->f64 (ref.cast $bignum (local.get $a))))
  2486. '((ref.test $flonum (local.get $a))
  2487. (struct.get $flonum $val (ref.cast $flonum (local.get $a))))
  2488. '((ref.test $fraction (local.get $a))
  2489. (struct.get
  2490. $flonum $val
  2491. (ref.cast
  2492. $flonum
  2493. (call $div
  2494. (call $inexact
  2495. (struct.get $fraction $num
  2496. (ref.cast $fraction
  2497. (local.get $a))))
  2498. (call $inexact
  2499. (struct.get $fraction $num
  2500. (ref.cast $fraction
  2501. (local.get $a))))))))))
  2502. (func $numeric-eqv? (param $a (ref eq)) (param $b (ref eq)) (result i32)
  2503. ,(arith-cond 'i32
  2504. `((call $fixnum? (local.get $a))
  2505. ,(arith-cond 'i32
  2506. '((call $fixnum? (local.get $b))
  2507. (i32.eq (i31.get_s (ref.cast i31 (local.get $a)))
  2508. (i31.get_s (ref.cast i31 (local.get $b)))))
  2509. '((ref.test $bignum (local.get $b))
  2510. (i32.const 0))
  2511. '((ref.test $flonum (local.get $b))
  2512. (i32.const 0))
  2513. '((ref.test $fraction (local.get $b))
  2514. (i32.const 0))))
  2515. `((ref.test $bignum (local.get $a))
  2516. ,(arith-cond 'i32
  2517. '((call $fixnum? (local.get $b))
  2518. (i32.const 0))
  2519. '((ref.test $bignum (local.get $b))
  2520. (call $eq-big-big
  2521. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  2522. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
  2523. '((ref.test $flonum (local.get $b))
  2524. (i32.const 0))
  2525. '((ref.test $fraction (local.get $b))
  2526. (i32.const 0))))
  2527. `((ref.test $flonum (local.get $a))
  2528. ,(arith-cond 'i32
  2529. '((call $fixnum? (local.get $b))
  2530. (i32.const 0))
  2531. '((ref.test $bignum (local.get $b))
  2532. (i32.const 0))
  2533. '((ref.test $flonum (local.get $b))
  2534. (f64.eq (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
  2535. (struct.get $flonum $val (ref.cast $flonum (local.get $b)))))
  2536. '((ref.test $fraction (local.get $b))
  2537. (i32.const 0))))
  2538. `((ref.test $fraction (local.get $a))
  2539. ,(arith-cond 'i32
  2540. '((call $fixnum? (local.get $b))
  2541. (i32.const 0))
  2542. '((ref.test $bignum (local.get $b))
  2543. (i32.const 0))
  2544. '((ref.test $flonum (local.get $b))
  2545. (i32.const 0))
  2546. '((ref.test $fraction (local.get $b))
  2547. (i32.and (call $numeric-eqv?
  2548. (struct.get $fraction $num (ref.cast $fraction (local.get $a)))
  2549. (struct.get $fraction $num (ref.cast $fraction (local.get $b))))
  2550. (call $numeric-eqv?
  2551. (struct.get $fraction $denom (ref.cast $fraction (local.get $a)))
  2552. (struct.get $fraction $denom (ref.cast $fraction (local.get $b))))))))))
  2553. (func $negative-integer? (param $a (ref eq)) (result i32)
  2554. ,(arith-cond 'i32
  2555. '((call $fixnum? (local.get $a))
  2556. (if (result i32)
  2557. (i32.ge_s (call $fixnum->i32
  2558. (ref.cast i31 (local.get $a)))
  2559. (i32.const 0))
  2560. (then (i32.const 0))
  2561. (else (i32.const 1))))
  2562. `((ref.test $bignum (local.get $a))
  2563. (if (result i32)
  2564. (f64.ge (call $bignum->f64
  2565. (ref.cast $bignum (local.get $a)))
  2566. (f64.const 0))
  2567. (then (i32.const 0))
  2568. (else (i32.const 1))))))
  2569. ;; TODO: write tests once `fixnum?' or similar is available
  2570. (func $normalize-bignum (param $a (ref $bignum)) (result (ref eq))
  2571. (local $a-val (ref extern))
  2572. (local $a64 i64)
  2573. (local.set $a-val (struct.get $bignum $val (local.get $a)))
  2574. (if (ref eq)
  2575. (call $bignum-is-i64 (local.get $a-val))
  2576. (then (local.set $a64 (call $bignum-get-i64 (local.get $a-val)))
  2577. (if (ref eq)
  2578. (i32.and (i64.le_s (i64.const #x-20000000)
  2579. (local.get $a64))
  2580. (i64.le_s (local.get $a64)
  2581. (i64.const #x1FFFFFFF)))
  2582. (then (ref.i31
  2583. (i32.shl
  2584. (i32.wrap_i64 (local.get $a64))
  2585. (i32.const 1))))
  2586. (else (local.get $a))))
  2587. (else (local.get $a))))
  2588. (func $normalize-fraction (param $a (ref $fraction)) (result (ref eq))
  2589. (if (call $numeric-eqv?
  2590. (struct.get $fraction $denom (local.get $a))
  2591. (ref.i31 (i32.const 0)))
  2592. (then (call $die
  2593. (string.const "division-by-zero")
  2594. (local.get $a))))
  2595. (if (call $negative-integer? (struct.get $fraction $denom (local.get $a)))
  2596. (then (local.set $a
  2597. (struct.new $fraction
  2598. (i32.const 0)
  2599. (call $mul
  2600. (struct.get $fraction $num (local.get $a))
  2601. (call $i32->fixnum (i32.const -1)))
  2602. (call $mul
  2603. (struct.get $fraction $denom (local.get $a))
  2604. (call $i32->fixnum (i32.const -1)))))))
  2605. (if (ref eq)
  2606. (call $numeric-eqv?
  2607. (struct.get $fraction $denom (local.get $a))
  2608. (ref.i31 (i32.const #b10)))
  2609. (then (struct.get $fraction $num (local.get $a)))
  2610. (else (local.get $a))))
  2611. (func $normalize-fraction/gcd (param $a (ref $fraction)) (result (ref eq))
  2612. (local $d (ref eq))
  2613. (local.set $d (call $gcd
  2614. (struct.get $fraction $num (local.get $a))
  2615. (struct.get $fraction $denom (local.get $a))))
  2616. (call $normalize-fraction
  2617. (struct.new $fraction
  2618. (i32.const 0)
  2619. (call $quo (struct.get $fraction $num (local.get $a)) (local.get $d))
  2620. (call $quo (struct.get $fraction $denom (local.get $a)) (local.get $d)))))
  2621. ;; Greatest common divisor: v. TAOCP II 4.5.2 Algorithm A (modern
  2622. ;; Euclidean algorithm). TODO: use a modernized version of
  2623. ;; Algorithm B
  2624. (func $gcd (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
  2625. ,(arith-cond
  2626. `((call $fixnum? (local.get $a))
  2627. ,(arith-cond
  2628. '((call $fixnum? (local.get $b))
  2629. (call $i32->fixnum
  2630. (call $gcd-i32
  2631. (call $fixnum->i32 (ref.cast i31 (local.get $a)))
  2632. (call $fixnum->i32 (ref.cast i31 (local.get $b))))))
  2633. '((ref.test $bignum (local.get $b))
  2634. (call $normalize-bignum
  2635. (struct.new $bignum
  2636. (i32.const 0)
  2637. (call $bignum-gcd
  2638. (call $bignum-from-i32
  2639. (call $fixnum->i32
  2640. (ref.cast i31 (local.get $a))))
  2641. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))))))
  2642. `((ref.test $bignum (local.get $a))
  2643. ,(arith-cond
  2644. '((call $fixnum? (local.get $b))
  2645. (call $normalize-bignum
  2646. (struct.new $bignum
  2647. (i32.const 0)
  2648. (call $bignum-gcd
  2649. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  2650. (call $bignum-from-i32
  2651. (call $fixnum->i32
  2652. (ref.cast i31 (local.get $b))))))))
  2653. '((ref.test $bignum (local.get $b))
  2654. (call $normalize-bignum
  2655. (struct.new $bignum
  2656. (i32.const 0)
  2657. (call $bignum-gcd
  2658. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  2659. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))))))))
  2660. (func $gcd-i32 (param $a i32) (param $b i32) (result i32)
  2661. (local $r i32)
  2662. ;; Ensure $a and $b are both positive
  2663. (if (i32.lt_s (local.get $a) (i32.const 0))
  2664. (then (local.set $a (i32.mul (local.get $a) (i32.const -1)))))
  2665. (if (i32.lt_s (local.get $b) (i32.const 0))
  2666. (then (local.set $b (i32.mul (local.get $b) (i32.const -1)))))
  2667. (if (i32.eqz (local.get $a))
  2668. (then (return (local.get $b))))
  2669. (if (i32.eqz (local.get $b))
  2670. (then (return (local.get $a))))
  2671. (block $blk
  2672. (loop $lp
  2673. (br_if $blk (i32.eqz (local.get $b)))
  2674. (local.set $r (i32.rem_u (local.get $a)
  2675. (local.get $b)))
  2676. (local.set $a (local.get $b))
  2677. (local.set $b (local.get $r))
  2678. (br $lp)))
  2679. (return (local.get $a)))
  2680. ;; The $A and $B parameters are 30-bit fixnums, with a zero LSB bit
  2681. ;; as the fixnum tag. We examine the top three bits of the result:
  2682. ;; if they're identical, no overflow has occurred and the result is
  2683. ;; represented as a fixnum; otherwise, the result won't fit into a
  2684. ;; fixnum and must be returned as a bignum.
  2685. (func $fixnum-add (param $a i32) (param $b i32) (result (ref eq))
  2686. (local $c i32)
  2687. (local $d i32)
  2688. (local.set $c (i32.add (local.get $a) (local.get $b)))
  2689. (local.set $d (i32.shr_u (local.get $c) (i32.const 29)))
  2690. (if (result (ref eq))
  2691. (i32.or (i32.eqz (local.get $d))
  2692. (i32.eq (local.get $d)
  2693. (i32.const #b111)))
  2694. (then (ref.i31 (local.get $c)))
  2695. (else (call $i32->bignum (i32.shr_s (local.get $c) (i32.const 1))))))
  2696. (func $fixnum-sub (param $a i32) (param $b i32) (result (ref eq))
  2697. (local $c i32)
  2698. (local $d i32)
  2699. (local.set $c (i32.sub (local.get $a) (local.get $b)))
  2700. (local.set $d (i32.shr_u (local.get $c) (i32.const 29)))
  2701. (if (result (ref eq))
  2702. (i32.or (i32.eqz (local.get $d))
  2703. (i32.eq (local.get $d)
  2704. (i32.const #b111)))
  2705. (then (ref.i31 (local.get $c)))
  2706. (else (call $i32->bignum (i32.shr_s (local.get $c) (i32.const 1))))))
  2707. (func $fixnum-mul (param $a32 i32) (param $b32 i32) (result (ref eq))
  2708. (local $a i64)
  2709. (local $b i64)
  2710. (local $c i64)
  2711. ;; Shift off one operand's tag bit so that the result is also
  2712. ;; properly tagged.
  2713. (local.set $a (i64.extend_i32_s
  2714. (i32.shr_s (local.get $a32) (i32.const 1))))
  2715. (local.set $b (i64.extend_i32_s (local.get $b32)))
  2716. (local.set $c (i64.mul (local.get $a) (local.get $b)))
  2717. (if (result (ref eq))
  2718. ;; Return a bignum if the (tagged) result lies outside of
  2719. ;; [2^30-1, 2^30].
  2720. (i32.and (i64.ge_s (local.get $c) (i64.const #x-40000000))
  2721. (i64.le_s (local.get $c) (i64.const #x03FFFFFFF)))
  2722. (then (ref.i31 (i32.wrap_i64 (local.get $c))))
  2723. (else
  2724. (call $normalize-bignum
  2725. (struct.new $bignum
  2726. (i32.const 0)
  2727. (call $bignum-from-i64
  2728. (i64.shr_s (local.get $c) (i64.const 1))))))))
  2729. (func $fixnum-add* (param $a (ref i31)) (param $b (ref i31)) (result (ref eq))
  2730. (call $fixnum-add
  2731. (i31.get_s (local.get $a))
  2732. (i31.get_s (local.get $b))))
  2733. (func $fixnum-sub* (param $a (ref i31)) (param $b (ref i31)) (result (ref eq))
  2734. (call $fixnum-sub
  2735. (i31.get_s (local.get $a))
  2736. (i31.get_s (local.get $b))))
  2737. (func $fixnum-mul* (param $a (ref i31)) (param $b (ref i31)) (result (ref eq))
  2738. (call $fixnum-mul
  2739. (i31.get_s (local.get $a))
  2740. (i31.get_s (local.get $b))))
  2741. (func $bignum-add* (param $a (ref $bignum)) (param $b (ref $bignum)) (result (ref $bignum))
  2742. (struct.new
  2743. $bignum
  2744. (i32.const 0)
  2745. (call $bignum-add
  2746. (struct.get $bignum $val (local.get $a))
  2747. (struct.get $bignum $val (local.get $b)))))
  2748. (func $bignum-sub* (param $a (ref $bignum)) (param $b (ref $bignum)) (result (ref $bignum))
  2749. (struct.new
  2750. $bignum
  2751. (i32.const 0)
  2752. (call $bignum-sub
  2753. (struct.get $bignum $val (local.get $a))
  2754. (struct.get $bignum $val (local.get $b)))))
  2755. (func $bignum-mul* (param $a (ref $bignum)) (param $b (ref $bignum)) (result (ref $bignum))
  2756. (struct.new
  2757. $bignum
  2758. (i32.const 0)
  2759. (call $bignum-mul
  2760. (struct.get $bignum $val (local.get $a))
  2761. (struct.get $bignum $val (local.get $b)))))
  2762. (func $bignum-quo* (param $a (ref $bignum)) (param $b (ref $bignum)) (result (ref $bignum))
  2763. (struct.new
  2764. $bignum
  2765. (i32.const 0)
  2766. (call $bignum-quo
  2767. (struct.get $bignum $val (local.get $a))
  2768. (struct.get $bignum $val (local.get $b)))))
  2769. (func $bignum-rem* (param $a (ref $bignum)) (param $b (ref $bignum)) (result (ref $bignum))
  2770. (struct.new
  2771. $bignum
  2772. (i32.const 0)
  2773. (call $bignum-rem
  2774. (struct.get $bignum $val (local.get $a))
  2775. (struct.get $bignum $val (local.get $b)))))
  2776. (func $bignum-mod* (param $a (ref $bignum)) (param $b (ref $bignum)) (result (ref $bignum))
  2777. (struct.new
  2778. $bignum
  2779. (i32.const 0)
  2780. (call $bignum-mod
  2781. (struct.get $bignum $val (local.get $a))
  2782. (struct.get $bignum $val (local.get $b)))))
  2783. ;; Exact fraction arithmetic
  2784. ;; Fraction addition
  2785. (func $add-fracnum-fixnum (param $a (ref $fraction)) (param $b (ref i31)) (result (ref eq))
  2786. (call $add-fracnum-fracnum
  2787. (local.get $a)
  2788. (struct.new $fraction
  2789. (i32.const 0)
  2790. (call $mul (local.get $b) (struct.get $fraction $denom (local.get $a)))
  2791. (struct.get $fraction $denom (local.get $a)))))
  2792. (func $add-fracnum-bignum (param $a (ref $fraction)) (param $b (ref $bignum)) (result (ref eq))
  2793. (call $add-fracnum-fracnum
  2794. (local.get $a)
  2795. (struct.new $fraction
  2796. (i32.const 0)
  2797. (call $mul (local.get $b) (struct.get $fraction $denom (local.get $a)))
  2798. (struct.get $fraction $denom (local.get $a)))))
  2799. (func $add-fracnum-fracnum (param $a (ref $fraction)) (param $b (ref $fraction)) (result (ref eq))
  2800. (local $d1 (ref eq))
  2801. (local $d2 (ref eq))
  2802. (local $t (ref eq))
  2803. (local.set $d1 (call $gcd
  2804. (struct.get $fraction $denom (local.get $a))
  2805. (struct.get $fraction $denom (local.get $b))))
  2806. (if (result (ref eq))
  2807. (if (result i32)
  2808. (call $fixnum? (local.get $d1))
  2809. (then (i32.eq (i31.get_s (ref.cast i31 (local.get $d1)))
  2810. (i32.const #b10)))
  2811. (else (f64.eq (call $bignum->f64 (ref.cast $bignum (local.get $d1)))
  2812. (f64.const 1))))
  2813. (then
  2814. (call $normalize-fraction
  2815. (struct.new $fraction
  2816. (i32.const 0)
  2817. (call $add
  2818. (call $mul
  2819. (struct.get $fraction $num (local.get $a))
  2820. (struct.get $fraction $denom (local.get $b)))
  2821. (call $mul
  2822. (struct.get $fraction $denom (local.get $a))
  2823. (struct.get $fraction $num (local.get $b))))
  2824. (call $mul
  2825. (struct.get $fraction $denom (local.get $a))
  2826. (struct.get $fraction $denom (local.get $b))))))
  2827. (else
  2828. (local.set $t
  2829. (call $add
  2830. (call $mul
  2831. (struct.get $fraction $num (local.get $a))
  2832. (call $quo
  2833. (struct.get $fraction $denom (local.get $b))
  2834. (local.get $d1)))
  2835. (call $mul
  2836. (struct.get $fraction $num (local.get $b))
  2837. (call $quo
  2838. (struct.get $fraction $denom (local.get $a))
  2839. (local.get $d1)))))
  2840. (local.set $d2 (call $gcd (local.get $t) (local.get $d1)))
  2841. (call $normalize-fraction
  2842. (struct.new $fraction
  2843. (i32.const 0)
  2844. (call $quo
  2845. (local.get $t)
  2846. (local.get $d2))
  2847. (call $mul
  2848. (call $quo
  2849. (struct.get $fraction $denom (local.get $a))
  2850. (local.get $d1))
  2851. (call $quo
  2852. (struct.get $fraction $denom (local.get $b))
  2853. (local.get $d2))))))))
  2854. ;; Fraction subtraction
  2855. (func $sub-fixnum-fracnum (param $a (ref i31)) (param $b (ref $fraction)) (result (ref eq))
  2856. (call $sub-fracnum-fracnum
  2857. (struct.new $fraction
  2858. (i32.const 0)
  2859. (call $mul (local.get $a) (struct.get $fraction $denom (local.get $b)))
  2860. (struct.get $fraction $denom (local.get $b)))
  2861. (local.get $b)))
  2862. (func $sub-bignum-fracnum (param $a (ref $bignum)) (param $b (ref $fraction)) (result (ref eq))
  2863. (call $sub-fracnum-fracnum
  2864. (struct.new $fraction
  2865. (i32.const 0)
  2866. (call $mul (local.get $a) (struct.get $fraction $denom (local.get $b)))
  2867. (struct.get $fraction $denom (local.get $b)))
  2868. (local.get $b)))
  2869. (func $sub-fracnum-fixnum (param $a (ref $fraction)) (param $b (ref i31)) (result (ref eq))
  2870. (call $sub-fracnum-fracnum
  2871. (local.get $a)
  2872. (struct.new $fraction
  2873. (i32.const 0)
  2874. (call $mul (local.get $b) (struct.get $fraction $denom (local.get $a)))
  2875. (struct.get $fraction $denom (local.get $a)))))
  2876. (func $sub-fracnum-bignum (param $a (ref $fraction)) (param $b (ref $bignum)) (result (ref eq))
  2877. (call $sub-fracnum-fracnum
  2878. (local.get $a)
  2879. (struct.new $fraction
  2880. (i32.const 0)
  2881. (call $mul (local.get $b) (struct.get $fraction $denom (local.get $a)))
  2882. (struct.get $fraction $denom (local.get $a)))))
  2883. (func $sub-fracnum-fracnum (param $a (ref $fraction)) (param $b (ref $fraction)) (result (ref eq))
  2884. (local $d1 (ref eq))
  2885. (local $d2 (ref eq))
  2886. (local $t (ref eq))
  2887. (local.set $d1 (call $gcd
  2888. (struct.get $fraction $denom (local.get $a))
  2889. (struct.get $fraction $denom (local.get $b))))
  2890. (if (result (ref eq))
  2891. ;; FIXME: use generic =
  2892. (if (result i32)
  2893. (ref.test i31 (local.get $d1))
  2894. (then (i32.eq (i31.get_s (ref.cast i31 (local.get $d1)))
  2895. (i32.const #b10)))
  2896. (else (i32.const 0)))
  2897. (then
  2898. (call $normalize-fraction
  2899. (struct.new $fraction
  2900. (i32.const 0)
  2901. (call $sub
  2902. (call $mul
  2903. (struct.get $fraction $num (local.get $a))
  2904. (struct.get $fraction $denom (local.get $b)))
  2905. (call $mul
  2906. (struct.get $fraction $denom (local.get $a))
  2907. (struct.get $fraction $num (local.get $b))))
  2908. (call $mul
  2909. (struct.get $fraction $denom (local.get $a))
  2910. (struct.get $fraction $denom (local.get $b))))))
  2911. (else
  2912. (local.set $t
  2913. (call $sub
  2914. (call $mul
  2915. (struct.get $fraction $num (local.get $a))
  2916. (call $quo
  2917. (struct.get $fraction $denom (local.get $b))
  2918. (local.get $d1)))
  2919. (call $mul
  2920. (struct.get $fraction $num (local.get $b))
  2921. (call $quo
  2922. (struct.get $fraction $denom (local.get $a))
  2923. (local.get $d1)))))
  2924. (local.set $d2 (call $gcd (local.get $t) (local.get $d1)))
  2925. (call $normalize-fraction
  2926. (struct.new $fraction
  2927. (i32.const 0)
  2928. (call $quo
  2929. (local.get $t)
  2930. (local.get $d2))
  2931. (call $mul
  2932. (call $quo
  2933. (struct.get $fraction $denom (local.get $a))
  2934. (local.get $d1))
  2935. (call $quo
  2936. (struct.get $fraction $denom (local.get $b))
  2937. (local.get $d2))))))))
  2938. ;; Fraction multiplication
  2939. (func $mul-fracnum-fixnum (param $a (ref $fraction)) (param $b (ref i31)) (result (ref eq))
  2940. (call $normalize-fraction/gcd
  2941. (struct.new $fraction
  2942. (i32.const 0)
  2943. (call $mul (local.get $b) (struct.get $fraction $num (local.get $a)))
  2944. (struct.get $fraction $denom (local.get $a)))))
  2945. (func $mul-fracnum-bignum (param $a (ref $fraction)) (param $b (ref $bignum)) (result (ref eq))
  2946. (call $normalize-fraction/gcd
  2947. (struct.new $fraction
  2948. (i32.const 0)
  2949. (call $mul (local.get $b) (struct.get $fraction $num (local.get $a)))
  2950. (struct.get $fraction $denom (local.get $a)))))
  2951. (func $mul-fracnum-fracnum (param $a (ref $fraction)) (param $b (ref $fraction)) (result (ref eq))
  2952. (local $d1 (ref eq))
  2953. (local $d2 (ref eq))
  2954. (local.set $d1 (call $gcd
  2955. (struct.get $fraction $num (local.get $a))
  2956. (struct.get $fraction $denom (local.get $b))))
  2957. (local.set $d2 (call $gcd
  2958. (struct.get $fraction $denom (local.get $a))
  2959. (struct.get $fraction $num (local.get $b))))
  2960. (call $normalize-fraction
  2961. (struct.new $fraction
  2962. (i32.const 0)
  2963. (call $mul
  2964. (call $quo
  2965. (struct.get $fraction $num (local.get $a))
  2966. (local.get $d1))
  2967. (call $quo
  2968. (struct.get $fraction $num (local.get $b))
  2969. (local.get $d2)))
  2970. (call $mul
  2971. (call $quo
  2972. (struct.get $fraction $denom (local.get $a))
  2973. (local.get $d2))
  2974. (call $quo
  2975. (struct.get $fraction $denom (local.get $b))
  2976. (local.get $d1))))))
  2977. ;; Fraction division
  2978. (func $div-fixnum-fracnum (param $a (ref i31)) (param $b (ref $fraction)) (result (ref eq))
  2979. (call $normalize-fraction/gcd
  2980. (struct.new $fraction
  2981. (i32.const 0)
  2982. (call $mul (local.get $a) (struct.get $fraction $denom (local.get $b)))
  2983. (struct.get $fraction $num (local.get $b)))))
  2984. (func $div-bignum-fracnum (param $a (ref $bignum)) (param $b (ref $fraction)) (result (ref eq))
  2985. (call $normalize-fraction/gcd
  2986. (struct.new $fraction
  2987. (i32.const 0)
  2988. (call $mul (local.get $a) (struct.get $fraction $denom (local.get $b)))
  2989. (struct.get $fraction $num (local.get $b)))))
  2990. (func $div-fracnum-fixnum (param $a (ref $fraction)) (param $b (ref i31)) (result (ref eq))
  2991. (call $normalize-fraction/gcd
  2992. (struct.new $fraction
  2993. (i32.const 0)
  2994. (call $mul (local.get $b) (struct.get $fraction $denom (local.get $a)))
  2995. (struct.get $fraction $num (local.get $a)))))
  2996. (func $div-fracnum-bignum (param $a (ref $fraction)) (param $b (ref $bignum)) (result (ref eq))
  2997. (call $normalize-fraction/gcd
  2998. (struct.new $fraction
  2999. (i32.const 0)
  3000. (call $mul (local.get $b) (struct.get $fraction $denom (local.get $a)))
  3001. (struct.get $fraction $num (local.get $a)))))
  3002. (func $div-fracnum-fracnum (param $a (ref $fraction)) (param $b (ref $fraction)) (result (ref eq))
  3003. (call $normalize-fraction/gcd
  3004. (struct.new $fraction
  3005. (i32.const 0)
  3006. (call $mul
  3007. (struct.get $fraction $num (local.get $a))
  3008. (struct.get $fraction $denom (local.get $b)))
  3009. (call $mul
  3010. (struct.get $fraction $denom (local.get $a))
  3011. (struct.get $fraction $num (local.get $b))))))
  3012. (func $add (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
  3013. ,(arith-cond
  3014. `((call $fixnum? (local.get $a))
  3015. ,(arith-cond
  3016. '((call $fixnum? (local.get $b))
  3017. (return (call $fixnum-add*
  3018. (ref.cast i31 (local.get $a))
  3019. (ref.cast i31 (local.get $b)))))
  3020. '((ref.test $bignum (local.get $b))
  3021. (return (call $normalize-bignum
  3022. (call $bignum-add*
  3023. (struct.new $bignum
  3024. (i32.const 0)
  3025. (call $bignum-from-i32
  3026. (i32.shr_s (i31.get_s (ref.cast i31 (local.get $a)))
  3027. (i32.const 1))))
  3028. (ref.cast $bignum (local.get $b))))))
  3029. '((ref.test $flonum (local.get $b))
  3030. (return
  3031. (struct.new $flonum
  3032. (i32.const 0)
  3033. (f64.add
  3034. (call $fixnum->f64 (ref.cast i31 (local.get $a)))
  3035. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
  3036. '((ref.test $fraction (local.get $b))
  3037. (return (call $add-fracnum-fixnum
  3038. (ref.cast $fraction (local.get $b))
  3039. (ref.cast i31 (local.get $a)))))))
  3040. `((ref.test $bignum (local.get $a))
  3041. ,(arith-cond
  3042. '((call $fixnum? (local.get $b))
  3043. (return (call $normalize-bignum
  3044. (call $bignum-add*
  3045. (ref.cast $bignum (local.get $a))
  3046. (struct.new $bignum
  3047. (i32.const 0)
  3048. (call $bignum-from-i32
  3049. (i32.shr_s (i31.get_s (ref.cast i31 (local.get $b)))
  3050. (i32.const 1))))))))
  3051. '((ref.test $bignum (local.get $b))
  3052. (return (call $normalize-bignum
  3053. (call $bignum-add*
  3054. (ref.cast $bignum (local.get $a))
  3055. (ref.cast $bignum (local.get $b))))))
  3056. '((ref.test $flonum (local.get $b))
  3057. (return
  3058. (struct.new $flonum
  3059. (i32.const 0)
  3060. (f64.add
  3061. (call $bignum->f64 (ref.cast $bignum (local.get $a)))
  3062. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
  3063. '((ref.test $fraction (local.get $b))
  3064. (return (call $add-fracnum-bignum
  3065. (ref.cast $fraction (local.get $b))
  3066. (ref.cast $bignum (local.get $a)))))))
  3067. `((ref.test $flonum (local.get $a))
  3068. ,(arith-cond
  3069. '((call $fixnum? (local.get $b))
  3070. (return (struct.new $flonum
  3071. (i32.const 0)
  3072. (f64.add
  3073. (call $flonum->f64 (ref.cast $flonum (local.get $a)))
  3074. (call $fixnum->f64 (ref.cast i31 (local.get $b)))))))
  3075. '((ref.test $bignum (local.get $b))
  3076. (return (struct.new $flonum
  3077. (i32.const 0)
  3078. (f64.add
  3079. (call $flonum->f64 (ref.cast $flonum (local.get $a)))
  3080. (call $bignum->f64 (ref.cast $bignum (local.get $b)))))))
  3081. '((ref.test $flonum (local.get $b))
  3082. (return (struct.new $flonum
  3083. (i32.const 0)
  3084. (f64.add
  3085. (call $flonum->f64 (ref.cast $flonum (local.get $a)))
  3086. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))))
  3087. `((ref.test $fraction (local.get $a))
  3088. ,(arith-cond
  3089. '((call $fixnum? (local.get $b))
  3090. (return (call $add-fracnum-fixnum
  3091. (ref.cast $fraction (local.get $a))
  3092. (ref.cast i31 (local.get $b)))))
  3093. '((ref.test $bignum (local.get $b))
  3094. (return (call $add-fracnum-bignum
  3095. (ref.cast $fraction (local.get $a))
  3096. (ref.cast $bignum (local.get $b)))))
  3097. '((ref.test $fraction (local.get $b))
  3098. (return (call $add-fracnum-fracnum
  3099. (ref.cast $fraction (local.get $a))
  3100. (ref.cast $fraction (local.get $b)))))))))
  3101. (func $sub (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
  3102. ,(arith-cond
  3103. `((call $fixnum? (local.get $a))
  3104. ,(arith-cond
  3105. '((call $fixnum? (local.get $b))
  3106. (return (call $fixnum-sub*
  3107. (ref.cast i31 (local.get $a))
  3108. (ref.cast i31 (local.get $b)))))
  3109. '((ref.test $bignum (local.get $b))
  3110. (return (call $normalize-bignum
  3111. (call $bignum-sub*
  3112. (struct.new $bignum
  3113. (i32.const 0)
  3114. (call $bignum-from-i32
  3115. (i32.shr_s (i31.get_s (ref.cast i31 (local.get $a)))
  3116. (i32.const 1))))
  3117. (ref.cast $bignum (local.get $b))))))
  3118. '((ref.test $flonum (local.get $b))
  3119. (return (struct.new $flonum
  3120. (i32.const 0)
  3121. (f64.sub
  3122. (call $fixnum->f64 (ref.cast i31 (local.get $a)))
  3123. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
  3124. '((ref.test $fraction (local.get $b))
  3125. (return (call $sub-fixnum-fracnum
  3126. (ref.cast i31 (local.get $a))
  3127. (ref.cast $fraction (local.get $b)))))))
  3128. `((ref.test $bignum (local.get $a))
  3129. ,(arith-cond
  3130. '((call $fixnum? (local.get $b))
  3131. (return (call $normalize-bignum
  3132. (call $bignum-sub*
  3133. (ref.cast $bignum (local.get $a))
  3134. (struct.new $bignum
  3135. (i32.const 0)
  3136. (call $bignum-from-i32
  3137. (i32.shr_s (i31.get_s (ref.cast i31 (local.get $b)))
  3138. (i32.const 1))))))))
  3139. '((ref.test $bignum (local.get $b))
  3140. (return (call $normalize-bignum
  3141. (call $bignum-sub*
  3142. (ref.cast $bignum (local.get $a))
  3143. (ref.cast $bignum (local.get $b))))))
  3144. '((ref.test $flonum (local.get $b))
  3145. (return (struct.new $flonum
  3146. (i32.const 0)
  3147. (f64.sub
  3148. (call $bignum->f64 (ref.cast $bignum (local.get $a)))
  3149. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
  3150. '((ref.test $fraction (local.get $b))
  3151. (return (call $sub-bignum-fracnum
  3152. (ref.cast $bignum (local.get $a))
  3153. (ref.cast $fraction (local.get $b)))))))
  3154. `((ref.test $flonum (local.get $a))
  3155. ,(arith-cond
  3156. '((call $fixnum? (local.get $b))
  3157. (return (struct.new $flonum
  3158. (i32.const 0)
  3159. (f64.sub
  3160. (call $flonum->f64 (ref.cast $flonum (local.get $a)))
  3161. (call $fixnum->f64 (ref.cast i31 (local.get $b)))))))
  3162. '((ref.test $bignum (local.get $b))
  3163. (return (struct.new $flonum
  3164. (i32.const 0)
  3165. (f64.sub
  3166. (call $flonum->f64 (ref.cast $flonum (local.get $a)))
  3167. (call $bignum->f64 (ref.cast $bignum (local.get $b)))))))
  3168. '((ref.test $flonum (local.get $b))
  3169. (return (struct.new $flonum
  3170. (i32.const 0)
  3171. (f64.sub
  3172. (call $flonum->f64 (ref.cast $flonum (local.get $a)))
  3173. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))))
  3174. `((ref.test $fraction (local.get $a))
  3175. ,(arith-cond
  3176. '((call $fixnum? (local.get $b))
  3177. (return (call $sub-fracnum-fixnum
  3178. (ref.cast $fraction (local.get $a))
  3179. (ref.cast i31 (local.get $b)))))
  3180. '((ref.test $bignum (local.get $b))
  3181. (return (call $sub-fracnum-bignum
  3182. (ref.cast $fraction (local.get $a))
  3183. (ref.cast $bignum (local.get $b)))))
  3184. '((ref.test $fraction (local.get $b))
  3185. (return (call $sub-fracnum-fracnum
  3186. (ref.cast $fraction (local.get $a))
  3187. (ref.cast $fraction (local.get $b)))))))))
  3188. (func $mul (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
  3189. ,(arith-cond
  3190. `((call $fixnum? (local.get $a))
  3191. ,(arith-cond
  3192. '((call $fixnum? (local.get $b))
  3193. (return (call $fixnum-mul*
  3194. (ref.cast i31 (local.get $a))
  3195. (ref.cast i31 (local.get $b)))))
  3196. '((ref.test $bignum (local.get $b))
  3197. (return (call $normalize-bignum
  3198. (call $bignum-mul*
  3199. (struct.new $bignum
  3200. (i32.const 0)
  3201. (call $bignum-from-i32
  3202. (i32.shr_s (i31.get_s (ref.cast i31 (local.get $a)))
  3203. (i32.const 1))))
  3204. (ref.cast $bignum (local.get $b))))))
  3205. '((ref.test $flonum (local.get $b))
  3206. (return (struct.new $flonum
  3207. (i32.const 0)
  3208. (f64.mul
  3209. (call $fixnum->f64 (ref.cast i31 (local.get $a)))
  3210. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
  3211. '((ref.test $fraction (local.get $b))
  3212. (return (call $mul-fracnum-fixnum
  3213. (ref.cast $fraction (local.get $b))
  3214. (ref.cast i31 (local.get $a)))))))
  3215. `((ref.test $bignum (local.get $a))
  3216. ,(arith-cond
  3217. '((call $fixnum? (local.get $b))
  3218. (return (call $normalize-bignum
  3219. (call $bignum-mul*
  3220. (ref.cast $bignum (local.get $a))
  3221. (struct.new $bignum
  3222. (i32.const 0)
  3223. (call $bignum-from-i32
  3224. (i32.shr_s (i31.get_s (ref.cast i31 (local.get $b)))
  3225. (i32.const 1))))))))
  3226. '((ref.test $bignum (local.get $b))
  3227. (return (call $normalize-bignum
  3228. (call $bignum-mul*
  3229. (ref.cast $bignum (local.get $a))
  3230. (ref.cast $bignum (local.get $b))))))
  3231. '((ref.test $flonum (local.get $b))
  3232. (return (struct.new $flonum
  3233. (i32.const 0)
  3234. (f64.mul
  3235. (call $bignum->f64 (ref.cast $bignum (local.get $a)))
  3236. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
  3237. '((ref.test $fraction (local.get $b))
  3238. (return (call $mul-fracnum-bignum
  3239. (ref.cast $fraction (local.get $b))
  3240. (ref.cast $bignum (local.get $a)))))))
  3241. `((ref.test $flonum (local.get $a))
  3242. ,(arith-cond
  3243. '((call $fixnum? (local.get $b))
  3244. (return (struct.new $flonum
  3245. (i32.const 0)
  3246. (f64.mul
  3247. (call $flonum->f64 (ref.cast $flonum (local.get $a)))
  3248. (call $fixnum->f64 (ref.cast i31 (local.get $b)))))))
  3249. '((ref.test $bignum (local.get $b))
  3250. (return (struct.new $flonum
  3251. (i32.const 0)
  3252. (f64.mul
  3253. (call $flonum->f64 (ref.cast $flonum (local.get $a)))
  3254. (call $bignum->f64 (ref.cast $bignum (local.get $b)))))))
  3255. '((ref.test $flonum (local.get $b))
  3256. (return (struct.new $flonum
  3257. (i32.const 0)
  3258. (f64.mul
  3259. (call $flonum->f64 (ref.cast $flonum (local.get $a)))
  3260. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
  3261. '((ref.test $fraction (local.get $b))
  3262. (return (struct.new $flonum
  3263. (i32.const 0)
  3264. (f64.mul
  3265. (call $flonum->f64 (ref.cast $flonum (local.get $a)))
  3266. (call $flonum->f64
  3267. (call $inexact (local.get $b)))))))))
  3268. `((ref.test $fraction (local.get $a))
  3269. ,(arith-cond
  3270. '((call $fixnum? (local.get $b))
  3271. (return (call $mul-fracnum-fixnum
  3272. (ref.cast $fraction (local.get $a))
  3273. (ref.cast i31 (local.get $b)))))
  3274. '((ref.test $bignum (local.get $b))
  3275. (return (call $mul-fracnum-bignum
  3276. (ref.cast $fraction (local.get $a))
  3277. (ref.cast $bignum (local.get $b)))))
  3278. '((ref.test $flonum (local.get $b))
  3279. (return (struct.new $flonum
  3280. (i32.const 0)
  3281. (f64.mul
  3282. (call $flonum->f64
  3283. (call $inexact (local.get $a)))
  3284. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
  3285. '((ref.test $fraction (local.get $b))
  3286. (return (call $mul-fracnum-fracnum
  3287. (ref.cast $fraction (local.get $a))
  3288. (ref.cast $fraction (local.get $b)))))))))
  3289. (func $div (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
  3290. ,(arith-cond
  3291. `((call $fixnum? (local.get $a))
  3292. ,(arith-cond
  3293. '((call $fixnum? (local.get $b))
  3294. (return (call $normalize-fraction/gcd
  3295. (struct.new $fraction
  3296. (i32.const 0)
  3297. (local.get $a)
  3298. (local.get $b)))))
  3299. '((ref.test $bignum (local.get $b))
  3300. (return (call $normalize-fraction/gcd
  3301. (struct.new $fraction
  3302. (i32.const 0)
  3303. (local.get $a)
  3304. (local.get $b)))))
  3305. '((ref.test $flonum (local.get $b))
  3306. (return (struct.new $flonum
  3307. (i32.const 0)
  3308. (f64.div
  3309. (call $fixnum->f64 (ref.cast i31 (local.get $a)))
  3310. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
  3311. '((ref.test $fraction (local.get $b))
  3312. (return (call $div-fixnum-fracnum
  3313. (ref.cast i31 (local.get $a))
  3314. (ref.cast $fraction (local.get $b)))))))
  3315. `((ref.test $bignum (local.get $a))
  3316. ,(arith-cond
  3317. '((call $fixnum? (local.get $b))
  3318. (return (call $normalize-fraction/gcd
  3319. (struct.new $fraction
  3320. (i32.const 0)
  3321. (local.get $a)
  3322. (local.get $b)))))
  3323. '((ref.test $bignum (local.get $b))
  3324. (return (call $normalize-fraction/gcd
  3325. (struct.new $fraction
  3326. (i32.const 0)
  3327. (local.get $a)
  3328. (local.get $b)))))
  3329. '((ref.test $flonum (local.get $b))
  3330. (return (struct.new $flonum
  3331. (i32.const 0)
  3332. (f64.div
  3333. (call $bignum->f64 (ref.cast $bignum (local.get $a)))
  3334. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
  3335. '((ref.test $fraction (local.get $b))
  3336. (return (call $div-fixnum-fracnum
  3337. (ref.cast i31 (local.get $a))
  3338. (ref.cast $fraction (local.get $b)))))))
  3339. `((ref.test $flonum (local.get $a))
  3340. ,(arith-cond
  3341. '((call $fixnum? (local.get $b))
  3342. (return (struct.new $flonum
  3343. (i32.const 0)
  3344. (f64.div
  3345. (call $flonum->f64 (ref.cast $flonum (local.get $a)))
  3346. (call $fixnum->f64 (ref.cast i31 (local.get $b)))))))
  3347. '((ref.test $bignum (local.get $b))
  3348. (return (struct.new $flonum
  3349. (i32.const 0)
  3350. (f64.div
  3351. (call $flonum->f64 (ref.cast $flonum (local.get $a)))
  3352. (call $bignum->f64 (ref.cast $bignum (local.get $b)))))))
  3353. '((ref.test $flonum (local.get $b))
  3354. (return (struct.new $flonum
  3355. (i32.const 0)
  3356. (f64.div
  3357. (call $flonum->f64 (ref.cast $flonum (local.get $a)))
  3358. (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))))
  3359. `((ref.test $fraction (local.get $a))
  3360. ,(arith-cond
  3361. '((call $fixnum? (local.get $b))
  3362. (return (call $div-fracnum-fixnum
  3363. (ref.cast $fraction (local.get $a))
  3364. (ref.cast i31 (local.get $b)))))
  3365. '((ref.test $bignum (local.get $b))
  3366. (return (call $div-fracnum-bignum
  3367. (ref.cast $fraction (local.get $a))
  3368. (ref.cast $bignum (local.get $b)))))
  3369. '((ref.test $fraction (local.get $b))
  3370. (return (call $div-fracnum-fracnum
  3371. (ref.cast $fraction (local.get $a))
  3372. (ref.cast $fraction (local.get $b)))))))))
  3373. (func $quo (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
  3374. (local $a-i32 i32)
  3375. (local $b-i32 i32)
  3376. ,(arith-cond
  3377. `((call $fixnum? (local.get $a))
  3378. ,(arith-cond
  3379. ;; Adapted from the `quo' fixnum fast path in (hoot compile).
  3380. ;; TODO: implement for b = -1
  3381. '((call $fixnum? (local.get $b))
  3382. (local.set $a-i32 (call $fixnum->i32
  3383. (ref.cast i31 (local.get $a))))
  3384. (local.set $b-i32 (call $fixnum->i32
  3385. (ref.cast i31 (local.get $b))))
  3386. (if (i32.eqz (local.get $b-i32))
  3387. (then
  3388. (call $die0 (string.const "$quo"))
  3389. (unreachable)))
  3390. (i32.div_s (local.get $a-i32) (local.get $b-i32))
  3391. (i32.const 1) (i32.shl)
  3392. (ref.i31))
  3393. '((ref.test $bignum (local.get $b))
  3394. (return (call $normalize-bignum
  3395. (call $bignum-quo*
  3396. (struct.new $bignum
  3397. (i32.const 0)
  3398. (call $bignum-from-i32
  3399. (call $fixnum->i32
  3400. (ref.cast i31 (local.get $a)))))
  3401. (ref.cast $bignum (local.get $b))))))
  3402. '((ref.test $flonum (local.get $b))
  3403. (if (ref eq)
  3404. (call $flonum-integer? (local.get $b))
  3405. (then
  3406. (call $inexact
  3407. (call $quo
  3408. (local.get $a)
  3409. (call $flonum->integer (local.get $b)))))
  3410. (else
  3411. (call $die0 (string.const "$quo/fixnum-flonum"))
  3412. (unreachable))))))
  3413. `((ref.test $bignum (local.get $a))
  3414. ,(arith-cond
  3415. '((call $fixnum? (local.get $b))
  3416. (return (call $normalize-bignum
  3417. (call $bignum-quo*
  3418. (ref.cast $bignum (local.get $a))
  3419. (struct.new $bignum
  3420. (i32.const 0)
  3421. (call $bignum-from-i32
  3422. (call $fixnum->i32
  3423. (ref.cast i31 (local.get $b)))))))))
  3424. '((ref.test $bignum (local.get $b))
  3425. (return (call $normalize-bignum
  3426. (call $bignum-quo*
  3427. (ref.cast $bignum (local.get $a))
  3428. (ref.cast $bignum (local.get $b))))))
  3429. '((ref.test $flonum (local.get $b))
  3430. (if (ref eq)
  3431. (call $flonum-integer? (local.get $b))
  3432. (then
  3433. (call $inexact
  3434. (call $quo
  3435. (local.get $a)
  3436. (call $flonum->integer (local.get $b)))))
  3437. (else
  3438. (call $die0 (string.const "$quo/bignum-flonum"))
  3439. (unreachable))))))
  3440. `((ref.test $flonum (local.get $a))
  3441. (if (ref eq)
  3442. (call $flonum-integer? (local.get $a))
  3443. (then
  3444. (call $inexact
  3445. (call $quo
  3446. (call $flonum->integer (local.get $a))
  3447. (local.get $b))))
  3448. (else
  3449. (call $die0 (string.const "$quo/flonum"))
  3450. (unreachable))))))
  3451. (func $rem (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
  3452. (local $a-i32 i32)
  3453. (local $b-i32 i32)
  3454. ,(arith-cond
  3455. `((call $fixnum? (local.get $a))
  3456. ,(arith-cond
  3457. ;; Adapted from the `rem' fixnum fast path in (hoot compile).
  3458. '((call $fixnum? (local.get $b))
  3459. (local.set $a-i32
  3460. (call $fixnum->i32
  3461. (ref.cast i31 (local.get $a))))
  3462. (local.set $b-i32
  3463. (call $fixnum->i32
  3464. (ref.cast i31 (local.get $b))))
  3465. (if (i32.eqz (local.get $b-i32))
  3466. (then
  3467. (call $die0 (string.const "$rem"))
  3468. (unreachable)))
  3469. (call $i32->fixnum
  3470. (i32.rem_s
  3471. (local.get $a-i32)
  3472. (local.get $b-i32))))
  3473. '((ref.test $bignum (local.get $b))
  3474. (return (call $normalize-bignum
  3475. (call $bignum-rem*
  3476. (struct.new $bignum
  3477. (i32.const 0)
  3478. (call $bignum-from-i32
  3479. (call $fixnum->i32
  3480. (ref.cast i31 (local.get $a)))))
  3481. (ref.cast $bignum (local.get $b))))))
  3482. '((ref.test $flonum (local.get $b))
  3483. (if (ref eq)
  3484. (call $flonum-integer? (local.get $b))
  3485. (then
  3486. (call $inexact
  3487. (call $rem
  3488. (local.get $a)
  3489. (call $flonum->integer (local.get $b)))))
  3490. (else
  3491. (call $die0 (string.const "$rem/fixnum-flonum"))
  3492. (unreachable))))))
  3493. `((ref.test $bignum (local.get $a))
  3494. ,(arith-cond
  3495. '((call $fixnum? (local.get $b))
  3496. (return (call $normalize-bignum
  3497. (call $bignum-rem*
  3498. (ref.cast $bignum (local.get $a))
  3499. (struct.new $bignum
  3500. (i32.const 0)
  3501. (call $bignum-from-i32
  3502. (call $fixnum->i32
  3503. (ref.cast i31 (local.get $b)))))))))
  3504. '((ref.test $bignum (local.get $b))
  3505. (return (call $normalize-bignum
  3506. (call $bignum-rem*
  3507. (ref.cast $bignum (local.get $a))
  3508. (ref.cast $bignum (local.get $b))))))
  3509. '((ref.test $flonum (local.get $b))
  3510. (if (ref eq)
  3511. (call $flonum-integer? (local.get $b))
  3512. (then
  3513. (call $inexact
  3514. (call $rem
  3515. (local.get $a)
  3516. (call $flonum->integer (local.get $b)))))
  3517. (else
  3518. (call $die0 (string.const "$rem/bignum-flonum"))
  3519. (unreachable))))))
  3520. '((ref.test $flonum (local.get $a))
  3521. (if (ref eq)
  3522. (call $flonum-integer? (local.get $a))
  3523. (then
  3524. (call $inexact
  3525. (call $rem
  3526. (call $flonum->integer (local.get $a))
  3527. (local.get $b))))
  3528. (else
  3529. (call $die0 (string.const "$rem/flonum"))
  3530. (unreachable))))))
  3531. (func $mod (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
  3532. (local $a-i32 i32)
  3533. (local $b-i32 i32)
  3534. (local $tem i32)
  3535. ,(arith-cond
  3536. `((call $fixnum? (local.get $a))
  3537. ,(arith-cond
  3538. ;; Adapted from the `mod' fixnum fast path in (hoot compile).
  3539. '((call $fixnum? (local.get $b))
  3540. (local.set $a-i32 (call $fixnum->i32
  3541. (ref.cast i31 (local.get $a))))
  3542. (local.set $b-i32 (call $fixnum->i32
  3543. (ref.cast i31 (local.get $b))))
  3544. (if (i32.eqz (local.get $b-i32))
  3545. (then
  3546. (call $die0 (string.const "$mod"))
  3547. (unreachable)))
  3548. (local.set $tem
  3549. (i32.rem_s (local.get $a-i32)
  3550. (local.get $b-i32)))
  3551. ;; If $B and the remainder have different signs,
  3552. ;; adjust the remainder by adding $B.
  3553. (if (i32.or
  3554. (i32.and (i32.lt_s (local.get $tem) (i32.const 0))
  3555. (i32.gt_s (local.get $b-i32) (i32.const 0)))
  3556. (i32.and (i32.gt_s (local.get $tem) (i32.const 0))
  3557. (i32.lt_s (local.get $b-i32) (i32.const 0))))
  3558. (then (local.set $tem (i32.add (local.get $tem)
  3559. (local.get $b-i32)))))
  3560. (call $i32->fixnum (local.get $tem)))
  3561. '((ref.test $bignum (local.get $b))
  3562. (return (call $normalize-bignum
  3563. (call $bignum-mod*
  3564. (struct.new $bignum
  3565. (i32.const 0)
  3566. (call $bignum-from-i32
  3567. (call $fixnum->i32
  3568. (ref.cast i31 (local.get $a)))))
  3569. (ref.cast $bignum (local.get $b))))))
  3570. '((ref.test $flonum (local.get $b))
  3571. (if (ref eq)
  3572. (call $flonum-integer? (local.get $b))
  3573. (then
  3574. (call $inexact
  3575. (call $mod
  3576. (local.get $a)
  3577. (call $flonum->integer (local.get $b)))))
  3578. (else
  3579. (call $die0 (string.const "$mod/fixnum-flonum"))
  3580. (unreachable))))))
  3581. `((ref.test $bignum (local.get $a))
  3582. ,(arith-cond
  3583. '((call $fixnum? (local.get $b))
  3584. (return (call $normalize-bignum
  3585. (call $bignum-mod*
  3586. (ref.cast $bignum (local.get $a))
  3587. (struct.new $bignum
  3588. (i32.const 0)
  3589. (call $bignum-from-i32
  3590. (call $fixnum->i32
  3591. (ref.cast i31 (local.get $b)))))))))
  3592. '((ref.test $bignum (local.get $b))
  3593. (return (call $normalize-bignum
  3594. (call $bignum-mod*
  3595. (ref.cast $bignum (local.get $a))
  3596. (ref.cast $bignum (local.get $b))))))
  3597. '((ref.test $flonum (local.get $b))
  3598. (if (ref eq)
  3599. (call $flonum-integer? (local.get $b))
  3600. (then
  3601. (call $inexact
  3602. (call $mod
  3603. (local.get $a)
  3604. (call $flonum->integer (local.get $b)))))
  3605. (else
  3606. (call $die0 (string.const "$mod/bignum-flonum"))
  3607. (unreachable))))))
  3608. '((ref.test $flonum (local.get $a))
  3609. (if (ref eq)
  3610. (call $flonum-integer? (local.get $a))
  3611. (then
  3612. (call $inexact
  3613. (call $mod
  3614. (call $flonum->integer (local.get $a))
  3615. (local.get $b))))
  3616. (else
  3617. (call $die0 (string.const "$mod/flonum"))
  3618. (unreachable))))))
  3619. ;; Bitwise operators and shifts
  3620. (func $logand (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
  3621. ,(arith-cond '(ref eq)
  3622. `((call $fixnum? (local.get $a))
  3623. ,(arith-cond '(ref eq)
  3624. '((call $fixnum? (local.get $b))
  3625. (call $i32->fixnum
  3626. (i32.and (call $fixnum->i32 (ref.cast i31 (local.get $a)))
  3627. (call $fixnum->i32 (ref.cast i31 (local.get $b))))))
  3628. '((ref.test $bignum (local.get $b))
  3629. (call $normalize-bignum
  3630. (struct.new $bignum
  3631. (i32.const 0)
  3632. (call $bignum-logand-i32
  3633. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))
  3634. (call $fixnum->i32 (ref.cast i31 (local.get $a)))))))
  3635. '(else
  3636. (call $die0 (string.const "$logand"))
  3637. (unreachable))))
  3638. `((ref.test $bignum (local.get $a))
  3639. ,(arith-cond '(ref eq)
  3640. '((call $fixnum? (local.get $b))
  3641. (call $normalize-bignum
  3642. (struct.new $bignum
  3643. (i32.const 0)
  3644. (call $bignum-logand-i32
  3645. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  3646. (call $fixnum->i32 (ref.cast i31 (local.get $b)))))))
  3647. '((ref.test $bignum (local.get $b))
  3648. (call $normalize-bignum
  3649. (struct.new $bignum
  3650. (i32.const 0)
  3651. (call $bignum-logand-bignum
  3652. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  3653. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))))
  3654. `(else
  3655. (call $die0 (string.const "$logand"))
  3656. (unreachable))))
  3657. '((ref.test $flonum (local.get $a))
  3658. (call $die0 (string.const "$logand"))
  3659. (unreachable))
  3660. '((ref.test $fraction (local.get $a))
  3661. (call $die0 (string.const "$logand"))
  3662. (unreachable))
  3663. '(else
  3664. (call $die0 (string.const "$logand"))
  3665. (unreachable))))
  3666. (func $logior (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
  3667. ,(arith-cond
  3668. `((call $fixnum? (local.get $a))
  3669. ,(arith-cond
  3670. '((call $fixnum? (local.get $b))
  3671. (call $i32->fixnum
  3672. (i32.or (call $fixnum->i32 (ref.cast i31 (local.get $a)))
  3673. (call $fixnum->i32 (ref.cast i31 (local.get $b))))))
  3674. '((ref.test $bignum (local.get $b))
  3675. (call $normalize-bignum
  3676. (struct.new $bignum
  3677. (i32.const 0)
  3678. (call $bignum-logior-i32
  3679. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))
  3680. (call $fixnum->i32 (ref.cast i31 (local.get $a)))))))
  3681. '(else
  3682. (call $die0 (string.const "$logior"))
  3683. (unreachable))))
  3684. `((ref.test $bignum (local.get $a))
  3685. ,(arith-cond
  3686. '((call $fixnum? (local.get $b))
  3687. (call $normalize-bignum
  3688. (struct.new $bignum
  3689. (i32.const 0)
  3690. (call $bignum-logior-i32
  3691. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  3692. (call $fixnum->i32 (ref.cast i31 (local.get $b)))))))
  3693. '((ref.test $bignum (local.get $b))
  3694. (call $normalize-bignum
  3695. (struct.new $bignum
  3696. (i32.const 0)
  3697. (call $bignum-logior-bignum
  3698. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  3699. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))))
  3700. `(else
  3701. (call $die0 (string.const "$logior"))
  3702. (unreachable))))
  3703. '((ref.test $flonum (local.get $a))
  3704. (call $die0 (string.const "$logior"))
  3705. (unreachable))
  3706. '((ref.test $fraction (local.get $a))
  3707. (call $die0 (string.const "$logior"))
  3708. (unreachable))
  3709. '(else
  3710. (call $die0 (string.const "$logior"))
  3711. (unreachable))))
  3712. (func $logxor (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
  3713. ,(arith-cond
  3714. `((call $fixnum? (local.get $a))
  3715. ,(arith-cond
  3716. '((call $fixnum? (local.get $b))
  3717. (call $i32->fixnum
  3718. (i32.xor (call $fixnum->i32 (ref.cast i31 (local.get $a)))
  3719. (call $fixnum->i32 (ref.cast i31 (local.get $b))))))
  3720. '((ref.test $bignum (local.get $b))
  3721. (call $normalize-bignum
  3722. (struct.new $bignum
  3723. (i32.const 0)
  3724. (call $bignum-logxor-i32
  3725. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))
  3726. (call $fixnum->i32 (ref.cast i31 (local.get $a)))))))
  3727. '(else
  3728. (call $die0 (string.const "$logxor"))
  3729. (unreachable))))
  3730. `((ref.test $bignum (local.get $a))
  3731. ,(arith-cond
  3732. '((call $fixnum? (local.get $b))
  3733. (call $normalize-bignum
  3734. (struct.new $bignum
  3735. (i32.const 0)
  3736. (call $bignum-logxor-i32
  3737. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  3738. (call $fixnum->i32 (ref.cast i31 (local.get $b)))))))
  3739. '((ref.test $bignum (local.get $b))
  3740. (call $normalize-bignum
  3741. (struct.new $bignum
  3742. (i32.const 0)
  3743. (call $bignum-logxor-bignum
  3744. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  3745. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))))
  3746. `(else
  3747. (call $die0 (string.const "$logxor"))
  3748. (unreachable))))
  3749. '((ref.test $flonum (local.get $a))
  3750. (call $die0 (string.const "$logxor"))
  3751. (unreachable))
  3752. '((ref.test $fraction (local.get $a))
  3753. (call $die0 (string.const "$logxor"))
  3754. (unreachable))
  3755. '(else
  3756. (call $die0 (string.const "$logxor"))
  3757. (unreachable))))
  3758. (func $logsub (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
  3759. ,(arith-cond
  3760. `((call $fixnum? (local.get $a))
  3761. ,(arith-cond
  3762. '((call $fixnum? (local.get $b))
  3763. '(call $i32->fixnum
  3764. (i32.and
  3765. (call $fixnum->i32 (ref.cast i31 (local.get $a)))
  3766. (i32.xor (call $fixnum->i32
  3767. (ref.cast i31 (local.get $b)))
  3768. (i32.const -1)))))
  3769. '((ref.test $bignum (local.get $b))
  3770. (call $normalize-bignum
  3771. (struct.new $bignum
  3772. (i32.const 0)
  3773. (call $i32-logsub-bignum
  3774. (call $fixnum->i32 (ref.cast i31 (local.get $a)))
  3775. (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))))
  3776. '(else
  3777. (call $die0 (string.const "$logsub"))
  3778. (unreachable))))
  3779. `((ref.test $bignum (local.get $a))
  3780. ,(arith-cond
  3781. '((call $fixnum? (local.get $b))
  3782. (call $normalize-bignum
  3783. (struct.new $bignum
  3784. (i32.const 0)
  3785. (call $bignum-logsub-i32
  3786. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  3787. (call $fixnum->i32 (ref.cast i31 (local.get $b)))))))
  3788. '((ref.test $bignum (local.get $b))
  3789. (call $normalize-bignum
  3790. (struct.new $bignum
  3791. (i32.const 0)
  3792. (call $bignum-logsub-bignum
  3793. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
  3794. (struct.get $bignum $val (ref.cast i31 (local.get $b)))))))
  3795. `(else
  3796. (call $die0 (string.const "$logsub"))
  3797. (unreachable))))
  3798. '((ref.test $flonum (local.get $a))
  3799. (call $die0 (string.const "$logsub"))
  3800. (unreachable))
  3801. '((ref.test $fraction (local.get $a))
  3802. (call $die0 (string.const "$logsub"))
  3803. (unreachable))
  3804. '(else
  3805. (call $die0 (string.const "$logsub"))
  3806. (unreachable))))
  3807. (func $rsh (param $a (ref eq)) (param $b i64) (result (ref eq))
  3808. ,(arith-cond
  3809. '((ref.test $bignum (local.get $a))
  3810. (call $normalize-bignum
  3811. (struct.new $bignum
  3812. (i32.const 0)
  3813. (call $bignum-rsh
  3814. (struct.get $bignum $val
  3815. (ref.cast $bignum (local.get $a)))
  3816. (local.get $b)))))
  3817. '(else
  3818. (call $die
  3819. (string.const "$rsh bad first arg")
  3820. (local.get $a))
  3821. (unreachable))))
  3822. (func $lsh (param $a (ref eq)) (param $b i64) (result (ref eq))
  3823. ,(arith-cond
  3824. '((call $fixnum? (local.get $a))
  3825. (call $normalize-bignum
  3826. (struct.new $bignum
  3827. (i32.const 0)
  3828. (call $i32-lsh
  3829. (call $fixnum->i32 (ref.cast i31 (local.get $a)))
  3830. (local.get $b)))))
  3831. '((ref.test $bignum (local.get $a))
  3832. (struct.new $bignum
  3833. (i32.const 0)
  3834. (call $bignum-lsh
  3835. (struct.get $bignum $val
  3836. (ref.cast $bignum (local.get $a)))
  3837. (local.get $b))))
  3838. '(else
  3839. (call $die
  3840. (string.const "$lsh bad first arg")
  3841. (local.get $a))
  3842. (unreachable))))
  3843. (func $inexact (param $x (ref eq)) (result (ref $flonum))
  3844. ,(arith-cond '(ref $flonum)
  3845. `((call $fixnum? (local.get $x))
  3846. (struct.new $flonum
  3847. (i32.const 0)
  3848. (call $fixnum->f64
  3849. (ref.cast i31 (local.get $x)))))
  3850. `((ref.test $bignum (local.get $x))
  3851. (struct.new $flonum
  3852. (i32.const 0)
  3853. (call $bignum->f64
  3854. (ref.cast $bignum (local.get $x)))))
  3855. `((ref.test $flonum (local.get $x))
  3856. (ref.cast $flonum (local.get $x)))
  3857. ;; FIXME: improve fraction approximation
  3858. `((ref.test $fraction (local.get $x))
  3859. (ref.cast $flonum
  3860. (call $div
  3861. (call $inexact
  3862. (struct.get $fraction $num (ref.cast $fraction (local.get $x))))
  3863. (call $inexact
  3864. (struct.get $fraction $denom (ref.cast $fraction (local.get $x)))))))))
  3865. ;; compute (logand x #xffffFFFF). precondition: x is exact integer.
  3866. (func $scm->u32/truncate (param $x (ref eq)) (result i32)
  3867. (if i32
  3868. (ref.test i31 (local.get $x))
  3869. (then (i32.shr_s (i31.get_s (ref.cast i31 (local.get $x)))
  3870. (i32.const 1)))
  3871. (else
  3872. (i32.wrap_i64
  3873. (call $bignum-get-i64
  3874. (struct.get $bignum $val
  3875. (ref.cast $bignum (local.get $x))))))))
  3876. (func $abs (param $x (ref eq)) (result (ref eq))
  3877. ,(arith-cond
  3878. '((call $fixnum? (local.get $x))
  3879. (if (result (ref eq))
  3880. (call $negative-integer? (local.get $x))
  3881. (then (call $mul (local.get $x) (call $i32->fixnum (i32.const -1))))
  3882. (else (local.get $x))))
  3883. '((ref.test $bignum (local.get $x))
  3884. (if (result (ref eq))
  3885. (call $negative-integer? (local.get $x))
  3886. (then (call $mul (local.get $x) (call $i32->fixnum (i32.const -1))))
  3887. (else (local.get $x))))
  3888. ;; FIXME: not actually tested yet, as the compiler typically uses $fabs
  3889. '((ref.test $flonum (local.get $x))
  3890. (struct.new $flonum
  3891. (i32.const 0)
  3892. (f64.abs (call $flonum->f64 (ref.cast $flonum (local.get $x))))))
  3893. '((ref.test $fraction (local.get $x))
  3894. (if (result (ref eq))
  3895. (call $negative-integer?
  3896. (struct.get $fraction $num
  3897. (ref.cast $fraction (local.get $x))))
  3898. (then (call $mul (local.get $x) (call $i32->fixnum (i32.const -1))))
  3899. (else (local.get $x))))))
  3900. (func $remz (param $m (ref eq)) (param $n (ref eq))
  3901. (result (ref eq))
  3902. ,(arith-cond
  3903. `((call $fixnum? (local.get $m))
  3904. ,(arith-cond
  3905. '((call $fixnum? (local.get $n))
  3906. (call $i32->fixnum
  3907. (i32.rem_s
  3908. (call $fixnum->i32
  3909. (ref.cast i31 (local.get $m)))
  3910. (call $fixnum->i32
  3911. (ref.cast i31 (local.get $n))))))
  3912. '((ref.test $bignum (local.get $n))
  3913. (call $bignum-rem*
  3914. (ref.cast $bignum
  3915. (call $i32->bignum
  3916. (call $fixnum->i32
  3917. (ref.cast i31
  3918. (local.get $m)))))
  3919. (ref.cast $bignum (local.get $n))))))
  3920. `((ref.test $bignum (local.get $m))
  3921. ,(arith-cond
  3922. '((call $fixnum? (local.get $n))
  3923. (call $bignum-rem*
  3924. (ref.cast $bignum (local.get $m))
  3925. (ref.cast $bignum
  3926. (call $i32->bignum
  3927. (call $fixnum->i32
  3928. (ref.cast i31
  3929. (local.get $n)))))))
  3930. '((ref.test $bignum (local.get $n))
  3931. (call $bignum-rem*
  3932. (ref.cast $bignum (local.get $m))
  3933. (ref.cast $bignum (local.get $n))))))))
  3934. ;; floor of $M/$N, with $M, $N in Z and $N > 0 and both integers
  3935. ;; normalized: (m - m mod n)/n, where m mod n = (% (+ (% m n) n) n)
  3936. (func $fracfloor (param $m (ref eq)) (param $n (ref eq)) (result (ref eq))
  3937. (call $div
  3938. (call $sub
  3939. (local.get $m)
  3940. (call $remz
  3941. (call $add
  3942. (call $remz
  3943. (local.get $m)
  3944. (local.get $n))
  3945. (local.get $n))
  3946. (local.get $n)))
  3947. (local.get $n)))
  3948. (func $floor (param $x (ref eq)) (result (ref eq))
  3949. ,(arith-cond
  3950. '((call $fixnum? (local.get $x))
  3951. (local.get $x))
  3952. '((ref.test $bignum (local.get $x))
  3953. (local.get $x))
  3954. '((ref.test $flonum (local.get $x))
  3955. (struct.new $flonum
  3956. (i32.const 0)
  3957. (f64.floor (call $flonum->f64 (ref.cast $flonum (local.get $x))))))
  3958. '((ref.test $fraction (local.get $x))
  3959. (call $fracfloor
  3960. (struct.get $fraction $num
  3961. (ref.cast $fraction (local.get $x)))
  3962. (struct.get $fraction $denom
  3963. (ref.cast $fraction (local.get $x)))))))
  3964. (func $ceiling (param $x (ref eq)) (result (ref eq))
  3965. ,(arith-cond
  3966. '((call $fixnum? (local.get $x))
  3967. (local.get $x))
  3968. '((ref.test $bignum (local.get $x))
  3969. (local.get $x))
  3970. '((ref.test $flonum (local.get $x))
  3971. (struct.new $flonum
  3972. (i32.const 0)
  3973. (f64.ceil (call $flonum->f64 (ref.cast $flonum (local.get $x))))))
  3974. '((ref.test $fraction (local.get $x))
  3975. (call $add
  3976. (call $floor (local.get $x))
  3977. (call $i32->fixnum (i32.const 1))))))
  3978. (func $sqrt (param $x (ref eq)) (result (ref $flonum))
  3979. ,(call-fmath '$fsqrt '(local.get $x)))
  3980. (func $sin (param $x (ref eq)) (result (ref eq))
  3981. ,(call-fmath '$fsin '(local.get $x)))
  3982. (func $cos (param $x (ref eq)) (result (ref eq))
  3983. ,(call-fmath '$fcos '(local.get $x)))
  3984. (func $tan (param $x (ref eq)) (result (ref eq))
  3985. ,(call-fmath '$ftan '(local.get $x)))
  3986. (func $asin (param $x (ref eq)) (result (ref eq))
  3987. ,(call-fmath '$fasin '(local.get $x)))
  3988. (func $acos (param $x (ref eq)) (result (ref eq))
  3989. ,(call-fmath '$facos '(local.get $x)))
  3990. (func $atan (param $x (ref eq)) (result (ref eq))
  3991. ,(call-fmath '$fatan '(local.get $x)))
  3992. (func $atan2 (param $x (ref eq)) (param $y (ref eq)) (result (ref eq))
  3993. ,(call-fmath '$fatan2 '(local.get $x) '(local.get $y)))
  3994. (func $log (param $x (ref eq)) (result (ref eq))
  3995. ,(call-fmath '$flog '(local.get $x)))
  3996. (func $exp (param $x (ref eq)) (result (ref eq))
  3997. ,(call-fmath '$fexp '(local.get $x)))
  3998. (func $u64->bignum (param $i64 i64) (result (ref eq))
  3999. (struct.new $bignum
  4000. (i32.const 0)
  4001. (call $bignum-from-u64 (local.get $i64))))
  4002. (func $s64->bignum (param $i64 i64) (result (ref eq))
  4003. (struct.new $bignum
  4004. (i32.const 0)
  4005. (call $bignum-from-i64 (local.get $i64))))
  4006. (func $bignum->u64 (param $x (ref $bignum)) (result i64)
  4007. (local $n (ref extern))
  4008. (local.set $n (struct.get $bignum $val (local.get $x)))
  4009. (if i64
  4010. (call $bignum-is-u64 (local.get $n))
  4011. (then (call $bignum-get-i64 (local.get $n)))
  4012. (else
  4013. (call $die (string.const "$bignum->u64 out of range")
  4014. (local.get $x))
  4015. (unreachable))))
  4016. (func $bignum->s64 (param $x (ref $bignum)) (result i64)
  4017. (local $n (ref extern))
  4018. (local.set $n (struct.get $bignum $val (local.get $x)))
  4019. (if i64
  4020. (call $bignum-is-i64 (local.get $n))
  4021. (then (call $bignum-get-i64 (local.get $n)))
  4022. (else
  4023. (call $die (string.const "$bignum->s64 out of range")
  4024. (local.get $x))
  4025. (unreachable))))
  4026. (func $scm->s64 (param $a (ref eq)) (result i64)
  4027. (if i64
  4028. (call $fixnum? (local.get $a))
  4029. (then
  4030. (i64.extend_i32_s
  4031. (i32.shr_s (i31.get_s (ref.cast i31 (local.get $a)))
  4032. (i32.const 1))))
  4033. (else
  4034. (if i64
  4035. (ref.test $bignum (local.get $a))
  4036. (then
  4037. (return_call $bignum->s64
  4038. (ref.cast $bignum (local.get $a))))
  4039. (else
  4040. (call $die (string.const "$scm->s64 bad arg")
  4041. (local.get $a))
  4042. (unreachable))))))
  4043. (func $scm->u64 (param $a (ref eq)) (result i64)
  4044. (local $i i32)
  4045. (if i64
  4046. (ref.test i31 (local.get $a))
  4047. (then
  4048. (local.set $i (i31.get_s (ref.cast i31 (local.get $a))))
  4049. (if i64
  4050. (i32.and (local.get $i) (i32.const ,(logior 1 (ash -1 31))))
  4051. (then
  4052. (call $die
  4053. (string.const "$scm->u64 bad arg")
  4054. (local.get $a))
  4055. (unreachable))
  4056. (else
  4057. (i64.extend_i32_u
  4058. (i32.shr_u (local.get $i) (i32.const 1))))))
  4059. (else
  4060. (if i64
  4061. (ref.test $bignum (local.get $a))
  4062. (then
  4063. (return_call $bignum->u64
  4064. (ref.cast $bignum (local.get $a))))
  4065. (else
  4066. (call $die
  4067. (string.const "$scm->u64 bad arg")
  4068. (local.get $a))
  4069. (unreachable))))))
  4070. (func $scm->u64/truncate (param $a (ref eq)) (result i64)
  4071. ,(arith-cond 'i64
  4072. '((call $fixnum? (local.get $a))
  4073. (i64.extend_i32_u
  4074. (call $fixnum->i32 (ref.cast i31 (local.get $a)))))
  4075. '((ref.test $bignum (local.get $a))
  4076. (call $bignum-get-i64
  4077. (struct.get $bignum $val (ref.cast $bignum (local.get $a)))))
  4078. '((i32.const 0)
  4079. (call $die
  4080. (string.const "$scm->u64 bad arg")
  4081. (local.get $a))
  4082. (unreachable))))
  4083. (func $s64->scm (param $a i64) (result (ref eq))
  4084. (if (result (ref eq))
  4085. (i32.and (i64.ge_s (local.get $a) (i64.const ,(ash -1 29)))
  4086. (i64.lt_s (local.get $a) (i64.const ,(ash 1 29))))
  4087. (then (ref.i31
  4088. (i32.shl (i32.wrap_i64 (local.get $a))
  4089. (i32.const 1))))
  4090. (else (return_call $s64->bignum (local.get $a)))))
  4091. (func $s32->scm (param $a i32) (result (ref eq))
  4092. (if (ref eq)
  4093. (i32.and (i32.ge_s (local.get $a) (i32.const ,(ash -1 29)))
  4094. (i32.lt_s (local.get $a) (i32.const ,(ash 1 29))))
  4095. (then (call $i32->fixnum (local.get $a)))
  4096. (else (return_call $s64->bignum (i64.extend_i32_s (local.get $a))))))
  4097. (func $string->wtf8
  4098. (param $str (ref string)) (result (ref $raw-bytevector))
  4099. (local $vu0 (ref $raw-bytevector))
  4100. (local.set $vu0
  4101. (array.new_default
  4102. $raw-bytevector
  4103. (string.measure_wtf8 (local.get $str))))
  4104. (string.encode_wtf8_array (local.get $str)
  4105. (local.get $vu0)
  4106. (i32.const 0))
  4107. (local.get $vu0))
  4108. (func $wtf8->string
  4109. (param $bv (ref $raw-bytevector)) (result (ref string))
  4110. (string.new_lossy_utf8_array (local.get $bv)
  4111. (i32.const 0)
  4112. (array.len (local.get $bv))))
  4113. (func $set-fluid-and-return-prev (param $nargs i32)
  4114. (param $arg0 (ref eq)) (param $arg1 (ref eq))
  4115. (param $arg2 (ref eq))
  4116. (local $fluid (ref $fluid))
  4117. (local $prev (ref eq))
  4118. (if (i32.eqz (local.get $nargs))
  4119. (then
  4120. (return_call $raise-arity-error
  4121. (string.const "[parameter conversion result]")
  4122. (ref.i31 (i32.const 1)))))
  4123. (global.set $scm-sp (i32.sub (global.get $scm-sp) (i32.const 1)))
  4124. (local.set $fluid
  4125. (ref.cast $fluid
  4126. (table.get $scm-stack (global.get $scm-sp))))
  4127. (local.set $prev (call $fluid-ref (local.get $fluid)))
  4128. (call $fluid-set! (local.get $fluid) (local.get $arg0))
  4129. (global.set $ret-sp (i32.sub (global.get $ret-sp) (i32.const 1)))
  4130. (return_call_ref $kvarargs
  4131. (i32.const 1)
  4132. (local.get $prev)
  4133. (ref.i31 (i32.const 1))
  4134. (ref.i31 (i32.const 1))
  4135. (table.get $ret-stack (global.get $ret-sp))))
  4136. (func $parameter (param $nargs i32) (param $arg0 (ref eq))
  4137. (param $arg1 (ref eq)) (param $arg2 (ref eq))
  4138. (local $parameter (ref $parameter))
  4139. (local.set $parameter (ref.cast $parameter (local.get $arg0)))
  4140. (if (i32.eq (local.get $nargs) (i32.const 1))
  4141. (then
  4142. (global.set $ret-sp
  4143. (i32.sub (global.get $ret-sp) (i32.const 1)))
  4144. (return_call_ref $kvarargs
  4145. (i32.const 1)
  4146. (call $fluid-ref
  4147. (struct.get $parameter $fluid
  4148. (local.get $parameter)))
  4149. (ref.i31 (i32.const 1))
  4150. (ref.i31 (i32.const 1))
  4151. (table.get $ret-stack (global.get $ret-sp)))))
  4152. (if (i32.ne (local.get $nargs) (i32.const 2))
  4153. (then
  4154. (return_call $raise-arity-error
  4155. (string.const "[parameter]")
  4156. (local.get $arg0))))
  4157. (global.set $scm-sp (i32.add (global.get $scm-sp) (i32.const 1)))
  4158. (call $maybe-grow-scm-stack)
  4159. (global.set $ret-sp (i32.add (global.get $ret-sp) (i32.const 1)))
  4160. (call $maybe-grow-ret-stack)
  4161. (table.set $scm-stack (i32.sub (global.get $scm-sp) (i32.const 1))
  4162. (struct.get $parameter $fluid (local.get $parameter)))
  4163. (table.set $ret-stack (i32.sub (global.get $ret-sp) (i32.const 1))
  4164. (ref.func $set-fluid-and-return-prev))
  4165. (return_call_ref $kvarargs
  4166. (i32.const 2)
  4167. (struct.get $parameter $convert
  4168. (local.get $parameter))
  4169. (local.get $arg1)
  4170. (ref.i31 (i32.const 1))
  4171. (struct.get $proc $func
  4172. (struct.get $parameter $convert
  4173. (local.get $parameter)))))
  4174. (table ,@(maybe-import '$argv) 0 (ref null eq))
  4175. (table ,@(maybe-import '$scm-stack) 0 (ref null eq))
  4176. (table ,@(maybe-import '$ret-stack) 0 (ref null $kvarargs))
  4177. (table ,@(maybe-import '$dyn-stack) 0 (ref null $dyn))
  4178. (memory ,@(maybe-import '$raw-stack) 0)
  4179. (global ,@(maybe-import '$arg3) (mut (ref eq)) ,@maybe-init-i31-zero)
  4180. (global ,@(maybe-import '$arg4) (mut (ref eq)) ,@maybe-init-i31-zero)
  4181. (global ,@(maybe-import '$arg5) (mut (ref eq)) ,@maybe-init-i31-zero)
  4182. (global ,@(maybe-import '$arg6) (mut (ref eq)) ,@maybe-init-i31-zero)
  4183. (global ,@(maybe-import '$arg7) (mut (ref eq)) ,@maybe-init-i31-zero)
  4184. (global ,@(maybe-import '$ret-sp) (mut i32) ,@maybe-init-i32-zero)
  4185. (global ,@(maybe-import '$scm-sp) (mut i32) ,@maybe-init-i32-zero)
  4186. (global ,@(maybe-import '$raw-sp) (mut i32) ,@maybe-init-i32-zero)
  4187. (global ,@(maybe-import '$dyn-sp) (mut i32) ,@maybe-init-i32-zero)
  4188. (global ,@(maybe-import '$current-fluids) (mut (ref $hash-table))
  4189. ,@maybe-init-hash-table)
  4190. (global ,@(maybe-import '$raise-exception) (mut (ref $proc))
  4191. ,@maybe-init-proc)
  4192. (global ,@(maybe-import '$with-exception-handler) (mut (ref $proc))
  4193. ,@maybe-init-proc)
  4194. (global ,@(maybe-import '$current-input-port) (mut (ref eq))
  4195. ,@maybe-init-i31-zero)
  4196. (global ,@(maybe-import '$current-output-port) (mut (ref eq))
  4197. ,@maybe-init-i31-zero)
  4198. (global ,@(maybe-import '$current-error-port) (mut (ref eq))
  4199. ,@maybe-init-i31-zero)
  4200. (global ,@(maybe-import '$default-prompt-tag) (mut (ref eq))
  4201. ,@maybe-init-i31-zero)
  4202. (global ,@(maybe-import '$make-size-error) (mut (ref $proc))
  4203. ,@maybe-init-proc)
  4204. (global ,@(maybe-import '$make-index-error) (mut (ref $proc))
  4205. ,@maybe-init-proc)
  4206. (global ,@(maybe-import '$make-range-error) (mut (ref $proc))
  4207. ,@maybe-init-proc)
  4208. (global ,@(maybe-import '$make-start-offset-error) (mut (ref $proc))
  4209. ,@maybe-init-proc)
  4210. (global ,@(maybe-import '$make-end-offset-error) (mut (ref $proc))
  4211. ,@maybe-init-proc)
  4212. (global ,@(maybe-import '$make-type-error) (mut (ref $proc))
  4213. ,@maybe-init-proc)
  4214. (global ,@(maybe-import '$make-unimplemented-error) (mut (ref $proc))
  4215. ,@maybe-init-proc)
  4216. (global ,@(maybe-import '$make-assertion-error) (mut (ref $proc))
  4217. ,@maybe-init-proc)
  4218. (global ,@(maybe-import '$make-not-seekable-error) (mut (ref $proc))
  4219. ,@maybe-init-proc)
  4220. (global ,@(maybe-import '$make-runtime-error-with-message) (mut (ref $proc))
  4221. ,@maybe-init-proc)
  4222. (global ,@(maybe-import '$make-runtime-error-with-message+irritants) (mut (ref $proc))
  4223. ,@maybe-init-proc)
  4224. (global ,@(maybe-import '$make-match-error) (mut (ref $proc))
  4225. ,@maybe-init-proc)
  4226. (global ,@(maybe-import '$make-arity-error) (mut (ref $proc))
  4227. ,@maybe-init-proc))))
  4228. (define (memoize f)
  4229. (define cache (make-hash-table))
  4230. (lambda args
  4231. (match (hash-ref cache args)
  4232. (#f (call-with-values (lambda () (apply f args))
  4233. (lambda res
  4234. (hash-set! cache args res)
  4235. (apply values res))))
  4236. (res (apply values res)))))
  4237. (define compute-stdlib/memoized (memoize compute-stdlib))