stdlib.scm 265 KB

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