stdlib.scm 221 KB

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