12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555 |
- ;;; Standard library for Hoot runtime
- ;;; Copyright (C) 2023,2024 Igalia, S.L.
- ;;; Copyright (C) 2023 Robin Templeton <robin@spritely.institute>
- ;;;
- ;;; Licensed under the Apache License, Version 2.0 (the "License");
- ;;; you may not use this file except in compliance with the License.
- ;;; You may obtain a copy of the License at
- ;;;
- ;;; http://www.apache.org/licenses/LICENSE-2.0
- ;;;
- ;;; Unless required by applicable law or agreed to in writing, software
- ;;; distributed under the License is distributed on an "AS IS" BASIS,
- ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ;;; See the License for the specific language governing permissions and
- ;;; limitations under the License.
- ;;; Commentary:
- ;;;
- ;;; Standard runtime routines for Hoot WebAssembly runtime.
- ;;;
- ;;; Code:
- (define-module (hoot stdlib)
- #:use-module (wasm wat)
- #:use-module (ice-9 match)
- #:use-module (ice-9 receive)
- #:export ((compute-stdlib/memoized . compute-stdlib)))
- (define (u32->s32 x)
- (centered-remainder x (ash 1 32)))
- (define (arith-cond . clauses)
- (receive (type clauses)
- (if (and (pair? clauses) (pair? (car clauses)) (pair? (caar clauses)))
- (values '(ref eq) clauses)
- (values (car clauses) (cdr clauses)))
- (if (null? clauses)
- '(unreachable)
- (let* ((clause1 (car clauses))
- (cond1 (car clause1))
- (res1 (cdr clause1)))
- (if (eq? cond1 'else)
- `(block ,type ,@res1)
- `(if ,type ,cond1
- (then ,@res1)
- (else ,(apply arith-cond type (cdr clauses)))))))))
- (define (call-fmath fn . args)
- `(struct.new $flonum
- (i32.const 0)
- (call ,fn
- ,@(map (lambda (arg)
- `(struct.get $flonum
- $val
- (call $inexact ,arg)))
- args))))
- (define (compute-stdlib import-abi?)
- (define (maybe-import id)
- (if import-abi?
- `(,id (import "abi" ,(symbol->string id)))
- `(,id)))
- (define maybe-init-proc
- (if import-abi?
- '()
- '((struct.new $proc (i32.const 0)
- (ref.func $invalid-continuation)))))
- (define maybe-init-i31-zero
- (if import-abi?
- '()
- '((ref.i31 (i32.const 0)))))
- (define maybe-init-i32-zero
- (if import-abi?
- '()
- '((i32.const 0))))
- (define maybe-init-hash-table
- (if import-abi?
- '()
- '((struct.new $hash-table (i32.const 0)
- (i32.const 0)
- (array.new $raw-scmvector (ref.i31 (i32.const 13))
- (i32.const 47))))))
- (define (struct-name nfields)
- (if (zero? nfields)
- '$struct
- (string->symbol (format #f "$struct/~a" nfields))))
- (define (struct-definition nfields)
- (define (field-name i) (string->symbol (format #f "$field~a" i)))
- `(struct
- (field $hash (mut i32))
- (field $vtable (mut (ref null $vtable)))
- ,@(map (lambda (i)
- `(field ,(field-name i) (mut (ref eq))))
- (iota nfields))))
- ;; If you change the field count, also update vtable-nfields in
- ;; backend.scm.
- (define vtable-fields
- '((field $nfields (mut (ref eq)))
- (field $printer (mut (ref eq)))
- (field $name (mut (ref eq)))
- (field $constructor (mut (ref eq)))
- (field $properties (mut (ref eq)))
- (field $parents (mut (ref eq)))
- (field $mutable-fields (mut (ref eq)))
- (field $compare (mut (ref eq)))
- (field $field-ref (mut (ref eq)))))
- (define vtable-nfields (length vtable-fields))
- (wat->wasm
- `((type $kvarargs
- (func (param $nargs i32)
- (param $arg0 (ref eq))
- (param $arg1 (ref eq))
- (param $arg2 (ref eq))))
- (type $raw-bitvector (array (mut i32)))
- (type $raw-bytevector (array (mut i8)))
- (type $raw-scmvector (array (mut (ref eq))))
- (rec
- (type $heap-object
- (sub
- (struct
- (field $hash (mut i32)))))
- (type $extern-ref
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $val (ref null extern)))))
- (type $heap-number
- (sub $heap-object
- (struct
- (field $hash (mut i32)))))
- (type $bignum
- (sub $heap-number
- (struct
- (field $hash (mut i32))
- (field $val (ref extern)))))
- (type $flonum
- (sub $heap-number
- (struct
- (field $hash (mut i32))
- (field $val f64))))
- (type $complex
- (sub $heap-number
- (struct
- (field $hash (mut i32))
- (field $real f64)
- (field $imag f64))))
- (type $fraction
- (sub $heap-number
- (struct
- (field $hash (mut i32))
- (field $num (ref eq))
- (field $denom (ref eq)))))
- (type $pair
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $car (mut (ref eq)))
- (field $cdr (mut (ref eq))))))
- (type $mutable-pair
- (sub $pair
- (struct
- (field $hash (mut i32))
- (field $car (mut (ref eq)))
- (field $cdr (mut (ref eq))))))
- (type $vector
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $vals (ref $raw-scmvector)))))
- (type $mutable-vector
- (sub $vector
- (struct
- (field $hash (mut i32))
- (field $vals (ref $raw-scmvector)))))
- (type $bytevector
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $vals (ref $raw-bytevector)))))
- (type $mutable-bytevector
- (sub $bytevector
- (struct
- (field $hash (mut i32))
- (field $vals (ref $raw-bytevector)))))
- (type $bitvector
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $len i32)
- (field $vals (ref $raw-bitvector)))))
- (type $mutable-bitvector
- (sub $bitvector
- (struct
- (field $hash (mut i32))
- (field $len i32)
- (field $vals (ref $raw-bitvector)))))
- (type $string
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $str (mut (ref string))))))
- (type $mutable-string
- (sub $string
- (struct
- (field $hash (mut i32))
- (field $str (mut (ref string))))))
- (type $proc
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $func (ref $kvarargs)))))
- (type $symbol
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $name (ref $string)))))
- (type $keyword
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $name (ref $symbol)))))
- (type $variable
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $val (mut (ref eq))))))
- (type $atomic-box
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $val (mut (ref eq))))))
- (type $hash-table
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $size (mut i32))
- (field $buckets (ref $raw-scmvector)))))
- (type $weak-table
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $val (ref extern)))))
- (type $fluid
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $init (ref eq)))))
- (type $dynamic-state
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $fluids (ref $hash-table)))))
- (type $syntax
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $expr (ref eq))
- (field $wrap (ref eq))
- (field $module (ref eq))
- (field $source (ref eq)))))
- (type $port
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $open? (mut (ref eq))) ;; #f | #t
- (field $read (ref eq)) ;; #f | (bv, start, count) -> size
- (field $write (ref eq)) ;; #f | (bv, start, count) -> size
- (field $input-waiting? (ref eq)) ;; #f | () -> bool
- (field $seek (ref eq)) ;; #f | (offset, whence) -> offset
- (field $close (ref eq)) ;; #f | () -> ()
- (field $truncate (ref eq)) ;; #f | (length) -> ()
- (field $repr (ref $string))
- (field $filename (mut (ref eq))) ;; #f | string
- (field $position (ref $mutable-pair)) ;; (line . column)
- (field $read-buf (mut (ref eq))) ;; #f | #(bv cur end has-eof?)
- (field $write-buf (mut (ref eq))) ;; #f | #(bv cur end)
- (field $read-buffering (mut (ref eq))) ;; #f | [1,size,1<<29)
- (field $r/w-random-access? (ref eq)) ;; #f | #t
- (field $fold-case? (mut (ref eq))) ;; #f | #t
- (field $private-data (ref eq))))) ;; whatever
- (type $struct
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- ;; Vtable link is mutable so that we can tie the knot for top
- ;; types.
- (field $vtable (mut (ref null $vtable))))))
- ,@(map (lambda (nfields)
- `(type ,(struct-name nfields)
- (sub ,(struct-name (1- nfields))
- ,(struct-definition nfields))))
- (iota vtable-nfields 1))
- (type $vtable
- (sub ,(struct-name vtable-nfields)
- (struct
- (field $hash (mut i32))
- (field $vtable (mut (ref null $vtable)))
- ,@vtable-fields)))
- (type $vtable-vtable
- (sub $vtable
- (struct
- (field $hash (mut i32))
- (field $vtable (mut (ref null $vtable)))
- ,@vtable-fields)))
- (type $parameter
- (sub $proc
- (struct
- (field $hash (mut i32))
- (field $func (ref $kvarargs))
- (field $fluid (ref $fluid))
- (field $convert (ref $proc)))))
- (type $dyn (sub (struct)))
- (type $dynwind
- (sub $dyn
- (struct
- (field $wind (ref $proc))
- (field $unwind (ref $proc)))))
- (type $dynprompt
- (sub $dyn
- (struct
- (field $raw-sp i32)
- (field $scm-sp i32)
- (field $ret-sp i32)
- (field $unwind-only? i8)
- (field $tag (ref eq))
- (field $handler (ref $kvarargs)))))
- (type $dynfluid
- (sub $dyn
- (struct
- (field $fluid (ref $fluid))
- (field $val (mut (ref eq))))))
- (type $dynstate
- (sub $dyn
- (struct
- (field $fluids (mut (ref $hash-table)))))))
- (type $raw-retvector (array (mut (ref $kvarargs))))
- (type $raw-dynvector (array (mut (ref $dyn))))
- (type $cont
- (sub $proc
- (struct
- (field $hash (mut i32))
- (field $func (ref $kvarargs))
- (field $prompt (ref $dynprompt))
- (field $raw-stack (ref $raw-bytevector))
- (field $scm-stack (ref $raw-scmvector))
- (field $ret-stack (ref $raw-retvector))
- (field $dyn-stack (ref $raw-dynvector)))))
- (global $root-vtable (ref $vtable-vtable) (call $make-root-vtable))
- (global $empty-vector (ref $vector)
- (struct.new $vector
- (i32.const 0) (array.new_fixed $raw-scmvector 0)))
- (func $make-root-vtable (result (ref $vtable-vtable))
- (local $ret (ref $vtable-vtable))
- (local.set $ret
- (struct.new $vtable-vtable
- (i32.const 0)
- (ref.null $vtable)
- (ref.i31 (i32.const ,(ash vtable-nfields 1)))
- (ref.i31 (i32.const 1)) ; printer
- (ref.i31 (i32.const 1)) ; name
- (ref.i31 (i32.const 1)) ; constructor
- (ref.i31 (i32.const 13)) ; properties
- (global.get $empty-vector) ; parents
- (ref.i31 (i32.const 0)) ; mutable-fields
- (ref.i31 (i32.const 0)) ; compare
- (ref.i31 (i32.const 0)))) ; field-ref
- (struct.set $vtable-vtable $vtable (local.get $ret) (local.get $ret))
- ;; Rely on Scheme to initialize printer, name, etc...
- (local.get $ret))
- (func $struct-ref (param $nargs i32) (param $arg0 (ref eq))
- (param $arg1 (ref eq)) (param $arg2 (ref eq))
- (local $proc (ref eq))
- (local.set $proc
- (struct.get $vtable $field-ref
- (struct.get $struct $vtable
- (ref.cast $struct
- (local.get $arg1)))))
- (return_call_ref $kvarargs
- (i32.const 3)
- (local.get $proc)
- (local.get $arg1)
- (local.get $arg2)
- (struct.get $proc $func (ref.cast $proc (local.get $proc)))))
- (global $struct-ref-primitive (ref eq)
- (struct.new $proc (i32.const 0) (ref.func $struct-ref)))
- (func $raise-exception (param $exn (ref eq))
- (return_call_ref $kvarargs
- (i32.const 2)
- (global.get $raise-exception)
- (local.get $exn)
- (ref.i31 (i32.const 1))
- (struct.get $proc $func (global.get $raise-exception))))
- (func $raise-returned-value
- (param $nargs i32)
- (param $arg0 (ref eq)) (param $arg1 (ref eq)) (param $arg2 (ref eq))
- (if (i32.ne (local.get $nargs) (i32.const 1))
- (then (call $die0
- (string.const "unexpected raise-exception return"))))
- (return_call $raise-exception (local.get $arg0)))
- (func $push-raise-returned-value
- (global.set $ret-sp (i32.add (global.get $ret-sp) (i32.const 1)))
- (call $maybe-grow-ret-stack)
- (table.set $ret-stack
- (i32.sub (global.get $ret-sp) (i32.const 1))
- (ref.func $raise-returned-value)))
- (func $raise-type-error
- (param $subr (ref string))
- (param $what (ref string))
- (param $val (ref eq))
- (call $push-raise-returned-value)
- (global.set $arg3 (struct.new $string (i32.const 0)
- (local.get $what)))
- (return_call_ref $kvarargs
- (i32.const 4)
- (global.get $make-type-error)
- (local.get $val)
- (struct.new $string (i32.const 0)
- (local.get $subr))
- (struct.get $proc $func
- (global.get $make-type-error))))
- (func $raise-range-error
- (param $subr (ref string))
- (param $val (ref eq))
- (call $push-raise-returned-value)
- (global.set $arg3 (ref.i31 (i32.const 1)))
- (global.set $arg4 (local.get $val))
- (return_call_ref $kvarargs
- (i32.const 5)
- (global.get $make-range-error)
- (local.get $val)
- (ref.i31 (i32.const 1))
- (struct.get $proc $func
- (global.get $make-range-error))))
- (func $raise-arity-error
- (param $subr (ref null string))
- (param $val (ref eq))
- (call $push-raise-returned-value)
- (return_call_ref $kvarargs
- (i32.const 3)
- (global.get $make-arity-error)
- (local.get $val)
- (if (ref eq)
- (ref.is_null (local.get $subr))
- (then (ref.i31 (i32.const 1)))
- (else (struct.new $string (i32.const 0)
- (ref.as_non_null
- (local.get $subr)))))
- (struct.get $proc $func
- (global.get $make-arity-error))))
- (func $raise-invalid-keyword-error (param $kw (ref eq))
- (call $push-raise-returned-value)
- (return_call_ref
- $kvarargs
- (i32.const 2)
- (global.get $make-invalid-keyword-error)
- (local.get $kw)
- (ref.i31 (i32.const 1))
- (struct.get $proc $func
- (global.get $make-invalid-keyword-error)))
- (unreachable))
- (func $raise-unrecognized-keyword-error (param $kw (ref eq))
- (call $push-raise-returned-value)
- (return_call_ref
- $kvarargs
- (i32.const 2)
- (global.get $make-unrecogized-keyword-error)
- (local.get $kw)
- (ref.i31 (i32.const 1))
- (struct.get $proc $func
- (global.get $make-unrecogized-keyword-error)))
- (unreachable))
- (func $raise-missing-keyword-argument-error (param $kw (ref eq))
- (call $push-raise-returned-value)
- (return_call_ref
- $kvarargs
- (i32.const 2)
- (global.get $make-missing-keyword-argument-error)
- (local.get $kw)
- (ref.i31 (i32.const 1))
- (struct.get $proc $func
- (global.get $make-missing-keyword-argument-error)))
- (unreachable))
- (func $raise-runtime-error-with-message
- (param $message (ref string))
- (call $push-raise-returned-value)
- (return_call_ref $kvarargs
- (i32.const 2)
- (global.get $make-runtime-error-with-message)
- (struct.new $string
- (i32.const 0)
- (local.get $message))
- (ref.i31 (i32.const 1))
- (struct.get $proc $func
- (global.get $make-runtime-error-with-message))))
- (func $raise-runtime-error-with-message+irritants
- (param $message (ref string))
- (param $irritants (ref eq))
- (call $push-raise-returned-value)
- (return_call_ref $kvarargs
- (i32.const 3)
- (global.get $make-runtime-error-with-message+irritants)
- (struct.new $string
- (i32.const 0)
- (local.get $message))
- (local.get $irritants)
- (struct.get $proc $func
- (global.get $make-runtime-error-with-message+irritants))))
- (func $string->bignum (import "rt" "bignum_from_string")
- (param (ref string))
- (result (ref extern)))
- (func $bignum-from-i32 (import "rt" "bignum_from_i32")
- (param i32)
- (result (ref extern)))
- (func $bignum-from-i64 (import "rt" "bignum_from_i64")
- (param i64)
- (result (ref extern)))
- (func $bignum-from-u64 (import "rt" "bignum_from_u64")
- (param i64)
- (result (ref extern)))
- (func $bignum-is-i64 (import "rt" "bignum_is_i64")
- (param (ref extern))
- (result i32))
- (func $bignum-is-u64 (import "rt" "bignum_is_u64")
- (param (ref extern))
- (result i32))
- (func $bignum-get-i64 (import "rt" "bignum_get_i64")
- (param (ref extern))
- (result i64))
- (func $bignum-add (import "rt" "bignum_add")
- (param (ref extern))
- (param (ref extern))
- (result (ref extern)))
- (func $bignum-add-i32 (import "rt" "bignum_add")
- (param (ref extern))
- (param i32)
- (result (ref extern)))
- (func $bignum-sub (import "rt" "bignum_sub")
- (param (ref extern))
- (param (ref extern))
- (result (ref extern)))
- (func $bignum-sub-i32 (import "rt" "bignum_sub")
- (param (ref extern))
- (param i32)
- (result (ref extern)))
- (func $bignum-sub-i32-i32 (import "rt" "bignum_sub")
- (param i32)
- (param i32)
- (result (ref extern)))
- (func $bignum-mul (import "rt" "bignum_mul")
- (param (ref extern))
- (param (ref extern))
- (result (ref extern)))
- (func $bignum-mul-i32 (import "rt" "bignum_mul")
- (param (ref extern))
- (param i32)
- (result (ref extern)))
- (func $bignum-lsh (import "rt" "bignum_lsh")
- (param (ref extern))
- (param i64)
- (result (ref extern)))
- (func $i32-lsh (import "rt" "bignum_lsh")
- (param i32)
- (param i64)
- (result (ref extern)))
- (func $bignum-rsh (import "rt" "bignum_rsh")
- (param (ref extern))
- (param i64)
- (result (ref extern)))
- (func $bignum-quo (import "rt" "bignum_quo")
- (param (ref extern))
- (param (ref extern))
- (result (ref extern)))
- (func $bignum-rem (import "rt" "bignum_rem")
- (param (ref extern))
- (param (ref extern))
- (result (ref extern)))
- (func $bignum-mod (import "rt" "bignum_mod")
- (param (ref extern))
- (param (ref extern))
- (result (ref extern)))
- (func $bignum-gcd (import "rt" "bignum_gcd")
- (param (ref extern))
- (param (ref extern))
- (result (ref extern)))
- (func $bignum-logand-i32 (import "rt" "bignum_logand")
- (param (ref extern))
- (param i32)
- (result (ref extern)))
- (func $bignum-logand-bignum (import "rt" "bignum_logand")
- (param (ref extern))
- (param (ref extern))
- (result (ref extern)))
- (func $bignum-logior-i32 (import "rt" "bignum_logior")
- (param (ref extern))
- (param i32)
- (result (ref extern)))
- (func $bignum-logior-bignum (import "rt" "bignum_logior")
- (param (ref extern))
- (param (ref extern))
- (result (ref extern)))
- (func $bignum-logxor-i32 (import "rt" "bignum_logxor")
- (param (ref extern))
- (param i32)
- (result (ref extern)))
- (func $bignum-logxor-bignum (import "rt" "bignum_logxor")
- (param (ref extern))
- (param (ref extern))
- (result (ref extern)))
- (func $i32-logsub-bignum (import "rt" "bignum_logsub")
- (param i32)
- (param (ref extern))
- (result (ref extern)))
- (func $bignum-logsub-i32 (import "rt" "bignum_logsub")
- (param (ref extern))
- (param i32)
- (result (ref extern)))
- (func $bignum-logsub-bignum (import "rt" "bignum_logsub")
- (param (ref extern))
- (param (ref extern))
- (result (ref extern)))
- (func $lt-fix-big (import "rt" "bignum_lt")
- (param i32)
- (param (ref extern))
- (result i32))
- (func $lt-big-fix (import "rt" "bignum_lt")
- (param (ref extern))
- (param i32)
- (result i32))
- (func $lt-big-big (import "rt" "bignum_lt")
- (param (ref extern))
- (param (ref extern))
- (result i32))
- (func $lt-big-flo (import "rt" "bignum_lt")
- (param (ref extern))
- (param f64)
- (result i32))
- (func $lt-flo-big (import "rt" "bignum_lt")
- (param f64)
- (param (ref extern))
- (result i32))
- (func $le-fix-big (import "rt" "bignum_le")
- (param i32)
- (param (ref extern))
- (result i32))
- (func $le-big-fix (import "rt" "bignum_le")
- (param (ref extern))
- (param i32)
- (result i32))
- (func $le-big-big (import "rt" "bignum_le")
- (param (ref extern))
- (param (ref extern))
- (result i32))
- (func $le-big-flo (import "rt" "bignum_le")
- (param (ref extern))
- (param f64)
- (result i32))
- (func $le-flo-big (import "rt" "bignum_le")
- (param f64)
- (param (ref extern))
- (result i32))
- (func $eq-fix-big (import "rt" "bignum_eq")
- (param i32)
- (param (ref extern))
- (result i32))
- (func $eq-big-fix (import "rt" "bignum_eq")
- (param (ref extern))
- (param i32)
- (result i32))
- (func $eq-big-big (import "rt" "bignum_eq")
- (param (ref extern))
- (param (ref extern))
- (result i32))
- (func $eq-big-flo (import "rt" "bignum_eq")
- (param (ref extern))
- (param f64)
- (result i32))
- (func $eq-flo-big (import "rt" "bignum_eq")
- (param f64)
- (param (ref extern))
- (result i32))
- (func $bignum-to-f64 (import "rt" "bignum_to_f64")
- (param (ref extern))
- (result f64))
- (func $f64-is-nan (import "rt" "f64_is_nan")
- (param f64)
- (result i32))
- (func $f64-is-infinite (import "rt" "f64_is_infinite")
- (param f64)
- (result i32))
- (func $flonum->string (import "rt" "flonum_to_string")
- (param f64)
- (result (ref string)))
- (func $string-upcase (import "rt" "string_upcase")
- (param (ref string))
- (result (ref string)))
- (func $string-downcase (import "rt" "string_downcase")
- (param (ref string))
- (result (ref string)))
- (func $make-weak-map (import "rt" "make_weak_map")
- (result (ref extern)))
- (func $weak-map-get (import "rt" "weak_map_get")
- (param (ref extern) (ref eq) (ref eq))
- (result (ref eq)))
- (func $weak-map-set (import "rt" "weak_map_set")
- (param (ref extern) (ref eq) (ref eq)))
- (func $weak-map-delete (import "rt" "weak_map_delete")
- (param (ref extern) (ref eq))
- (result i32))
- ;; FIXME: These are very much temporary.
- (func $write-stdout (import "io" "write_stdout") (param (ref string)))
- (func $write-stderr (import "io" "write_stderr") (param (ref string)))
- (func $read-stdin (import "io" "read_stdin") (result (ref string)))
- (func $file-exists? (import "io" "file_exists")
- (param (ref string)) (result i32))
- (func $open-input-file (import "io" "open_input_file")
- (param (ref string)) (result (ref extern)))
- (func $open-output-file (import "io" "open_output_file")
- (param (ref string)) (result (ref extern)))
- (func $close-file (import "io" "close_file") (param (ref extern)))
- (func $read-file (import "io" "read_file")
- (param (ref extern)) (param i32) (result i32))
- (func $write-file (import "io" "write_file")
- (param (ref extern)) (param i32) (result i32))
- (func $seek-file (import "io" "seek_file")
- (param (ref extern)) (param i32) (param i32) (result i32))
- (func $file-random-access? (import "io" "file_random_access")
- (param (ref extern)) (result i32))
- (func $file-buffer-size (import "io" "file_buffer_size")
- (param (ref extern)) (result i32))
- (func $file-buffer-ref (import "io" "file_buffer_ref")
- (param (ref extern)) (param i32) (result i32))
- (func $file-buffer-set! (import "io" "file_buffer_set")
- (param (ref extern)) (param i32) (param i32))
- (func $delete-file (import "io" "delete_file") (param (ref string)))
- (func $fsqrt (import "rt" "fsqrt") (param f64) (result f64))
- (func $fsin (import "rt" "fsin") (param f64) (result f64))
- (func $fcos (import "rt" "fcos") (param f64) (result f64))
- (func $ftan (import "rt" "ftan") (param f64) (result f64))
- (func $fasin (import "rt" "fasin") (param f64) (result f64))
- (func $facos (import "rt" "facos") (param f64) (result f64))
- (func $fatan (import "rt" "fatan") (param f64) (result f64))
- (func $fatan2 (import "rt" "fatan2") (param f64 f64) (result f64))
- (func $flog (import "rt" "flog") (param f64) (result f64))
- (func $fexp (import "rt" "fexp") (param f64) (result f64))
- (func $jiffies-per-second (import "rt" "jiffies_per_second") (result i32))
- (func $current-jiffy (import "rt" "current_jiffy") (result f64))
- (func $current-second (import "rt" "current_second") (result f64))
- (func $die (import "rt" "die")
- (param (ref string) (ref eq)))
- (func $debug-str (import "debug" "debug_str")
- (param (ref string)))
- (func $debug-str-i32 (import "debug" "debug_str_i32")
- (param (ref string) i32))
- (func $debug-str-scm (import "debug" "debug_str_scm")
- (param (ref string) (ref eq)))
- (func $procedure->extern (import "ffi" "procedure_to_extern")
- (param (ref eq)) (result (ref extern)))
- (func $die0 (param $reason (ref string))
- (call $die (local.get 0) (ref.i31 (i32.const 1))))
- ;; Thomas Wang's integer hasher, from
- ;; http://www.cris.com/~Ttwang/tech/inthash.htm.
- (func $integer-hash (param $v i32) (result i32)
- (local.set $v (i32.xor (i32.xor (local.get $v) (i32.const 61))
- (i32.shr_u (local.get $v) (i32.const 16))))
- (local.set $v (i32.add (local.get $v)
- (i32.shl (local.get $v) (i32.const 3))))
- (local.set $v (i32.xor (local.get $v)
- (i32.shr_u (local.get $v) (i32.const 4))))
- (local.set $v (i32.mul (local.get $v)
- (i32.const #x27d4eb2d)))
- (i32.xor (local.get $v)
- (i32.shr_u (local.get $v) (i32.const 15))))
- (func $finish-heap-object-hash (param $hash i32) (result i32)
- (local.set $hash (call $integer-hash (local.get $hash)))
- (if i32 (local.get $hash)
- (then (local.get $hash))
- (else (call $integer-hash (i32.const 42)))))
- (global $hashq-counter (mut i32) (i32.const 0))
- (func $immediate-hashq (param $v (ref i31)) (result i32)
- (call $integer-hash (i31.get_u (local.get $v))))
- (func $heap-object-hashq (param $v (ref $heap-object)) (result i32)
- (local $tag i32)
- (local.set $tag (struct.get $heap-object $hash (local.get $v)))
- (loop $init-if-zero
- (block
- $done
- (br_if $done (local.get $tag))
- (global.set $hashq-counter
- (i32.sub (global.get $hashq-counter) (i32.const 1)))
- (struct.set $heap-object $hash (local.get $v)
- (local.tee $tag (call $integer-hash
- (global.get $hashq-counter))))
- ;; Check and retry if result is zero.
- (br $init-if-zero)))
- (local.get $tag))
- (func $hashq (param $v (ref eq)) (result i32)
- (if i32
- (ref.test i31 (local.get $v))
- (then
- (return_call $immediate-hashq
- (ref.cast i31 (local.get $v))))
- (else
- (return_call $heap-object-hashq
- (ref.cast $heap-object (local.get $v))))))
- ;; 32-bit murmur3 hashing function ported from C and specialized
- ;; for both bytevectors and bitvectors.
- (func $hash-bytevector (param $bv (ref $bytevector)) (result i32)
- (local $raw (ref $raw-bytevector))
- (local $len i32)
- (local $i i32)
- (local $h1 i32)
- (local.set $raw (struct.get $bytevector $vals (local.get $bv)))
- (local.set $len (array.len (local.get $raw)))
- (local.set $i (i32.const 4))
- (local.set $h1 (i32.const ,(u32->s32 #xfeedbaba)))
- ;; Hash most (potentially all) of the bytevector contents 4
- ;; bytes at a time.
- (loop $loop
- (block $done
- (br_if $done (i32.gt_s (local.get $i) (local.get $len)))
- ;; Sigh, we can't directly read i32s from an
- ;; (array i8) so we read 4 separate bytes and
- ;; shift them.
- (array.get_u $raw-bytevector
- (local.get $raw)
- (i32.sub (local.get $i) (i32.const 4)))
- (i32.shl (array.get_u $raw-bytevector
- (local.get $raw)
- (i32.sub (local.get $i) (i32.const 3)))
- (i32.const 8))
- (i32.or)
- (i32.shl (array.get_u $raw-bytevector
- (local.get $raw)
- (i32.sub (local.get $i) (i32.const 2)))
- (i32.const 16))
- (i32.or)
- (i32.shl (array.get_u $raw-bytevector
- (local.get $raw)
- (i32.sub (local.get $i) (i32.const 1)))
- (i32.const 24))
- (i32.or)
- ;; Combine with hash from last iteration.
- (i32.const ,(u32->s32 #xcc9e2d51))
- (i32.mul)
- (i32.const 15)
- (i32.rotl)
- (i32.const ,(u32->s32 #x1b873593))
- (i32.mul)
- (local.get $h1)
- (i32.xor)
- (i32.const 13)
- (i32.rotl)
- (i32.const 5)
- (i32.mul)
- (i32.const ,(u32->s32 #xe6546b64))
- (i32.add)
- (local.set $h1)
- (local.set $i (i32.add (local.get $i) (i32.const 4)))
- (br $loop)))
- ;; Handle the remaining 1-3 bytes when length isn't
- ;; divisible by 4. Inner blocks fall through to the outer
- ;; blocks.
- (i32.const 0)
- (block $done (param i32) (result i32)
- (block $1-byte (param i32) (result i32)
- (block $2-bytes (param i32) (result i32)
- (block $3-bytes (param i32) (result i32)
- (block (param i32) (result i32)
- (i32.and (local.get $len) (i32.const 3))
- (br_table $done $1-byte $2-bytes $3-bytes $done)
- (unreachable)))
- (array.get_u $raw-bytevector
- (local.get $raw)
- (i32.sub (local.get $i) (i32.const 2)))
- (i32.const 16)
- (i32.shl)
- (i32.xor))
- (array.get_u $raw-bytevector
- (local.get $raw)
- (i32.sub (local.get $i) (i32.const 3)))
- (i32.const 8)
- (i32.shl)
- (i32.xor))
- (array.get_u $raw-bytevector
- (local.get $raw)
- (i32.sub (local.get $i) (i32.const 4)))
- (i32.xor)
- (i32.const ,(u32->s32 #xcc9e2d51))
- (i32.mul)
- (i32.const 15)
- (i32.rotl)
- (i32.const ,(u32->s32 #x1b873593))
- (i32.mul))
- (local.get $h1)
- (i32.xor)
- (local.set $h1)
- ;; Finalize by incorporating bytevector length and mixing.
- (local.set $h1 (i32.xor
- (local.get $h1)
- (array.len (local.get $raw))))
- (local.set $h1 (i32.mul
- (i32.xor
- (local.get $h1)
- (i32.shr_u (local.get $h1) (i32.const 16)))
- (i32.const ,(u32->s32 #x85ebca6b))))
- (local.set $h1 (i32.mul
- (i32.xor
- (local.get $h1)
- (i32.shr_u (local.get $h1) (i32.const 13)))
- (i32.const ,(u32->s32 #xc2b2ae35))))
- (i32.xor (local.get $h1)
- (i32.shr_u (local.get $h1) (i32.const 16))))
- (func $hash-bitvector (param $bv (ref $bitvector)) (result i32)
- (local $raw (ref $raw-bitvector))
- (local $len i32)
- (local $i i32)
- (local $h1 i32)
- (local.set $raw (struct.get $bitvector $vals (local.get $bv)))
- (local.set $len (array.len (local.get $raw)))
- (local.set $i (i32.const 0))
- (local.set $h1 (i32.const ,(u32->s32 #xdecafbad)))
- ;; Hash bitvector contents.
- (loop $loop
- (block $done
- (br_if $done (i32.eq (local.get $i) (local.get $len)))
- (array.get $raw-bitvector
- (local.get $raw)
- (local.get $i))
- (i32.const ,(u32->s32 #xcc9e2d51))
- (i32.mul)
- (i32.const 15)
- (i32.rotl)
- (i32.const ,(u32->s32 #x1b873593))
- (i32.mul)
- (local.get $h1)
- (i32.xor)
- (i32.const 13)
- (i32.rotl)
- (i32.const 5)
- (i32.mul)
- (i32.const ,(u32->s32 #xe6546b64))
- (i32.add)
- (local.set $h1)
- (local.set $i (i32.add (local.get $i) (i32.const 1)))
- (br $loop)))
- ;; Finalize by incorporating bitvector length and mixing.
- (local.set $h1 (i32.xor
- (local.get $h1)
- (struct.get $bitvector $len (local.get $bv))))
- (local.set $h1 (i32.mul
- (i32.xor
- (local.get $h1)
- (i32.shr_u (local.get $h1) (i32.const 16)))
- (i32.const ,(u32->s32 #x85ebca6b))))
- (local.set $h1 (i32.mul
- (i32.xor
- (local.get $h1)
- (i32.shr_u (local.get $h1) (i32.const 13)))
- (i32.const ,(u32->s32 #xc2b2ae35))))
- (i32.xor (local.get $h1)
- (i32.shr_u (local.get $h1) (i32.const 16))))
- (func $grow-raw-stack
- ;; Grow the stack by at least 50% and at least the needed
- ;; space. Trap if we fail to grow.
- ;; additional_size = (current_size >> 1) | needed_size
- (if (i32.eq
- (memory.grow
- $raw-stack
- (i32.or (i32.shr_u (memory.size $raw-stack) (i32.const 1))
- ;; Wasm pages are 64 kB.
- (i32.sub (i32.add (i32.shr_u (global.get $raw-sp)
- (i32.const 16))
- (i32.const 1))
- (memory.size $raw-stack))))
- (i32.const -1))
- (then (call $die0 (string.const "$grow-raw-stack")) (unreachable))))
- (func $maybe-grow-raw-stack
- (if (i32.lt_u (i32.shl (memory.size $raw-stack) (i32.const 16))
- (global.get $raw-sp))
- (then (call $grow-raw-stack))))
- (func $grow-scm-stack
- ;; Grow as in $grow-raw-stack.
- (if (i32.eq
- (table.grow $scm-stack
- (ref.i31 (i32.const 0))
- (i32.or (i32.shr_u (table.size $scm-stack)
- (i32.const 1))
- (i32.sub (global.get $scm-sp)
- (table.size $scm-stack))))
- (i32.const -1))
- (then
- (call $die0 (string.const "$grow-scm-stack"))
- (unreachable))))
- (func $maybe-grow-scm-stack
- (if (i32.lt_u (table.size $scm-stack) (global.get $scm-sp))
- (then (call $grow-scm-stack))))
- (func $invalid-continuation (type $kvarargs)
- (call $die0 (string.const "$invalid-continuation"))
- (unreachable))
- (func $grow-ret-stack
- ;; Grow as in $grow-raw-stack.
- (if (i32.eq (table.grow $ret-stack
- (ref.func $invalid-continuation)
- (i32.or (i32.shr_u (table.size $ret-stack)
- (i32.const 1))
- (i32.sub (global.get $ret-sp)
- (table.size $ret-stack))))
- (i32.const -1))
- (then
- (call $die0 (string.const "$grow-ret-stack"))
- (unreachable))))
- (func $maybe-grow-ret-stack
- (if (i32.lt_u (table.size $ret-stack) (global.get $ret-sp))
- (then (call $grow-ret-stack))))
- (func $grow-dyn-stack
- ;; Grow as in $grow-ret-stack.
- (if (i32.eq (table.grow $dyn-stack
- (ref.null $dyn)
- (i32.or (i32.shr_u (table.size $dyn-stack)
- (i32.const 1))
- (i32.sub (global.get $dyn-sp)
- (table.size $dyn-stack))))
- (i32.const -1))
- (then
- (call $die0 (string.const "$grow-dyn-stack"))
- (unreachable))))
- (func $maybe-grow-dyn-stack
- (if (i32.lt_u (table.size $dyn-stack) (global.get $dyn-sp))
- (then (call $grow-dyn-stack))))
- (func $collect-rest-args (param $nargs i32)
- (param $arg0 (ref eq)) (param $arg1 (ref eq)) (param $arg2 (ref eq))
- (param $npositional i32)
- (result (ref eq))
- (local $ret (ref eq))
- (local.set $ret (ref.i31 (i32.const 13))) ;; null
- (block
- $done
- (block
- $nargs1
- (block
- $nargs2
- (block
- $nargs3
- (block
- $nargs4
- (block
- $nargs5
- (block
- $nargs6
- (block
- $nargs7
- (block
- $nargs8
- (block
- $nargsN
- (br_table $done
- $nargs1
- $nargs2
- $nargs3
- $nargs4
- $nargs5
- $nargs6
- $nargs7
- $nargs8
- $nargsN
- (local.get $nargs)))
- (loop $lp
- (if (i32.gt_u (local.get $nargs) (i32.const 8))
- (then
- (br_if $done (i32.le_u (local.get $nargs)
- (local.get $npositional)))
- (local.set
- $ret
- (struct.new
- $pair
- (i32.const 0)
- (ref.as_non_null
- (table.get
- $argv
- (i32.sub
- (local.tee $nargs
- (i32.sub (local.get $nargs) (i32.const 1)))
- (i32.const 8))))
- (local.get $ret)))
- (br $lp)))))
- (br_if $done (i32.le_u (i32.const 8) (local.get $npositional)))
- (local.set $ret
- (struct.new $pair (i32.const 0)
- (global.get $arg7) (local.get $ret))))
- (br_if $done (i32.le_u (i32.const 7) (local.get $npositional)))
- (local.set $ret
- (struct.new $pair (i32.const 0)
- (global.get $arg6) (local.get $ret))))
- (br_if $done (i32.le_u (i32.const 6) (local.get $npositional)))
- (local.set $ret
- (struct.new $pair (i32.const 0)
- (global.get $arg5) (local.get $ret))))
- (br_if $done (i32.le_u (i32.const 5) (local.get $npositional)))
- (local.set $ret
- (struct.new $pair (i32.const 0)
- (global.get $arg4) (local.get $ret))))
- (br_if $done (i32.le_u (i32.const 4) (local.get $npositional)))
- (local.set $ret
- (struct.new $pair (i32.const 0)
- (global.get $arg3) (local.get $ret))))
- (br_if $done (i32.le_u (i32.const 3) (local.get $npositional)))
- (local.set $ret
- (struct.new $pair (i32.const 0)
- (local.get $arg2) (local.get $ret))))
- (br_if $done (i32.le_u (i32.const 2) (local.get $npositional)))
- (local.set $ret
- (struct.new $pair (i32.const 0)
- (local.get $arg1) (local.get $ret)))
- )
- (br_if $done (i32.le_u (i32.const 1) (local.get $npositional)))
- (local.set $ret
- (struct.new $pair (i32.const 0)
- (local.get $arg0) (local.get $ret))))
- (local.get $ret))
- (func $values (param $nargs i32) (param $arg0 (ref eq))
- (param $arg1 (ref eq)) (param $arg2 (ref eq))
- (block
- $done
- (local.set $arg0 (local.get $arg1))
- (local.set $arg1 (local.get $arg2))
- (br_if $done (i32.le_u (local.get $nargs) (i32.const 3)))
- (local.set $arg2 (global.get $arg3))
- (global.set $arg3 (global.get $arg4))
- (global.set $arg4 (global.get $arg5))
- (global.set $arg5 (global.get $arg6))
- (global.set $arg6 (global.get $arg7))
- (br_if $done (i32.le_u (local.get $nargs) (i32.const 8)))
- (global.set $arg7 (ref.as_non_null (table.get $argv (i32.const 0))))
- (table.copy $argv $argv (i32.const 0) (i32.const 1)
- (i32.sub (local.get $nargs) (i32.const 9))))
- (i32.sub (local.get $nargs) (i32.const 1))
- (local.get $arg0)
- (local.get $arg1)
- (local.get $arg2)
- (global.set $ret-sp (i32.sub (global.get $ret-sp) (i32.const 1)))
- (global.get $ret-sp)
- (table.get $ret-stack)
- (return_call_ref $kvarargs))
- (global $values-primitive (ref eq)
- (struct.new $proc (i32.const 0) (ref.func $values)))
- (global $append-primitive (mut (ref $proc))
- (struct.new $proc (i32.const 0) (ref.func $invalid-continuation)))
- (func $make-hash-table (result (ref $hash-table))
- (struct.new $hash-table (i32.const 0) (i32.const 0)
- (array.new $raw-scmvector
- (ref.i31 (i32.const 13)) (i32.const 47))))
- (func $hashq-lookup (param $tab (ref $hash-table)) (param $k (ref eq))
- (result (ref null $pair))
- (local $idx i32)
- (local $buckets (ref $raw-scmvector))
- (local $chain (ref eq))
- (local $head (ref $pair))
- (local $link (ref $pair))
- (local.set $buckets
- (struct.get $hash-table $buckets (local.get $tab)))
- (local.set $idx
- (i32.rem_u (call $hashq (local.get $k))
- (array.len (local.get $buckets))))
- (local.set $chain
- (array.get $raw-scmvector
- (local.get $buckets) (local.get $idx)))
- (loop $lp
- (if (i32.eqz (ref.test $pair (local.get $chain)))
- (then (return (ref.null $pair)))
- (else
- (local.set $link (ref.cast $pair (local.get $chain)))
- (local.set $head
- (ref.cast $pair
- (struct.get $pair $car
- (local.get $link))))
- (if (ref.eq (struct.get $pair $car (local.get $head))
- (local.get $k))
- (then
- (return (local.get $head)))
- (else
- (local.set $chain
- (struct.get $pair $cdr (local.get $link)))
- (br $lp))))))
- (unreachable))
- (func $hashq-lookup/default
- (param $table (ref $hash-table))
- (param $key (ref eq))
- (param $default (ref eq))
- (result (ref eq))
- (local $handle (ref null $pair))
- (local.set $handle (call $hashq-lookup
- (local.get $table)
- (local.get $key)))
- (if (ref eq)
- (ref.is_null (local.get $handle))
- (then (local.get $default))
- (else (ref.as_non_null (local.get $handle)))))
- (func $hashq-insert (param $tab (ref $hash-table)) (param $k (ref eq))
- (param $v (ref eq))
- (local $idx i32)
- (local $buckets (ref $raw-scmvector))
- (local.set $buckets (struct.get $hash-table $buckets (local.get $tab)))
- (local.set $idx (i32.rem_u (call $hashq (local.get $k))
- (array.len (local.get $buckets))))
- (array.set
- $raw-scmvector
- (local.get $buckets) (local.get $idx)
- (struct.new
- $pair (i32.const 0)
- (struct.new $pair (i32.const 0) (local.get $k) (local.get $v))
- (array.get $raw-scmvector (local.get $buckets) (local.get $idx))))
- (struct.set $hash-table $size
- (local.get $tab)
- (i32.add (struct.get $hash-table $size (local.get $tab))
- (i32.const 1))))
- (func $hashq-ref (param $tab (ref $hash-table)) (param $k (ref eq))
- (param $default (ref eq))
- (result (ref eq))
- (local $handle (ref null $pair))
- (local.set $handle
- (call $hashq-lookup (local.get $tab) (local.get $k)))
- (if (ref eq)
- (ref.is_null (local.get $handle))
- (then (local.get $default))
- (else (struct.get $pair $cdr (local.get $handle)))))
- (func $hashq-update (param $tab (ref $hash-table)) (param $k (ref eq))
- (param $v (ref eq)) (param $default (ref eq))
- (result (ref eq))
- (local $handle (ref null $pair))
- (local.set $handle
- (call $hashq-lookup (local.get $tab) (local.get $k)))
- (if (ref eq)
- (ref.is_null (local.get $handle))
- (then
- (call $hashq-insert (local.get $tab) (local.get $k)
- (local.get $v))
- (local.get $default))
- (else
- (struct.get $pair $cdr (local.get $handle))
- (struct.set $pair $cdr (local.get $handle)
- (local.get $v)))))
- (func $hashq-set! (param $tab (ref $hash-table)) (param $k (ref eq))
- (param $v (ref eq))
- (call $hashq-update (local.get $tab) (local.get $k)
- (local.get $v) (ref.i31 (i32.const 1)))
- (drop))
- (func $hashq-delete! (param $tab (ref $hash-table)) (param $k (ref eq))
- (local $idx i32)
- (local $buckets (ref $raw-scmvector))
- (local $chain (ref eq))
- (local $head (ref $pair))
- (local $link (ref $pair))
- (local $last (ref null $pair))
- (local.set $buckets
- (struct.get $hash-table $buckets (local.get $tab)))
- (local.set $idx
- (i32.rem_u (call $hashq (local.get $k))
- (array.len (local.get $buckets))))
- (local.set $chain
- (array.get $raw-scmvector
- (local.get $buckets) (local.get $idx)))
- (loop $lp
- (if (i32.eqz (ref.test $pair (local.get $chain)))
- (then (return))
- (else
- (local.set $link (ref.cast $pair (local.get $chain)))
- (local.set $head
- (ref.cast $pair
- (struct.get $pair $car
- (local.get $link))))
- (if (ref.eq (struct.get $pair $car (local.get $head))
- (local.get $k))
- (then
- (struct.set $hash-table $size
- (local.get $tab)
- (i32.sub (struct.get $hash-table $size
- (local.get $tab))
- (i32.const 1)))
- (if (ref.is_null (local.get $last))
- (then
- (array.set $raw-scmvector
- (local.get $buckets)
- (local.get $idx)
- (struct.get $pair $cdr
- (local.get $link)))
- (return))
- (else
- (struct.set $pair $cdr
- (ref.as_non_null (local.get $last))
- (struct.get $pair $cdr
- (local.get $link)))
- (return))))
- (else
- (local.set $chain
- (struct.get $pair $cdr (local.get $link)))
- (local.set $last (local.get $link))
- (br $lp))))))
- (unreachable))
- ;; A specialized hash table, because it's not a hashq lookup.
- (type $symtab-entry
- (struct (field $sym (ref $symbol))
- (field $next (ref null $symtab-entry))))
- (type $symtab (array (mut (ref null $symtab-entry))))
- (global $the-symtab (ref $symtab)
- (array.new $symtab (ref.null $symtab-entry) (i32.const 47)))
- ,(cond
- (import-abi?
- '(func $intern-symbol! (import "abi" "$intern-symbol!")
- (param $sym (ref $symbol)) (result (ref $symbol))))
- (else
- '(func $intern-symbol!
- (param $sym (ref $symbol)) (result (ref $symbol))
- (local $hash i32)
- (local $idx i32)
- (local $entry (ref null $symtab-entry))
- (local.set $hash (struct.get $heap-object $hash (local.get $sym)))
- (local.set $idx (i32.rem_u (local.get $hash)
- (array.len (global.get $the-symtab))))
- (local.set $entry
- (array.get $symtab (global.get $the-symtab)
- (local.get $idx)))
- (block
- $insert
- (loop $lp
- (br_if $insert (ref.is_null (local.get $entry)))
- (block
- $next
- (br_if $next
- (i32.ne (struct.get $symbol $hash
- (struct.get $symtab-entry $sym
- (local.get $entry)))
- (local.get $hash)))
- (br_if $next
- (i32.eqz
- (string.eq
- (struct.get $string $str
- (struct.get $symbol $name
- (struct.get $symtab-entry $sym
- (local.get $entry))))
- (struct.get $string $str
- (struct.get $symbol $name
- (local.get $sym))))))
- (return (struct.get $symtab-entry $sym (local.get $entry))))
- (local.set $entry
- (struct.get $symtab-entry $next (local.get $entry)))
- (br $lp)))
- (array.set $symtab (global.get $the-symtab) (local.get $idx)
- (struct.new $symtab-entry
- (local.get $sym)
- (array.get $symtab (global.get $the-symtab)
- (local.get $idx))))
- (local.get $sym))))
- ;; For now, the Java string hash function, except over codepoints
- ;; rather than WTF-16 code units.
- (func $string-hash (param $str (ref string)) (result i32)
- (local $iter (ref stringview_iter))
- (local $hash i32)
- (local $codepoint i32)
- (local.set $iter (string.as_iter (local.get $str)))
- (block $done
- (loop $lp
- (local.set $codepoint (stringview_iter.next (local.get $iter)))
- (br_if $done (i32.eq (i32.const -1) (local.get $codepoint)))
- (local.set $hash
- (i32.add (i32.mul (local.get $hash) (i32.const 31))
- (local.get $codepoint)))
- (br $lp)))
- (local.get $hash))
- (func $string->symbol (param $str (ref $string)) (result (ref $symbol))
- (call $intern-symbol!
- (struct.new $symbol
- (call $finish-heap-object-hash
- (call $string-hash
- (struct.get $string $str
- (local.get $str))))
- (local.get $str))))
- (global $the-kwtab (ref $hash-table)
- (struct.new $hash-table (i32.const 0) (i32.const 0)
- (array.new $raw-scmvector
- (ref.i31 (i32.const 13)) (i32.const 47))))
- ,(cond
- (import-abi?
- '(func $intern-keyword! (import "abi" "$intern-keyword!")
- (param $sym (ref $keyword)) (result (ref $keyword))))
- (else
- '(func $intern-keyword! (param $kw (ref $keyword)) (result (ref $keyword))
- (local $handle (ref null $pair))
- (local.set $handle
- (call $hashq-lookup (global.get $the-kwtab)
- (struct.get $keyword $name (local.get $kw))))
- (if (ref $keyword)
- (ref.is_null (local.get $handle))
- (then
- (call $hashq-insert (global.get $the-kwtab)
- (struct.get $keyword $name (local.get $kw))
- (local.get $kw))
- (local.get $kw))
- (else
- (ref.cast $keyword
- (struct.get $pair $cdr (local.get $handle))))))))
- (func $symbol->keyword (param $sym (ref $symbol)) (result (ref $keyword))
- (call $intern-keyword!
- (struct.new $keyword
- (call $finish-heap-object-hash
- (struct.get $symbol $hash (local.get $sym)))
- (local.get $sym))))
- (func $push-dyn (param $dyn (ref $dyn))
- (local $dyn-sp i32)
- (global.set $dyn-sp
- (i32.add (local.tee $dyn-sp (global.get $dyn-sp))
- (i32.const 1)))
- (call $maybe-grow-dyn-stack)
- (table.set $dyn-stack (local.get $dyn-sp) (local.get $dyn)))
- (func $wind-dynstate (param $dynstate (ref $dynstate))
- (local $fluids (ref $hash-table))
- (local.set $fluids (global.get $current-fluids))
- (global.set $current-fluids
- (struct.get $dynstate $fluids (local.get $dynstate)))
- (struct.set $dynstate $fluids (local.get $dynstate)
- (local.get $fluids)))
- (func $push-dynamic-state (param $state (ref $dynamic-state))
- (local $dynstate (ref $dynstate))
- (call $push-dyn
- (local.tee $dynstate
- (struct.new $dynstate
- (struct.get $dynamic-state $fluids
- (local.get $state)))))
- (return_call $wind-dynstate (local.get $dynstate)))
- (func $pop-dynamic-state
- (local $sp i32)
- (global.set $dyn-sp
- (local.tee $sp (i32.sub (global.get $dyn-sp)
- (i32.const 1))))
- (return_call $wind-dynstate
- (ref.cast $dynstate
- (table.get $dyn-stack (local.get $sp)))))
- (func $wind-dynfluid (param $dynfluid (ref $dynfluid))
- (local $fluid (ref $fluid))
- (local.set $fluid
- (struct.get $dynfluid $fluid (local.get $dynfluid)))
- (struct.set
- $dynfluid $val
- (local.get $dynfluid)
- (call $hashq-update (global.get $current-fluids)
- (local.get $fluid)
- (struct.get $dynfluid $val (local.get $dynfluid))
- (struct.get $fluid $init (local.get $fluid)))))
- (func $push-fluid (param $fluid (ref $fluid)) (param $val (ref eq))
- (local $dynfluid (ref $dynfluid))
- (local.set $dynfluid
- (struct.new $dynfluid
- (local.get $fluid) (local.get $val)))
- (call $push-dyn (local.get $dynfluid))
- (call $wind-dynfluid (local.get $dynfluid)))
- (func $pop-fluid
- (local $sp i32)
- (global.set $dyn-sp
- (local.tee $sp (i32.sub (global.get $dyn-sp)
- (i32.const 1))))
- (call $wind-dynfluid
- (ref.cast $dynfluid (table.get $dyn-stack (local.get $sp)))))
- (func $fluid-ref (param $fluid (ref $fluid)) (result (ref eq))
- (call $hashq-ref (global.get $current-fluids)
- (local.get $fluid)
- (struct.get $fluid $init (local.get $fluid))))
- (func $fluid-ref* (param $fluid (ref $fluid)) (param $depth i32)
- (result (ref eq))
- (local $sp i32)
- (local $dyn (ref $dyn))
- (if (local.get $depth)
- (then
- (local.set $sp (global.get $dyn-sp))
- (loop $lp
- (if (local.get $sp)
- (then
- (local.set $sp (i32.sub (local.get $sp) (i32.const 1)))
- (local.set $dyn (ref.as_non_null
- (table.get $dyn-stack (local.get $sp))))
- (br_if $lp (i32.eqz
- (ref.test $dynfluid (local.get $dyn))))
- (local.set $depth
- (i32.sub (local.get $depth) (i32.const 1)))
- (br_if $lp (local.get $depth))
- (return
- (struct.get
- $dynfluid $val
- (ref.cast $dynfluid (local.get $dyn)))))
- (else (return (ref.i31 (i32.const 1)))))))
- (else (return_call $fluid-ref (local.get $fluid))))
- (unreachable))
- (func $fluid-set! (param $fluid (ref $fluid)) (param $val (ref eq))
- (call $hashq-set! (global.get $current-fluids)
- (local.get $fluid)
- (local.get $val)))
- (func $find-prompt (param $tag (ref eq))
- (result (ref $dynprompt) i32)
- (local $dyn (ref $dyn))
- (local $prompt (ref $dynprompt))
- (local $sp i32)
- (local.set $sp (global.get $dyn-sp))
- (loop $lp
- (if (local.get $sp)
- (then
- (local.set $sp (i32.sub (local.get $sp) (i32.const 1)))
- ;; FIXME: could br_on_cast_fail to $lp; need to fix
- ;; the assembler.
- (local.set $dyn (ref.as_non_null
- (table.get $dyn-stack (local.get $sp))))
- (if (ref.test $dynprompt (local.get $dyn))
- (then
- (local.set $prompt
- (ref.cast $dynprompt (local.get $dyn)))
- (if (ref.eq (struct.get $dynprompt $tag
- (local.get $prompt))
- (local.get $tag))
- (then (return (local.get $prompt)
- (local.get $sp)))
- (else (br $lp)))))
- (br $lp))
- (else
- (call $raise-runtime-error-with-message+irritants
- (string.const "prompt not found")
- (struct.new $pair
- (i32.const 0)
- (local.get $tag)
- (ref.i31 (i32.const 13)))))))
- (unreachable))
- (func $rewind
- (param $raw-sp-adjust i32)
- (param $scm-sp-adjust i32)
- (param $ret-sp-adjust i32)
- (param $dyn (ref $raw-dynvector))
- (param $i i32)
- (param $args (ref eq))
- (local $d (ref $dyn))
- (local $dynwind (ref $dynwind))
- (local $dynprompt (ref $dynprompt))
- (local $dynfluid (ref $dynfluid))
- (local $dynstate (ref $dynstate))
- (local $base i32)
- (loop $lp
- (if (i32.eq (local.get $i) (array.len (local.get $dyn)))
- (then
- (return_call $apply (i32.const 3)
- (global.get $apply-primitive)
- (global.get $values-primitive)
- (local.get $args))))
- (local.set $d (array.get $raw-dynvector
- (local.get $dyn)
- (local.get $i)))
- (block
- $next
- (if (ref.test $dynwind (local.get $d))
- (then
- (local.set $dynwind (ref.cast $dynwind (local.get $d)))
- (local.set $base (global.get $raw-sp))
- (global.set $raw-sp (i32.add (local.get $base) (i32.const 16)))
- (global.set $scm-sp (i32.add (global.get $scm-sp) (i32.const 2)))
- (global.set $ret-sp (i32.add (global.get $ret-sp) (i32.const 1)))
- (call $maybe-grow-raw-stack)
- (call $maybe-grow-scm-stack)
- (call $maybe-grow-ret-stack)
- (i32.store $raw-stack offset=0 (local.get $base)
- (local.get $raw-sp-adjust))
- (i32.store $raw-stack offset=4 (local.get $base)
- (local.get $scm-sp-adjust))
- (i32.store $raw-stack offset=8 (local.get $base)
- (local.get $ret-sp-adjust))
- (i32.store $raw-stack offset=12 (local.get $base)
- (local.get $i))
- (table.set $scm-stack
- (i32.sub (global.get $scm-sp) (i32.const 2))
- (local.get $dyn))
- (table.set $scm-stack
- (i32.sub (global.get $scm-sp) (i32.const 1))
- (local.get $args))
- (table.set $ret-stack
- (i32.sub (global.get $ret-sp) (i32.const 1))
- (ref.func $keep-rewinding))
- (return_call_ref $kvarargs
- (i32.const 1)
- (struct.get $dynwind $wind
- (local.get $dynwind))
- (ref.i31 (i32.const 0))
- (ref.i31 (i32.const 0))
- (struct.get
- $proc $func
- (struct.get $dynwind $wind
- (local.get $dynwind))))))
- (if (ref.test $dynprompt (local.get $d))
- (then
- (local.set $dynprompt (ref.cast $dynprompt (local.get $d)))
- (local.set
- $d
- (struct.new
- $dynprompt
- (i32.add
- (struct.get $dynprompt $raw-sp (local.get $dynprompt))
- (local.get $raw-sp-adjust))
- (i32.add
- (struct.get $dynprompt $scm-sp (local.get $dynprompt))
- (local.get $scm-sp-adjust))
- (i32.add
- (struct.get $dynprompt $ret-sp (local.get $dynprompt))
- (local.get $ret-sp-adjust))
- (struct.get_u $dynprompt $unwind-only?
- (local.get $dynprompt))
- (struct.get $dynprompt $tag (local.get $dynprompt))
- (struct.get $dynprompt $handler (local.get $dynprompt))))
- (br $next)))
- (if (ref.test $dynfluid (local.get $d))
- (then
- (local.set $dynfluid (ref.cast $dynfluid (local.get $d)))
- (call $wind-dynfluid (local.get $dynfluid))
- (br $next)))
- (if (ref.test $dynstate (local.get $d))
- (then
- (local.set $dynstate (ref.cast $dynstate (local.get $d)))
- (call $wind-dynstate (local.get $dynstate))
- (br $next))
- (else (unreachable))))
- (call $push-dyn (local.get $d))
- (local.set $i (i32.add (local.get $i) (i32.const 1)))
- (br $lp)))
- (func $restore-raw-stack (param $v (ref $raw-bytevector))
- (local $sp i32)
- (local $i i32)
- (local $len i32)
- (local.set $sp (global.get $raw-sp))
- (local.set $i (i32.const 0))
- (local.set $len (array.len (local.get $v)))
- (global.set $raw-sp (i32.add (local.get $sp) (local.get $len)))
- (call $maybe-grow-raw-stack)
- (loop $lp
- (if (i32.lt_u (local.get $i) (local.get $len))
- (then
- (i32.store8 $raw-stack
- (i32.add (local.get $sp) (local.get $i))
- (array.get_u $raw-bytevector
- (local.get $v)
- (local.get $i)))
- (local.set $i (i32.add (local.get $i) (i32.const 1)))
- (br $lp)))))
- (func $restore-scm-stack (param $v (ref $raw-scmvector))
- (local $sp i32)
- (local $i i32)
- (local $len i32)
- (local.set $sp (global.get $scm-sp))
- (local.set $len (array.len (local.get $v)))
- (global.set $scm-sp (i32.add (local.get $sp) (local.get $len)))
- (call $maybe-grow-scm-stack)
- (loop $lp
- (if (i32.lt_u (local.get $i) (local.get $len))
- (then
- (table.set $scm-stack
- (i32.add (local.get $sp) (local.get $i))
- (array.get $raw-scmvector
- (local.get $v)
- (local.get $i)))
- (local.set $i (i32.add (local.get $i) (i32.const 1)))
- (br $lp)))))
- (func $restore-ret-stack (param $v (ref $raw-retvector))
- (local $sp i32)
- (local $i i32)
- (local $len i32)
- (local.set $sp (global.get $ret-sp))
- (local.set $len (array.len (local.get $v)))
- (global.set $ret-sp (i32.add (local.get $sp) (local.get $len)))
- (call $maybe-grow-ret-stack)
- (loop $lp
- (if (i32.lt_u (local.get $i) (local.get $len))
- (then
- (table.set $ret-stack
- (i32.add (local.get $sp) (local.get $i))
- (array.get $raw-retvector
- (local.get $v)
- (local.get $i)))
- (local.set $i (i32.add (local.get $i) (i32.const 1)))
- (br $lp)))))
- (func $compose-continuation (param $nargs i32)
- (param $arg0 (ref eq)) (param $arg1 (ref eq)) (param $arg2 (ref eq))
- (local $cont (ref $cont))
- (local $prompt (ref $dynprompt))
- (local $raw-sp-adjust i32)
- (local $scm-sp-adjust i32)
- (local $ret-sp-adjust i32)
- (local $args (ref eq))
- (local.set $cont (ref.cast $cont (local.get $arg0)))
- (local.set $prompt (struct.get $cont $prompt (local.get $cont)))
- (local.set $raw-sp-adjust
- (i32.sub (global.get $raw-sp)
- (struct.get $dynprompt $raw-sp
- (local.get $prompt))))
- (local.set $scm-sp-adjust
- (i32.sub (global.get $scm-sp)
- (struct.get $dynprompt $scm-sp
- (local.get $prompt))))
- (local.set $ret-sp-adjust
- (i32.sub (global.get $ret-sp)
- (struct.get $dynprompt $ret-sp
- (local.get $prompt))))
- (local.set $args
- (call $collect-rest-args (local.get $nargs)
- (local.get $arg0)
- (local.get $arg1)
- (local.get $arg2)
- (i32.const 1)))
- (call $restore-raw-stack
- (struct.get $cont $raw-stack (local.get $cont)))
- (call $restore-scm-stack
- (struct.get $cont $scm-stack (local.get $cont)))
- (call $restore-ret-stack
- (struct.get $cont $ret-stack (local.get $cont)))
- ;; Dyn stack is restored incrementally via $rewind.
- (return_call $rewind
- (local.get $raw-sp-adjust)
- (local.get $scm-sp-adjust)
- (local.get $ret-sp-adjust)
- (struct.get $cont $dyn-stack (local.get $cont))
- (i32.const 0)
- (local.get $args)))
- (func $capture-raw-stack (param $base-sp i32)
- (result (ref $raw-bytevector))
- (local $v (ref $raw-bytevector))
- (local $i i32)
- (local $len i32)
- (local.set $len (i32.sub (global.get $raw-sp) (local.get $base-sp)))
- (local.set $v (array.new_default $raw-bytevector
- (local.get $len)))
- (local.set $i (i32.const 0))
- (loop $lp
- (if (i32.lt_u (local.get $i) (local.get $len))
- (then
- (array.set $raw-bytevector
- (local.get $v)
- (local.get $i)
- (i32.load8_u $raw-stack
- (i32.add (local.get $base-sp)
- (local.get $i))))
- (local.set $i (i32.add (local.get $i) (i32.const 1)))
- (br $lp))))
- (local.get $v))
- (func $capture-scm-stack (param $base-sp i32)
- (result (ref $raw-scmvector))
- (local $v (ref $raw-scmvector))
- (local $i i32)
- (local $len i32)
- (local.set $len (i32.sub (global.get $scm-sp) (local.get $base-sp)))
- (local.set $v
- (array.new $raw-scmvector
- (ref.i31 (i32.const 1))
- (local.get $len)))
- (loop $lp
- (if (i32.lt_u (local.get $i) (local.get $len))
- (then
- (array.set $raw-scmvector
- (local.get $v)
- (local.get $i)
- (ref.as_non_null
- (table.get $scm-stack
- (i32.add (local.get $base-sp)
- (local.get $i)))))
- (local.set $i (i32.add (local.get $i) (i32.const 1)))
- (br $lp))))
- (local.get $v))
- (func $capture-ret-stack (param $base-sp i32)
- (result (ref $raw-retvector))
- (local $v (ref $raw-retvector))
- (local $i i32)
- (local $len i32)
- (local.set $len (i32.sub (global.get $ret-sp) (local.get $base-sp)))
- (local.set $v
- (array.new $raw-retvector
- (ref.func $invalid-continuation)
- (local.get $len)))
- (loop $lp
- (if (i32.lt_u (local.get $i) (local.get $len))
- (then
- (array.set $raw-retvector
- (local.get $v)
- (local.get $i)
- (ref.as_non_null
- (table.get $ret-stack
- (i32.add (local.get $base-sp)
- (local.get $i)))))
- (local.set $i (i32.add (local.get $i) (i32.const 1)))
- (br $lp))))
- (local.get $v))
- (func $capture-dyn-stack (param $base-sp i32)
- (result (ref $raw-dynvector))
- (local $v (ref $raw-dynvector))
- (local $i i32)
- (local $len i32)
- (local.set $len (i32.sub (global.get $dyn-sp) (local.get $base-sp)))
- (local.set $v
- (array.new $raw-dynvector
- (struct.new $dyn)
- (local.get $len)))
- (loop $lp
- (if (i32.lt_u (local.get $i) (local.get $len))
- (then
- (array.set $raw-dynvector
- (local.get $v)
- (local.get $i)
- (ref.as_non_null
- (table.get $dyn-stack
- (i32.add (local.get $base-sp)
- (local.get $i)))))
- (local.set $i (i32.add (local.get $i) (i32.const 1)))
- (br $lp))))
- (local.get $v))
- (func $capture-continuation (param $prompt (ref $dynprompt))
- (param $prompt-dyn-sp i32)
- (result (ref eq))
- (if (result (ref eq))
- (struct.get_u $dynprompt $unwind-only? (local.get $prompt))
- (then (ref.i31 (i32.const 1)))
- (else
- (struct.new
- $cont
- (i32.const 0)
- (ref.func $compose-continuation)
- (local.get $prompt)
- (call $capture-raw-stack
- (struct.get $dynprompt $raw-sp (local.get $prompt)))
- (call $capture-scm-stack
- (struct.get $dynprompt $scm-sp (local.get $prompt)))
- (call $capture-ret-stack
- ;; Increment to avoid including the prompt unwind
- ;; continuation. We rely on the compiler
- ;; generating code for non-unwind-only prompt
- ;; bodies that consists of just a closure call.
- (i32.add
- (struct.get $dynprompt $ret-sp (local.get $prompt))
- (i32.const 1)))
- (call $capture-dyn-stack
- ;; Incremented to avoid including the prompt
- ;; itself.
- (i32.add (local.get $prompt-dyn-sp) (i32.const 1)))))))
- (func $keep-unwinding (param $nargs i32)
- (param $arg0 (ref eq)) (param $arg1 (ref eq)) (param $arg2 (ref eq))
- (local $tag (ref eq))
- (local $cont (ref eq))
- (local $args (ref eq))
- (local.set $tag
- (ref.as_non_null
- (table.get $scm-stack
- (i32.sub (global.get $scm-sp) (i32.const 3)))))
- (local.set $cont
- (ref.as_non_null
- (table.get $scm-stack
- (i32.sub (global.get $scm-sp) (i32.const 2)))))
- (local.set $args
- (ref.as_non_null
- (table.get $scm-stack
- (i32.sub (global.get $scm-sp) (i32.const 1)))))
- (global.set $scm-sp (i32.sub (global.get $scm-sp) (i32.const 3)))
- (return_call $unwind-to-prompt
- (local.get $tag) (local.get $cont) (local.get $args)))
- (func $keep-rewinding (param $nargs i32)
- (param $arg0 (ref eq)) (param $arg1 (ref eq)) (param $arg2 (ref eq))
- (local $raw-sp-adjust i32)
- (local $scm-sp-adjust i32)
- (local $ret-sp-adjust i32)
- (local $i i32)
- (local $dyn (ref $raw-dynvector))
- (local $d (ref $dynwind))
- (local $args (ref eq))
- (global.set $raw-sp (i32.sub (global.get $raw-sp) (i32.const 16)))
- (local.set $raw-sp-adjust
- (i32.load $raw-stack offset=0 (global.get $raw-sp)))
- (local.set $scm-sp-adjust
- (i32.load $raw-stack offset=4 (global.get $raw-sp)))
- (local.set $ret-sp-adjust
- (i32.load $raw-stack offset=8 (global.get $raw-sp)))
- (local.set $i
- (i32.load $raw-stack offset=12 (global.get $raw-sp)))
- (global.set $scm-sp (i32.sub (global.get $scm-sp) (i32.const 2)))
- (local.set $dyn (ref.cast
- $raw-dynvector
- (table.get $scm-stack (global.get $scm-sp))))
- (local.set $args (ref.as_non_null
- (table.get $scm-stack
- (i32.add (global.get $scm-sp)
- (i32.const 1)))))
- (local.set $d (ref.cast $dynwind
- (array.get $raw-dynvector
- (local.get $dyn) (local.get $i))))
- (call $push-dyn (local.get $d))
- (return_call $rewind
- (local.get $raw-sp-adjust)
- (local.get $scm-sp-adjust)
- (local.get $ret-sp-adjust)
- (local.get $dyn)
- (i32.add (local.get $i) (i32.const 1))
- (local.get $args)))
- (func $unwind-to-prompt
- (param $tag (ref eq)) (param $cont (ref eq)) (param $args (ref eq))
- (local $prompt (ref $dynprompt))
- (local $dynwind (ref $dynwind))
- (local $dyn (ref $dyn))
- ;; During an abort-to-prompt that crosses a dynamic-wind,
- ;; after the dynamic-wind unwinder returns, it could be that
- ;; the dynamic stack is different from where the
- ;; abort-to-prompt started. It could be that the prompt is
- ;; no longer in the continuation; that's why we look it up
- ;; again here. More annoyingly, it could be that the prompt
- ;; becomes not unwind-only! FIXME to check that if $cont is
- ;; #f, that the prompt is indeed still unwind-only.
- (call $find-prompt (local.get $tag))
- (drop) ;; prompt dyn-sp
- (local.set $prompt)
- (loop $lp
- (global.set $dyn-sp
- (i32.sub (global.get $dyn-sp) (i32.const 1)))
- (local.set $dyn (ref.as_non_null
- (table.get $dyn-stack (global.get $dyn-sp))))
- (if (ref.eq (local.get $dyn) (local.get $prompt))
- (then
- ;; Unwind control stacks.
- (global.set $raw-sp (struct.get $dynprompt $raw-sp
- (local.get $prompt)))
- (global.set $scm-sp (struct.get $dynprompt $scm-sp
- (local.get $prompt)))
- (global.set $ret-sp (struct.get $dynprompt $ret-sp
- (local.get $prompt)))
- ;; Use apply + values to pass values to handler.
- (global.set $ret-sp
- (i32.add (global.get $ret-sp) (i32.const 1)))
- (call $maybe-grow-ret-stack)
- (table.set $ret-stack
- (i32.sub (global.get $ret-sp) (i32.const 1))
- (struct.get $dynprompt $handler
- (local.get $prompt)))
- (throw $trampoline-tag
- (i32.const 3)
- (global.get $apply-primitive)
- (global.get $values-primitive)
- (struct.new $pair (i32.const 0)
- (local.get $cont)
- (local.get $args))
- (struct.get $proc $func
- (ref.cast $proc
- (global.get $apply-primitive)))
- (i32.const 1))))
- ;; Something else is on the stack; what is it?
- (if (ref.test $dynwind (local.get $dyn))
- (then
- (local.set $dynwind (ref.cast $dynwind (local.get $dyn)))
- (global.set $scm-sp (i32.add (global.get $scm-sp) (i32.const 3)))
- (global.set $ret-sp (i32.add (global.get $ret-sp) (i32.const 1)))
- (call $maybe-grow-scm-stack)
- (call $maybe-grow-ret-stack)
- (table.set $scm-stack
- (i32.sub (global.get $scm-sp) (i32.const 3))
- (local.get $tag))
- (table.set $scm-stack
- (i32.sub (global.get $scm-sp) (i32.const 2))
- (local.get $cont))
- (table.set $scm-stack
- (i32.sub (global.get $scm-sp) (i32.const 1))
- (local.get $args))
- (table.set $ret-stack
- (i32.sub (global.get $ret-sp) (i32.const 1))
- (ref.func $keep-unwinding))
- (return_call_ref $kvarargs
- (i32.const 1)
- (struct.get $dynwind $unwind
- (local.get $dynwind))
- (ref.i31 (i32.const 0))
- (ref.i31 (i32.const 0))
- (struct.get
- $proc $func
- (struct.get $dynwind $unwind
- (local.get $dynwind))))))
- (br_if $lp (ref.test $dynprompt (local.get $dyn)))
- (if (ref.test $dynfluid (local.get $dyn))
- (then
- (call $wind-dynfluid (ref.cast $dynfluid (local.get $dyn)))
- (br $lp)))
- (if (ref.test $dynstate (local.get $dyn))
- (then
- (call $wind-dynstate (ref.cast $dynstate (local.get $dyn)))
- (br $lp)))
- (unreachable)))
- (func $abort-to-prompt (param $nargs i32) (param $arg0 (ref eq))
- (param $arg1 (ref eq)) (param $arg2 (ref eq))
- (if (i32.lt_u (local.get $nargs) (i32.const 2))
- (then
- (return_call $raise-arity-error
- (string.const "abort-to-prompt")
- (global.get $abort-to-prompt-primitive))))
- ;; $arg0 is the closure, $arg1 is tag, and the values are in
- ;; $arg2 and up, which we collect to a rest list.
- (return_call $unwind-to-prompt (local.get $arg1)
- (call $capture-continuation
- (call $find-prompt (local.get $arg1)))
- (call $collect-rest-args (local.get $nargs)
- (local.get $arg0)
- (local.get $arg1)
- (local.get $arg2)
- (i32.const 2))))
- (global $abort-to-prompt-primitive (ref eq)
- (struct.new $proc (i32.const 0) (ref.func $abort-to-prompt)))
- (func $maybe-grow-argv (param $size i32)
- (local $diff i32)
- (local.set $diff (i32.sub (local.get $size)
- (table.size $argv)))
- (if (i32.gt_s (local.get $diff) (i32.const 0))
- (then
- (table.grow $argv
- (ref.null eq)
- (local.get $diff))
- (drop))))
- (func $compute-npositional/kwargs (param $nargs i32)
- (param $arg0 (ref eq))
- (param $arg1 (ref eq))
- (param $arg2 (ref eq))
- (param $nreq i32)
- (result i32)
- (local $npos i32)
- (local.set $npos (local.get $nreq))
- (loop $lp
- (if (i32.lt_u (local.get $npos) (local.get $nargs))
- (then
- (if (i32.eqz
- (ref.test $keyword
- (call $arg-ref
- (local.get $npos)
- (local.get $arg0)
- (local.get $arg1)
- (local.get $arg2))))
- (then
- (local.set $npos
- (i32.add (local.get $npos) (i32.const 1)))
- (br $lp))))))
- (local.get $npos))
- (func $keyword->idx (param $kw (ref eq))
- (param $all-kws (ref eq))
- (result i32)
- (local $idx i32)
- (local $pair (ref $pair))
- (loop $lp
- (if (ref.test $pair (local.get $all-kws))
- (then
- (if (ref.eq (struct.get
- $pair $car
- (ref.cast $pair (local.get $all-kws)))
- (local.get $kw))
- (then (return (local.get $idx))))
- (local.set $all-kws
- (struct.get
- $pair $cdr
- (ref.cast $pair (local.get $all-kws))))
- (local.set $idx
- (i32.add (i32.const 1) (local.get $idx)))
- (br $lp))))
- (i32.const -1))
- (func $arg-ref (param $n i32)
- (param $arg0 (ref eq))
- (param $arg1 (ref eq))
- (param $arg2 (ref eq))
- (result (ref eq))
- (block
- $n0
- (block
- $n1
- (block
- $n2
- (block
- $n3
- (block
- $n4
- (block
- $n5
- (block
- $n6
- (block
- $n7
- (block
- $nv
- (br_table $n0
- $n1
- $n2
- $n3
- $n4
- $n5
- $n6
- $n7
- $nv
- (local.get $n)))
- (return (ref.as_non_null
- (table.get $argv (i32.sub (local.get $n) (i32.const 8))))))
- (return (global.get $arg7)))
- (return (global.get $arg6)))
- (return (global.get $arg5)))
- (return (global.get $arg4)))
- (return (global.get $arg3)))
- (return (local.get $arg2)))
- (return (local.get $arg1)))
- (return (local.get $arg0)))
- (func $collect-apply-args
- (param $nargs i32) (param $arg2 (ref eq))
- (result (ref eq))
- (local $ret (ref eq))
- (if (i32.le_u (local.get $nargs) (i32.const 3))
- (then
- (call $die0 (string.const "bad collect-apply-args call"))
- (unreachable)))
- (local.set $ret
- (call $arg-ref
- (local.tee $nargs
- (i32.sub (local.get $nargs)
- (i32.const 1)))
- (ref.i31 (i32.const 1))
- (ref.i31 (i32.const 1))
- (local.get $arg2)))
- (loop $lp
- (if (i32.le_u (i32.const 3) (local.get $nargs))
- (then
- (local.set $ret
- (struct.new
- $pair
- (i32.const 0)
- (call $arg-ref
- (local.tee $nargs
- (i32.sub (local.get $nargs)
- (i32.const 1)))
- (ref.i31 (i32.const 1))
- (ref.i31 (i32.const 1))
- (local.get $arg2))
- (local.get $ret)))
- (br $lp))))
- (local.get $ret))
- (func $apply-to-non-list (param $tail (ref eq))
- (call $raise-runtime-error-with-message+irritants
- (string.const "apply to non-list")
- (struct.new $pair
- (i32.const 0)
- (local.get $tail)
- (ref.i31 (i32.const 13)))))
- (func $get-callee-code (param $callee (ref eq)) (result (ref $kvarargs))
- (call $die (string.const "$get-callee-code") (local.get $callee))
- (unreachable))
- (func $apply (param $nargs i32) (param $arg0 (ref eq))
- (param $arg1 (ref eq)) (param $arg2 (ref eq))
- (local $args (ref eq))
- (if (i32.lt_u (local.get $nargs) (i32.const 3))
- (then
- (return_call $raise-arity-error
- (string.const "apply")
- (global.get $apply-primitive))))
- (local.set $arg0 (local.get $arg1))
- (local.set $args
- (if (ref eq)
- (i32.eq (local.get $nargs) (i32.const 3))
- (then (local.get $arg2))
- (else (call $collect-apply-args
- (local.get $nargs)
- (local.get $arg2)))))
- (if
- (ref.test $pair (local.get $args))
- (then
- (local.set $arg1
- (struct.get $pair $car
- (ref.cast $pair (local.get $args))))
- (if
- (ref.test
- $pair
- (local.tee $args
- (struct.get $pair $cdr
- (ref.cast $pair (local.get $args)))))
- (then
- (local.set $arg2
- (struct.get $pair $car
- (ref.cast $pair (local.get $args))))
- (if
- (ref.test
- $pair
- (local.tee $args
- (struct.get $pair $cdr
- (ref.cast $pair (local.get $args)))))
- (then
- (global.set $arg3
- (struct.get $pair $car
- (ref.cast $pair (local.get $args))))
- (if
- (ref.test
- $pair
- (local.tee $args
- (struct.get $pair $cdr
- (ref.cast $pair (local.get $args)))))
- (then
- (global.set $arg4
- (struct.get $pair $car
- (ref.cast $pair (local.get $args))))
- (if
- (ref.test
- $pair
- (local.tee $args
- (struct.get $pair $cdr
- (ref.cast $pair (local.get $args)))))
- (then
- (global.set $arg5
- (struct.get $pair $car
- (ref.cast $pair (local.get $args))))
- (if
- (ref.test
- $pair
- (local.tee $args
- (struct.get $pair $cdr
- (ref.cast $pair (local.get $args)))))
- (then
- (global.set $arg6
- (struct.get $pair $car
- (ref.cast $pair (local.get $args))))
- (if
- (ref.test
- $pair
- (local.tee $args
- (struct.get $pair $cdr
- (ref.cast $pair (local.get $args)))))
- (then
- (global.set $arg7
- (struct.get $pair $car
- (ref.cast $pair (local.get $args))))
- (local.set $nargs (i32.const 8))
- (loop $lp
- (if
- (ref.test
- $pair
- (local.tee $args
- (struct.get $pair $cdr
- (ref.cast $pair (local.get $args)))))
- (then
- (if (i32.lt_u (table.size $argv)
- (i32.sub (local.get $nargs) (i32.const 7)))
- (then
- (table.grow $argv
- (struct.get $pair $car
- (ref.cast $pair (local.get $args)))
- (i32.const 1))
- (drop))
- (else
- (table.set $argv
- (i32.sub (local.get $nargs) (i32.const 8))
- (struct.get $pair $car
- (ref.cast $pair (local.get $args))))))
- (local.set $nargs (i32.add (local.get $nargs) (i32.const 1)))
- (br $lp)))))
- (else (local.set $nargs (i32.const 7)))))
- (else (local.set $nargs (i32.const 6)))))
- (else (local.set $nargs (i32.const 5)))))
- (else (local.set $nargs (i32.const 4)))))
- (else (local.set $nargs (i32.const 3)))))
- (else (local.set $nargs (i32.const 2)))))
- (else (local.set $nargs (i32.const 1))))
- (if (i32.eqz (ref.eq (local.get $args) (ref.i31 (i32.const 13))))
- (then (return_call $apply-to-non-list (local.get $args))))
- (return_call_ref $kvarargs
- (local.get $nargs)
- (local.get $arg0)
- (local.get $arg1)
- (local.get $arg2)
- (if (ref $kvarargs)
- (ref.test $proc (local.get $arg0))
- (then (struct.get $proc $func
- (ref.cast $proc (local.get $arg0))))
- (else (call $get-callee-code (local.get $arg0))))))
- (global $apply-primitive (ref eq)
- (struct.new $proc (i32.const 0) (ref.func $apply)))
- ;; Helper function for $f64->exact
- (func $decode-f64 (param $frac i64) (param $expt i32) (param $sign i32)
- (result (ref eq))
- (if (i32.eq (local.get $sign) (i32.const 1))
- (then (local.set $frac (i64.mul (local.get $frac) (i64.const -1)))))
- (if (ref eq)
- (i32.lt_s (local.get $expt) (i32.const 0))
- ;; divide $frac by 1/(2**|expt|)
- (then
- (call $div
- (call $s64->bignum (local.get $frac))
- (call $lsh
- (call $i32->fixnum (i32.const 2))
- (i64.mul (i64.const -1)
- (i64.extend_i32_s
- (i32.add
- (local.get $expt)
- (i32.const 1)))))))
- ;; multiply $frac by 2**expt
- (else
- (call $mul
- (call $s64->bignum (local.get $frac))
- (call $lsh
- (call $i32->fixnum (i32.const 2))
- (i64.extend_i32_s
- (i32.add (local.get $expt)
- (i32.const 1))))))))
- ;; Callers must ensure that the argument is a rational float (not
- ;; an infinity or NaN).
- ;; TODO: Optimize for conversion of $X to an integer.
- ;; (at least when it can be represeted with an i32 or i64).
- (func $f64->exact (param $x f64) (result (ref eq))
- (local $bits i64)
- (local $raw-frac i64) ; raw significand
- (local $frac i64) ; decoded significand
- (local $raw-expt i32) ; biased exponent
- (local $expt i32) ; actual exponent
- (local $sign i32)
- ;; Split $X into three parts:
- ;; - the fraction [Knuth] or significand (52 bits, with an
- ;; implicit leading 1 bit),
- ;; - the exponent (with an offset of 1023; here, since we
- ;; represent the significand as an integer, the offset is
- ;; increased by 52 bits to 1075),
- ;; - and a sign bit.
- ;; Special cases:
- ;; (a) E = 0, F = 0 => (signed) zero;
- ;; (b) E = 0, F /= 0 => subnormal: interpret F as
- ;; non-normalized with an exponent of -1074;
- ;; (c) E = #x7FF, F = 0 => (signed) infinity;
- ;; (d) E = #x7FF, F /= 0 => NaN.
- ;; Otherwise, $X represents (1+F)*(2**(E-1023)).
- (local.set $bits (i64.reinterpret_f64 (local.get $x)))
- (local.set $raw-frac
- (i64.and (local.get $bits)
- (i64.const #xFFFFFFFFFFFFF)))
- (local.set $raw-expt
- (i32.wrap_i64
- (i64.and (i64.shr_u (local.get $bits) (i64.const 52))
- (i64.const #x7FF))))
- (local.set $sign (i32.wrap_i64
- (i64.shr_u (local.get $bits) (i64.const 63))))
- (if (ref eq)
- (i32.and (i32.eqz (local.get $raw-expt))
- (i64.eqz (local.get $raw-frac)))
- (then ; zero (E = 0, F = 0)
- (call $i32->fixnum (i32.const 0)))
- (else
- (if (ref eq)
- (i32.eqz (local.get $raw-expt))
- (then ; subnormal (E = 0, F /= 0)
- (local.set $frac (local.get $raw-frac))
- (local.set $expt (i32.const -1074))
- (call $decode-f64
- (local.get $frac)
- (local.get $expt)
- (local.get $sign)))
- (else
- (if (ref eq)
- (i32.eqz (i32.eq (local.get $raw-expt)
- (i32.const #x7FF)))
- (then ; normal (E /= 0, F /= #xFF)
- ;; set "hidden" bit of significand
- (local.set $frac
- (i64.or (local.get $raw-frac)
- (i64.const ,(ash 1 52))))
- (local.set $expt
- (i32.sub (local.get $raw-expt)
- (i32.const 1075)))
- (call $decode-f64
- (local.get $frac)
- (local.get $expt)
- (local.get $sign)))
- (else ; nonrational (inf or NaN)
- (call $die
- (string.const "$decode-float bad arg")
- (struct.new $flonum
- (i32.const 0)
- (local.get $x)))
- (unreachable))))))))
- (func $slow-< (param $a (ref eq)) (param $b (ref eq)) (result i32)
- ,(arith-cond
- 'i32
- `((call $fixnum? (local.get $a))
- ,(arith-cond
- 'i32
- `((call $fixnum? (local.get $b))
- (i32.lt_s (i31.get_s (ref.cast i31 (local.get $a)))
- (i31.get_s (ref.cast i31 (local.get $b)))))
- `((ref.test $bignum (local.get $b))
- (call $lt-fix-big
- (call $fixnum->i32 (ref.cast i31 (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
- `((ref.test $flonum (local.get $b))
- (f64.lt (call $fixnum->f64 (ref.cast i31 (local.get $a)))
- (call $flonum->f64 (ref.cast $flonum (local.get $b)))))
- `((ref.test $fraction (local.get $b))
- (call $slow-<
- (call $mul
- (local.get $a)
- (struct.get $fraction $denom
- (ref.cast $fraction (local.get $b))))
- (struct.get $fraction $num
- (ref.cast $fraction (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "<")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- 'i32
- `((call $fixnum? (local.get $b))
- (call $lt-big-fix
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (call $fixnum->i32 (ref.cast i31 (local.get $b)))))
- `((ref.test $bignum (local.get $b))
- (call $lt-big-big
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
- `((ref.test $flonum (local.get $b))
- (call $lt-big-flo
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (struct.get $flonum $val (ref.cast $flonum (local.get $b)))))
- `((ref.test $fraction (local.get $b))
- (call $slow-<
- (call $mul
- (local.get $a)
- (struct.get $fraction $denom
- (ref.cast $fraction (local.get $b))))
- (struct.get $fraction $num
- (ref.cast $fraction (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "<")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $flonum (local.get $a))
- ,(arith-cond
- 'i32
- `((call $fixnum? (local.get $b))
- (f64.lt (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
- (call $fixnum->f64 (ref.cast i31 (local.get $b)))))
- `((ref.test $bignum (local.get $b))
- (call $lt-flo-big
- (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
- `((ref.test $flonum (local.get $b))
- (f64.lt (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
- (struct.get $flonum $val (ref.cast $flonum (local.get $b)))))
- `((ref.test $fraction (local.get $b))
- ,(arith-cond
- 'i32
- '((call $f64-is-nan
- (call $flonum->f64
- (ref.cast $flonum (local.get $a))))
- (i32.const 0))
- '((call $f64-is-infinite
- (call $flonum->f64
- (ref.cast $flonum (local.get $a))))
- (f64.lt (call $flonum->f64
- (ref.cast $flonum (local.get $a)))
- (f64.const 0)))
- '(else
- (call $slow-<
- (call $f64->exact (call $flonum->f64 (ref.cast $flonum (local.get $a))))
- (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "<")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $fraction (local.get $a))
- ,(arith-cond
- 'i32
- `((i32.or (call $fixnum? (local.get $b))
- (i32.or (ref.test $bignum (local.get $b))
- (ref.test $fraction (local.get $b))))
- (call $slow-<
- (struct.get $fraction $num
- (ref.cast $fraction (local.get $a)))
- (call $mul
- (local.get $b)
- (struct.get $fraction $denom
- (ref.cast $fraction (local.get $a))))))
- `((ref.test $flonum (local.get $b))
- ,(arith-cond
- 'i32
- '((call $f64-is-nan
- (call $flonum->f64
- (ref.cast $flonum (local.get $b))))
- (i32.const 0))
- '((call $f64-is-infinite
- (call $flonum->f64
- (ref.cast $flonum (local.get $b))))
- (f64.lt (f64.const 0)
- (call $flonum->f64
- (ref.cast $flonum (local.get $b)))))
- '(else
- (call $slow-<
- (local.get $a)
- (call $f64->exact
- (call $flonum->f64
- (ref.cast $flonum (local.get $b))))))))
- '(else
- (call $raise-type-error
- (string.const "<")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- '(else
- (call $raise-type-error
- (string.const "<")
- (string.const "a")
- (local.get $a))
- (unreachable))))
- (func $slow-<= (param $a (ref eq)) (param $b (ref eq)) (result i32)
- ,(arith-cond
- 'i32
- `((call $fixnum? (local.get $a))
- ,(arith-cond
- 'i32
- `((call $fixnum? (local.get $b))
- (i32.le_s (i31.get_s (ref.cast i31 (local.get $a)))
- (i31.get_s (ref.cast i31 (local.get $b)))))
- `((ref.test $bignum (local.get $b))
- (call $le-fix-big
- (call $fixnum->i32 (ref.cast i31 (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
- `((ref.test $flonum (local.get $b))
- (f64.le (call $fixnum->f64 (ref.cast i31 (local.get $a)))
- (call $flonum->f64 (ref.cast $flonum (local.get $b)))))
- `((ref.test $fraction (local.get $b))
- (call $slow-<=
- (call $mul
- (local.get $a)
- (struct.get $fraction $denom
- (ref.cast $fraction (local.get $b))))
- (struct.get $fraction $num
- (ref.cast $fraction (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "<=")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- 'i32
- `((call $fixnum? (local.get $b))
- (call $le-big-fix
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (call $fixnum->i32 (ref.cast i31 (local.get $b)))))
- `((ref.test $bignum (local.get $b))
- (call $le-big-big
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
- `((ref.test $flonum (local.get $b))
- (call $le-big-flo
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (struct.get $flonum $val (ref.cast $flonum (local.get $b)))))
- `((ref.test $fraction (local.get $b))
- (call $slow-<=
- (call $mul
- (local.get $a)
- (struct.get $fraction $denom
- (ref.cast $fraction (local.get $b))))
- (struct.get $fraction $num
- (ref.cast $fraction (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "<=")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $flonum (local.get $a))
- ,(arith-cond
- 'i32
- `((call $fixnum? (local.get $b))
- (f64.le (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
- (call $fixnum->f64 (ref.cast i31 (local.get $b)))))
- `((ref.test $bignum (local.get $b))
- (call $le-flo-big
- (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
- `((ref.test $flonum (local.get $b))
- (f64.le (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
- (struct.get $flonum $val (ref.cast $flonum (local.get $b)))))
- `((ref.test $fraction (local.get $b))
- ,(arith-cond
- 'i32
- '((call $f64-is-nan
- (call $flonum->f64
- (ref.cast $flonum (local.get $a))))
- (i32.const 0))
- '((call $f64-is-infinite
- (call $flonum->f64
- (ref.cast $flonum (local.get $a))))
- (f64.lt (call $flonum->f64
- (ref.cast $flonum (local.get $a)))
- (f64.const 0)))
- '(else
- (call $slow-<=
- (call $f64->exact (call $flonum->f64 (ref.cast $flonum (local.get $a))))
- (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "<=")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $fraction (local.get $a))
- ,(arith-cond
- 'i32
- `((i32.or (call $fixnum? (local.get $b))
- (i32.or (ref.test $bignum (local.get $b))
- (ref.test $fraction (local.get $b))))
- (call $slow-<=
- (struct.get $fraction $num
- (ref.cast $fraction (local.get $a)))
- (call $mul
- (local.get $b)
- (struct.get $fraction $denom
- (ref.cast $fraction (local.get $a))))))
- `((ref.test $flonum (local.get $b))
- ,(arith-cond
- 'i32
- '((call $f64-is-nan
- (call $flonum->f64
- (ref.cast $flonum (local.get $b))))
- (i32.const 0))
- '((call $f64-is-infinite
- (call $flonum->f64
- (ref.cast $flonum (local.get $b))))
- (f64.le (f64.const 0)
- (call $flonum->f64
- (ref.cast $flonum (local.get $b)))))
- '(else
- (call $slow-<=
- (local.get $a)
- (call $f64->exact (call $flonum->f64 (ref.cast $flonum (local.get $b))))))))
- '(else
- (call $raise-type-error
- (string.const "<=")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- '(else
- (call $raise-type-error
- (string.const "<=")
- (string.const "a")
- (local.get $a))
- (unreachable))))
- (func $slow-= (param $a (ref eq)) (param $b (ref eq)) (result i32)
- ,(arith-cond
- 'i32
- `((call $fixnum? (local.get $a))
- ,(arith-cond
- 'i32
- `((call $fixnum? (local.get $b))
- (i32.eq (i31.get_s (ref.cast i31 (local.get $a)))
- (i31.get_s (ref.cast i31 (local.get $b)))))
- `((ref.test $bignum (local.get $b))
- (call $eq-fix-big
- (call $fixnum->i32 (ref.cast i31 (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
- `((ref.test $flonum (local.get $b))
- (f64.eq (call $fixnum->f64 (ref.cast i31 (local.get $a)))
- (call $flonum->f64 (ref.cast $flonum (local.get $b)))))
- `((ref.test $fraction (local.get $b))
- (call $slow-=
- (call $mul
- (local.get $a)
- (struct.get $fraction $denom
- (ref.cast $fraction (local.get $b))))
- (struct.get $fraction $num
- (ref.cast $fraction (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "=")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- 'i32
- `((call $fixnum? (local.get $b))
- (call $eq-big-fix
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (call $fixnum->i32 (ref.cast i31 (local.get $b)))))
- `((ref.test $bignum (local.get $b))
- (call $eq-big-big
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
- `((ref.test $flonum (local.get $b))
- (call $eq-big-flo
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (struct.get $flonum $val (ref.cast $flonum (local.get $b)))))
- `((ref.test $fraction (local.get $b))
- (call $slow-=
- (call $mul
- (local.get $a)
- (struct.get $fraction $denom
- (ref.cast $fraction (local.get $b))))
- (struct.get $fraction $num
- (ref.cast $fraction (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "=")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $flonum (local.get $a))
- ,(arith-cond
- 'i32
- `((call $fixnum? (local.get $b))
- (f64.eq (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
- (call $fixnum->f64 (ref.cast i31 (local.get $b)))))
- `((ref.test $bignum (local.get $b))
- (call $eq-flo-big
- (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
- `((ref.test $flonum (local.get $b))
- (f64.eq (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
- (struct.get $flonum $val (ref.cast $flonum (local.get $b)))))
- `((ref.test $fraction (local.get $b))
- ,(arith-cond
- 'i32
- '((call $f64-is-nan
- (call $flonum->f64
- (ref.cast $flonum (local.get $a))))
- (i32.const 0))
- '((call $f64-is-infinite
- (call $flonum->f64
- (ref.cast $flonum (local.get $a))))
- (f64.eq (call $flonum->f64
- (ref.cast $flonum (local.get $a)))
- (f64.const 0)))
- '(else
- (call $slow-=
- (call $f64->exact (call $flonum->f64 (ref.cast $flonum (local.get $a))))
- (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "=")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $fraction (local.get $a))
- ,(arith-cond
- 'i32
- `((i32.or (call $fixnum? (local.get $b))
- (i32.or (ref.test $bignum (local.get $b))
- (ref.test $fraction (local.get $b))))
- (call $slow-=
- (struct.get $fraction $num
- (ref.cast $fraction (local.get $a)))
- (call $mul
- (local.get $b)
- (struct.get $fraction $denom
- (ref.cast $fraction (local.get $a))))))
- `((ref.test $flonum (local.get $b))
- ,(arith-cond
- 'i32
- '((call $f64-is-nan
- (call $flonum->f64
- (ref.cast $flonum (local.get $b))))
- (i32.const 0))
- '((call $f64-is-infinite
- (call $flonum->f64
- (ref.cast $flonum (local.get $b))))
- (f64.eq (f64.const 0)
- (call $flonum->f64
- (ref.cast $flonum (local.get $b)))))
- '(else
- (call $slow-=
- (local.get $a)
- (call $f64->exact (call $flonum->f64 (ref.cast $flonum (local.get $b))))))))
- '(else
- (call $raise-type-error
- (string.const "=")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- '(else
- (call $raise-type-error
- (string.const "=")
- (string.const "a")
- (local.get $a))
- (unreachable))))
- (func $heap-numbers-equal? (param $a (ref eq)) (param $b (ref eq))
- (result i32)
- ,(arith-cond
- 'i32
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- 'i32
- `((ref.test $bignum (local.get $b))
- (call $eq-big-big
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
- '(else
- (i32.const 0))))
- `((ref.test $flonum (local.get $a))
- ,(arith-cond
- 'i32
- `((ref.test $flonum (local.get $b))
- (i32.or
- (i32.and (call $f64-is-nan (struct.get $flonum $val (ref.cast $flonum (local.get $a))))
- (call $f64-is-nan (struct.get $flonum $val (ref.cast $flonum (local.get $a)))))
- (f64.eq (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
- (struct.get $flonum $val (ref.cast $flonum (local.get $b))))))
- '(else
- (i32.const 0))))
- `((ref.test $fraction (local.get $a))
- ,(arith-cond
- 'i32
- `((ref.test $fraction (local.get $b))
- (i32.and
- (call $slow-=
- (struct.get $fraction $num
- (ref.cast $fraction (local.get $a)))
- (struct.get $fraction $num
- (ref.cast $fraction (local.get $b))))
- (call $slow-=
- (struct.get $fraction $denom
- (ref.cast $fraction (local.get $a)))
- (struct.get $fraction $denom
- (ref.cast $fraction (local.get $b))))))
- '(else
- (i32.const 0))))))
- (func $string-set! (param $str (ref $string)) (param $idx i32)
- (param $ch i32)
- (call $die0 (string.const "$string-set!")) (unreachable))
- ;; cf. compile-test in (hoot compile)
- (func $fixnum? (param $a (ref eq)) (result i32)
- (if (result i32)
- (ref.test i31 (local.get $a))
- (then (i32.eqz
- (i32.and (i31.get_s (ref.cast i31 (local.get $a)))
- (i32.const #b1))))
- (else (i32.const 0))))
- (func $fixnum->i32 (param $a (ref i31)) (result i32)
- (i32.shr_s (i31.get_s (local.get $a)) (i32.const 1)))
- (func $fixnum->i64 (param $a (ref i31)) (result i64)
- (i64.extend_i32_s (call $fixnum->i32 (local.get $a))))
- (func $fixnum->f64 (param $a (ref i31)) (result f64)
- (f64.convert_i32_s (call $fixnum->i32 (local.get $a))))
- (func $flonum->f64 (param $a (ref $flonum)) (result f64)
- (struct.get $flonum $val (local.get $a)))
- (func $i32->fixnum (param $a i32) (result (ref i31))
- (ref.i31 (i32.shl (local.get $a) (i32.const 1))))
- (func $i32->bignum (param $a i32) (result (ref eq))
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i64
- (i64.extend_i32_s (local.get $a)))))
- (func $bignum->f64 (param $a (ref $bignum)) (result f64)
- (call $bignum-to-f64 (struct.get $bignum $val (local.get $a))))
- (func $f64-integer? (param $a f64) (result i32)
- ;; Adapted from the f64-int test in (hoot compile). The
- ;; subtraction here detects infinities: (f64.trunc ±inf.0)
- ;; returns an infinity, and the subtraction then produces a
- ;; NaN. (This also detects NaNs correctly, as (f64.trunc
- ;; +nan.0) returns a NaN.)
- (f64.eq
- (f64.sub
- (f64.trunc (local.get $a))
- (local.get $a))
- (f64.const 0)))
- ;; Callers must check that $A is an integer.
- (func $f64->integer (param $a f64) (result (ref eq))
- (call $f64->exact (local.get $a)))
- (func $flonum-integer? (param $a (ref eq)) (result i32)
- (call $f64-integer?
- (struct.get $flonum $val
- (ref.cast $flonum (local.get $a)))))
- ;; Callers must check that $A is an integer.
- (func $flonum->integer (param $a (ref eq)) (result (ref eq))
- (call $f64->integer
- (struct.get $flonum $val
- (ref.cast $flonum (local.get $a)))))
- (func $scm->f64 (param $a (ref eq)) (result f64)
- ,(arith-cond 'f64
- '((call $fixnum? (local.get $a))
- (call $fixnum->f64 (ref.cast i31 (local.get $a))))
- '((ref.test $bignum (local.get $a))
- (call $bignum->f64 (ref.cast $bignum (local.get $a))))
- '((ref.test $flonum (local.get $a))
- (struct.get $flonum $val (ref.cast $flonum (local.get $a))))
- '((ref.test $fraction (local.get $a))
- (struct.get
- $flonum $val
- (ref.cast
- $flonum
- (call $div
- (call $inexact
- (struct.get $fraction $num
- (ref.cast $fraction
- (local.get $a))))
- (call $inexact
- (struct.get $fraction $num
- (ref.cast $fraction
- (local.get $a))))))))))
- (func $numeric-eqv? (param $a (ref eq)) (param $b (ref eq)) (result i32)
- ,(arith-cond 'i32
- `((call $fixnum? (local.get $a))
- ,(arith-cond 'i32
- '((call $fixnum? (local.get $b))
- (i32.eq (i31.get_s (ref.cast i31 (local.get $a)))
- (i31.get_s (ref.cast i31 (local.get $b)))))
- '((ref.test $bignum (local.get $b))
- (i32.const 0))
- '((ref.test $flonum (local.get $b))
- (i32.const 0))
- '((ref.test $fraction (local.get $b))
- (i32.const 0))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond 'i32
- '((call $fixnum? (local.get $b))
- (i32.const 0))
- '((ref.test $bignum (local.get $b))
- (call $eq-big-big
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))
- '((ref.test $flonum (local.get $b))
- (i32.const 0))
- '((ref.test $fraction (local.get $b))
- (i32.const 0))))
- `((ref.test $flonum (local.get $a))
- ,(arith-cond 'i32
- '((call $fixnum? (local.get $b))
- (i32.const 0))
- '((ref.test $bignum (local.get $b))
- (i32.const 0))
- '((ref.test $flonum (local.get $b))
- (f64.eq (struct.get $flonum $val (ref.cast $flonum (local.get $a)))
- (struct.get $flonum $val (ref.cast $flonum (local.get $b)))))
- '((ref.test $fraction (local.get $b))
- (i32.const 0))))
- `((ref.test $fraction (local.get $a))
- ,(arith-cond 'i32
- '((call $fixnum? (local.get $b))
- (i32.const 0))
- '((ref.test $bignum (local.get $b))
- (i32.const 0))
- '((ref.test $flonum (local.get $b))
- (i32.const 0))
- '((ref.test $fraction (local.get $b))
- (i32.and (call $numeric-eqv?
- (struct.get $fraction $num (ref.cast $fraction (local.get $a)))
- (struct.get $fraction $num (ref.cast $fraction (local.get $b))))
- (call $numeric-eqv?
- (struct.get $fraction $denom (ref.cast $fraction (local.get $a)))
- (struct.get $fraction $denom (ref.cast $fraction (local.get $b))))))))))
- (func $negative-integer? (param $a (ref eq)) (result i32)
- ,(arith-cond 'i32
- '((call $fixnum? (local.get $a))
- (if (result i32)
- (i32.ge_s (call $fixnum->i32
- (ref.cast i31 (local.get $a)))
- (i32.const 0))
- (then (i32.const 0))
- (else (i32.const 1))))
- `((ref.test $bignum (local.get $a))
- (if (result i32)
- (f64.ge (call $bignum->f64
- (ref.cast $bignum (local.get $a)))
- (f64.const 0))
- (then (i32.const 0))
- (else (i32.const 1))))))
- ;; TODO: write tests once `fixnum?' or similar is available
- (func $normalize-bignum (param $a (ref $bignum)) (result (ref eq))
- (local $a-val (ref extern))
- (local $a64 i64)
- (local.set $a-val (struct.get $bignum $val (local.get $a)))
- (if (ref eq)
- (call $bignum-is-i64 (local.get $a-val))
- (then (local.set $a64 (call $bignum-get-i64 (local.get $a-val)))
- (if (ref eq)
- (i32.and (i64.le_s (i64.const #x-20000000)
- (local.get $a64))
- (i64.le_s (local.get $a64)
- (i64.const #x1FFFFFFF)))
- (then (ref.i31
- (i32.shl
- (i32.wrap_i64 (local.get $a64))
- (i32.const 1))))
- (else (local.get $a))))
- (else (local.get $a))))
- (func $normalize-fraction (param $a (ref $fraction)) (result (ref eq))
- (if (call $numeric-eqv?
- (struct.get $fraction $denom (local.get $a))
- (ref.i31 (i32.const 0)))
- (then
- (call $raise-runtime-error-with-message
- (string.const "division by zero"))))
- (if (call $negative-integer? (struct.get $fraction $denom (local.get $a)))
- (then (local.set $a
- (struct.new $fraction
- (i32.const 0)
- (call $mul
- (struct.get $fraction $num (local.get $a))
- (call $i32->fixnum (i32.const -1)))
- (call $mul
- (struct.get $fraction $denom (local.get $a))
- (call $i32->fixnum (i32.const -1)))))))
- (if (ref eq)
- (call $numeric-eqv?
- (struct.get $fraction $denom (local.get $a))
- (ref.i31 (i32.const #b10)))
- (then (struct.get $fraction $num (local.get $a)))
- (else (local.get $a))))
- (func $normalize-fraction/gcd (param $a (ref $fraction)) (result (ref eq))
- (local $d (ref eq))
- (local.set $d (call $gcd
- (struct.get $fraction $num (local.get $a))
- (struct.get $fraction $denom (local.get $a))))
- (call $normalize-fraction
- (struct.new $fraction
- (i32.const 0)
- (call $quo (struct.get $fraction $num (local.get $a)) (local.get $d))
- (call $quo (struct.get $fraction $denom (local.get $a)) (local.get $d)))))
- ;; Greatest common divisor: v. TAOCP II 4.5.2 Algorithm A (modern
- ;; Euclidean algorithm). TODO: use a modernized version of
- ;; Algorithm B
- (func $gcd (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
- ,(arith-cond
- `((call $fixnum? (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (call $i32->fixnum
- (call $gcd-i32
- (call $fixnum->i32 (ref.cast i31 (local.get $a)))
- (call $fixnum->i32 (ref.cast i31 (local.get $b))))))
- '((ref.test $bignum (local.get $b))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-gcd
- (call $bignum-from-i32
- (call $fixnum->i32
- (ref.cast i31 (local.get $a))))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-gcd
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (call $bignum-from-i32
- (call $fixnum->i32
- (ref.cast i31 (local.get $b))))))))
- '((ref.test $bignum (local.get $b))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-gcd
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))))))))
- (func $gcd-i32 (param $a i32) (param $b i32) (result i32)
- (local $r i32)
- ;; Ensure $a and $b are both positive
- (if (i32.lt_s (local.get $a) (i32.const 0))
- (then (local.set $a (i32.mul (local.get $a) (i32.const -1)))))
- (if (i32.lt_s (local.get $b) (i32.const 0))
- (then (local.set $b (i32.mul (local.get $b) (i32.const -1)))))
- (if (i32.eqz (local.get $a))
- (then (return (local.get $b))))
- (if (i32.eqz (local.get $b))
- (then (return (local.get $a))))
- (block $blk
- (loop $lp
- (br_if $blk (i32.eqz (local.get $b)))
- (local.set $r (i32.rem_u (local.get $a)
- (local.get $b)))
- (local.set $a (local.get $b))
- (local.set $b (local.get $r))
- (br $lp)))
- (return (local.get $a)))
- ;; The $A and $B parameters are 30-bit fixnums, with a zero LSB bit
- ;; as the fixnum tag. We examine the top three bits of the result:
- ;; if they're identical, no overflow has occurred and the result is
- ;; represented as a fixnum; otherwise, the result won't fit into a
- ;; fixnum and must be returned as a bignum.
- (func $fixnum-add (param $a i32) (param $b i32) (result (ref eq))
- (local $c i32)
- (local $d i32)
- (local.set $c (i32.add (local.get $a) (local.get $b)))
- (local.set $d (i32.shr_u (local.get $c) (i32.const 29)))
- (if (result (ref eq))
- (i32.or (i32.eqz (local.get $d))
- (i32.eq (local.get $d)
- (i32.const #b111)))
- (then (ref.i31 (local.get $c)))
- (else (call $i32->bignum (i32.shr_s (local.get $c) (i32.const 1))))))
- (func $fixnum-sub (param $a i32) (param $b i32) (result (ref eq))
- (local $c i32)
- (local $d i32)
- (local.set $c (i32.sub (local.get $a) (local.get $b)))
- (local.set $d (i32.shr_u (local.get $c) (i32.const 29)))
- (if (result (ref eq))
- (i32.or (i32.eqz (local.get $d))
- (i32.eq (local.get $d)
- (i32.const #b111)))
- (then (ref.i31 (local.get $c)))
- (else (call $i32->bignum (i32.shr_s (local.get $c) (i32.const 1))))))
- (func $fixnum-mul (param $a32 i32) (param $b32 i32) (result (ref eq))
- (local $a i64)
- (local $b i64)
- (local $c i64)
- ;; Shift off one operand's tag bit so that the result is also
- ;; properly tagged.
- (local.set $a (i64.extend_i32_s
- (i32.shr_s (local.get $a32) (i32.const 1))))
- (local.set $b (i64.extend_i32_s (local.get $b32)))
- (local.set $c (i64.mul (local.get $a) (local.get $b)))
- (if (result (ref eq))
- ;; Return a bignum if the (tagged) result lies outside of
- ;; [2^30-1, 2^30].
- (i32.and (i64.ge_s (local.get $c) (i64.const #x-40000000))
- (i64.le_s (local.get $c) (i64.const #x03FFFFFFF)))
- (then (ref.i31 (i32.wrap_i64 (local.get $c))))
- (else
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i64
- (i64.shr_s (local.get $c) (i64.const 1))))))))
- (func $fixnum-add* (param $a (ref i31)) (param $b (ref i31)) (result (ref eq))
- (call $fixnum-add
- (i31.get_s (local.get $a))
- (i31.get_s (local.get $b))))
- (func $fixnum-sub* (param $a (ref i31)) (param $b (ref i31)) (result (ref eq))
- (call $fixnum-sub
- (i31.get_s (local.get $a))
- (i31.get_s (local.get $b))))
- (func $fixnum-mul* (param $a (ref i31)) (param $b (ref i31)) (result (ref eq))
- (call $fixnum-mul
- (i31.get_s (local.get $a))
- (i31.get_s (local.get $b))))
- (func $bignum-add* (param $a (ref $bignum)) (param $b (ref $bignum)) (result (ref $bignum))
- (struct.new
- $bignum
- (i32.const 0)
- (call $bignum-add
- (struct.get $bignum $val (local.get $a))
- (struct.get $bignum $val (local.get $b)))))
- (func $bignum-sub* (param $a (ref $bignum)) (param $b (ref $bignum)) (result (ref $bignum))
- (struct.new
- $bignum
- (i32.const 0)
- (call $bignum-sub
- (struct.get $bignum $val (local.get $a))
- (struct.get $bignum $val (local.get $b)))))
- (func $bignum-mul* (param $a (ref $bignum)) (param $b (ref $bignum)) (result (ref $bignum))
- (struct.new
- $bignum
- (i32.const 0)
- (call $bignum-mul
- (struct.get $bignum $val (local.get $a))
- (struct.get $bignum $val (local.get $b)))))
- (func $bignum-quo* (param $a (ref $bignum)) (param $b (ref $bignum)) (result (ref $bignum))
- (struct.new
- $bignum
- (i32.const 0)
- (call $bignum-quo
- (struct.get $bignum $val (local.get $a))
- (struct.get $bignum $val (local.get $b)))))
- (func $bignum-rem* (param $a (ref $bignum)) (param $b (ref $bignum)) (result (ref $bignum))
- (struct.new
- $bignum
- (i32.const 0)
- (call $bignum-rem
- (struct.get $bignum $val (local.get $a))
- (struct.get $bignum $val (local.get $b)))))
- (func $bignum-mod* (param $a (ref $bignum)) (param $b (ref $bignum)) (result (ref $bignum))
- (struct.new
- $bignum
- (i32.const 0)
- (call $bignum-mod
- (struct.get $bignum $val (local.get $a))
- (struct.get $bignum $val (local.get $b)))))
- ;; Exact fraction arithmetic
- ;; Fraction addition
- (func $add-fracnum-fixnum (param $a (ref $fraction)) (param $b (ref i31)) (result (ref eq))
- (call $add-fracnum-fracnum
- (local.get $a)
- (struct.new $fraction
- (i32.const 0)
- (call $mul (local.get $b) (struct.get $fraction $denom (local.get $a)))
- (struct.get $fraction $denom (local.get $a)))))
- (func $add-fracnum-bignum (param $a (ref $fraction)) (param $b (ref $bignum)) (result (ref eq))
- (call $add-fracnum-fracnum
- (local.get $a)
- (struct.new $fraction
- (i32.const 0)
- (call $mul (local.get $b) (struct.get $fraction $denom (local.get $a)))
- (struct.get $fraction $denom (local.get $a)))))
- (func $add-fracnum-fracnum (param $a (ref $fraction)) (param $b (ref $fraction)) (result (ref eq))
- (local $d1 (ref eq))
- (local $d2 (ref eq))
- (local $t (ref eq))
- (local.set $d1 (call $gcd
- (struct.get $fraction $denom (local.get $a))
- (struct.get $fraction $denom (local.get $b))))
- (if (result (ref eq))
- (if (result i32)
- (call $fixnum? (local.get $d1))
- (then (i32.eq (i31.get_s (ref.cast i31 (local.get $d1)))
- (i32.const #b10)))
- (else (f64.eq (call $bignum->f64 (ref.cast $bignum (local.get $d1)))
- (f64.const 1))))
- (then
- (call $normalize-fraction
- (struct.new $fraction
- (i32.const 0)
- (call $add
- (call $mul
- (struct.get $fraction $num (local.get $a))
- (struct.get $fraction $denom (local.get $b)))
- (call $mul
- (struct.get $fraction $denom (local.get $a))
- (struct.get $fraction $num (local.get $b))))
- (call $mul
- (struct.get $fraction $denom (local.get $a))
- (struct.get $fraction $denom (local.get $b))))))
- (else
- (local.set $t
- (call $add
- (call $mul
- (struct.get $fraction $num (local.get $a))
- (call $quo
- (struct.get $fraction $denom (local.get $b))
- (local.get $d1)))
- (call $mul
- (struct.get $fraction $num (local.get $b))
- (call $quo
- (struct.get $fraction $denom (local.get $a))
- (local.get $d1)))))
- (local.set $d2 (call $gcd (local.get $t) (local.get $d1)))
- (call $normalize-fraction
- (struct.new $fraction
- (i32.const 0)
- (call $quo
- (local.get $t)
- (local.get $d2))
- (call $mul
- (call $quo
- (struct.get $fraction $denom (local.get $a))
- (local.get $d1))
- (call $quo
- (struct.get $fraction $denom (local.get $b))
- (local.get $d2))))))))
- ;; Fraction subtraction
- (func $sub-fixnum-fracnum (param $a (ref i31)) (param $b (ref $fraction)) (result (ref eq))
- (call $sub-fracnum-fracnum
- (struct.new $fraction
- (i32.const 0)
- (call $mul (local.get $a) (struct.get $fraction $denom (local.get $b)))
- (struct.get $fraction $denom (local.get $b)))
- (local.get $b)))
- (func $sub-bignum-fracnum (param $a (ref $bignum)) (param $b (ref $fraction)) (result (ref eq))
- (call $sub-fracnum-fracnum
- (struct.new $fraction
- (i32.const 0)
- (call $mul (local.get $a) (struct.get $fraction $denom (local.get $b)))
- (struct.get $fraction $denom (local.get $b)))
- (local.get $b)))
- (func $sub-fracnum-fixnum (param $a (ref $fraction)) (param $b (ref i31)) (result (ref eq))
- (call $sub-fracnum-fracnum
- (local.get $a)
- (struct.new $fraction
- (i32.const 0)
- (call $mul (local.get $b) (struct.get $fraction $denom (local.get $a)))
- (struct.get $fraction $denom (local.get $a)))))
- (func $sub-fracnum-bignum (param $a (ref $fraction)) (param $b (ref $bignum)) (result (ref eq))
- (call $sub-fracnum-fracnum
- (local.get $a)
- (struct.new $fraction
- (i32.const 0)
- (call $mul (local.get $b) (struct.get $fraction $denom (local.get $a)))
- (struct.get $fraction $denom (local.get $a)))))
- (func $sub-fracnum-fracnum (param $a (ref $fraction)) (param $b (ref $fraction)) (result (ref eq))
- (local $d1 (ref eq))
- (local $d2 (ref eq))
- (local $t (ref eq))
- (local.set $d1 (call $gcd
- (struct.get $fraction $denom (local.get $a))
- (struct.get $fraction $denom (local.get $b))))
- (if (result (ref eq))
- ;; FIXME: use generic =
- (if (result i32)
- (ref.test i31 (local.get $d1))
- (then (i32.eq (i31.get_s (ref.cast i31 (local.get $d1)))
- (i32.const #b10)))
- (else (i32.const 0)))
- (then
- (call $normalize-fraction
- (struct.new $fraction
- (i32.const 0)
- (call $sub
- (call $mul
- (struct.get $fraction $num (local.get $a))
- (struct.get $fraction $denom (local.get $b)))
- (call $mul
- (struct.get $fraction $denom (local.get $a))
- (struct.get $fraction $num (local.get $b))))
- (call $mul
- (struct.get $fraction $denom (local.get $a))
- (struct.get $fraction $denom (local.get $b))))))
- (else
- (local.set $t
- (call $sub
- (call $mul
- (struct.get $fraction $num (local.get $a))
- (call $quo
- (struct.get $fraction $denom (local.get $b))
- (local.get $d1)))
- (call $mul
- (struct.get $fraction $num (local.get $b))
- (call $quo
- (struct.get $fraction $denom (local.get $a))
- (local.get $d1)))))
- (local.set $d2 (call $gcd (local.get $t) (local.get $d1)))
- (call $normalize-fraction
- (struct.new $fraction
- (i32.const 0)
- (call $quo
- (local.get $t)
- (local.get $d2))
- (call $mul
- (call $quo
- (struct.get $fraction $denom (local.get $a))
- (local.get $d1))
- (call $quo
- (struct.get $fraction $denom (local.get $b))
- (local.get $d2))))))))
- ;; Fraction multiplication
- (func $mul-fracnum-fixnum (param $a (ref $fraction)) (param $b (ref i31)) (result (ref eq))
- (call $normalize-fraction/gcd
- (struct.new $fraction
- (i32.const 0)
- (call $mul (local.get $b) (struct.get $fraction $num (local.get $a)))
- (struct.get $fraction $denom (local.get $a)))))
- (func $mul-fracnum-bignum (param $a (ref $fraction)) (param $b (ref $bignum)) (result (ref eq))
- (call $normalize-fraction/gcd
- (struct.new $fraction
- (i32.const 0)
- (call $mul (local.get $b) (struct.get $fraction $num (local.get $a)))
- (struct.get $fraction $denom (local.get $a)))))
- (func $mul-fracnum-fracnum (param $a (ref $fraction)) (param $b (ref $fraction)) (result (ref eq))
- (local $d1 (ref eq))
- (local $d2 (ref eq))
- (local.set $d1 (call $gcd
- (struct.get $fraction $num (local.get $a))
- (struct.get $fraction $denom (local.get $b))))
- (local.set $d2 (call $gcd
- (struct.get $fraction $denom (local.get $a))
- (struct.get $fraction $num (local.get $b))))
- (call $normalize-fraction
- (struct.new $fraction
- (i32.const 0)
- (call $mul
- (call $quo
- (struct.get $fraction $num (local.get $a))
- (local.get $d1))
- (call $quo
- (struct.get $fraction $num (local.get $b))
- (local.get $d2)))
- (call $mul
- (call $quo
- (struct.get $fraction $denom (local.get $a))
- (local.get $d2))
- (call $quo
- (struct.get $fraction $denom (local.get $b))
- (local.get $d1))))))
- ;; Fraction division
- (func $div-fixnum-fracnum (param $a (ref i31)) (param $b (ref $fraction)) (result (ref eq))
- (call $normalize-fraction/gcd
- (struct.new $fraction
- (i32.const 0)
- (call $mul (local.get $a) (struct.get $fraction $denom (local.get $b)))
- (struct.get $fraction $num (local.get $b)))))
- (func $div-bignum-fracnum (param $a (ref $bignum)) (param $b (ref $fraction)) (result (ref eq))
- (call $normalize-fraction/gcd
- (struct.new $fraction
- (i32.const 0)
- (call $mul (local.get $a) (struct.get $fraction $denom (local.get $b)))
- (struct.get $fraction $num (local.get $b)))))
- (func $div-fracnum-fixnum (param $a (ref $fraction)) (param $b (ref i31)) (result (ref eq))
- (call $normalize-fraction/gcd
- (struct.new $fraction
- (i32.const 0)
- (call $mul (local.get $b) (struct.get $fraction $denom (local.get $a)))
- (struct.get $fraction $num (local.get $a)))))
- (func $div-fracnum-bignum (param $a (ref $fraction)) (param $b (ref $bignum)) (result (ref eq))
- (call $normalize-fraction/gcd
- (struct.new $fraction
- (i32.const 0)
- (struct.get $fraction $num (local.get $a))
- (call $mul (local.get $b) (struct.get $fraction $denom (local.get $a))))))
- (func $div-fracnum-fracnum (param $a (ref $fraction)) (param $b (ref $fraction)) (result (ref eq))
- (call $normalize-fraction/gcd
- (struct.new $fraction
- (i32.const 0)
- (call $mul
- (struct.get $fraction $num (local.get $a))
- (struct.get $fraction $denom (local.get $b)))
- (call $mul
- (struct.get $fraction $denom (local.get $a))
- (struct.get $fraction $num (local.get $b))))))
- ;; Complex number arithmetic
- (func $add-complex-complex (param $a (ref $complex)) (param $b (ref $complex)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.add (struct.get $complex $real (local.get $a))
- (struct.get $complex $real (local.get $b)))
- (f64.add (struct.get $complex $imag (local.get $a))
- (struct.get $complex $imag (local.get $b)))))
- (func $add-complex-fixnum (param $a (ref $complex)) (param $b (ref i31)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.add (struct.get $complex $real (local.get $a))
- (f64.convert_i32_s
- (i32.shr_s (i31.get_s (local.get $b))
- (i32.const 1))))
- (struct.get $complex $imag (local.get $a))))
- (func $add-complex-bignum (param $a (ref $complex)) (param $b (ref $bignum)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.add (struct.get $complex $real (local.get $a))
- (call $bignum->f64 (local.get $b)))
- (struct.get $complex $imag (local.get $a))))
- (func $add-complex-flonum (param $a (ref $complex)) (param $b (ref $flonum)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.add (struct.get $complex $real (local.get $a))
- (struct.get $flonum $val (local.get $b)))
- (struct.get $complex $imag (local.get $a))))
- (func $add-complex-fracnum (param $a (ref $complex)) (param $b (ref $fraction)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.add (struct.get $complex $real (local.get $a))
- (struct.get $flonum $val (call $inexact (local.get $b))))
- (struct.get $complex $imag (local.get $a))))
- (func $add-complex-complex (param $a (ref $complex)) (param $b (ref $complex)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.add (struct.get $complex $real (local.get $a))
- (struct.get $complex $real (local.get $b)))
- (f64.add (struct.get $complex $imag (local.get $a))
- (struct.get $complex $imag (local.get $b)))))
- (func $sub-complex-fixnum (param $a (ref $complex)) (param $b (ref i31)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.sub (struct.get $complex $real (local.get $a))
- (f64.convert_i32_s
- (i32.shr_s (i31.get_s (local.get $b))
- (i32.const 1))))
- (struct.get $complex $imag (local.get $a))))
- (func $sub-fixnum-complex (param $a (ref i31)) (param $b (ref $complex)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.sub (f64.convert_i32_s
- (i32.shr_s (i31.get_s (local.get $a))
- (i32.const 1)))
- (struct.get $complex $real (local.get $b)))
- (f64.neg (struct.get $complex $imag (local.get $b)))))
- (func $sub-complex-bignum (param $a (ref $complex)) (param $b (ref $bignum)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.sub (struct.get $complex $real (local.get $a))
- (call $bignum->f64 (local.get $b)))
- (struct.get $complex $imag (local.get $a))))
- (func $sub-bignum-complex (param $a (ref $bignum)) (param $b (ref $complex)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.sub (call $bignum->f64 (local.get $a))
- (struct.get $complex $real (local.get $b)))
- (f64.neg (struct.get $complex $imag (local.get $b)))))
- (func $sub-complex-flonum (param $a (ref $complex)) (param $b (ref $flonum)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.sub (struct.get $complex $real (local.get $a))
- (struct.get $flonum $val (local.get $b)))
- (struct.get $complex $imag (local.get $a))))
- (func $sub-flonum-complex (param $a (ref $flonum)) (param $b (ref $complex)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.sub (struct.get $flonum $val (local.get $a))
- (struct.get $complex $real (local.get $b)))
- (f64.neg (struct.get $complex $imag (local.get $b)))))
- (func $sub-complex-fracnum (param $a (ref $complex)) (param $b (ref $fraction)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.sub (struct.get $complex $real (local.get $a))
- (struct.get $flonum $val (call $inexact (local.get $b))))
- (struct.get $complex $imag (local.get $a))))
- (func $sub-fracnum-complex (param $a (ref $fraction)) (param $b (ref $complex)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.sub (struct.get $flonum $val (call $inexact (local.get $a)))
- (struct.get $complex $real (local.get $b)))
- (f64.neg (struct.get $complex $imag (local.get $b)))))
- (func $sub-complex-complex (param $a (ref $complex)) (param $b (ref $complex)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.sub (struct.get $complex $real (local.get $a))
- (struct.get $complex $real (local.get $b)))
- (f64.sub (struct.get $complex $imag (local.get $a))
- (struct.get $complex $imag (local.get $b)))))
- (func $mul-complex-fixnum (param $a (ref $complex)) (param $b (ref i31)) (result (ref eq))
- (local $c f64)
- (local.set $c (f64.convert_i32_s
- (i32.shr_s (i31.get_s (local.get $b))
- (i32.const 1))))
- (struct.new $complex
- (i32.const 0)
- (f64.mul (struct.get $complex $real (local.get $a))
- (local.get $c))
- (f64.mul (struct.get $complex $imag (local.get $a))
- (local.get $c))))
- (func $mul-complex-bignum (param $a (ref $complex)) (param $b (ref $bignum)) (result (ref eq))
- (local $c f64)
- (local.set $c (call $bignum->f64 (local.get $b)))
- (struct.new $complex
- (i32.const 0)
- (f64.mul (struct.get $complex $real (local.get $a))
- (local.get $c))
- (f64.mul (struct.get $complex $imag (local.get $a))
- (local.get $c))))
- (func $mul-complex-flonum (param $a (ref $complex)) (param $b (ref $flonum)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.mul (struct.get $complex $real (local.get $a))
- (struct.get $flonum $val (local.get $b)))
- (f64.mul (struct.get $complex $imag (local.get $a))
- (struct.get $flonum $val (local.get $b)))))
- (func $mul-complex-fracnum (param $a (ref $complex)) (param $b (ref $fraction)) (result (ref eq))
- (local $c f64)
- (local.set $c (struct.get $flonum $val (call $inexact (local.get $b))))
- (struct.new $complex
- (i32.const 0)
- (f64.mul (struct.get $complex $real (local.get $a))
- (local.get $c))
- (f64.mul (struct.get $complex $imag (local.get $a))
- (local.get $c))))
- (func $mul-complex-complex (param $a (ref $complex)) (param $b (ref $complex)) (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.sub (f64.mul (struct.get $complex $real (local.get $a))
- (struct.get $complex $real (local.get $b)))
- (f64.mul (struct.get $complex $imag (local.get $a))
- (struct.get $complex $imag (local.get $b))))
- (f64.add (f64.mul (struct.get $complex $real (local.get $a))
- (struct.get $complex $imag (local.get $b)))
- (f64.mul (struct.get $complex $imag (local.get $a))
- (struct.get $complex $real (local.get $b))))))
- (func $div-complex-fixnum (param $a (ref $complex)) (param $b (ref i31)) (result (ref eq))
- (local $ra f64)
- (local $ia f64)
- (local $rb f64)
- (local $d f64)
- (local.set $ra (struct.get $complex $real (local.get $a)))
- (local.set $ia (struct.get $complex $imag (local.get $a)))
- (local.set $rb (f64.convert_i32_s
- (i32.shr_s (i31.get_s (local.get $b))
- (i32.const 1))))
- (local.set $d (f64.mul (local.get $rb) (local.get $rb)))
- (struct.new $complex
- (i32.const 0)
- (f64.div (f64.mul (local.get $ra)
- (local.get $rb))
- (local.get $d))
- (f64.div (f64.mul (local.get $ia)
- (local.get $rb))
- (local.get $d))))
- (func $div-fixnum-complex (param $a (ref i31)) (param $b (ref $complex)) (result (ref eq))
- (local $ra f64)
- (local $rb f64)
- (local $ib f64)
- (local $d f64)
- (local.set $ra (f64.convert_i32_s
- (i32.shr_s (i31.get_s (local.get $a))
- (i32.const 1))))
- (local.set $rb (struct.get $complex $real (local.get $b)))
- (local.set $ib (struct.get $complex $imag (local.get $b)))
- (local.set $d (f64.add (f64.mul (local.get $rb) (local.get $rb))
- (f64.mul (local.get $ib) (local.get $ib))))
- (struct.new $complex
- (i32.const 0)
- (f64.div (f64.mul (local.get $ra)
- (local.get $rb))
- (local.get $d))
- (f64.div (f64.neg
- (f64.mul (local.get $ra)
- (local.get $ib)))
- (local.get $d))))
- (func $div-complex-bignum (param $a (ref $complex)) (param $b (ref $bignum)) (result (ref eq))
- (local $ra f64)
- (local $ia f64)
- (local $rb f64)
- (local $d f64)
- (local.set $ra (struct.get $complex $real (local.get $a)))
- (local.set $ia (struct.get $complex $imag (local.get $a)))
- (local.set $rb (call $bignum->f64 (local.get $b)))
- (local.set $d (f64.mul (local.get $rb) (local.get $rb)))
- (struct.new $complex
- (i32.const 0)
- (f64.div (f64.mul (local.get $ra)
- (local.get $rb))
- (local.get $d))
- (f64.div (f64.mul (local.get $ia)
- (local.get $rb))
- (local.get $d))))
- (func $div-bignum-complex (param $a (ref $bignum)) (param $b (ref $complex)) (result (ref eq))
- (local $ra f64)
- (local $rb f64)
- (local $ib f64)
- (local $d f64)
- (local.set $ra (call $bignum->f64 (local.get $a)))
- (local.set $rb (struct.get $complex $real (local.get $b)))
- (local.set $ib (struct.get $complex $imag (local.get $b)))
- (local.set $d (f64.add (f64.mul (local.get $rb) (local.get $rb))
- (f64.mul (local.get $ib) (local.get $ib))))
- (struct.new $complex
- (i32.const 0)
- (f64.div (f64.mul (local.get $ra)
- (local.get $rb))
- (local.get $d))
- (f64.div (f64.neg
- (f64.mul (local.get $ra)
- (local.get $ib)))
- (local.get $d))))
- (func $div-complex-flonum (param $a (ref $complex)) (param $b (ref $flonum)) (result (ref eq))
- (local $ra f64)
- (local $ia f64)
- (local $rb f64)
- (local $d f64)
- (local.set $ra (struct.get $complex $real (local.get $a)))
- (local.set $ia (struct.get $complex $imag (local.get $a)))
- (local.set $rb (struct.get $flonum $val (local.get $b)))
- (local.set $d (f64.mul (local.get $rb) (local.get $rb)))
- (struct.new $complex
- (i32.const 0)
- (f64.div (f64.mul (local.get $ra)
- (local.get $rb))
- (local.get $d))
- (f64.div (f64.mul (local.get $ia)
- (local.get $rb))
- (local.get $d))))
- (func $div-flonum-complex (param $a (ref $flonum)) (param $b (ref $complex)) (result (ref eq))
- (local $ra f64)
- (local $rb f64)
- (local $ib f64)
- (local $d f64)
- (local.set $ra (struct.get $flonum $val (local.get $a)))
- (local.set $rb (struct.get $complex $real (local.get $b)))
- (local.set $ib (struct.get $complex $imag (local.get $b)))
- (local.set $d (f64.add (f64.mul (local.get $rb) (local.get $rb))
- (f64.mul (local.get $ib) (local.get $ib))))
- (struct.new $complex
- (i32.const 0)
- (f64.div (f64.mul (local.get $ra)
- (local.get $rb))
- (local.get $d))
- (f64.div (f64.neg
- (f64.mul (local.get $ra)
- (local.get $ib)))
- (local.get $d))))
- (func $div-complex-fracnum (param $a (ref $complex)) (param $b (ref $fraction)) (result (ref eq))
- (call $div-complex-flonum (local.get $a) (call $inexact (local.get $b))))
- (func $div-fracnum-complex (param $a (ref $fraction)) (param $b (ref $complex)) (result (ref eq))
- (call $div-flonum-complex (call $inexact (local.get $a)) (local.get $b)))
- (func $div-complex-complex (param $a (ref $complex)) (param $b (ref $complex)) (result (ref eq))
- (local $ra f64)
- (local $ia f64)
- (local $rb f64)
- (local $ib f64)
- (local $d f64)
- (local.set $ra (struct.get $complex $real (local.get $a)))
- (local.set $ia (struct.get $complex $imag (local.get $a)))
- (local.set $rb (struct.get $complex $real (local.get $b)))
- (local.set $ib (struct.get $complex $imag (local.get $b)))
- (local.set $d (f64.add (f64.mul (local.get $rb) (local.get $rb))
- (f64.mul (local.get $ib) (local.get $ib))))
- (struct.new $complex
- (i32.const 0)
- (f64.div (f64.add (f64.mul (local.get $ra)
- (local.get $rb))
- (f64.mul (local.get $ia)
- (local.get $ib)))
- (local.get $d))
- (f64.div (f64.sub (f64.mul (local.get $ia)
- (local.get $rb))
- (f64.mul (local.get $ra)
- (local.get $ib)))
- (local.get $d))))
- (func $add (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
- ,(arith-cond
- `((call $fixnum? (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $fixnum-add*
- (ref.cast i31 (local.get $a))
- (ref.cast i31 (local.get $b)))))
- '((ref.test $bignum (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-add*
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i32
- (i32.shr_s (i31.get_s (ref.cast i31 (local.get $a)))
- (i32.const 1))))
- (ref.cast $bignum (local.get $b))))))
- '((ref.test $flonum (local.get $b))
- (return
- (struct.new $flonum
- (i32.const 0)
- (f64.add
- (call $fixnum->f64 (ref.cast i31 (local.get $a)))
- (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (call $add-fracnum-fixnum
- (ref.cast $fraction (local.get $b))
- (ref.cast i31 (local.get $a)))))
- '((ref.test $complex (local.get $b))
- (return (call $add-complex-fixnum
- (ref.cast $complex (local.get $b))
- (ref.cast i31 (local.get $a)))))
- '(else
- (call $raise-type-error
- (string.const "+")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-add*
- (ref.cast $bignum (local.get $a))
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i32
- (i32.shr_s (i31.get_s (ref.cast i31 (local.get $b)))
- (i32.const 1))))))))
- '((ref.test $bignum (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-add*
- (ref.cast $bignum (local.get $a))
- (ref.cast $bignum (local.get $b))))))
- '((ref.test $flonum (local.get $b))
- (return
- (struct.new $flonum
- (i32.const 0)
- (f64.add
- (call $bignum->f64 (ref.cast $bignum (local.get $a)))
- (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (call $add-fracnum-bignum
- (ref.cast $fraction (local.get $b))
- (ref.cast $bignum (local.get $a)))))
- '((ref.test $complex (local.get $b))
- (return (call $add-complex-bignum
- (ref.cast $complex (local.get $b))
- (ref.cast $bignum (local.get $a)))))
- '(else
- (call $raise-type-error
- (string.const "+")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $flonum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.add
- (call $flonum->f64 (ref.cast $flonum (local.get $a)))
- (call $fixnum->f64 (ref.cast i31 (local.get $b)))))))
- '((ref.test $bignum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.add
- (call $flonum->f64 (ref.cast $flonum (local.get $a)))
- (call $bignum->f64 (ref.cast $bignum (local.get $b)))))))
- '((ref.test $flonum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.add
- (call $flonum->f64 (ref.cast $flonum (local.get $a)))
- (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.add
- (struct.get $flonum $val
- (ref.cast $flonum (local.get $a)))
- (struct.get $flonum $val
- (call $inexact (local.get $b)))))))
- '((ref.test $complex (local.get $b))
- (return (call $add-complex-flonum
- (ref.cast $complex (local.get $b))
- (ref.cast $flonum (local.get $a)))))
- '(else
- (call $raise-type-error
- (string.const "+")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $fraction (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $add-fracnum-fixnum
- (ref.cast $fraction (local.get $a))
- (ref.cast i31 (local.get $b)))))
- '((ref.test $bignum (local.get $b))
- (return (call $add-fracnum-bignum
- (ref.cast $fraction (local.get $a))
- (ref.cast $bignum (local.get $b)))))
- '((ref.test $flonum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.add
- (struct.get $flonum $val
- (call $inexact (local.get $a)))
- (struct.get $flonum $val
- (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (call $add-fracnum-fracnum
- (ref.cast $fraction (local.get $a))
- (ref.cast $fraction (local.get $b)))))
- '((ref.test $complex (local.get $b))
- (return (call $add-complex-fracnum
- (ref.cast $complex (local.get $b))
- (ref.cast $fraction (local.get $a)))))
- '(else
- (call $raise-type-error
- (string.const "+")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $complex (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $add-complex-fixnum
- (ref.cast $complex (local.get $a))
- (ref.cast i31 (local.get $b)))))
- '((ref.test $bignum (local.get $b))
- (return (call $add-complex-bignum
- (ref.cast $complex (local.get $a))
- (ref.cast $bignum (local.get $b)))))
- '((ref.test $flonum (local.get $b))
- (return (call $add-complex-flonum
- (ref.cast $complex (local.get $a))
- (ref.cast $flonum (local.get $b)))))
- '((ref.test $fraction (local.get $b))
- (return (call $add-complex-fracnum
- (ref.cast $complex (local.get $a))
- (ref.cast $fraction (local.get $b)))))
- '((ref.test $complex (local.get $b))
- (return (call $add-complex-complex
- (ref.cast $complex (local.get $a))
- (ref.cast $complex (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "+")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- '(else
- (call $raise-type-error
- (string.const "+")
- (string.const "a")
- (local.get $a))
- (unreachable))))
- (func $sub (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
- ,(arith-cond
- `((call $fixnum? (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $fixnum-sub*
- (ref.cast i31 (local.get $a))
- (ref.cast i31 (local.get $b)))))
- '((ref.test $bignum (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-sub*
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i32
- (i32.shr_s (i31.get_s (ref.cast i31 (local.get $a)))
- (i32.const 1))))
- (ref.cast $bignum (local.get $b))))))
- '((ref.test $flonum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.sub
- (call $fixnum->f64 (ref.cast i31 (local.get $a)))
- (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (call $sub-fixnum-fracnum
- (ref.cast i31 (local.get $a))
- (ref.cast $fraction (local.get $b)))))
- '((ref.test $complex (local.get $b))
- (return (call $sub-fixnum-complex
- (ref.cast i31 (local.get $a))
- (ref.cast $complex (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "-")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-sub*
- (ref.cast $bignum (local.get $a))
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i32
- (i32.shr_s (i31.get_s (ref.cast i31 (local.get $b)))
- (i32.const 1))))))))
- '((ref.test $bignum (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-sub*
- (ref.cast $bignum (local.get $a))
- (ref.cast $bignum (local.get $b))))))
- '((ref.test $flonum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.sub
- (call $bignum->f64 (ref.cast $bignum (local.get $a)))
- (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (call $sub-bignum-fracnum
- (ref.cast $bignum (local.get $a))
- (ref.cast $fraction (local.get $b)))))
- '((ref.test $complex (local.get $b))
- (return (call $sub-bignum-complex
- (ref.cast $bignum (local.get $a))
- (ref.cast $complex (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "-")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $flonum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.sub
- (call $flonum->f64 (ref.cast $flonum (local.get $a)))
- (call $fixnum->f64 (ref.cast i31 (local.get $b)))))))
- '((ref.test $bignum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.sub
- (call $flonum->f64 (ref.cast $flonum (local.get $a)))
- (call $bignum->f64 (ref.cast $bignum (local.get $b)))))))
- '((ref.test $flonum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.sub
- (call $flonum->f64 (ref.cast $flonum (local.get $a)))
- (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.sub
- (struct.get $flonum $val
- (ref.cast $flonum (local.get $a)))
- (struct.get $flonum $val
- (call $inexact (local.get $b)))))))
- '((ref.test $complex (local.get $b))
- (return (call $sub-flonum-complex
- (ref.cast $flonum (local.get $a))
- (ref.cast $complex (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "-")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $fraction (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $sub-fracnum-fixnum
- (ref.cast $fraction (local.get $a))
- (ref.cast i31 (local.get $b)))))
- '((ref.test $bignum (local.get $b))
- (return (call $sub-fracnum-bignum
- (ref.cast $fraction (local.get $a))
- (ref.cast $bignum (local.get $b)))))
- '((ref.test $flonum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.sub
- (struct.get $flonum $val
- (call $inexact (local.get $a)))
- (struct.get $flonum $val
- (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (call $sub-fracnum-fracnum
- (ref.cast $fraction (local.get $a))
- (ref.cast $fraction (local.get $b)))))
- '((ref.test $complex (local.get $b))
- (return (call $sub-fracnum-complex
- (ref.cast $fraction (local.get $a))
- (ref.cast $complex (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "-")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $complex (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $sub-complex-fixnum
- (ref.cast $complex (local.get $a))
- (ref.cast i31 (local.get $b)))))
- '((ref.test $bignum (local.get $b))
- (return (call $sub-complex-bignum
- (ref.cast $complex (local.get $a))
- (ref.cast $bignum (local.get $b)))))
- '((ref.test $flonum (local.get $b))
- (return (call $sub-complex-flonum
- (ref.cast $complex (local.get $a))
- (ref.cast $flonum (local.get $b)))))
- '((ref.test $fraction (local.get $b))
- (return (call $sub-complex-fracnum
- (ref.cast $complex (local.get $a))
- (ref.cast $fraction (local.get $b)))))
- '((ref.test $complex (local.get $b))
- (return (call $sub-complex-complex
- (ref.cast $complex (local.get $a))
- (ref.cast $complex (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "-")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- '(else
- (call $raise-type-error
- (string.const "-")
- (string.const "a")
- (local.get $a))
- (unreachable))))
- (func $mul (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
- ,(arith-cond
- `((call $fixnum? (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $fixnum-mul*
- (ref.cast i31 (local.get $a))
- (ref.cast i31 (local.get $b)))))
- '((ref.test $bignum (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-mul*
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i32
- (i32.shr_s (i31.get_s (ref.cast i31 (local.get $a)))
- (i32.const 1))))
- (ref.cast $bignum (local.get $b))))))
- '((ref.test $flonum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.mul
- (call $fixnum->f64 (ref.cast i31 (local.get $a)))
- (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (call $mul-fracnum-fixnum
- (ref.cast $fraction (local.get $b))
- (ref.cast i31 (local.get $a)))))
- '((ref.test $complex (local.get $b))
- (return (call $mul-complex-fixnum
- (ref.cast $complex (local.get $b))
- (ref.cast i31 (local.get $a)))))
- '(else
- (call $raise-type-error
- (string.const "*")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-mul*
- (ref.cast $bignum (local.get $a))
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i32
- (i32.shr_s (i31.get_s (ref.cast i31 (local.get $b)))
- (i32.const 1))))))))
- '((ref.test $bignum (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-mul*
- (ref.cast $bignum (local.get $a))
- (ref.cast $bignum (local.get $b))))))
- '((ref.test $flonum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.mul
- (call $bignum->f64 (ref.cast $bignum (local.get $a)))
- (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (call $mul-fracnum-bignum
- (ref.cast $fraction (local.get $b))
- (ref.cast $bignum (local.get $a)))))
- '((ref.test $complex (local.get $b))
- (return (call $mul-complex-bignum
- (ref.cast $complex (local.get $b))
- (ref.cast $bignum (local.get $a)))))
- '(else
- (call $raise-type-error
- (string.const "*")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $flonum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.mul
- (call $flonum->f64 (ref.cast $flonum (local.get $a)))
- (call $fixnum->f64 (ref.cast i31 (local.get $b)))))))
- '((ref.test $bignum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.mul
- (call $flonum->f64 (ref.cast $flonum (local.get $a)))
- (call $bignum->f64 (ref.cast $bignum (local.get $b)))))))
- '((ref.test $flonum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.mul
- (call $flonum->f64 (ref.cast $flonum (local.get $a)))
- (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.mul
- (struct.get $flonum $val
- (ref.cast $flonum (local.get $a)))
- (struct.get $flonum $val
- (call $inexact (local.get $b)))))))
- '((ref.test $complex (local.get $b))
- (return (call $mul-complex-flonum
- (ref.cast $complex (local.get $b))
- (ref.cast $flonum (local.get $a)))))
- '(else
- (call $raise-type-error
- (string.const "*")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $fraction (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $mul-fracnum-fixnum
- (ref.cast $fraction (local.get $a))
- (ref.cast i31 (local.get $b)))))
- '((ref.test $bignum (local.get $b))
- (return (call $mul-fracnum-bignum
- (ref.cast $fraction (local.get $a))
- (ref.cast $bignum (local.get $b)))))
- '((ref.test $flonum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.mul
- (struct.get $flonum $val
- (call $inexact (local.get $a)))
- (struct.get $flonum $val
- (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (call $mul-fracnum-fracnum
- (ref.cast $fraction (local.get $a))
- (ref.cast $fraction (local.get $b)))))
- '((ref.test $complex (local.get $b))
- (return (call $mul-complex-fracnum
- (ref.cast $complex (local.get $b))
- (ref.cast $fraction (local.get $a)))))
- '(else
- (call $raise-type-error
- (string.const "*")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $complex (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $mul-complex-fixnum
- (ref.cast $complex (local.get $a))
- (ref.cast i31 (local.get $b)))))
- '((ref.test $bignum (local.get $b))
- (return (call $mul-complex-bignum
- (ref.cast $complex (local.get $a))
- (ref.cast $bignum (local.get $b)))))
- '((ref.test $flonum (local.get $b))
- (return (call $mul-complex-flonum
- (ref.cast $complex (local.get $a))
- (ref.cast $flonum (local.get $b)))))
- '((ref.test $fraction (local.get $b))
- (return (call $mul-complex-fracnum
- (ref.cast $complex (local.get $a))
- (ref.cast $fraction (local.get $b)))))
- '((ref.test $complex (local.get $b))
- (return (call $mul-complex-complex
- (ref.cast $complex (local.get $a))
- (ref.cast $complex (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "*")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- '(else
- (call $raise-type-error
- (string.const "*")
- (string.const "a")
- (local.get $a))
- (unreachable))))
- (func $div (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
- ,(arith-cond
- `((call $fixnum? (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $normalize-fraction/gcd
- (struct.new $fraction
- (i32.const 0)
- (local.get $a)
- (local.get $b)))))
- '((ref.test $bignum (local.get $b))
- (return (call $normalize-fraction/gcd
- (struct.new $fraction
- (i32.const 0)
- (local.get $a)
- (local.get $b)))))
- '((ref.test $flonum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.div
- (call $fixnum->f64 (ref.cast i31 (local.get $a)))
- (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (call $div-fixnum-fracnum
- (ref.cast i31 (local.get $a))
- (ref.cast $fraction (local.get $b)))))
- '((ref.test $complex (local.get $b))
- (return (call $div-fixnum-complex
- (ref.cast i31 (local.get $a))
- (ref.cast $complex (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "/")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $normalize-fraction/gcd
- (struct.new $fraction
- (i32.const 0)
- (local.get $a)
- (local.get $b)))))
- '((ref.test $bignum (local.get $b))
- (return (call $normalize-fraction/gcd
- (struct.new $fraction
- (i32.const 0)
- (local.get $a)
- (local.get $b)))))
- '((ref.test $flonum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.div
- (call $bignum->f64 (ref.cast $bignum (local.get $a)))
- (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (call $div-bignum-fracnum
- (ref.cast $bignum (local.get $a))
- (ref.cast $fraction (local.get $b)))))
- '((ref.test $complex (local.get $b))
- (return (call $div-bignum-complex
- (ref.cast $bignum (local.get $a))
- (ref.cast $complex (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "/")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $flonum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.div
- (call $flonum->f64 (ref.cast $flonum (local.get $a)))
- (call $fixnum->f64 (ref.cast i31 (local.get $b)))))))
- '((ref.test $bignum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.div
- (call $flonum->f64 (ref.cast $flonum (local.get $a)))
- (call $bignum->f64 (ref.cast $bignum (local.get $b)))))))
- '((ref.test $flonum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.div
- (call $flonum->f64 (ref.cast $flonum (local.get $a)))
- (call $flonum->f64 (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.div
- (struct.get $flonum $val
- (ref.cast $flonum (local.get $a)))
- (struct.get $flonum $val
- (call $inexact (local.get $b)))))))
- '((ref.test $complex (local.get $b))
- (return (call $div-flonum-complex
- (ref.cast $flonum (local.get $a))
- (ref.cast $complex (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "/")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $fraction (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $div-fracnum-fixnum
- (ref.cast $fraction (local.get $a))
- (ref.cast i31 (local.get $b)))))
- '((ref.test $bignum (local.get $b))
- (return (call $div-fracnum-bignum
- (ref.cast $fraction (local.get $a))
- (ref.cast $bignum (local.get $b)))))
- '((ref.test $flonum (local.get $b))
- (return (struct.new $flonum
- (i32.const 0)
- (f64.div
- (struct.get $flonum $val
- (call $inexact (local.get $a)))
- (struct.get $flonum $val
- (ref.cast $flonum (local.get $b)))))))
- '((ref.test $fraction (local.get $b))
- (return (call $div-fracnum-fracnum
- (ref.cast $fraction (local.get $a))
- (ref.cast $fraction (local.get $b)))))
- '((ref.test $complex (local.get $b))
- (return (call $div-fracnum-complex
- (ref.cast $fraction (local.get $a))
- (ref.cast $complex (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "/")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $complex (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $div-complex-fixnum
- (ref.cast $complex (local.get $a))
- (ref.cast i31 (local.get $b)))))
- '((ref.test $bignum (local.get $b))
- (return (call $div-complex-bignum
- (ref.cast $complex (local.get $a))
- (ref.cast $bignum (local.get $b)))))
- '((ref.test $flonum (local.get $b))
- (return (call $div-complex-flonum
- (ref.cast $complex (local.get $a))
- (ref.cast $flonum (local.get $b)))))
- '((ref.test $fraction (local.get $b))
- (return (call $div-complex-fracnum
- (ref.cast $complex (local.get $a))
- (ref.cast $fraction (local.get $b)))))
- '((ref.test $complex (local.get $b))
- (return (call $div-complex-complex
- (ref.cast $complex (local.get $a))
- (ref.cast $complex (local.get $b)))))
- '(else
- (call $raise-type-error
- (string.const "/")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- '(else
- (call $raise-type-error
- (string.const "/")
- (string.const "a")
- (local.get $a))
- (unreachable))))
- (func $quo (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
- (local $a-i32 i32)
- (local $b-i32 i32)
- ,(arith-cond
- `((call $fixnum? (local.get $a))
- ,(arith-cond
- ;; Adapted from the `quo' fixnum fast path in (hoot compile).
- `((call $fixnum? (local.get $b))
- (local.set $a-i32 (call $fixnum->i32
- (ref.cast i31 (local.get $a))))
- (local.set $b-i32 (call $fixnum->i32
- (ref.cast i31 (local.get $b))))
- (if (i32.eqz (local.get $b-i32))
- (then
- (call $raise-runtime-error-with-message
- (string.const "division by zero"))
- (unreachable)))
- (local.set $a-i32
- (i32.div_s (local.get $a-i32)
- (local.get $b-i32)))
- ;; Dividing -2^29 (the most negative fixnum) by -1
- ;; returns 2^29, which is one greater than the most
- ;; positive fixnum (because two's complement is
- ;; asymmetrical.) In this case we need to return a
- ;; bignum.
- (if (ref eq)
- (i32.eq (local.get $a-i32) (i32.const ,(ash 1 29)))
- (then
- (call $i32->bignum (i32.const ,(ash 1 29))))
- (else
- (ref.i31
- (i32.shl (local.get $a-i32)
- (i32.const 1))))))
- '((ref.test $bignum (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-quo*
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i32
- (call $fixnum->i32
- (ref.cast i31 (local.get $a)))))
- (ref.cast $bignum (local.get $b))))))
- '((ref.test $flonum (local.get $b))
- (if (ref eq)
- (call $flonum-integer? (local.get $b))
- (then
- (call $inexact
- (call $quo
- (local.get $a)
- (call $flonum->integer (local.get $b)))))
- (else
- (call $raise-type-error
- (string.const "quotient")
- (string.const "b")
- (local.get $b))
- (unreachable))))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-quo*
- (ref.cast $bignum (local.get $a))
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i32
- (call $fixnum->i32
- (ref.cast i31 (local.get $b)))))))))
- '((ref.test $bignum (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-quo*
- (ref.cast $bignum (local.get $a))
- (ref.cast $bignum (local.get $b))))))
- '((ref.test $flonum (local.get $b))
- (if (ref eq)
- (call $flonum-integer? (local.get $b))
- (then
- (call $inexact
- (call $quo
- (local.get $a)
- (call $flonum->integer (local.get $b)))))
- (else
- (call $raise-type-error
- (string.const "quotient")
- (string.const "b")
- (local.get $b))
- (unreachable))))))
- `((ref.test $flonum (local.get $a))
- (if (ref eq)
- (call $flonum-integer? (local.get $a))
- (then
- (call $inexact
- (call $quo
- (call $flonum->integer (local.get $a))
- (local.get $b))))
- (else
- (call $raise-type-error
- (string.const "quotient")
- (string.const "a")
- (local.get $a))
- (unreachable))))))
- (func $rem (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
- (local $a-i32 i32)
- (local $b-i32 i32)
- ,(arith-cond
- `((call $fixnum? (local.get $a))
- ,(arith-cond
- ;; Adapted from the `rem' fixnum fast path in (hoot compile).
- '((call $fixnum? (local.get $b))
- (local.set $a-i32
- (call $fixnum->i32
- (ref.cast i31 (local.get $a))))
- (local.set $b-i32
- (call $fixnum->i32
- (ref.cast i31 (local.get $b))))
- (if (i32.eqz (local.get $b-i32))
- (then
- (call $raise-runtime-error-with-message
- (string.const "division by zero"))
- (unreachable)))
- (call $i32->fixnum
- (i32.rem_s
- (local.get $a-i32)
- (local.get $b-i32))))
- '((ref.test $bignum (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-rem*
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i32
- (call $fixnum->i32
- (ref.cast i31 (local.get $a)))))
- (ref.cast $bignum (local.get $b))))))
- '((ref.test $flonum (local.get $b))
- (if (ref eq)
- (call $flonum-integer? (local.get $b))
- (then
- (call $inexact
- (call $rem
- (local.get $a)
- (call $flonum->integer (local.get $b)))))
- (else
- (call $raise-type-error
- (string.const "remainder")
- (string.const "b")
- (local.get $b))
- (unreachable))))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-rem*
- (ref.cast $bignum (local.get $a))
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i32
- (call $fixnum->i32
- (ref.cast i31 (local.get $b)))))))))
- '((ref.test $bignum (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-rem*
- (ref.cast $bignum (local.get $a))
- (ref.cast $bignum (local.get $b))))))
- '((ref.test $flonum (local.get $b))
- (if (ref eq)
- (call $flonum-integer? (local.get $b))
- (then
- (call $inexact
- (call $rem
- (local.get $a)
- (call $flonum->integer (local.get $b)))))
- (else
- (call $raise-type-error
- (string.const "remainder")
- (string.const "b")
- (local.get $b))
- (unreachable))))))
- '((ref.test $flonum (local.get $a))
- (if (ref eq)
- (call $flonum-integer? (local.get $a))
- (then
- (call $inexact
- (call $rem
- (call $flonum->integer (local.get $a))
- (local.get $b))))
- (else
- (call $raise-type-error
- (string.const "remainder")
- (string.const "a")
- (local.get $a))
- (unreachable))))))
- (func $mod (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
- (local $a-i32 i32)
- (local $b-i32 i32)
- (local $tem i32)
- ,(arith-cond
- `((call $fixnum? (local.get $a))
- ,(arith-cond
- ;; Adapted from the `mod' fixnum fast path in (hoot compile).
- '((call $fixnum? (local.get $b))
- (local.set $a-i32 (call $fixnum->i32
- (ref.cast i31 (local.get $a))))
- (local.set $b-i32 (call $fixnum->i32
- (ref.cast i31 (local.get $b))))
- (if (i32.eqz (local.get $b-i32))
- (then
- (call $raise-runtime-error-with-message
- (string.const "division by zero"))
- (unreachable)))
- (local.set $tem
- (i32.rem_s (local.get $a-i32)
- (local.get $b-i32)))
- ;; If $B and the remainder have different signs,
- ;; adjust the remainder by adding $B.
- (if (i32.or
- (i32.and (i32.lt_s (local.get $tem) (i32.const 0))
- (i32.gt_s (local.get $b-i32) (i32.const 0)))
- (i32.and (i32.gt_s (local.get $tem) (i32.const 0))
- (i32.lt_s (local.get $b-i32) (i32.const 0))))
- (then (local.set $tem (i32.add (local.get $tem)
- (local.get $b-i32)))))
- (call $i32->fixnum (local.get $tem)))
- '((ref.test $bignum (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-mod*
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i32
- (call $fixnum->i32
- (ref.cast i31 (local.get $a)))))
- (ref.cast $bignum (local.get $b))))))
- '((ref.test $flonum (local.get $b))
- (if (ref eq)
- (call $flonum-integer? (local.get $b))
- (then
- (call $inexact
- (call $mod
- (local.get $a)
- (call $flonum->integer (local.get $b)))))
- (else
- (call $raise-type-error
- (string.const "modulo")
- (string.const "b")
- (local.get $b))
- (unreachable))))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-mod*
- (ref.cast $bignum (local.get $a))
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i32
- (call $fixnum->i32
- (ref.cast i31 (local.get $b)))))))))
- '((ref.test $bignum (local.get $b))
- (return (call $normalize-bignum
- (call $bignum-mod*
- (ref.cast $bignum (local.get $a))
- (ref.cast $bignum (local.get $b))))))
- '((ref.test $flonum (local.get $b))
- (if (ref eq)
- (call $flonum-integer? (local.get $b))
- (then
- (call $inexact
- (call $mod
- (local.get $a)
- (call $flonum->integer (local.get $b)))))
- (else
- (call $raise-type-error
- (string.const "modulo")
- (string.const "b")
- (local.get $b))
- (unreachable))))))
- '((ref.test $flonum (local.get $a))
- (if (ref eq)
- (call $flonum-integer? (local.get $a))
- (then
- (call $inexact
- (call $mod
- (call $flonum->integer (local.get $a))
- (local.get $b))))
- (else
- (call $raise-type-error
- (string.const "modulo")
- (string.const "a")
- (local.get $a))
- (unreachable))))))
- ;; Bitwise operators and shifts
- (func $logand (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
- ,(arith-cond
- `((call $fixnum? (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (call $i32->fixnum
- (i32.and (call $fixnum->i32 (ref.cast i31 (local.get $a)))
- (call $fixnum->i32 (ref.cast i31 (local.get $b))))))
- '((ref.test $bignum (local.get $b))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-logand-i32
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))
- (call $fixnum->i32 (ref.cast i31 (local.get $a)))))))
- '(else
- (call $raise-type-error
- (string.const "logand")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-logand-i32
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (call $fixnum->i32 (ref.cast i31 (local.get $b)))))))
- '((ref.test $bignum (local.get $b))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-logand-bignum
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))))
- `(else
- (call $raise-type-error
- (string.const "logand")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- '(else
- (call $raise-type-error
- (string.const "logand")
- (string.const "a")
- (local.get $a))
- (unreachable))))
- (func $logior (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
- ,(arith-cond
- `((call $fixnum? (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (call $i32->fixnum
- (i32.or (call $fixnum->i32 (ref.cast i31 (local.get $a)))
- (call $fixnum->i32 (ref.cast i31 (local.get $b))))))
- '((ref.test $bignum (local.get $b))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-logior-i32
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))
- (call $fixnum->i32 (ref.cast i31 (local.get $a)))))))
- '(else
- (call $raise-type-error
- (string.const "logior")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-logior-i32
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (call $fixnum->i32 (ref.cast i31 (local.get $b)))))))
- '((ref.test $bignum (local.get $b))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-logior-bignum
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))))
- `(else
- (call $raise-type-error
- (string.const "logior")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- '(else
- (call $raise-type-error
- (string.const "logior")
- (string.const "a")
- (local.get $a))
- (unreachable))))
- (func $logxor (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
- ,(arith-cond
- `((call $fixnum? (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (call $i32->fixnum
- (i32.xor (call $fixnum->i32 (ref.cast i31 (local.get $a)))
- (call $fixnum->i32 (ref.cast i31 (local.get $b))))))
- '((ref.test $bignum (local.get $b))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-logxor-i32
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))
- (call $fixnum->i32 (ref.cast i31 (local.get $a)))))))
- '(else
- (call $raise-type-error
- (string.const "logxor")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-logxor-i32
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (call $fixnum->i32 (ref.cast i31 (local.get $b)))))))
- '((ref.test $bignum (local.get $b))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-logxor-bignum
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))))
- `(else
- (call $raise-type-error
- (string.const "logxor")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- '(else
- (call $raise-type-error
- (string.const "logxor")
- (string.const "a")
- (local.get $a))
- (unreachable))))
- (func $logsub (param $a (ref eq)) (param $b (ref eq)) (result (ref eq))
- ,(arith-cond
- `((call $fixnum? (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- '(call $i32->fixnum
- (i32.and
- (call $fixnum->i32 (ref.cast i31 (local.get $a)))
- (i32.xor (call $fixnum->i32
- (ref.cast i31 (local.get $b)))
- (i32.const -1)))))
- '((ref.test $bignum (local.get $b))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $i32-logsub-bignum
- (call $fixnum->i32 (ref.cast i31 (local.get $a)))
- (struct.get $bignum $val (ref.cast $bignum (local.get $b)))))))
- '(else
- (call $raise-type-error
- (string.const "logsub")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- `((ref.test $bignum (local.get $a))
- ,(arith-cond
- '((call $fixnum? (local.get $b))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-logsub-i32
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (call $fixnum->i32 (ref.cast i31 (local.get $b)))))))
- '((ref.test $bignum (local.get $b))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-logsub-bignum
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))
- (struct.get $bignum $val (ref.cast i31 (local.get $b)))))))
- '(else
- (call $raise-type-error
- (string.const "logsub")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- '(else
- (call $raise-type-error
- (string.const "logsub")
- (string.const "b")
- (local.get $b))
- (unreachable))))
- (func $rsh (param $a (ref eq)) (param $b i64) (result (ref eq))
- ,(arith-cond
- '((ref.test $bignum (local.get $a))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-rsh
- (struct.get $bignum $val
- (ref.cast $bignum (local.get $a)))
- (local.get $b)))))
- '(else
- (call $die
- (string.const "$rsh bad first arg")
- (local.get $a))
- (unreachable))))
- (func $lsh (param $a (ref eq)) (param $b i64) (result (ref eq))
- ,(arith-cond
- '((call $fixnum? (local.get $a))
- (call $normalize-bignum
- (struct.new $bignum
- (i32.const 0)
- (call $i32-lsh
- (call $fixnum->i32 (ref.cast i31 (local.get $a)))
- (local.get $b)))))
- '((ref.test $bignum (local.get $a))
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-lsh
- (struct.get $bignum $val
- (ref.cast $bignum (local.get $a)))
- (local.get $b))))
- '(else
- (call $die
- (string.const "$lsh bad first arg")
- (local.get $a))
- (unreachable))))
- (func $inexact (param $x (ref eq)) (result (ref $flonum))
- ,(arith-cond '(ref $flonum)
- `((call $fixnum? (local.get $x))
- (struct.new $flonum
- (i32.const 0)
- (call $fixnum->f64
- (ref.cast i31 (local.get $x)))))
- `((ref.test $bignum (local.get $x))
- (struct.new $flonum
- (i32.const 0)
- (call $bignum->f64
- (ref.cast $bignum (local.get $x)))))
- `((ref.test $flonum (local.get $x))
- (ref.cast $flonum (local.get $x)))
- ;; FIXME: improve fraction approximation
- `((ref.test $fraction (local.get $x))
- (ref.cast $flonum
- (call $div
- (call $inexact
- (struct.get $fraction $num (ref.cast $fraction (local.get $x))))
- (call $inexact
- (struct.get $fraction $denom (ref.cast $fraction (local.get $x)))))))))
- ;; compute (logand x #xffffFFFF). precondition: x is exact integer.
- (func $scm->u32/truncate (param $x (ref eq)) (result i32)
- (if i32
- (ref.test i31 (local.get $x))
- (then (i32.shr_s (i31.get_s (ref.cast i31 (local.get $x)))
- (i32.const 1)))
- (else
- (i32.wrap_i64
- (call $bignum-get-i64
- (struct.get $bignum $val
- (ref.cast $bignum (local.get $x))))))))
- (func $abs (param $x (ref eq)) (result (ref eq))
- ,(arith-cond
- '((call $fixnum? (local.get $x))
- (if (result (ref eq))
- (call $negative-integer? (local.get $x))
- (then (call $mul (local.get $x) (call $i32->fixnum (i32.const -1))))
- (else (local.get $x))))
- '((ref.test $bignum (local.get $x))
- (if (result (ref eq))
- (call $negative-integer? (local.get $x))
- (then (call $mul (local.get $x) (call $i32->fixnum (i32.const -1))))
- (else (local.get $x))))
- ;; FIXME: not actually tested yet, as the compiler typically uses $fabs
- '((ref.test $flonum (local.get $x))
- (struct.new $flonum
- (i32.const 0)
- (f64.abs (call $flonum->f64 (ref.cast $flonum (local.get $x))))))
- '((ref.test $fraction (local.get $x))
- (if (result (ref eq))
- (call $negative-integer?
- (struct.get $fraction $num
- (ref.cast $fraction (local.get $x))))
- (then (call $mul (local.get $x) (call $i32->fixnum (i32.const -1))))
- (else (local.get $x))))))
- (func $remz (param $m (ref eq)) (param $n (ref eq))
- (result (ref eq))
- ,(arith-cond
- `((call $fixnum? (local.get $m))
- ,(arith-cond
- '((call $fixnum? (local.get $n))
- (call $i32->fixnum
- (i32.rem_s
- (call $fixnum->i32
- (ref.cast i31 (local.get $m)))
- (call $fixnum->i32
- (ref.cast i31 (local.get $n))))))
- '((ref.test $bignum (local.get $n))
- (call $bignum-rem*
- (ref.cast $bignum
- (call $i32->bignum
- (call $fixnum->i32
- (ref.cast i31
- (local.get $m)))))
- (ref.cast $bignum (local.get $n))))))
- `((ref.test $bignum (local.get $m))
- ,(arith-cond
- '((call $fixnum? (local.get $n))
- (call $bignum-rem*
- (ref.cast $bignum (local.get $m))
- (ref.cast $bignum
- (call $i32->bignum
- (call $fixnum->i32
- (ref.cast i31
- (local.get $n)))))))
- '((ref.test $bignum (local.get $n))
- (call $bignum-rem*
- (ref.cast $bignum (local.get $m))
- (ref.cast $bignum (local.get $n))))))))
- ;; floor of $M/$N, with $M, $N in Z and $N > 0 and both integers
- ;; normalized: (m - m mod n)/n, where m mod n = (% (+ (% m n) n) n)
- (func $fracfloor (param $m (ref eq)) (param $n (ref eq)) (result (ref eq))
- (call $div
- (call $sub
- (local.get $m)
- (call $remz
- (call $add
- (call $remz
- (local.get $m)
- (local.get $n))
- (local.get $n))
- (local.get $n)))
- (local.get $n)))
- (func $floor (param $x (ref eq)) (result (ref eq))
- ,(arith-cond
- '((call $fixnum? (local.get $x))
- (local.get $x))
- '((ref.test $bignum (local.get $x))
- (local.get $x))
- '((ref.test $flonum (local.get $x))
- (struct.new $flonum
- (i32.const 0)
- (f64.floor (call $flonum->f64 (ref.cast $flonum (local.get $x))))))
- '((ref.test $fraction (local.get $x))
- (call $fracfloor
- (struct.get $fraction $num
- (ref.cast $fraction (local.get $x)))
- (struct.get $fraction $denom
- (ref.cast $fraction (local.get $x)))))))
- (func $ceiling (param $x (ref eq)) (result (ref eq))
- ,(arith-cond
- '((call $fixnum? (local.get $x))
- (local.get $x))
- '((ref.test $bignum (local.get $x))
- (local.get $x))
- '((ref.test $flonum (local.get $x))
- (struct.new $flonum
- (i32.const 0)
- (f64.ceil (call $flonum->f64 (ref.cast $flonum (local.get $x))))))
- '((ref.test $fraction (local.get $x))
- (call $add
- (call $floor (local.get $x))
- (call $i32->fixnum (i32.const 1))))))
- (func $sqrt (param $x (ref eq)) (result (ref $flonum))
- ,(call-fmath '$fsqrt '(local.get $x)))
- (func $sin (param $x (ref eq)) (result (ref eq))
- ,(call-fmath '$fsin '(local.get $x)))
- (func $cos (param $x (ref eq)) (result (ref eq))
- ,(call-fmath '$fcos '(local.get $x)))
- (func $tan (param $x (ref eq)) (result (ref eq))
- ,(call-fmath '$ftan '(local.get $x)))
- (func $asin (param $x (ref eq)) (result (ref eq))
- ,(call-fmath '$fasin '(local.get $x)))
- (func $acos (param $x (ref eq)) (result (ref eq))
- ,(call-fmath '$facos '(local.get $x)))
- (func $atan (param $x (ref eq)) (result (ref eq))
- ,(call-fmath '$fatan '(local.get $x)))
- (func $atan2 (param $x (ref eq)) (param $y (ref eq)) (result (ref eq))
- ,(call-fmath '$fatan2 '(local.get $x) '(local.get $y)))
- (func $log (param $x (ref eq)) (result (ref eq))
- ,(call-fmath '$flog '(local.get $x)))
- (func $exp (param $x (ref eq)) (result (ref eq))
- ,(call-fmath '$fexp '(local.get $x)))
- (func $u64->bignum (param $i64 i64) (result (ref eq))
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-u64 (local.get $i64))))
- (func $s64->bignum (param $i64 i64) (result (ref eq))
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i64 (local.get $i64))))
- (func $bignum->u64 (param $x (ref $bignum)) (result i64)
- (local $n (ref extern))
- (local.set $n (struct.get $bignum $val (local.get $x)))
- (if i64
- (call $bignum-is-u64 (local.get $n))
- (then (call $bignum-get-i64 (local.get $n)))
- (else
- (call $die (string.const "$bignum->u64 out of range")
- (local.get $x))
- (unreachable))))
- (func $bignum->s64 (param $x (ref $bignum)) (result i64)
- (local $n (ref extern))
- (local.set $n (struct.get $bignum $val (local.get $x)))
- (if i64
- (call $bignum-is-i64 (local.get $n))
- (then (call $bignum-get-i64 (local.get $n)))
- (else
- (call $die (string.const "$bignum->s64 out of range")
- (local.get $x))
- (unreachable))))
- (func $scm->s64 (param $a (ref eq)) (result i64)
- (if i64
- (call $fixnum? (local.get $a))
- (then
- (i64.extend_i32_s
- (i32.shr_s (i31.get_s (ref.cast i31 (local.get $a)))
- (i32.const 1))))
- (else
- (if i64
- (ref.test $bignum (local.get $a))
- (then
- (return_call $bignum->s64
- (ref.cast $bignum (local.get $a))))
- (else
- (call $die (string.const "$scm->s64 bad arg")
- (local.get $a))
- (unreachable))))))
- (func $scm->u64 (param $a (ref eq)) (result i64)
- (local $i i32)
- (if i64
- (ref.test i31 (local.get $a))
- (then
- (local.set $i (i31.get_s (ref.cast i31 (local.get $a))))
- (if i64
- (i32.and (local.get $i) (i32.const ,(logior 1 (ash -1 31))))
- (then
- (call $die
- (string.const "$scm->u64 bad arg")
- (local.get $a))
- (unreachable))
- (else
- (i64.extend_i32_u
- (i32.shr_u (local.get $i) (i32.const 1))))))
- (else
- (if i64
- (ref.test $bignum (local.get $a))
- (then
- (return_call $bignum->u64
- (ref.cast $bignum (local.get $a))))
- (else
- (call $die
- (string.const "$scm->u64 bad arg")
- (local.get $a))
- (unreachable))))))
- (func $scm->u64/truncate (param $a (ref eq)) (result i64)
- ,(arith-cond 'i64
- '((call $fixnum? (local.get $a))
- (i64.extend_i32_u
- (call $fixnum->i32 (ref.cast i31 (local.get $a)))))
- '((ref.test $bignum (local.get $a))
- (call $bignum-get-i64
- (struct.get $bignum $val (ref.cast $bignum (local.get $a)))))
- '((i32.const 0)
- (call $die
- (string.const "$scm->u64 bad arg")
- (local.get $a))
- (unreachable))))
- (func $s64->scm (param $a i64) (result (ref eq))
- (if (result (ref eq))
- (i32.and (i64.ge_s (local.get $a) (i64.const ,(ash -1 29)))
- (i64.lt_s (local.get $a) (i64.const ,(ash 1 29))))
- (then (ref.i31
- (i32.shl (i32.wrap_i64 (local.get $a))
- (i32.const 1))))
- (else (return_call $s64->bignum (local.get $a)))))
- (func $s32->scm (param $a i32) (result (ref eq))
- (if (ref eq)
- (i32.and (i32.ge_s (local.get $a) (i32.const ,(ash -1 29)))
- (i32.lt_s (local.get $a) (i32.const ,(ash 1 29))))
- (then (call $i32->fixnum (local.get $a)))
- (else (return_call $s64->bignum (i64.extend_i32_s (local.get $a))))))
- (func $string->wtf8
- (param $str (ref string)) (result (ref $raw-bytevector))
- (local $vu0 (ref $raw-bytevector))
- (local.set $vu0
- (array.new_default
- $raw-bytevector
- (string.measure_wtf8 (local.get $str))))
- (string.encode_wtf8_array (local.get $str)
- (local.get $vu0)
- (i32.const 0))
- (local.get $vu0))
- (func $wtf8->string
- (param $bv (ref $raw-bytevector)) (result (ref string))
- (string.new_lossy_utf8_array (local.get $bv)
- (i32.const 0)
- (array.len (local.get $bv))))
- (func $set-fluid-and-return-prev (param $nargs i32)
- (param $arg0 (ref eq)) (param $arg1 (ref eq))
- (param $arg2 (ref eq))
- (local $fluid (ref $fluid))
- (local $prev (ref eq))
- (if (i32.eqz (local.get $nargs))
- (then
- (return_call $raise-arity-error
- (string.const "[parameter conversion result]")
- (ref.i31 (i32.const 1)))))
- (global.set $scm-sp (i32.sub (global.get $scm-sp) (i32.const 1)))
- (local.set $fluid
- (ref.cast $fluid
- (table.get $scm-stack (global.get $scm-sp))))
- (local.set $prev (call $fluid-ref (local.get $fluid)))
- (call $fluid-set! (local.get $fluid) (local.get $arg0))
- (global.set $ret-sp (i32.sub (global.get $ret-sp) (i32.const 1)))
- (return_call_ref $kvarargs
- (i32.const 1)
- (local.get $prev)
- (ref.i31 (i32.const 1))
- (ref.i31 (i32.const 1))
- (table.get $ret-stack (global.get $ret-sp))))
- (func $parameter (param $nargs i32) (param $arg0 (ref eq))
- (param $arg1 (ref eq)) (param $arg2 (ref eq))
- (local $parameter (ref $parameter))
- (local.set $parameter (ref.cast $parameter (local.get $arg0)))
- (if (i32.eq (local.get $nargs) (i32.const 1))
- (then
- (global.set $ret-sp
- (i32.sub (global.get $ret-sp) (i32.const 1)))
- (return_call_ref $kvarargs
- (i32.const 1)
- (call $fluid-ref
- (struct.get $parameter $fluid
- (local.get $parameter)))
- (ref.i31 (i32.const 1))
- (ref.i31 (i32.const 1))
- (table.get $ret-stack (global.get $ret-sp)))))
- (if (i32.ne (local.get $nargs) (i32.const 2))
- (then
- (return_call $raise-arity-error
- (string.const "[parameter]")
- (local.get $arg0))))
- (global.set $scm-sp (i32.add (global.get $scm-sp) (i32.const 1)))
- (call $maybe-grow-scm-stack)
- (global.set $ret-sp (i32.add (global.get $ret-sp) (i32.const 1)))
- (call $maybe-grow-ret-stack)
- (table.set $scm-stack (i32.sub (global.get $scm-sp) (i32.const 1))
- (struct.get $parameter $fluid (local.get $parameter)))
- (table.set $ret-stack (i32.sub (global.get $ret-sp) (i32.const 1))
- (ref.func $set-fluid-and-return-prev))
- (return_call_ref $kvarargs
- (i32.const 2)
- (struct.get $parameter $convert
- (local.get $parameter))
- (local.get $arg1)
- (ref.i31 (i32.const 1))
- (struct.get $proc $func
- (struct.get $parameter $convert
- (local.get $parameter)))))
- (table ,@(maybe-import '$argv) 0 (ref null eq))
- (table ,@(maybe-import '$scm-stack) 0 (ref null eq))
- (table ,@(maybe-import '$ret-stack) 0 (ref null $kvarargs))
- (table ,@(maybe-import '$dyn-stack) 0 (ref null $dyn))
- (memory ,@(maybe-import '$raw-stack) 0)
- (tag ,@(maybe-import '$trampoline-tag)
- (param $nargs i32)
- (param $arg0 (ref eq))
- (param $arg1 (ref eq))
- (param $arg2 (ref eq))
- (param $func (ref $kvarargs))
- (param $nreturns i32))
- (global ,@(maybe-import '$arg3) (mut (ref eq)) ,@maybe-init-i31-zero)
- (global ,@(maybe-import '$arg4) (mut (ref eq)) ,@maybe-init-i31-zero)
- (global ,@(maybe-import '$arg5) (mut (ref eq)) ,@maybe-init-i31-zero)
- (global ,@(maybe-import '$arg6) (mut (ref eq)) ,@maybe-init-i31-zero)
- (global ,@(maybe-import '$arg7) (mut (ref eq)) ,@maybe-init-i31-zero)
- (global ,@(maybe-import '$ret-sp) (mut i32) ,@maybe-init-i32-zero)
- (global ,@(maybe-import '$scm-sp) (mut i32) ,@maybe-init-i32-zero)
- (global ,@(maybe-import '$raw-sp) (mut i32) ,@maybe-init-i32-zero)
- (global ,@(maybe-import '$dyn-sp) (mut i32) ,@maybe-init-i32-zero)
- (global ,@(maybe-import '$current-fluids) (mut (ref $hash-table))
- ,@maybe-init-hash-table)
- (global ,@(maybe-import '$raise-exception) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$with-exception-handler) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$current-input-port) (mut (ref eq))
- ,@maybe-init-i31-zero)
- (global ,@(maybe-import '$current-output-port) (mut (ref eq))
- ,@maybe-init-i31-zero)
- (global ,@(maybe-import '$current-error-port) (mut (ref eq))
- ,@maybe-init-i31-zero)
- (global ,@(maybe-import '$default-prompt-tag) (mut (ref eq))
- ,@maybe-init-i31-zero)
- (global ,@(maybe-import '$make-size-error) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-index-error) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-range-error) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-start-offset-error) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-end-offset-error) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-type-error) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-unimplemented-error) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-assertion-error) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-not-seekable-error) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-runtime-error-with-message) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-runtime-error-with-message+irritants) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-match-error) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-arity-error) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-invalid-keyword-error) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-unrecogized-keyword-error) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-missing-keyword-argument-error) (mut (ref $proc))
- ,@maybe-init-proc))))
- (define (memoize f)
- (define cache (make-hash-table))
- (lambda args
- (match (hash-ref cache args)
- (#f (call-with-values (lambda () (apply f args))
- (lambda res
- (hash-set! cache args res)
- (apply values res))))
- (res (apply values res)))))
- (define compute-stdlib/memoized (memoize compute-stdlib))
|