stdlib.scm 264 KB

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