12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817 |
- ;;; 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)
- #:export ((compute-stdlib/memoized . compute-stdlib)))
- (define (u32->s32 x)
- (centered-remainder x (ash 1 32)))
- (define (fixnum-immediate i) `(ref.i31 (i32.const ,(ash i 1))))
- (define min-fixnum (- (ash 1 29)))
- (define max-fixnum (1- (ash 1 29)))
- (define* (compute-stdlib import-abi? #:optional (max-struct-nfields 0))
- (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))))
- (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)))))
- (define vtable-nfields (length vtable-fields))
- (define max-struct-nfields* (max max-struct-nfields vtable-nfields))
- (define no-source
- '((ref.null string)
- (i32.const 0)
- (i32.const 0)))
- (define propagate-source
- '((local.get $file)
- (local.get $line)
- (local.get $col)))
- (define (call-fmath fn . args)
- ;; FIXME: Most of these operations are specified to support complex
- ;; numbers, but we don't do that yet.
- `(struct.new $flonum
- (i32.const 0)
- (call ,fn
- ,@(map (lambda (arg)
- `(call $scm->f64 ,arg
- ,@propagate-source))
- args))))
- (define* (dispatch-unary-numeric-operation
- op x #:key
- (source propagate-source)
- (s64? #f)
- (u64? #f)
- (exact-integer? (or s64? u64?))
- (real? exact-integer?)
- (check? #t)
- (subr #f)
- (prelude '())
- (expected-type (cond
- (s64? "exact integer in s64 range")
- (u64? "exact integer in u64 range")
- (exact-integer? "exact integer")
- (real? "real number")
- (else "number")))
- (unpack-fixnum
- (if check?
- `((if ,(let ((check '(i32.and (local.tee $tmp-i32 (i31.get_s))
- (i32.const 1))))
- (if s64?
- `(i32.or ,check
- (i32.lt_s (local.get $tmp-i32)
- (i32.const 0)))
- check))
- (then (br $bad-operand (ref.i31 (local.get $tmp-i32)))))
- (i32.shr_s (local.get $tmp-i32) (i32.const 1)))
- `((i32.shr_s (i31.get_s) (i32.const 1)))))
- (unpack-bignum
- (if (and check? (or s64? u64?))
- `((local.tee $tmp-bignum (struct.get $bignum $val))
- (if (i32.eqz (call ,(if s64?
- '$bignum-is-i64
- '$bignum-is-u64)))
- (then (br $bad-operand (local.get ,x))))
- (local.get $tmp-bignum))
- `((struct.get $bignum $val))))
- (unpack-flonum `((struct.get $flonum $val)))
- (unpack-fraction
- `((struct.get $fraction $num (local.tee $tmp-fraction))
- (struct.get $fraction $denom (local.get $tmp-fraction))))
- (unpack-complex
- `((struct.get $complex $real (local.tee $tmp-complex))
- (struct.get $complex $imag (local.get $tmp-complex))))
- (dispatch
- (lambda (type)
- `((return_call ,(symbol-append op '- type))))))
- (define (bad-operand-block body)
- (if check?
- `((block $bad-operand (ref eq) ,@body)
- (call $raise-type-error
- (string.const ,subr)
- (string.const ,expected-type)
- (local.get ,x)
- ,@source)
- (unreachable))
- body))
- (define (complex-block body)
- (if real?
- body
- `((block $complex (ref $complex) ,@body)
- ,@unpack-complex ,@(dispatch 'complex))))
- (define (fraction-block body)
- (if exact-integer?
- body
- `((block $fraction (ref $fraction) ,@body)
- ,@unpack-fraction ,@(dispatch 'fraction))))
- (define (flonum-block body)
- (if exact-integer?
- body
- `((block $flonum (ref $flonum) ,@body)
- ,@unpack-flonum ,@(dispatch 'flonum))))
- (define (bignum-block body)
- `((block $bignum (ref $bignum) ,@body)
- ,@unpack-bignum ,@(dispatch 'bignum)))
- (define (fixnum-block body)
- `((block $i31 (ref i31) ,@body)
- ,@unpack-fixnum ,@(dispatch 'fixnum)))
- (define (test-type type label) `(br_on_cast ,label (ref eq) (ref ,type)))
- (define (test-type/tail type label)
- (if check?
- `(,(test-type type label)
- (br $bad-operand))
- `((ref.cast ,type))))
- (define (type-checks types)
- (match types
- (((head-type head-label) ... (tail-type tail-label))
- (cons `(local.get ,x)
- (append (map test-type head-type head-label)
- (test-type/tail tail-type tail-label ))))))
- (define (locals body)
- (define-syntax add-locals
- (syntax-rules ()
- ((_ body) body)
- ((_ body ((name type) test) . rest)
- (let ((locals (add-locals body . rest)))
- (if test
- (cons '(local name type) locals)
- locals)))))
- (add-locals
- body
- (($tmp-i32 i32) check?)
- (($tmp-bignum (ref extern)) (and check? (or s64? u64?)))
- (($tmp-fraction (ref $fraction)) (not exact-integer?))
- (($tmp-complex (ref $complex)) (not real?))))
- (locals
- (bad-operand-block
- (fixnum-block
- (bignum-block
- (flonum-block
- (fraction-block
- (complex-block
- (type-checks
- `((i31 $i31)
- ($bignum $bignum)
- ,@(if exact-integer? '() '(($flonum $flonum)))
- ,@(if exact-integer? '() '(($fraction $fraction)))
- ,@(if real? '() '(($complex $complex)))))))))))))
- (define* (dispatch-binary-numeric-operation
- op a b #:key
- (source propagate-source)
- (integer? #f)
- (exact? #f)
- (real? (or integer? exact?))
- (check? #t)
- (subr #f)
- (prelude '())
- (expected-type (cond
- (integer? (if exact? "exact integer" "integer"))
- (exact? "exact number")
- (real? "real number")
- (else "number")))
- (unpack-fixnum
- (if check?
- `((if (i32.and (local.tee $tmp-i32 (i31.get_s))
- (i32.const 1))
- (then (br $bad-operand (ref.i31 (local.get $tmp-i32)))))
- (i32.shr_s (local.get $tmp-i32) (i32.const 1)))
- `((i32.shr_s (i31.get_s) (i32.const 1)))))
- (unpack-bignum `((struct.get $bignum $val)))
- (unpack-flonum
- (if (and integer? check?)
- `((local.tee $tmp-flonum)
- (if (i32.eqz
- (call $f64-integer?
- (local.tee $tmp-f64 (struct.get $flonum $val))))
- (then (br $bad-operand (local.get $tmp-flonum))))
- (local.get $tmp-f64))
- `((struct.get $flonum $val))))
- (unpack-fraction
- `((struct.get $fraction $num (local.tee $tmp-fraction))
- (struct.get $fraction $denom (local.get $tmp-fraction))))
- (unpack-complex
- `((struct.get $complex $real (local.tee $tmp-complex))
- (struct.get $complex $imag (local.get $tmp-complex))))
- (unpacked-fixnum '(i32))
- (unpacked-bignum '((ref extern)))
- (unpacked-flonum '(f64))
- (unpacked-fraction '((ref eq) (ref eq)))
- (unpacked-complex '(f64 f64))
- (dispatch
- (lambda (a-type b-type)
- `((return_call ,(symbol-append op '- a-type '- b-type))))))
- (define (locals body)
- (define-syntax add-locals
- (syntax-rules ()
- ((_ body) body)
- ((_ body ((name type) test) . rest)
- (let ((locals (add-locals body . rest)))
- (if test
- (cons '(local name type) locals)
- locals)))))
- (add-locals
- body
- (($tmp-i32 i32) check?)
- (($tmp-f64 f64) (and integer? check? (not exact?)))
- (($tmp-flonum (ref $flonum)) (and integer? check? (not exact?)))
- (($tmp-scm (ref eq)) check?)
- (($tmp-fraction (ref $fraction)) (not integer?))
- (($tmp-complex (ref $complex)) (not real?))))
- (define (bad-operand-block body)
- (if check?
- `((block $bad-operand (ref eq) ,@body)
- (local.set $tmp-scm)
- (call $raise-type-error
- (string.const ,subr)
- (string.const ,expected-type)
- (local.get $tmp-scm)
- ,@source)
- (unreachable))
- body))
- (define (test-type type label) `(br_on_cast ,label (ref eq) (ref ,type)))
- (define (test-type/tail type label)
- (if check?
- `(,(test-type type label)
- (br $bad-operand))
- `((ref.cast ,type))))
- (define (type-checks x types)
- (match types
- (((head-type head-label) ... (tail-type tail-label))
- (cons `(local.get ,x)
- (append (map test-type head-type head-label)
- (test-type/tail tail-type tail-label))))))
- (define (dispatch-b a-params a-type)
- (define (fixnum-block body)
- `((block $b-i31
- (param ,@a-params) (result ,@a-params (ref i31))
- ,@body)
- ,@unpack-fixnum
- ,@(dispatch a-type 'fixnum)))
- (define (bignum-block body)
- `((block $b-bignum
- (param ,@a-params) (result ,@a-params (ref $bignum))
- ,@body)
- ,@unpack-bignum
- ,@(dispatch a-type 'bignum)))
- (define (flonum-block body)
- (if exact?
- body
- `((block $b-flonum
- (param ,@a-params) (result ,@a-params (ref $flonum))
- ,@body)
- ,@unpack-flonum
- ,@(dispatch a-type 'flonum))))
- (define (fraction-block body)
- (if integer?
- body
- `((block $b-fraction
- (param ,@a-params) (result ,@a-params (ref $fraction))
- ,@body)
- ,@unpack-fraction
- ,@(dispatch a-type 'fraction))))
- (define (complex-block body)
- (if real?
- body
- `((block $b-complex
- (param ,@a-params) (result ,@a-params (ref $complex))
- ,@body)
- ,@unpack-complex
- ,@(dispatch a-type 'complex))))
- (fixnum-block
- (bignum-block
- (flonum-block
- (fraction-block
- (complex-block
- (type-checks b
- `((i31 $b-i31)
- ($bignum $b-bignum)
- ,@(if exact? '() '(($flonum $b-flonum)))
- ,@(if integer? '() '(($fraction $b-fraction)))
- ,@(if real? '() '(($complex $b-complex)))))))))))
- (define (dispatch-a)
- (define (fixnum-block body)
- `((block $a-i31 (ref i31) ,@body)
- ,@unpack-fixnum
- ,@(dispatch-b unpacked-fixnum 'fixnum)))
- (define (bignum-block body)
- `((block $a-bignum (ref $bignum) ,@body)
- ,@unpack-bignum
- ,@(dispatch-b unpacked-bignum 'bignum)))
- (define (flonum-block body)
- (if exact?
- body
- `((block $a-flonum (ref $flonum) ,@body)
- ,@unpack-flonum
- ,@(dispatch-b unpacked-flonum 'flonum))))
- (define (fraction-block body)
- (if integer?
- body
- `((block $a-fraction (ref $fraction) ,@body)
- ,@unpack-fraction
- ,@(dispatch-b unpacked-fraction 'fraction))))
- (define (complex-block body)
- (if real?
- body
- `((block $a-complex (ref $complex) ,@body)
- ,@unpack-complex
- ,@(dispatch-b unpacked-complex 'complex))))
- (fixnum-block
- (bignum-block
- (flonum-block
- (fraction-block
- (complex-block
- (type-checks a
- `((i31 $a-i31)
- ($bignum $a-bignum)
- ,@(if exact? '() '(($flonum $a-flonum)))
- ,@(if integer? '() '(($fraction $a-fraction)))
- ,@(if real? '() '(($complex $a-complex)))))))))))
- (locals (append prelude (bad-operand-block (dispatch-a)))))
- (define (commutative-arithmetic-operation-implementations op)
- `((func ,(symbol-append op '-bignum-fixnum)
- (param $a (ref extern)) (param $b i32)
- (result (ref eq))
- (return_call ,(symbol-append op '-fixnum-bignum)
- (local.get $b) (local.get $a)))
- (func ,(symbol-append op '-flonum-fixnum)
- (param $a f64) (param $b i32)
- (result (ref eq))
- (return_call ,(symbol-append op '-fixnum-flonum)
- (local.get $b) (local.get $a)))
- (func ,(symbol-append op '-flonum-bignum)
- (param $a f64) (param $b (ref extern))
- (result (ref eq))
- (return_call ,(symbol-append op '-bignum-flonum)
- (local.get $b) (local.get $a)))
- (func ,(symbol-append op '-fraction-fixnum)
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b i32)
- (result (ref eq))
- (return_call ,(symbol-append op '-fixnum-fraction)
- (local.get $b)
- (local.get $a-num) (local.get $a-denom)))
- (func ,(symbol-append op '-fraction-bignum)
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b (ref extern))
- (result (ref eq))
- (return_call ,(symbol-append op '-bignum-fraction)
- (local.get $b)
- (local.get $a-num) (local.get $a-denom)))
- (func ,(symbol-append op '-fraction-flonum)
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b f64)
- (result (ref eq))
- (return_call ,(symbol-append op '-flonum-fraction)
- (local.get $b)
- (local.get $a-num) (local.get $a-denom)))
- (func ,(symbol-append op '-complex-fixnum)
- (param $a-real f64) (param $a-imag f64)
- (param $b i32)
- (result (ref eq))
- (return_call ,(symbol-append op '-fixnum-complex)
- (local.get $b)
- (local.get $a-real) (local.get $a-imag)))
- (func ,(symbol-append op '-complex-bignum)
- (param $a-real f64) (param $a-imag f64)
- (param $b (ref extern))
- (result (ref eq))
- (return_call ,(symbol-append op '-bignum-complex)
- (local.get $b)
- (local.get $a-real) (local.get $a-imag)))
- (func ,(symbol-append op '-complex-flonum)
- (param $a-real f64) (param $a-imag f64)
- (param $b f64)
- (result (ref eq))
- (return_call ,(symbol-append op '-flonum-complex)
- (local.get $b)
- (local.get $a-real) (local.get $a-imag)))
- (func ,(symbol-append op '-complex-fraction)
- (param $a-real f64) (param $a-imag f64)
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call ,(symbol-append op '-fraction-complex)
- (local.get $b-num) (local.get $b-denom)
- (local.get $a-real) (local.get $a-imag)))))
- (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 $code-ref
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $val (ref func)))))
- (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 $syntax-transformer
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $type (ref eq))
- (field $value (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
- (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 $val (ref eq))
- ;; Satisfy the validator by setting a default value.
- (local.set $val (ref.i31 (i32.const 1)))
- (if (call $fixnum? (local.get $arg2))
- (then
- ;; This is pretty gnarly, but we need to pick the
- ;; right struct type to cast to based on the field
- ;; index.
- (block $done (ref eq)
- (block $out-of-bounds (ref eq)
- ,@(let lp ((i 0))
- (define (block-name nfields)
- (string->symbol (format #f "$ref-field~a" nfields)))
- (if (= i max-struct-nfields*)
- `((local.get $arg1)
- (i32.shr_s (i31.get_s
- (ref.cast i31 (local.get $arg2)))
- (i32.const 1))
- (br_table ,@(map block-name
- (iota max-struct-nfields*))
- $out-of-bounds)
- (unreachable))
- `((block ,(block-name i) (ref eq)
- ,@(lp (1+ i)))
- (br_on_cast_fail $out-of-bounds (ref eq)
- (ref ,(struct-name (1+ i))))
- (struct.get ,(struct-name (1+ i)) ,(+ i 2))
- (br $done)))))
- (drop)
- (call $raise-range-error
- (string.const "struct-ref")
- (local.get $arg2)
- ,@no-source)
- (unreachable))
- (local.set $val))
- (else
- (call $raise-type-error
- (string.const "struct-ref")
- (string.const "idx")
- (local.get $arg2)
- ,@no-source)
- (unreachable)))
- (i32.const 1)
- (local.get $val)
- (ref.i31 (i32.const 1))
- (ref.i31 (i32.const 1))
- (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 $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 $annotate-exception (param $exn (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (return_call_ref $kvarargs
- (i32.const 5)
- (global.get $annotate-with-source)
- (local.get $exn)
- (if (ref eq)
- (ref.is_null (local.get $file))
- (then (ref.i31 (i32.const 1)))
- (else (struct.new
- $string (i32.const 0)
- (ref.as_non_null (local.get $file)))))
- (global.set $arg3
- (call $i32->fixnum (local.get $line)))
- (global.set $arg4
- (call $i32->fixnum (local.get $col)))
- (struct.get $proc $func
- (global.get $annotate-with-source))))
- (func $raise-exception-with-annotation (param $exn (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- ;; FIXME: Annotate the exception.
- (call $push-raise-returned-value)
- (return_call $annotate-exception (local.get $exn)
- (local.get $file) (local.get $line) (local.get $col)))
- (global $exception-source-file (mut (ref null string)) (ref.null string))
- (global $exception-source-line (mut i32) (i32.const 0))
- (global $exception-source-column (mut i32) (i32.const 0))
- (func $annotate-returned-exception
- (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 make-exception return"))))
- (return_call $annotate-exception
- (local.get $arg0)
- (global.get $exception-source-file)
- (global.get $exception-source-line)
- (global.get $exception-source-column)))
- (func $push-annotate-returned-exception
- (param $file (ref null string)) (param $line i32) (param $col i32)
- ;; If line is 0, there is no source; nothing to do..
- (if (local.get $line)
- (then
- (global.set $exception-source-file (local.get $file))
- (global.set $exception-source-line (local.get $line))
- (global.set $exception-source-column (local.get $col))
- (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 $annotate-returned-exception)))))
- (func $push-annotate-and-raise-returned-exception
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (call $push-raise-returned-value)
- (call $push-annotate-returned-exception
- (local.get $file) (local.get $line) (local.get $col)))
- ;; FIXME: In all of these, we need to plumb $file, $line, and $col
- ;; to $annotate-with-source.
- (func $raise-type-error
- (param $subr (ref string))
- (param $what (ref string))
- (param $val (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (call $push-annotate-and-raise-returned-exception
- (local.get $file) (local.get $line) (local.get $col))
- (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))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (call $push-annotate-and-raise-returned-exception
- (local.get $file) (local.get $line) (local.get $col))
- (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))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (call $push-annotate-and-raise-returned-exception
- (local.get $file) (local.get $line) (local.get $col))
- (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))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (call $push-annotate-and-raise-returned-exception
- (local.get $file) (local.get $line) (local.get $col))
- (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))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (call $push-annotate-and-raise-returned-exception
- (local.get $file) (local.get $line) (local.get $col))
- (return_call_ref
- $kvarargs
- (i32.const 2)
- (global.get $make-unrecognized-keyword-error)
- (local.get $kw)
- (ref.i31 (i32.const 1))
- (struct.get $proc $func
- (global.get $make-unrecognized-keyword-error)))
- (unreachable))
- (func $raise-missing-keyword-argument-error (param $kw (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (call $push-annotate-and-raise-returned-exception
- (local.get $file) (local.get $line) (local.get $col))
- (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))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (call $push-annotate-and-raise-returned-exception
- (local.get $file) (local.get $line) (local.get $col))
- (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))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (call $push-annotate-and-raise-returned-exception
- (local.get $file) (local.get $line) (local.get $col))
- (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-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 $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-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-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 $bignum->f64 (import "rt" "bignum_to_f64")
- (param (ref extern))
- (result f64))
- (func $f64-is-nan (param $x f64) (result i32)
- (i32.eqz (f64.eq (local.get $x) (local.get $x))))
- ,@(let ((sign-bit (ash -1 63))
- (exponent-bits (ash (1- (ash 1 11)) 52)))
- ;; An f64 has 1 sign bit, 11 exponent bits, and 52 signicand
- ;; bits. If all exponent bits are set, it is an infinity if
- ;; all significand bits are 0, otherwise it is a nan.
- `((func $f64-is-infinite (param $x f64) (result i32)
- (i64.eq
- (i64.const ,exponent-bits)
- (i64.and (i64.const ,(lognot sign-bit))
- (i64.reinterpret_f64 (local.get $x)))))
- (func $f64-is-finite (param $x f64) (result i32)
- (i64.ne
- (i64.const ,exponent-bits)
- (i64.and (i64.reinterpret_f64 (local.get $x))
- (i64.const ,exponent-bits))))))
- (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 $quit (import "rt" "quit") (param i32))
- (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 $code-name (import "debug" "code_name")
- (param (ref func))
- (result (ref null string)))
- (func $code-source (import "debug" "code_source")
- (param (ref func))
- (result (ref null string) i32 i32))
- (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) i32)
- (local $fresh (ref $symbol))
- (local $interned (ref $symbol))
- (local.set $fresh
- (struct.new $symbol
- (call $finish-heap-object-hash
- (call $string-hash
- (struct.get $string $str
- (local.get $str))))
- (local.get $str)))
- (local.set $interned (call $intern-symbol! (local.get $fresh)))
- (local.get $interned)
- (ref.eq (local.get $interned) (local.get $fresh)))
- (func $string->symbol (param $str (ref $string)) (result (ref $symbol))
- (call $string->symbol* (local.get $str))
- (drop))
- (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)))
- ,@no-source))))
- (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)
- ,@no-source)))
- ;; $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)))
- ,@no-source))
- (func $get-callee-code (param $callee (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref $kvarargs))
- (block $proc (ref $proc)
- (br_on_cast $proc (ref eq) (ref $proc) (local.get $callee))
- (call $raise-type-error
- (string.const "apply")
- (string.const "procedure")
- (local.get $callee)
- ,@propagate-source)
- (unreachable))
- (struct.get $proc $func))
- (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)
- ,@no-source)))
- (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)
- ,@no-source)))))
- (global $apply-primitive (ref eq)
- (struct.new $proc (i32.const 0) (ref.func $apply)))
- ;; TODO: write tests once `fixnum?' or similar is available
- (func $bignum->scm (param $val (ref extern)) (result (ref eq))
- (local $i64 i64)
- (if (call $bignum-is-i64 (local.get $val))
- (then
- (local.set $i64 (call $bignum-get-i64 (local.get $val)))
- (if (i32.and (i64.le_s (i64.const #x-20000000)
- (local.get $i64))
- (i64.le_s (local.get $i64)
- (i64.const #x1FFFFFFF)))
- (then
- (return (ref.i31
- (i32.shl
- (i32.wrap_i64 (local.get $i64))
- (i32.const 1))))))))
- (struct.new $bignum (i32.const 0) (local.get $val)))
- ;; Helper function for $f64->exact
- (func $decode-f64 (param $frac i64) (param $expt i32) (param $sign i32)
- (result (ref eq) (ref eq))
- (if (i32.eq (local.get $sign) (i32.const 1))
- (then (local.set $frac (i64.mul (local.get $frac) (i64.const -1)))))
- (if (result (ref eq) (ref eq))
- (i32.lt_s (local.get $expt) (i32.const 0))
- (then
- ;; Divide $frac by 1/(2**|expt|). Note: might not be
- ;; fully reduced.
- (call $s64->scm (local.get $frac))
- (call $lsh-fixnum
- (i32.const 2)
- (i64.mul (i64.const -1)
- (i64.extend_i32_s
- (i32.add
- (local.get $expt)
- (i32.const 1))))))
- (else
- ;; Multiply $frac by 2**expt
- (call $multiply-integers
- (call $s64->scm (local.get $frac))
- (call $lsh-fixnum
- (i32.const 2)
- (i64.extend_i32_s
- (i32.add (local.get $expt)
- (i32.const 1)))))
- ,(fixnum-immediate 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->ratio (param $x f64) (result (ref eq) (ref eq))
- (local $bits i64)
- (local $raw-frac i64) ; raw significand
- (local $raw-expt i32) ; biased 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 (i32.and (i32.eqz (local.get $raw-expt))
- (i64.eqz (local.get $raw-frac)))
- (then ; zero (E = 0, F = 0)
- (return ,(fixnum-immediate 0)
- ,(fixnum-immediate 1))))
- (if (i32.eqz (local.get $raw-expt))
- (then ; subnormal (E = 0, F /= 0)
- (return_call $decode-f64
- (local.get $raw-frac)
- (i32.const -1074)
- (local.get $sign))))
- (if (i32.eq (local.get $raw-expt) (i32.const #x7FF))
- (then
- ;; nonrational (inf or NaN)
- (call $die0 (string.const "$decode-float bad arg"))
- (unreachable)))
- ;; normal (E /= 0, F /= #xFF)
- (return_call $decode-f64
- (i64.or (local.get $raw-frac)
- (i64.const ,(ash 1 52)))
- (i32.sub (local.get $raw-expt)
- (i32.const 1075))
- (local.get $sign)))
- (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 $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)))
- (func $fixnum->f64 (param $i i32) (result f64)
- (f64.convert_i32_s (local.get $i)))
- (func $integer->f64 (param $i (ref eq)) (result f64)
- (block
- $i31 (ref i31)
- (br_on_cast $i31 (ref eq) (ref i31) (local.get $i))
- (return_call $bignum->f64
- (struct.get $bignum $val (ref.cast $bignum))))
- (return_call $fixnum->f64 (i32.shr_s (i31.get_s) (i32.const 1))))
- (func $fraction->f64 (param $num (ref eq)) (param $denom (ref eq))
- (result f64)
- (f64.div (call $integer->f64 (local.get $num))
- (call $integer->f64 (local.get $denom))))
- (func $i64->scm (param $n i64) (result (ref eq))
- (if (ref eq)
- (i32.and (i64.ge_s (local.get $n) (i64.const ,min-fixnum))
- (i64.le_s (local.get $n) (i64.const ,max-fixnum)))
- (then (return_call $i32->fixnum (i32.wrap_i64 (local.get $n))))
- (else (struct.new $bignum
- (i32.const 0)
- (call $bignum-from-i64 (local.get $n))))))
- (func $i32->scm (param $n i32) (result (ref eq))
- (return_call $i64->scm (i64.extend_i32_s (local.get $n))))
- (func $scm->f64 (param $a (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result f64)
- ,@(dispatch-unary-numeric-operation
- '$scm->f64 '$a
- #:real? #t
- #:subr "scm->f64"
- #:dispatch (match-lambda
- ('flonum '((return)))
- (tp
- `((return_call ,(symbol-append '$ tp '->f64)))))))
- ;; Greatest common divisor: v. TAOCP II 4.5.2 Algorithm A (modern
- ;; Euclidean algorithm). TODO: use a modernized version of
- ;; Algorithm 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)))
- (func $negate-fixnum (param $n i32) (result (ref eq))
- (if (ref eq)
- (i32.eq (local.get $n) (i32.const ,min-fixnum))
- (then (return_call $i32->bignum (i32.const ,(- min-fixnum))))
- (else (return_call $i32->fixnum
- (i32.sub (i32.const 0) (local.get $n))))))
- (func $negate-bignum (param $n (ref extern)) (result (ref eq))
- (if (ref eq)
- (call $eq-big-flo (local.get $n) (f64.const ,(1+ max-fixnum)))
- (then ,(fixnum-immediate min-fixnum))
- (else
- (struct.new $bignum
- (i32.const 0)
- (call $bignum-mul-i32
- (local.get $n) (i32.const -1))))))
- (func $negate-integer (param $n (ref eq)) (result (ref eq))
- (block $i31 (ref i31)
- (br_on_cast $i31 (ref eq) (ref i31) (local.get $n))
- (return_call $negate-bignum
- (struct.get $bignum $val (ref.cast $bignum))))
- (return_call $negate-fixnum (i32.shr_s (i31.get_s) (i32.const 1))))
- (func $negate-flonum (param $n f64) (result (ref eq))
- (struct.new $flonum (i32.const 0) (f64.neg (local.get $n))))
- (func $negate-fraction (param $num (ref eq)) (param $denom (ref eq))
- (result (ref eq))
- (struct.new $fraction (i32.const 0)
- (call $negate-integer (local.get $num))
- (call $negate-integer (local.get $denom))))
- (func $negate-complex (param $real f64) (param $imag f64) (result (ref eq))
- (struct.new $complex (i32.const 0)
- (f64.neg (local.get $real)) (f64.neg (local.get $imag))))
- (func $negate (param $n (ref eq)) (result (ref eq))
- ,@(dispatch-unary-numeric-operation '$negate '$n #:check? #f))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Less-than.
- (func $<-fixnum-fixnum
- (param $a i32) (param $b i32) (result i32)
- (i32.lt_s (local.get $a) (local.get $b)))
- (func $<-fixnum-bignum
- (param $a i32) (param $b (ref extern)) (result i32)
- (return_call $lt-fix-big (local.get $a) (local.get $b)))
- (func $<-fixnum-flonum
- (param $a i32) (param $b f64) (result i32)
- (f64.lt (f64.convert_i32_s (local.get $a)) (local.get $b)))
- (func $<-fixnum-fraction (param $a i32)
- (param $b-num (ref eq)) (param $b-denom (ref eq)) (result i32)
- (return_call $<-fraction-fraction
- (call $i32->fixnum (local.get $a))
- ,(fixnum-immediate 1)
- (local.get $b-num)
- (local.get $b-denom)))
- (func $<-bignum-fixnum (param $a (ref extern)) (param $b i32)
- (result i32)
- (return_call $lt-big-fix (local.get $a) (local.get $b)))
- (func $<-bignum-bignum (param $a (ref extern)) (param $b (ref extern))
- (result i32)
- (return_call $lt-big-big (local.get $a) (local.get $b)))
- (func $<-bignum-flonum (param $a (ref extern)) (param $b f64)
- (result i32)
- (return_call $lt-big-flo (local.get $a) (local.get $b)))
- (func $<-bignum-fraction (param $a (ref extern))
- (param $b-num (ref eq)) (param $b-denom (ref eq)) (result i32)
- (return_call $<-fraction-fraction
- (struct.new $bignum (i32.const 0) (local.get $a))
- ,(fixnum-immediate 1)
- (local.get $b-num)
- (local.get $b-denom)))
- (func $<-flonum-fixnum
- (param $a f64) (param $b i32) (result i32)
- (f64.lt (local.get $a) (f64.convert_i32_s (local.get $b))))
- (func $<-flonum-bignum
- (param $a f64) (param $b (ref extern)) (result i32)
- (return_call $lt-flo-big (local.get $a) (local.get $b)))
- (func $<-flonum-flonum
- (param $a f64) (param $b f64) (result i32)
- (f64.lt (local.get $a) (local.get $b)))
- (func $<-flonum-fraction
- (param $a f64) (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result i32)
- (if (call $f64-is-finite (local.get $a))
- (then (return_call $<-fraction-fraction
- (call $f64->ratio (local.get $a))
- (local.get $b-num) (local.get $b-denom))))
- (f64.lt (local.get $a) (f64.const 0)))
- (func $<-fraction-fixnum
- (param $a-num (ref eq)) (param $a-denom (ref eq)) (param $b i32)
- (result i32)
- (return_call $<-fraction-fraction
- (local.get $a-num)
- (local.get $a-denom)
- (call $i32->fixnum (local.get $b))
- ,(fixnum-immediate 1)))
- (func $<-fraction-bignum
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b (ref extern))
- (result i32)
- (return_call $<-fraction-fraction
- (local.get $a-num)
- (local.get $a-denom)
- (struct.new $bignum (i32.const 0) (local.get $b))
- ,(fixnum-immediate 1)))
- (func $<-fraction-flonum
- (param $a-num (ref eq)) (param $a-denom (ref eq)) (param $b f64)
- (result i32)
- (if (call $f64-is-finite (local.get $b))
- (then
- (return_call $<-fraction-fraction
- (local.get $a-num) (local.get $a-denom)
- (call $f64->ratio (local.get $b)))))
- (f64.lt (f64.const 0) (local.get $b)))
- (func $<-fraction-fraction
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result i32)
- (return_call $<-integers
- (call $multiply-integers
- (local.get $a-num) (local.get $b-denom))
- (call $multiply-integers
- (local.get $b-num) (local.get $a-denom))))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Less-than-or-equal.
- (func $<=-fixnum-fixnum
- (param $a i32) (param $b i32) (result i32)
- (i32.eqz (call $<-fixnum-fixnum (local.get $b) (local.get $a))))
- (func $<=-fixnum-bignum
- (param $a i32) (param $b (ref extern)) (result i32)
- (i32.eqz (call $<-bignum-fixnum (local.get $b) (local.get $a))))
- (func $<=-fixnum-flonum
- (param $a i32) (param $b f64) (result i32)
- (f64.le (f64.convert_i32_s (local.get $a)) (local.get $b)))
- (func $<=-fixnum-fraction (param $a i32)
- (param $b-num (ref eq)) (param $b-denom (ref eq)) (result i32)
- (i32.eqz
- (call $<-fraction-fixnum
- (local.get $b-num) (local.get $b-denom) (local.get $a))))
- (func $<=-bignum-fixnum (param $a (ref extern)) (param $b i32)
- (result i32)
- (i32.eqz (call $<-fixnum-bignum (local.get $b) (local.get $a))))
- (func $<=-bignum-bignum (param $a (ref extern)) (param $b (ref extern))
- (result i32)
- (i32.eqz (call $<-bignum-bignum (local.get $b) (local.get $a))))
- (func $<=-bignum-flonum (param $a (ref extern)) (param $b f64)
- (result i32)
- (return_call $le-big-flo (local.get $a) (local.get $b)))
- (func $<=-bignum-fraction (param $a (ref extern))
- (param $b-num (ref eq)) (param $b-denom (ref eq)) (result i32)
- (i32.eqz
- (call $<-fraction-bignum
- (local.get $b-num) (local.get $b-denom) (local.get $a))))
- (func $<=-flonum-fixnum
- (param $a f64) (param $b i32) (result i32)
- (f64.le (local.get $a) (f64.convert_i32_s (local.get $b))))
- (func $<=-flonum-bignum
- (param $a f64) (param $b (ref extern)) (result i32)
- (return_call $le-flo-big (local.get $a) (local.get $b)))
- (func $<=-flonum-flonum
- (param $a f64) (param $b f64) (result i32)
- (f64.le (local.get $a) (local.get $b)))
- (func $<=-flonum-fraction
- (param $a f64) (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result i32)
- (if (call $f64-is-finite (local.get $a))
- (then
- (return_call $<=-fraction-fraction
- (call $f64->ratio (local.get $a))
- (local.get $b-num) (local.get $b-denom))))
- (f64.lt (local.get $a) (f64.const 0)))
- (func $<=-fraction-fixnum
- (param $a-num (ref eq)) (param $a-denom (ref eq)) (param $b i32)
- (result i32)
- (i32.eqz
- (call $<-fixnum-fraction
- (local.get $b) (local.get $a-num) (local.get $a-denom))))
- (func $<=-fraction-bignum
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b (ref extern))
- (result i32)
- (i32.eqz
- (call $<-bignum-fraction
- (local.get $b) (local.get $a-num) (local.get $a-denom))))
- (func $<=-fraction-flonum
- (param $a-num (ref eq)) (param $a-denom (ref eq)) (param $b f64)
- (result i32)
- (if (call $f64-is-finite (local.get $b))
- (then
- (return_call $<=-fraction-fraction
- (local.get $a-num) (local.get $a-denom)
- (call $f64->ratio (local.get $b)))))
- (f64.lt (f64.const 0) (local.get $b)))
- (func $<=-fraction-fraction
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result i32)
- (i32.eqz
- (call $<-fraction-fraction
- (local.get $b-num) (local.get $b-denom)
- (local.get $a-num) (local.get $a-denom))))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Numerical equality.
- (func $=-fixnum-fixnum
- (param $a i32) (param $b i32) (result i32)
- (i32.eq (local.get $a) (local.get $b)))
- (func $=-fixnum-bignum
- (param $a i32) (param $b (ref extern)) (result i32)
- (i32.const 0))
- (func $=-fixnum-flonum
- (param $a i32) (param $b f64) (result i32)
- (return_call $=-flonum-fixnum (local.get $b) (local.get $a)))
- (func $=-fixnum-fraction (param $a i32)
- (param $b-num (ref eq)) (param $b-denom (ref eq)) (result i32)
- (i32.const 0))
- (func $=-fixnum-complex (param $a i32)
- (param $b-real f64) (param $b-imag f64) (result i32)
- (return_call $=-complex-fixnum
- (local.get $b-real) (local.get $b-imag) (local.get $a)))
- (func $=-bignum-fixnum (param $a (ref extern)) (param $b i32)
- (result i32)
- (i32.const 0))
- (func $=-bignum-bignum (param $a (ref extern)) (param $b (ref extern))
- (result i32)
- (call $eq-big-big (local.get $a) (local.get $b)))
- (func $=-bignum-flonum (param $a (ref extern)) (param $b f64)
- (result i32)
- (return_call $=-flonum-bignum (local.get $b) (local.get $a)))
- (func $=-bignum-fraction (param $a (ref extern))
- (param $b-num (ref eq)) (param $b-denom (ref eq)) (result i32)
- (i32.const 0))
- (func $=-bignum-complex (param $a (ref extern))
- (param $b-real f64) (param $b-imag f64) (result i32)
- (return_call $=-complex-bignum
- (local.get $b-real) (local.get $b-imag) (local.get $a)))
- (func $=-flonum-fixnum
- (param $a f64) (param $b i32) (result i32)
- (f64.eq (local.get $a) (f64.convert_i32_s (local.get $b))))
- (func $=-flonum-bignum
- (param $a f64) (param $b (ref extern)) (result i32)
- (return_call $eq-big-flo (local.get $b) (local.get $a)))
- (func $=-flonum-flonum
- (param $a f64) (param $b f64) (result i32)
- (f64.eq (local.get $a) (local.get $b)))
- (func $=-flonum-fraction
- (param $a f64) (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result i32)
- (return_call $=-fraction-flonum
- (local.get $b-num) (local.get $b-denom) (local.get $a)))
- (func $=-flonum-complex (param $a f64)
- (param $b-real f64) (param $b-imag f64) (result i32)
- (return_call $=-complex-flonum
- (local.get $b-real) (local.get $b-imag) (local.get $a)))
- (func $=-fraction-fixnum
- (param $a-num (ref eq)) (param $a-denom (ref eq)) (param $b i32)
- (result i32)
- (i32.const 0))
- (func $=-fraction-bignum
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b (ref extern))
- (result i32)
- (i32.const 0))
- (func $=-fraction-flonum
- (param $a-num (ref eq)) (param $a-denom (ref eq)) (param $b f64)
- (result i32)
- (if (call $f64-is-finite (local.get $b))
- (then
- (return_call $=-fraction-fraction
- (local.get $a-num) (local.get $a-denom)
- (call $f64->ratio (local.get $b)))))
- (i32.const 0))
- (func $=-fraction-fraction
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result i32)
- (return_call $=-integers
- (call $multiply-integers
- (local.get $a-num) (local.get $b-denom))
- (call $multiply-integers
- (local.get $b-num) (local.get $a-denom))))
- (func $=-fraction-complex
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b-real f64) (param $b-imag f64)
- (result i32)
- (return_call $=-complex-fraction
- (local.get $b-real) (local.get $b-imag)
- (local.get $a-num) (local.get $a-denom)))
- (func $=-complex-fixnum
- (param $a-real f64) (param $a-imag f64) (param $b i32)
- (result i32)
- (if (f64.eq (local.get $a-imag) (f64.const 0.0))
- (then (return_call $=-flonum-fixnum
- (local.get $a-real) (local.get $b))))
- (i32.const 0))
- (func $=-complex-bignum
- (param $a-real f64) (param $a-imag f64) (param $b (ref extern))
- (result i32)
- (if (f64.eq (local.get $a-imag) (f64.const 0.0))
- (then (return_call $=-flonum-bignum
- (local.get $a-real) (local.get $b))))
- (i32.const 0))
- (func $=-complex-flonum
- (param $a-real f64) (param $a-imag f64) (param $b f64)
- (result i32)
- (return_call $=-complex-complex
- (local.get $a-real) (local.get $a-imag)
- (local.get $b) (f64.const 0.0)))
- (func $=-complex-fraction
- (param $a-real f64) (param $a-imag f64)
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result i32)
- (if (f64.eq (local.get $a-imag) (f64.const 0.0))
- (then (return_call $=-flonum-fraction
- (local.get $a-real)
- (local.get $b-num) (local.get $b-denom))))
- (i32.const 0))
- (func $=-complex-complex
- (param $a-real f64) (param $a-imag f64)
- (param $b-real f64) (param $b-imag f64)
- (result i32)
- (i32.and (f64.eq (local.get $a-real) (local.get $b-real))
- (f64.eq (local.get $a-imag) (local.get $b-imag))))
- (func $<-integers (param $a (ref eq)) (param $b (ref eq))
- (result i32)
- ,@(dispatch-binary-numeric-operation
- '$< '$a '$b #:exact? #t #:integer? #t #:check? #f))
- (func $=-integers (param $a (ref eq)) (param $b (ref eq))
- (result i32)
- ,@(dispatch-binary-numeric-operation
- '$= '$a '$b #:exact? #t #:integer? #t #:check? #f))
- (func $< (param $a (ref eq)) (param $b (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result i32)
- ,@(dispatch-binary-numeric-operation '$< '$a '$b
- #:real? #t #:subr "<"))
- (func $<= (param $a (ref eq)) (param $b (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result i32)
- ,@(dispatch-binary-numeric-operation '$<= '$a '$b
- #:real? #t #:subr "<="))
- (func $= (param $a (ref eq)) (param $b (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result i32)
- ,@(dispatch-binary-numeric-operation '$= '$a '$b #:subr "="))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; eqv? between heap numbers
- (func $heap-numbers-equal? (param $a (ref eq)) (param $b (ref eq))
- (result i32)
- (local $tmp-fraction (ref $fraction))
- (local $tmp-complex-a (ref $complex))
- (local $tmp-complex-b (ref $complex))
- (block
- $nope (ref eq)
- (block
- $complex (ref $complex)
- (block
- $fraction (ref $fraction)
- (block
- $flonum (ref $flonum)
- (local.get $a)
- (br_on_cast $flonum (ref eq) (ref $flonum))
- (br_on_cast $fraction (ref eq) (ref $fraction))
- (br_on_cast $complex (ref eq) (ref $complex))
- (struct.get $bignum $val (ref.cast $bignum))
- (local.get $b)
- (br_on_cast_fail $nope (ref eq) (ref $bignum))
- (struct.get $bignum $val)
- (return_call $=-bignum-bignum))
- (struct.get $flonum $val)
- (i64.reinterpret_f64)
- (br_on_cast_fail $nope (ref eq) (ref $flonum) (local.get $b))
- (struct.get $flonum $val)
- (i64.reinterpret_f64)
- (return (i64.eq)))
- (struct.get $fraction $num (local.tee $tmp-fraction))
- (struct.get $fraction $denom (local.get $tmp-fraction))
- (br_on_cast_fail $nope (ref eq) (ref $fraction) (local.get $b))
- (struct.get $fraction $num (local.tee $tmp-fraction))
- (struct.get $fraction $denom (local.get $tmp-fraction))
- (return_call $=-fraction-fraction))
- (local.set $tmp-complex-a)
- (br_on_cast_fail $nope (ref eq) (ref $complex) (local.get $b))
- (local.set $tmp-complex-b)
- (return
- (i32.and
- (i64.eq
- (i64.reinterpret_f64
- (struct.get $complex $real (local.get $tmp-complex-a)))
- (i64.reinterpret_f64
- (struct.get $complex $real (local.get $tmp-complex-b))))
- (i64.eq
- (i64.reinterpret_f64
- (struct.get $complex $imag (local.get $tmp-complex-a)))
- (i64.reinterpret_f64
- (struct.get $complex $imag (local.get $tmp-complex-b)))))))
- (return (i32.const 0)))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Addition
- (func $add-fixnum-fixnum (param $a i32) (param $b i32) (result (ref eq))
- (return_call $i32->scm (i32.add (local.get $a) (local.get $b))))
- (func $add-fixnum-bignum (param $a i32) (param $b (ref extern))
- (result (ref eq))
- (return_call $bignum->scm
- (call $bignum-add-i32 (local.get $b) (local.get $a))))
- (func $add-fixnum-flonum (param $a i32) (param $b f64)
- (result (ref eq))
- (return_call $add-flonum-flonum
- (f64.convert_i32_s (local.get $a))
- (local.get $b)))
- (func $add-fixnum-fraction (param $a i32)
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $add-fraction-fraction
- (call $i32->fixnum (local.get $a))
- ,(fixnum-immediate 1)
- (local.get $b-num)
- (local.get $b-denom)))
- (func $add-fixnum-complex (param $a i32)
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $add-complex-complex
- (f64.convert_i32_s (local.get $a)) (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $add-bignum-bignum (param $a (ref extern)) (param $b (ref extern))
- (result (ref eq))
- (return_call $bignum->scm
- (call $bignum-add (local.get $a) (local.get $b))))
- (func $add-bignum-flonum (param $a (ref extern)) (param $b f64)
- (result (ref eq))
- (return_call $add-flonum-flonum
- (call $bignum->f64 (local.get $a))
- (local.get $b)))
- (func $add-bignum-fraction (param $a (ref extern))
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $add-fraction-fraction
- (struct.new $bignum (i32.const 0) (local.get $a))
- ,(fixnum-immediate 1)
- (local.get $b-num)
- (local.get $b-denom)))
- (func $add-bignum-complex (param $a (ref extern))
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $add-complex-complex
- (call $bignum->f64 (local.get $a)) (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $add-flonum-flonum (param $a f64) (param $b f64)
- (result (ref eq))
- (struct.new $flonum
- (i32.const 0)
- (f64.add (local.get $a) (local.get $b))))
- (func $add-flonum-fraction (param $a f64)
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $add-flonum-flonum
- (local.get $a)
- (call $fraction->f64
- (local.get $b-num) (local.get $b-denom))))
- (func $add-flonum-complex (param $a f64)
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $add-complex-complex
- (local.get $a) (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $add-fraction-fraction
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $divide-integers
- (call $add-integers
- (call $multiply-integers
- (local.get $a-num)
- (local.get $b-denom))
- (call $multiply-integers
- (local.get $b-num)
- (local.get $a-denom)))
- (call $multiply-integers
- (local.get $a-denom) (local.get $b-denom))))
- (func $add-fraction-complex
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $add-complex-complex
- (call $fraction->f64
- (local.get $a-num) (local.get $a-denom))
- (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $add-complex-complex
- (param $a-real f64) (param $a-imag f64)
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.add (local.get $a-real) (local.get $b-real))
- (f64.add (local.get $a-imag) (local.get $b-imag))))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Subtraction
- (func $sub-fixnum-fixnum (param $a i32) (param $b i32) (result (ref eq))
- (return_call $i32->scm (i32.sub (local.get $a) (local.get $b))))
- (func $sub-fixnum-bignum (param $a i32) (param $b (ref extern))
- (result (ref eq))
- (return_call $bignum->scm
- (call $bignum-add-i32
- (call $bignum-mul-i32 (local.get $b) (i32.const -1))
- (local.get $a))))
- (func $sub-fixnum-flonum (param $a i32) (param $b f64)
- (result (ref eq))
- (return_call $add-fixnum-flonum (local.get $a)
- (f64.neg (local.get $b))))
- (func $sub-fixnum-fraction (param $a i32)
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $sub-fraction-fraction
- (call $i32->fixnum (local.get $a))
- ,(fixnum-immediate 1)
- (local.get $b-num)
- (local.get $b-denom)))
- (func $sub-fixnum-complex (param $a i32)
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $sub-complex-complex
- (f64.convert_i32_s (local.get $a)) (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $sub-bignum-fixnum (param $a (ref extern)) (param $b i32)
- (result (ref eq))
- (return_call $bignum->scm
- (call $bignum-sub-i32 (local.get $a) (local.get $b))))
- (func $sub-bignum-bignum (param $a (ref extern)) (param $b (ref extern))
- (result (ref eq))
- (return_call $bignum->scm
- (call $bignum-sub (local.get $a) (local.get $b))))
- (func $sub-bignum-flonum (param $a (ref extern)) (param $b f64)
- (result (ref eq))
- (return_call $add-bignum-flonum (local.get $a)
- (f64.neg (local.get $b))))
- (func $sub-bignum-fraction (param $a (ref extern))
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $sub-fraction-fraction
- (struct.new $bignum (i32.const 0) (local.get $a))
- ,(fixnum-immediate 1)
- (local.get $b-num)
- (local.get $b-denom)))
- (func $sub-bignum-complex (param $a (ref extern))
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $sub-complex-complex
- (call $bignum->f64 (local.get $a)) (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $sub-flonum-fixnum (param $a f64) (param $b i32)
- (result (ref eq))
- (struct.new $flonum
- (i32.const 0)
- (f64.sub (local.get $a)
- (f64.convert_i32_s (local.get $b)))))
- (func $sub-flonum-bignum (param $a f64) (param $b (ref extern))
- (result (ref eq))
- (struct.new $flonum
- (i32.const 0)
- (f64.sub (local.get $a)
- (call $bignum->f64 (local.get $b)))))
- (func $sub-flonum-flonum (param $a f64) (param $b f64)
- (result (ref eq))
- (struct.new $flonum
- (i32.const 0)
- (f64.sub (local.get $a) (local.get $b))))
- (func $sub-flonum-fraction (param $a f64)
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (struct.new $flonum
- (i32.const 0)
- (f64.sub
- (local.get $a)
- (call $fraction->f64
- (local.get $b-num) (local.get $b-denom)))))
- (func $sub-flonum-complex (param $a f64)
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $sub-complex-complex
- (local.get $a) (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $sub-fraction-fixnum
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b i32)
- (result (ref eq))
- (return_call $sub-fraction-fraction
- (local.get $a-num)
- (local.get $a-denom)
- (call $i32->fixnum (local.get $b))
- ,(fixnum-immediate 1)))
- (func $sub-fraction-bignum
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b (ref extern))
- (result (ref eq))
- (return_call $sub-fraction-fraction
- (local.get $a-num)
- (local.get $a-denom)
- (struct.new $bignum (i32.const 0) (local.get $b))
- ,(fixnum-immediate 1)))
- (func $sub-fraction-flonum
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b f64)
- (result (ref eq))
- (struct.new $flonum
- (i32.const 0)
- (f64.sub
- (call $fraction->f64
- (local.get $a-num) (local.get $a-denom))
- (local.get $b))))
- (func $sub-fraction-fraction
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $divide-integers
- (call $sub-integers
- (call $multiply-integers
- (local.get $a-num)
- (local.get $b-denom))
- (call $multiply-integers
- (local.get $b-num)
- (local.get $a-denom)))
- (call $multiply-integers
- (local.get $a-denom) (local.get $b-denom))))
- (func $sub-fraction-complex
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $sub-complex-complex
- (call $fraction->f64
- (local.get $a-num) (local.get $a-denom))
- (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $sub-complex-fixnum
- (param $a-real f64) (param $a-imag f64)
- (param $b i32)
- (result (ref eq))
- (return_call $sub-complex-complex
- (local.get $a-real) (local.get $a-imag)
- (f64.convert_i32_s (local.get $b)) (f64.const 0)))
- (func $sub-complex-bignum
- (param $a-real f64) (param $a-imag f64)
- (param $b (ref extern))
- (result (ref eq))
- (return_call $sub-complex-complex
- (local.get $a-real) (local.get $a-imag)
- (call $bignum->f64 (local.get $b)) (f64.const 0)))
- (func $sub-complex-flonum
- (param $a-real f64) (param $a-imag f64)
- (param $b f64)
- (result (ref eq))
- (return_call $sub-complex-complex
- (local.get $a-real) (local.get $a-imag)
- (local.get $b) (f64.const 0)))
- (func $sub-complex-fraction
- (param $a-real f64) (param $a-imag f64)
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $sub-complex-complex
- (local.get $a-real) (local.get $a-imag)
- (call $fraction->f64
- (local.get $b-num) (local.get $b-denom))
- (f64.const 0)))
- (func $sub-complex-complex
- (param $a-real f64) (param $a-imag f64)
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.sub (local.get $a-real) (local.get $b-real))
- (f64.sub (local.get $a-imag) (local.get $b-imag))))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Multiplication
- (func $mul-fixnum-fixnum (param $a i32) (param $b i32) (result (ref eq))
- (return_call $i64->scm
- (i64.mul (i64.extend_i32_s (local.get $a))
- (i64.extend_i32_s (local.get $b)))))
- (func $mul-fixnum-bignum (param $a i32) (param $b (ref extern))
- (result (ref eq))
- (return_call $bignum->scm
- (call $bignum-mul-i32 (local.get $b) (local.get $a))))
- (func $mul-fixnum-flonum (param $a i32) (param $b f64)
- (result (ref eq))
- (return_call $mul-flonum-flonum
- (f64.convert_i32_s (local.get $a))
- (local.get $b)))
- (func $mul-fixnum-fraction (param $a i32)
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $mul-fraction-fraction
- (call $i32->fixnum (local.get $a))
- ,(fixnum-immediate 1)
- (local.get $b-num)
- (local.get $b-denom)))
- (func $mul-fixnum-complex (param $a i32)
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $mul-complex-complex
- (f64.convert_i32_s (local.get $a)) (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $mul-bignum-bignum (param $a (ref extern)) (param $b (ref extern))
- (result (ref eq))
- (return_call $bignum->scm
- (call $bignum-mul (local.get $a) (local.get $b))))
- (func $mul-bignum-flonum (param $a (ref extern)) (param $b f64)
- (result (ref eq))
- (return_call $mul-flonum-flonum
- (call $bignum->f64 (local.get $a))
- (local.get $b)))
- (func $mul-bignum-fraction (param $a (ref extern))
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $mul-fraction-fraction
- (struct.new $bignum (i32.const 0) (local.get $a))
- ,(fixnum-immediate 1)
- (local.get $b-num)
- (local.get $b-denom)))
- (func $mul-bignum-complex (param $a (ref extern))
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $mul-complex-complex
- (call $bignum->f64 (local.get $a)) (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $mul-flonum-flonum (param $a f64) (param $b f64)
- (result (ref eq))
- (struct.new $flonum
- (i32.const 0)
- (f64.mul (local.get $a) (local.get $b))))
- (func $mul-flonum-fraction (param $a f64)
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $mul-flonum-flonum
- (local.get $a)
- (call $fraction->f64
- (local.get $b-num) (local.get $b-denom))))
- (func $mul-flonum-complex (param $a f64)
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $mul-complex-complex
- (local.get $a) (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $mul-fraction-fraction
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $divide-integers
- (call $multiply-integers
- (local.get $a-num) (local.get $b-num))
- (call $multiply-integers
- (local.get $a-denom) (local.get $b-denom))))
- (func $mul-fraction-complex
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $mul-complex-complex
- (call $fraction->f64
- (local.get $a-num) (local.get $a-denom))
- (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $mul-complex-complex
- (param $a-real f64) (param $a-imag f64)
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (struct.new $complex
- (i32.const 0)
- (f64.sub (f64.mul (local.get $a-real) (local.get $b-real))
- (f64.mul (local.get $a-imag) (local.get $b-imag)))
- (f64.add (f64.mul (local.get $a-real) (local.get $b-imag))
- (f64.mul (local.get $a-imag) (local.get $b-real)))))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Division
- (func $div-fixnum-fixnum (param $a i32) (param $b i32) (result (ref eq))
- (local $gcd i32)
- (if (i32.eq (local.get $a) (i32.const 0))
- (then (return ,(fixnum-immediate 0))))
- (if (i32.eq (local.get $b) (i32.const 1))
- (then (return_call $i32->fixnum (local.get $a))))
- (if (i32.lt_s (local.get $b) (i32.const 0))
- (then (return_call $divide-integers
- (call $negate-fixnum (local.get $a))
- (call $negate-fixnum (local.get $b)))))
- (if (i32.eqz (i32.rem_s (local.get $a) (local.get $b)))
- (then (return_call $i32->fixnum
- (i32.div_s (local.get $a) (local.get $b)))))
- (local.set $gcd (call $gcd-i32 (local.get $a) (local.get $b)))
- (struct.new $fraction
- (i32.const 0)
- (call $i32->fixnum
- (i32.div_s (local.get $a) (local.get $gcd)))
- (call $i32->fixnum
- (i32.div_s (local.get $b) (local.get $gcd)))))
- (func $div-fixnum-bignum (param $a i32) (param $b (ref extern))
- (result (ref eq))
- (if (i32.eq (local.get $a) (i32.const 0))
- (then (return ,(fixnum-immediate 0))))
- (return_call $div-bignum-bignum
- (call $bignum-from-i32 (local.get $a))
- (local.get $b)))
- (func $div-fixnum-flonum (param $a i32) (param $b f64)
- (result (ref eq))
- (return_call $div-flonum-flonum (f64.convert_i32_s (local.get $a))
- (local.get $b)))
- (func $div-fixnum-fraction (param $a i32)
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $divide-integers
- (call $multiply-integers
- (call $i32->fixnum (local.get $a))
- (local.get $b-denom))
- (local.get $b-num)))
- (func $div-fixnum-complex (param $a i32)
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $div-complex-complex
- (f64.convert_i32_s (local.get $a)) (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $div-bignum-fixnum (param $a (ref extern)) (param $b i32)
- (result (ref eq))
- (if (i32.eq (local.get $b) (i32.const 1))
- (then (return (struct.new $bignum (i32.const 0) (local.get $a)))))
- (if (i32.lt_s (local.get $b) (i32.const 0))
- (then (return_call $divide-integers
- (call $negate-bignum (local.get $a))
- (call $negate-fixnum (local.get $b)))))
- (return_call $div-bignum-bignum
- (local.get $a) (call $bignum-from-i32 (local.get $b))))
- (func $div-bignum-bignum (param $a (ref extern)) (param $b (ref extern))
- (result (ref eq))
- (local $gcd (ref extern))
- (if (call $lt-big-fix (local.get $b) (i32.const 0))
- (then (return_call $divide-integers
- (call $negate-bignum (local.get $a))
- (call $negate-bignum (local.get $b)))))
- (local.set $gcd (call $bignum-gcd (local.get $a) (local.get $b)))
- (if (call $eq-big-big (local.get $gcd) (local.get $b))
- (then (return
- (call $bignum->scm
- (call $bignum-quo (local.get $a) (local.get $b))))))
- (struct.new $fraction
- (i32.const 0)
- (call $bignum->scm
- (call $bignum-quo (local.get $a) (local.get $gcd)))
- (call $bignum->scm
- (call $bignum-quo (local.get $b) (local.get $gcd)))))
- (func $div-bignum-flonum (param $a (ref extern)) (param $b f64)
- (result (ref eq))
- (return_call $div-flonum-flonum (call $bignum->f64 (local.get $a))
- (local.get $b)))
- (func $div-bignum-fraction (param $a (ref extern))
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $divide-integers
- (call $multiply-integers
- (struct.new $bignum (i32.const 0) (local.get $a))
- (local.get $b-denom))
- (local.get $b-num)))
- (func $div-bignum-complex (param $a (ref extern))
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $div-complex-complex
- (call $bignum->f64 (local.get $a)) (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $div-flonum-fixnum (param $a f64) (param $b i32)
- (result (ref eq))
- (return_call $div-flonum-flonum (local.get $a)
- (f64.convert_i32_s (local.get $b))))
- (func $div-flonum-bignum (param $a f64) (param $b (ref extern))
- (result (ref eq))
- (return_call $div-flonum-flonum
- (local.get $a)
- (call $bignum->f64 (local.get $b))))
- (func $div-flonum-flonum (param $a f64) (param $b f64)
- (result (ref eq))
- (struct.new $flonum
- (i32.const 0)
- (f64.div (local.get $a) (local.get $b))))
- (func $div-flonum-fraction (param $a f64)
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $div-flonum-flonum
- (local.get $a)
- (call $fraction->f64
- (local.get $b-num) (local.get $b-denom))))
- (func $div-flonum-complex (param $a f64)
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $div-complex-complex
- (local.get $a) (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $div-fraction-fixnum
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b i32)
- (result (ref eq))
- (return_call $divide-integers
- (local.get $a-num)
- (call $multiply-integers
- (local.get $a-denom)
- (call $i32->fixnum (local.get $b)))))
- (func $div-fraction-bignum
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b (ref extern))
- (result (ref eq))
- (return_call $divide-integers
- (local.get $a-num)
- (call $multiply-integers
- (local.get $a-denom)
- (struct.new $bignum (i32.const 0) (local.get $b)))))
- (func $div-fraction-flonum
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b f64)
- (result (ref eq))
- (return_call $div-flonum-flonum
- (call $fraction->f64
- (local.get $a-num) (local.get $a-denom))
- (local.get $b)))
- (func $div-fraction-fraction
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $divide-integers
- (call $multiply-integers
- (local.get $a-num)
- (local.get $b-denom))
- (call $multiply-integers
- (local.get $b-num)
- (local.get $a-denom))))
- (func $div-fraction-complex
- (param $a-num (ref eq)) (param $a-denom (ref eq))
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (return_call $div-complex-complex
- (call $fraction->f64
- (local.get $a-num) (local.get $a-denom))
- (f64.const 0)
- (local.get $b-real) (local.get $b-imag)))
- (func $div-complex-fixnum
- (param $a-real f64) (param $a-imag f64)
- (param $b i32)
- (result (ref eq))
- (return_call $div-complex-complex
- (local.get $a-real) (local.get $a-imag)
- (f64.convert_i32_s (local.get $b)) (f64.const 0)))
- (func $div-complex-bignum
- (param $a-real f64) (param $a-imag f64)
- (param $b (ref extern))
- (result (ref eq))
- (return_call $div-complex-complex
- (local.get $a-real) (local.get $a-imag)
- (call $bignum->f64 (local.get $b)) (f64.const 0)))
- (func $div-complex-flonum
- (param $a-real f64) (param $a-imag f64)
- (param $b f64)
- (result (ref eq))
- (return_call $div-complex-complex
- (local.get $a-real) (local.get $a-imag)
- (local.get $b) (f64.const 0)))
- (func $div-complex-fraction
- (param $a-real f64) (param $a-imag f64)
- (param $b-num (ref eq)) (param $b-denom (ref eq))
- (result (ref eq))
- (return_call $div-complex-complex
- (local.get $a-real) (local.get $a-imag)
- (call $fraction->f64
- (local.get $b-num) (local.get $b-denom))
- (f64.const 0)))
- (func $div-complex-complex
- (param $a-real f64) (param $a-imag f64)
- (param $b-real f64) (param $b-imag f64)
- (result (ref eq))
- (local $d f64)
- (local.set $d (f64.add (f64.mul (local.get $b-real)
- (local.get $b-real))
- (f64.mul (local.get $b-imag)
- (local.get $b-imag))))
- (struct.new $complex
- (i32.const 0)
- (f64.div (f64.add (f64.mul (local.get $a-real)
- (local.get $b-real))
- (f64.mul (local.get $a-imag)
- (local.get $b-imag)))
- (local.get $d))
- (f64.div (f64.sub (f64.mul (local.get $a-imag)
- (local.get $b-real))
- (f64.mul (local.get $a-real)
- (local.get $b-imag)))
- (local.get $d))))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Quotient
- (func $quo-fixnum-fixnum
- (param $a i32) (param $b i32) (result (ref eq))
- (if (i32.eq (local.get $b) (i32.const -1))
- (then (return_call $negate-fixnum (local.get $a))))
- (call $i32->fixnum (i32.div_s (local.get $a) (local.get $b))))
- (func $quo-fixnum-bignum
- (param $a i32) (param $b (ref extern)) (result (ref eq))
- ,(fixnum-immediate 0))
- (func $quo-fixnum-flonum
- (param $a i32) (param $b f64) (result (ref eq))
- (return_call $quo-flonum-flonum
- (f64.convert_i32_s (local.get $a)) (local.get $b)))
- (func $quo-bignum-fixnum
- (param $a (ref extern)) (param $b i32) (result (ref eq))
- (if (i32.eq (local.get $b) (i32.const -1))
- (then (return_call $negate-bignum (local.get $a))))
- (call $bignum->scm
- (call $bignum-quo
- (local.get $a) (call $bignum-from-i32 (local.get $b)))))
- (func $quo-bignum-bignum
- (param $a (ref extern)) (param $b (ref extern)) (result (ref eq))
- (call $bignum->scm
- (call $bignum-quo (local.get $a) (local.get $b))))
- (func $quo-bignum-flonum
- (param $a (ref extern)) (param $b f64) (result (ref eq))
- (return_call $quo-flonum-flonum
- (call $bignum->f64 (local.get $a)) (local.get $b)))
- (func $quo-flonum-fixnum
- (param $a f64) (param $b i32) (result (ref eq))
- (return_call $quo-flonum-flonum
- (local.get $a) (f64.convert_i32_s (local.get $b))))
- (func $quo-flonum-bignum
- (param $a f64) (param $b (ref extern)) (result (ref eq))
- (return_call $quo-flonum-flonum
- (local.get $a) (call $bignum->f64 (local.get $b))))
- (func $quo-flonum-flonum
- (param $a f64) (param $b f64) (result (ref eq))
- (struct.new $flonum (i32.const 0)
- (f64.trunc (f64.div (local.get $a) (local.get $b)))))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Remainder
- (func $rem-fixnum-fixnum
- (param $a i32) (param $b i32) (result (ref eq))
- (call $i32->fixnum (i32.rem_s (local.get $a) (local.get $b))))
- (func $rem-fixnum-bignum
- (param $a i32) (param $b (ref extern)) (result (ref eq))
- (return_call $rem-bignum-bignum
- (call $bignum-from-i32 (local.get $a))
- (local.get $b)))
- (func $rem-fixnum-flonum
- (param $a i32) (param $b f64) (result (ref eq))
- (return_call $rem-flonum-flonum
- (f64.convert_i32_s (local.get $a)) (local.get $b)))
- (func $rem-bignum-fixnum
- (param $a (ref extern)) (param $b i32) (result (ref eq))
- (return_call $rem-bignum-bignum
- (local.get $a)
- (call $bignum-from-i32 (local.get $b))))
- (func $rem-bignum-bignum
- (param $a (ref extern)) (param $b (ref extern)) (result (ref eq))
- (call $bignum->scm
- (call $bignum-rem (local.get $a) (local.get $b))))
- (func $rem-bignum-flonum
- (param $a (ref extern)) (param $b f64) (result (ref eq))
- (return_call $rem-flonum-flonum
- (call $bignum->f64 (local.get $a)) (local.get $b)))
- (func $rem-flonum-fixnum
- (param $a f64) (param $b i32) (result (ref eq))
- (return_call $rem-flonum-flonum
- (local.get $a) (f64.convert_i32_s (local.get $b))))
- (func $rem-flonum-bignum
- (param $a f64) (param $b (ref extern)) (result (ref eq))
- (return_call $rem-flonum-flonum
- (local.get $a) (call $bignum->f64 (local.get $b))))
- (func $rem-flonum-flonum
- (param $a f64) (param $b f64) (result (ref eq))
- (struct.new $flonum (i32.const 0)
- (f64.sub (local.get $a)
- (f64.mul (local.get $b)
- (f64.trunc
- (f64.div (local.get $a)
- (local.get $b)))))))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Modulo
- (func $mod-fixnum-fixnum
- (param $a i32) (param $b i32) (result (ref eq))
- (local $res i32)
- (local.set $res (i32.rem_s (local.get $a) (local.get $b)))
- (if (i32.ne (i32.lt_s (local.get $b) (i32.const 0))
- (i32.lt_s (local.get $res) (i32.const 0)))
- (then
- (return_call $i32->scm
- (i32.add (local.get $res) (local.get $b)))))
- (return_call $i32->fixnum (local.get $res)))
- (func $mod-fixnum-bignum
- (param $a i32) (param $b (ref extern)) (result (ref eq))
- (return_call $mod-bignum-bignum
- (call $bignum-from-i32 (local.get $a))
- (local.get $b)))
- (func $mod-fixnum-flonum
- (param $a i32) (param $b f64) (result (ref eq))
- (return_call $mod-flonum-flonum
- (f64.convert_i32_s (local.get $a)) (local.get $b)))
- (func $mod-bignum-fixnum
- (param $a (ref extern)) (param $b i32) (result (ref eq))
- (return_call $mod-bignum-bignum
- (local.get $a)
- (call $bignum-from-i32 (local.get $b))))
- (func $mod-bignum-bignum
- (param $a (ref extern)) (param $b (ref extern)) (result (ref eq))
- (call $bignum->scm
- (call $bignum-mod (local.get $a) (local.get $b))))
- (func $mod-bignum-flonum
- (param $a (ref extern)) (param $b f64) (result (ref eq))
- (return_call $mod-flonum-flonum
- (call $bignum->f64 (local.get $a)) (local.get $b)))
- (func $mod-flonum-fixnum
- (param $a f64) (param $b i32) (result (ref eq))
- (return_call $mod-flonum-flonum
- (local.get $a) (f64.convert_i32_s (local.get $b))))
- (func $mod-flonum-bignum
- (param $a f64) (param $b (ref extern)) (result (ref eq))
- (return_call $mod-flonum-flonum
- (local.get $a) (call $bignum->f64 (local.get $b))))
- (func $mod-flonum-flonum
- (param $a f64) (param $b f64) (result (ref eq))
- (struct.new $flonum (i32.const 0)
- (f64.sub (local.get $a)
- (f64.mul (local.get $b)
- (f64.floor
- (f64.div (local.get $a)
- (local.get $b)))))))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Bitwise AND.
- (func $logand-fixnum-fixnum
- (param $a i32) (param $b i32) (result (ref eq))
- (return_call $i32->fixnum (i32.and (local.get $a (local.get $b)))))
- (func $logand-fixnum-bignum
- (param $a i32) (param $b (ref extern)) (result (ref eq))
- (return_call
- $i32->fixnum
- (i32.wrap_i64
- (call $bignum-get-i64
- (call $bignum-logand-i32 (local.get $b) (local.get $a))))))
- (func $logand-bignum-fixnum
- (param $a (ref extern)) (param $b i32) (result (ref eq))
- (return_call $logand-fixnum-bignum (local.get $b) (local.get $a)))
- (func $logand-bignum-bignum
- (param $a (ref extern)) (param $b (ref extern)) (result (ref eq))
- (return_call $bignum->scm
- (call $bignum-logand-bignum (local.get $a) (local.get $b))))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Bitwise OR.
- (func $logior-fixnum-fixnum
- (param $a i32) (param $b i32) (result (ref eq))
- (return_call $i32->fixnum (i32.or (local.get $a (local.get $b)))))
- (func $logior-fixnum-bignum
- (param $a i32) (param $b (ref extern)) (result (ref eq))
- (return_call $bignum->scm
- (call $bignum-logior-i32 (local.get $b) (local.get $a))))
- (func $logior-bignum-fixnum
- (param $a (ref extern)) (param $b i32) (result (ref eq))
- (return_call $logior-fixnum-bignum (local.get $b) (local.get $a)))
- (func $logior-bignum-bignum
- (param $a (ref extern)) (param $b (ref extern)) (result (ref eq))
- (return_call $bignum->scm
- (call $bignum-logior-bignum (local.get $a) (local.get $b))))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Bitwise XOR.
- (func $logxor-fixnum-fixnum
- (param $a i32) (param $b i32) (result (ref eq))
- (return_call $i32->fixnum (i32.xor (local.get $a (local.get $b)))))
- (func $logxor-fixnum-bignum
- (param $a i32) (param $b (ref extern)) (result (ref eq))
- (return_call $bignum->scm
- (call $bignum-logxor-i32 (local.get $b) (local.get $a))))
- (func $logxor-bignum-fixnum
- (param $a (ref extern)) (param $b i32) (result (ref eq))
- (return_call $logxor-fixnum-bignum (local.get $b) (local.get $a)))
- (func $logxor-bignum-bignum
- (param $a (ref extern)) (param $b (ref extern)) (result (ref eq))
- (return_call $bignum->scm
- (call $bignum-logxor-bignum (local.get $a) (local.get $b))))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Bitwise subtraction.
- (func $logsub-fixnum-fixnum
- (param $a i32) (param $b i32) (result (ref eq))
- (return_call $i32->fixnum
- (i32.and (local.get $a)
- (i32.xor (local.get $b) (i32.const -1)))))
- (func $logsub-fixnum-bignum
- (param $a i32) (param $b (ref extern)) (result (ref eq))
- (return_call $logand-fixnum-bignum (local.get $a)
- (call $bignum-logxor-i32
- (local.get $b) (i32.const -1))))
- (func $logsub-bignum-fixnum
- (param $a (ref extern)) (param $b i32) (result (ref eq))
- (return_call $logand-bignum-fixnum (local.get $a)
- (i32.xor (local.get $b) (i32.const -1))))
- (func $logsub-bignum-bignum
- (param $a (ref extern)) (param $b (ref extern)) (result (ref eq))
- (return_call $bignum->scm
- (call $bignum-logand-bignum
- (local.get $a)
- (call $bignum-logxor-i32
- (local.get $b) (i32.const -1)))))
- ,@(commutative-arithmetic-operation-implementations '$add)
- ,@(commutative-arithmetic-operation-implementations '$mul)
- (func $fixnum-add (param $a i32) (param $b i32) (result (ref eq))
- (return_call $add-fixnum-fixnum
- (i32.shr_s (local.get $a) (i32.const 1))
- (i32.shr_s (local.get $b) (i32.const 1))))
- (func $fixnum-sub (param $a i32) (param $b i32) (result (ref eq))
- (return_call $sub-fixnum-fixnum
- (i32.shr_s (local.get $a) (i32.const 1))
- (i32.shr_s (local.get $b) (i32.const 1))))
- (func $fixnum-mul (param $a i32) (param $b i32) (result (ref eq))
- (return_call $mul-fixnum-fixnum
- (i32.shr_s (local.get $a) (i32.const 1))
- (i32.shr_s (local.get $b) (i32.const 1))))
- (func $add-integers (param $a (ref eq)) (param $b (ref eq))
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation
- '$add '$a '$b #:check? #f #:exact? #t #:integer? #t))
- (func $sub-integers (param $a (ref eq)) (param $b (ref eq))
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation
- '$sub '$a '$b #:check? #f #:exact? #t #:integer? #t))
- (func $multiply-integers (param $a (ref eq)) (param $b (ref eq))
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation
- '$mul '$a '$b #:check? #f #:exact? #t #:integer? #t))
- (func $divide-integers (param $a (ref eq)) (param $b (ref eq))
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation
- '$div '$a '$b #:check? #f #:exact? #t #:integer? #t))
- (func $rem-integers (param $a (ref eq)) (param $b (ref eq))
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation
- '$rem '$a '$b #:check? #f #:exact? #t #:integer? #t))
- (func $add (param $a (ref eq)) (param $b (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation '$add '$a '$b #:subr "+"))
- (func $sub (param $a (ref eq)) (param $b (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation '$sub '$a '$b #:subr "-"))
- (func $mul (param $a (ref eq)) (param $b (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation '$mul '$a '$b #:subr "*"))
- (func $div (param $a (ref eq)) (param $b (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation
- '$div '$a '$b #:subr "/"
- #:prelude `((if (ref.eq (local.get $b) ,(fixnum-immediate 0))
- (then
- (call $raise-runtime-error-with-message
- (string.const "division by zero")
- ,@propagate-source)
- (unreachable))))))
- (func $quo (param $a (ref eq)) (param $b (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation
- '$quo '$a '$b #:subr "quotient" #:integer? #t
- #:prelude `((if (ref.eq (local.get $b) ,(fixnum-immediate 0))
- (then
- (call $raise-runtime-error-with-message
- (string.const "division by zero")
- ,@propagate-source)
- (unreachable))))))
- (func $rem (param $a (ref eq)) (param $b (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation
- '$rem '$a '$b #:subr "remainder" #:integer? #t
- #:prelude `((if (ref.eq (local.get $b) ,(fixnum-immediate 0))
- (then
- (call $raise-runtime-error-with-message
- (string.const "division by zero")
- ,@propagate-source)
- (unreachable))))))
- (func $mod (param $a (ref eq)) (param $b (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation
- '$mod '$a '$b #:subr "modulo" #:integer? #t
- #:prelude `((if (ref.eq (local.get $b) ,(fixnum-immediate 0))
- (then
- (call $raise-runtime-error-with-message
- (string.const "division by zero")
- ,@propagate-source)
- (unreachable))))))
- (func $logand (param $a (ref eq)) (param $b (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation
- '$logand '$a '$b #:subr "logand" #:exact? #t #:integer? #t))
- (func $logior (param $a (ref eq)) (param $b (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation
- '$logior '$a '$b #:subr "logior" #:exact? #t #:integer? #t))
- (func $logxor (param $a (ref eq)) (param $b (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation
- '$logxor '$a '$b #:subr "logxor" #:exact? #t #:integer? #t))
- (func $logsub (param $a (ref eq)) (param $b (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-binary-numeric-operation
- '$logsub '$a '$b #:subr "logsub" #:exact? #t #:integer? #t))
- (func $rsh-fixnum (param $a i32) (param $b i64) (result (ref eq))
- (return_call $i32->fixnum
- (i32.shr_s (local.get $a)
- (if i32
- (i64.lt_u (local.get $b) (i64.const 30))
- (then (i32.wrap_i64 (local.get $b)))
- (else (i32.const 30))))))
- (func $rsh-bignum (param $a (ref extern)) (param $b i64) (result (ref eq))
- (return_call $bignum->scm
- (call $bignum-rsh (local.get $a) (local.get $b))))
- (func $rsh (param $a (ref eq)) (param $b i64)
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-unary-numeric-operation
- '$rsh '$a #:subr "rsh" #:exact-integer? #t
- #:dispatch (lambda (tp)
- `((local.get $b)
- (return_call ,(symbol-append '$rsh- tp))))))
- (func $lsh-fixnum
- (param $a i32) (param $b i64) (result (ref eq))
- (return_call $bignum->scm
- (call $i32-lsh (local.get $a) (local.get $b))))
- (func $lsh-bignum
- (param $a (ref extern)) (param $b i64) (result (ref eq))
- (return_call $bignum->scm
- (call $bignum-lsh (local.get $a) (local.get $b))))
- (func $lsh (param $a (ref eq)) (param $b i64)
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-unary-numeric-operation
- '$lsh '$a #:subr "lsh" #:exact-integer? #t
- #:dispatch (lambda (tp)
- `((local.get $b)
- (return_call ,(symbol-append '$lsh- tp))))))
- (func $inexact-fixnum (param $i i32) (result (ref eq))
- (struct.new $flonum (i32.const 0)
- (call $fixnum->f64 (local.get $i))))
- (func $inexact-bignum (param $i (ref extern)) (result (ref eq))
- (struct.new $flonum (i32.const 0)
- (call $bignum->f64 (local.get $i))))
- (func $inexact-fraction (param $num (ref eq)) (param $denom (ref eq))
- (result (ref eq))
- (struct.new $flonum (i32.const 0)
- (call $fraction->f64
- (local.get $num) (local.get $denom))))
- (func $inexact (param $x (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-unary-numeric-operation
- '$inexact '$x
- #:subr "inexact"
- #:unpack-flonum '()
- #:unpack-complex '()
- #:dispatch (match-lambda
- ((or 'flonum 'complex) '((return)))
- (tp
- `((return_call ,(symbol-append '$inexact- tp)))))))
- (func $abs-fixnum (param $x i32) (result (ref eq))
- (if (i32.lt_s (local.get $x) (i32.const 0))
- (then (return_call $negate-fixnum (local.get $x))))
- (return_call $i32->fixnum (local.get $x)))
- (func $abs-bignum (param $x (ref extern)) (result (ref eq))
- (if (call $lt-big-fix (local.get $x) (i32.const 0))
- (then (return_call $negate-bignum (local.get $x))))
- (struct.new $bignum (i32.const 0) (local.get $x)))
- (func $abs-flonum (param $x f64) (result (ref eq))
- (struct.new $flonum (i32.const 0)
- (f64.abs (local.get $x))))
- (func $abs-integer (param $x (ref eq)) (result (ref eq))
- (block $i31 (ref i31)
- (br_on_cast $i31 (ref eq) (ref i31) (local.get $x))
- (return_call $abs-bignum
- (struct.get $bignum $val
- (ref.cast $bignum (local.get $x)))))
- (return_call $abs-fixnum (i32.shr_s (i31.get_s) (i32.const 1))))
- (func $abs-fraction (param $x-num (ref eq)) (param $x-denom (ref eq))
- (result (ref eq))
- (struct.new $fraction (i32.const 0)
- (call $abs-integer (local.get $x-num))
- (local.get $x-denom)))
- (func $abs (param $x (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-unary-numeric-operation '$abs '$x
- #:subr "abs" #:real? #t))
- (func $floor-flonum (param $x f64) (result (ref eq))
- (struct.new $flonum (i32.const 0) (f64.floor (local.get $x))))
- ;; 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 $floor-fraction
- (param $m (ref eq)) (param $n (ref eq)) (result (ref eq))
- (call $divide-integers
- (call $sub-integers
- (local.get $m)
- (call $rem-integers
- (call $add-integers
- (call $rem-integers
- (local.get $m) (local.get $n))
- (local.get $n))
- (local.get $n)))
- (local.get $n)))
- (func $floor (param $x (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,@(dispatch-unary-numeric-operation
- '$floor '$x
- #:real? #t
- #:subr "floor"
- #:unpack-fixnum `((if (i32.and (i31.get_s) (i32.const 1))
- (then (br $bad-operand (local.get $x))))
- (local.get $x))
- #:unpack-bignum '()
- #:dispatch (match-lambda
- ((or 'fixnum 'bignum) '((return)))
- (tp
- `((return_call ,(symbol-append '$floor- tp)))))))
- (func $ceiling-flonum (param $x f64) (result (ref eq))
- (struct.new $flonum (i32.const 0) (f64.ceil (local.get $x))))
- (func $ceiling-fraction
- (param $m (ref eq)) (param $n (ref eq)) (result (ref eq))
- (return_call $add-integers
- (call $floor-fraction (local.get $m) (local.get $n))
- ,(fixnum-immediate 1)))
- (func $ceiling (param $x (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- (local $tmp-fraction (ref $fraction))
- ,@(dispatch-unary-numeric-operation
- '$ceiling '$x
- #:real? #t
- #:subr "ceiling"
- #:unpack-fixnum `((if (i32.and (i31.get_s) (i32.const 1))
- (then (br $bad-operand (local.get $x))))
- (local.get $x))
- #:unpack-bignum '()
- #:dispatch (match-lambda
- ((or 'fixnum 'bignum) '((return)))
- (tp
- `((return_call ,(symbol-append '$ceiling- tp)))))))
- (func $sqrt (param $x (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref $flonum))
- ,(call-fmath '$fsqrt '(local.get $x)))
- (func $sin (param $x (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,(call-fmath '$fsin '(local.get $x)))
- (func $cos (param $x (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,(call-fmath '$fcos '(local.get $x)))
- (func $tan (param $x (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,(call-fmath '$ftan '(local.get $x)))
- (func $asin (param $x (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,(call-fmath '$fasin '(local.get $x)))
- (func $acos (param $x (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,(call-fmath '$facos '(local.get $x)))
- (func $atan (param $x (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,(call-fmath '$fatan '(local.get $x)))
- (func $atan2 (param $x (ref eq)) (param $y (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result (ref eq))
- ,(call-fmath '$fatan2 '(local.get $x) '(local.get $y)))
- (func $log (param $x f64) (result (ref eq))
- (struct.new $flonum (i32.const 0) (call $flog (local.get $x))))
- (func $exp (param $x f64) (result (ref eq))
- (struct.new $flonum (i32.const 0) (call $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 $scm->s64 (param $a (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result i64)
- ,@(dispatch-unary-numeric-operation
- '$scm->s64 '$a
- #:s64? #t
- #:subr "scm->s64"
- #:dispatch (match-lambda
- ('fixnum '((return (i64.extend_i32_s))))
- ('bignum '((return_call $bignum-get-i64))))))
- (func $scm->u64 (param $a (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result i64)
- (local $tmp-i32 i32)
- (local $tmp-bignum (ref extern))
- ,@(dispatch-unary-numeric-operation
- '$scm->u64 '$a
- #:u64? #t
- #:subr "scm->u64"
- #:dispatch (match-lambda
- ('fixnum '((return (i64.extend_i32_s))))
- ('bignum '((return_call $bignum-get-i64))))))
- (func $scm->u64/truncate (param $a (ref eq))
- (param $file (ref null string)) (param $line i32) (param $col i32)
- (result i64)
- (local $tmp-i32 i32)
- ,@(dispatch-unary-numeric-operation
- '$scm->u64 '$a
- #:exact-integer? #t
- #:subr "scm->u64/truncate"
- #:dispatch (match-lambda
- ('fixnum '((return (i64.extend_i32_s))))
- ('bignum '((return_call $bignum-get-i64))))))
- (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))
- ,@no-source)))
- (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)
- ,@no-source)))
- (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-unrecognized-keyword-error) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-missing-keyword-argument-error) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$make-syntax-violation) (mut (ref $proc))
- ,@maybe-init-proc)
- (global ,@(maybe-import '$annotate-with-source) (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))
|