stdlib.scm 218 KB

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