prelude.scm 159 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385
  1. ;;; Hoot standard prelude
  2. ;;; Copyright (C) 2023 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. ;;; This file defines the standard environment available to Hoot
  19. ;;; programs. It includes all of R7RS's (scheme base) and a limited
  20. ;;; number of extensions.
  21. ;;;
  22. ;;; Code:
  23. (define-syntax-rule (simple-match e cs ...)
  24. (let ((v e)) (simple-match-1 v cs ...)))
  25. (define-syntax simple-match-1
  26. (syntax-rules ()
  27. ((_ v) (raise (%make-match-error v)))
  28. ((_ v (pat e0 e ...) cs ...)
  29. (let ((fk (lambda () (simple-match-1 v cs ...))))
  30. (simple-match-pat v pat (let () e0 e ...) (fk))))))
  31. (define-syntax simple-match-patv
  32. (syntax-rules ()
  33. ((_ v idx () kt kf) kt)
  34. ((_ v idx (x . y) kt kf)
  35. (simple-match-pat (vector-ref v idx) x
  36. (simple-match-patv v (1+ idx) y kt kf)
  37. kf))))
  38. (define-syntax simple-match-pat
  39. (syntax-rules (_ quote unquote ? and or not)
  40. ((_ v _ kt kf) kt)
  41. ((_ v () kt kf) (if (null? v) kt kf))
  42. ((_ v #t kt kf) (if (eq? v #t) kt kf))
  43. ((_ v #f kt kf) (if (eq? v #f) kt kf))
  44. ((_ v (and) kt kf) kt)
  45. ((_ v (and x . y) kt kf)
  46. (simple-match-pat v x (simple-match-pat v (and . y) kt kf) kf))
  47. ((_ v (or) kt kf) kf)
  48. ((_ v (or x . y) kt kf)
  49. (let ((tk (lambda () kt)))
  50. (simple-match-pat v x (tk) (simple-match-pat v (or . y) (tk) kf))))
  51. ((_ v (not pat) kt kf) (simple-match-pat v pat kf kt))
  52. ((_ v (quote lit) kt kf)
  53. (if (eq? v (quote lit)) kt kf))
  54. ((_ v (? proc) kt kf) (simple-match-pat v (? proc _) kt kf))
  55. ((_ v (? proc pat) kt kf)
  56. (if (proc v) (simple-match-pat v pat kt kf) kf))
  57. ((_ v (x . y) kt kf)
  58. (if (pair? v)
  59. (let ((vx (car v)) (vy (cdr v)))
  60. (simple-match-pat vx x (simple-match-pat vy y kt kf) kf))
  61. kf))
  62. ((_ v #(x ...) kt kf)
  63. (if (and (vector? v)
  64. (eq? (vector-length v) (length '(x ...))))
  65. (simple-match-patv v 0 (x ...) kt kf)
  66. kf))
  67. ((_ v var kt kf) (let ((var v)) kt))))
  68. (define-syntax-rule (match e cs ...) (simple-match e cs ...))
  69. (define (raise exn) (%raise-exception exn))
  70. (define (raise-continuable exn)
  71. ((%inline-wasm '(func (result (ref eq))
  72. (global.get $raise-exception)))
  73. exn #:continuable? #t))
  74. (define raise-exception
  75. (case-lambda*
  76. ((exn) (%raise-exception exn))
  77. ;; FIXME: keyword
  78. ((exn #:optional continuable-keyword continuable?)
  79. (if continuable?
  80. (raise-continuable exn)
  81. (%raise-exception exn)))))
  82. ;; Guile extensions.
  83. (define (1+ x) (%+ x 1))
  84. (define (1- x) (%- x 1))
  85. (define (ash x y) (%ash x y))
  86. (define (fold f seed l)
  87. (let lp ((seed seed) (l l))
  88. (match l
  89. (() seed)
  90. ((x . l) (lp (f x seed) l)))))
  91. (define (fold-right f seed l)
  92. (let lp ((l l))
  93. (match l
  94. (() seed)
  95. ((x . l) (f x (lp l))))))
  96. (define-syntax-rule (define-associative-eta-expansion f %f)
  97. (begin
  98. (define (%generic . args)
  99. (let lp ((seed (%f)) (args args))
  100. (match args
  101. (() seed)
  102. ((x . args) (lp (%f x seed) args)))))
  103. (define-syntax f
  104. (lambda (stx)
  105. (syntax-case stx ()
  106. ((_ . x) #'(%f . x))
  107. (id (identifier? #'id) #'%generic))))))
  108. (define-associative-eta-expansion logand %logand)
  109. (define-associative-eta-expansion logior %logior)
  110. (define-associative-eta-expansion logxor %logxor)
  111. (define (lognot x) (%lognot x))
  112. (define (logtest j k) (%logtest j k))
  113. (define (logbit? idx k) (%logbit? idx k))
  114. (define (keyword? x) (%keyword? x))
  115. (define (symbol->keyword sym) (%symbol->keyword sym))
  116. (define (keyword->symbol kw) (%keyword->symbol kw))
  117. (define-syntax-rule (define-exception-constructor (name arg ...) global)
  118. (define (name arg ...)
  119. ((%inline-wasm '(func (result (ref eq)) (global.get global))) arg ...)))
  120. (define-exception-constructor (%make-size-error val max who)
  121. $make-size-error)
  122. (define-exception-constructor (%make-index-error val size who)
  123. $make-index-error)
  124. (define-exception-constructor (%make-range-error val min max who)
  125. $make-range-error)
  126. (define-exception-constructor (%make-start-offset-error val size who)
  127. $make-start-offset-error)
  128. (define-exception-constructor (%make-end-offset-error val size who)
  129. $make-end-offset-error)
  130. (define-exception-constructor (%make-type-error val who what)
  131. $make-type-error)
  132. (define-exception-constructor (%make-unimplemented-error who)
  133. $make-unimplemented-error)
  134. (define-exception-constructor (%make-assertion-error expr who)
  135. $make-assertion-error)
  136. (define-exception-constructor (%make-not-seekable-error port who)
  137. $make-not-seekable-error)
  138. (define-exception-constructor (%make-runtime-error-with-message msg)
  139. $make-runtime-error-with-message)
  140. (define-exception-constructor (%make-runtime-error-with-message+irritants msg irritants)
  141. $make-runtime-error-with-message+irritants)
  142. (define-exception-constructor (%make-match-error v)
  143. $make-match-error)
  144. (define-exception-constructor (%make-arity-error v who)
  145. $make-arity-error)
  146. (define error
  147. (case-lambda
  148. ((msg)
  149. (raise (%make-runtime-error-with-message msg)))
  150. ((msg . args)
  151. (raise (%make-runtime-error-with-message+irritants msg args)))))
  152. (define-syntax-rule (assert expr who)
  153. (unless expr
  154. (raise (%make-assertion-error 'expr who))))
  155. (define-syntax-rule (check-size x max who)
  156. (unless (and (exact-integer? x) (<= 0 x) (<= x max))
  157. (raise (%make-size-error x max who))))
  158. (define-syntax-rule (check-index x size who)
  159. (unless (and (exact-integer? x) (<= 0 x) (< x size))
  160. (raise (%make-index-error x size who))))
  161. (define-syntax-rule (check-range x min max who)
  162. (unless (and (exact-integer? x) (<= min x) (<= x max))
  163. (raise (%make-range-error x min max who))))
  164. (define-syntax-rule (check-type x predicate who)
  165. (unless (predicate x)
  166. (raise (%make-type-error x who 'predicate))))
  167. (define (bitvector? x) (%bitvector? x))
  168. (define* (make-bitvector len #:optional (fill #f))
  169. (check-size len (1- (ash 1 29)) 'make-bitvector)
  170. (%inline-wasm
  171. '(func (param $len i32) (param $init i32) (result (ref eq))
  172. (struct.new $mutable-bitvector
  173. (i32.const 0)
  174. (local.get $len)
  175. (array.new $raw-bitvector
  176. (local.get $init)
  177. (i32.add (i32.shr_u (i32.sub (local.get $len)
  178. (i32.const 1))
  179. (i32.const 5))
  180. (i32.const 1)))))
  181. len
  182. (match fill (#f 0) (#t -1))))
  183. (define (bitvector-length bv)
  184. (check-type bv bitvector? 'bitvector-length)
  185. (%inline-wasm
  186. '(func (param $bv (ref $bitvector))
  187. (result (ref eq))
  188. (ref.i31
  189. (i32.shl (struct.get $bitvector $len (local.get $bv))
  190. (i32.const 1))))
  191. bv))
  192. (define (bitvector-ref bv i)
  193. (check-type bv bitvector? 'bitvector-ref)
  194. (check-index i (bitvector-length bv) 'bitvector-ref)
  195. (%inline-wasm
  196. '(func (param $bv (ref $bitvector))
  197. (param $i i32)
  198. (result (ref eq))
  199. (if (ref eq)
  200. (i32.and
  201. (array.get $raw-bitvector
  202. (struct.get $bitvector $vals (local.get $bv))
  203. (i32.shr_s (local.get $i) (i32.const 5)))
  204. (i32.shl (i32.const 1) (local.get $i)))
  205. (then (ref.i31 (i32.const 17)))
  206. (else (ref.i31 (i32.const 1)))))
  207. bv i))
  208. (define (bitvector-set-bit! bv i)
  209. (define (mutable-bitvector? x)
  210. (%inline-wasm
  211. '(func (param $bv (ref eq)) (result (ref eq))
  212. (if (ref eq)
  213. (ref.test $mutable-bitvector (local.get $bv))
  214. (then (ref.i31 (i32.const 17)))
  215. (else (ref.i31 (i32.const 1)))))
  216. x))
  217. (check-type bv mutable-bitvector? 'bitvector-set-bit!)
  218. (check-index i (bitvector-length bv) 'bitvector-set-bit!)
  219. (%inline-wasm
  220. '(func (param $bv (ref $mutable-bitvector))
  221. (param $i i32)
  222. (local $i0 i32)
  223. (local.set $i0 (i32.shr_s (local.get $i) (i32.const 5)))
  224. (array.set $raw-bitvector
  225. (struct.get $bitvector $vals (local.get $bv))
  226. (local.get $i0)
  227. (i32.or
  228. (array.get $raw-bitvector
  229. (struct.get $bitvector $vals (local.get $bv))
  230. (i32.shr_s (local.get $i) (i32.const 5)))
  231. (i32.shl (i32.const 1) (local.get $i)))))
  232. bv i))
  233. ;; bitvector-set!, list->bitvector etc not yet implemented
  234. (define (%generic-cons* head . tail)
  235. (if (null? tail)
  236. head
  237. (cons head (apply %generic-cons* tail))))
  238. (define-syntax cons*
  239. (lambda (stx)
  240. (syntax-case stx ()
  241. ((_) #'(%generic-cons*))
  242. ((_ a) #'a)
  243. ((_ a . b) #'(%cons a (cons* . b)))
  244. (f (identifier? #'f) #'%generic-cons*))))
  245. (define* (make-fluid #:optional default-value)
  246. (%inline-wasm '(func (param $default (ref eq)) (result (ref eq))
  247. (struct.new $fluid (i32.const 0)
  248. (local.get $default)))
  249. default-value))
  250. (define (fluid-ref x) (%fluid-ref x))
  251. (define (fluid-set! x y) (%fluid-set! x y))
  252. (define (with-fluid* fluid val thunk) (%with-fluid* fluid val thunk))
  253. (define (with-dynamic-state state thunk) (%with-dynamic-state state thunk))
  254. (define-syntax with-fluids
  255. (lambda (stx)
  256. (define (emit-with-fluids bindings body)
  257. (syntax-case bindings ()
  258. (()
  259. body)
  260. (((f v) . bindings)
  261. #`(with-fluid* f v
  262. (lambda ()
  263. #,(emit-with-fluids #'bindings body))))))
  264. (syntax-case stx ()
  265. ((_ ((fluid val) ...) exp exp* ...)
  266. (with-syntax (((fluid-tmp ...) (generate-temporaries #'(fluid ...)))
  267. ((val-tmp ...) (generate-temporaries #'(val ...))))
  268. #`(let ((fluid-tmp fluid) ...)
  269. (let ((val-tmp val) ...)
  270. #,(emit-with-fluids #'((fluid-tmp val-tmp) ...)
  271. #'(let () exp exp* ...)))))))))
  272. (define* (make-parameter init #:optional (conv (lambda (x) x)))
  273. (let ((fluid (make-fluid (conv init))))
  274. (%inline-wasm
  275. '(func (param $fluid (ref eq))
  276. (param $convert (ref eq))
  277. (result (ref eq))
  278. (struct.new $parameter
  279. (i32.const 0)
  280. (ref.func $parameter)
  281. (ref.cast $fluid (local.get $fluid))
  282. (ref.cast $proc (local.get $convert))))
  283. fluid conv)))
  284. (define-syntax parameterize
  285. (lambda (x)
  286. (syntax-case x ()
  287. ((_ ((parameter value) ...) body body* ...)
  288. (with-syntax (((p ...) (generate-temporaries #'(parameter ...))))
  289. #'(let ((p parameter) ...)
  290. (define (parameter? x)
  291. (%inline-wasm
  292. '(func (param $x (ref eq)) (result (ref eq))
  293. (if (ref eq)
  294. (ref.test $parameter (local.get $x))
  295. (then (ref.i31 (i32.const 17)))
  296. (else (ref.i31 (i32.const 1)))))
  297. x))
  298. (define (parameter-fluid x)
  299. (%inline-wasm
  300. '(func (param $param (ref $parameter)) (result (ref eq))
  301. (struct.get $parameter $fluid (local.get $param)))
  302. x))
  303. (define (parameter-convert x)
  304. (%inline-wasm
  305. '(func (param $param (ref $parameter)) (result (ref eq))
  306. (struct.get $parameter $convert (local.get $param)))
  307. x))
  308. (check-type p parameter? 'parameterize)
  309. ...
  310. (with-fluids (((parameter-fluid p) ((parameter-convert p) value))
  311. ...)
  312. body body* ...)))))))
  313. (define (make-atomic-box x) (%make-atomic-box x))
  314. (define (atomic-box-ref x) (%atomic-box-ref x))
  315. (define (atomic-box-set! x y) (%atomic-box-set! x y))
  316. (define (atomic-box-swap! x y) (%atomic-box-swap! x y))
  317. (define (atomic-box-compare-and-swap! x y z) (%atomic-box-compare-and-swap! x y z))
  318. (define (list . args) args)
  319. (define-syntax-rule (define-primcall f %f arg ...)
  320. (begin
  321. (define (generic arg ...)
  322. (%f arg ...))
  323. (define-syntax f
  324. (lambda (stx)
  325. (syntax-case stx ()
  326. ((_ . x) #'(%f . x))
  327. (id (identifier? #'id) #'generic))))))
  328. (define-primcall call-with-prompt %call-with-prompt tag body handler)
  329. (define* (make-prompt-tag #:optional (stem "prompt"))
  330. (list stem))
  331. (cond-expand
  332. (hoot-main
  333. (define default-prompt-tag (make-parameter (make-prompt-tag "%")))
  334. (%inline-wasm
  335. '(func (param $default-prompt-tag (ref eq))
  336. (global.set $default-prompt-tag (local.get $default-prompt-tag)))
  337. default-prompt-tag))
  338. (hoot-aux
  339. (define default-prompt-tag
  340. (%inline-wasm
  341. '(func (result (ref eq)) (global.get $default-prompt-tag))))))
  342. (define (%backtrace)
  343. (define (scm-sp)
  344. (%inline-wasm
  345. '(func (result (ref eq))
  346. (ref.i31 (i32.shl (global.get $scm-sp) (i32.const 1))))))
  347. (define (raw-sp)
  348. (%inline-wasm
  349. '(func (result (ref eq))
  350. (ref.i31 (i32.shl (global.get $raw-sp) (i32.const 1))))))
  351. (define (ret-sp)
  352. (%inline-wasm
  353. '(func (result (ref eq))
  354. (ref.i31 (i32.shl (global.get $ret-sp) (i32.const 1))))))
  355. (define (dyn-sp)
  356. (%inline-wasm
  357. '(func (result (ref eq))
  358. (ref.i31 (i32.shl (global.get $dyn-sp) (i32.const 1))))))
  359. (define (scm-ref n)
  360. (%inline-wasm
  361. '(func (param $n (ref i31))
  362. (result (ref eq))
  363. (ref.as_non_null
  364. (table.get $scm-stack
  365. (i32.shr_s (i31.get_s (local.get $n))
  366. (i32.const 1)))))
  367. n))
  368. (define (raw-ref n)
  369. (%inline-wasm
  370. '(func (param $n (ref i31))
  371. (result (ref eq))
  372. (ref.i31
  373. (i32.shl
  374. (i32.load8_s $raw-stack
  375. (i32.shr_s (i31.get_s (local.get $n))
  376. (i32.const 1)))
  377. (i32.const 1))))
  378. n))
  379. (let ((scm-sp (scm-sp))
  380. (raw-sp (raw-sp))
  381. (ret-sp (ret-sp))
  382. (dyn-sp (dyn-sp)))
  383. (%debug "scm backtrace" scm-sp)
  384. (let lp ((i 1))
  385. (when (<= 0 (- scm-sp i))
  386. (%debug "scm" (scm-ref (- scm-sp i)))
  387. (lp (1+ i))))
  388. (%debug "raw backtrace" raw-sp)
  389. (let lp ((i 1))
  390. (when (<= 0 (- raw-sp i))
  391. (%debug "raw" (raw-ref (- raw-sp i)))
  392. (lp (1+ i))))
  393. (%debug "ret stack height" ret-sp)
  394. (%debug "dyn stack height" dyn-sp)
  395. (%debug "")))
  396. ;; This is an implementation of call/cc in terms of delimited
  397. ;; continuations. It correct except as regards dynamic-wind: capturing
  398. ;; the continuation unwinds all dynamic-winds, then rewinds them; and
  399. ;; invoking the continuation does the same, even if the invoking and
  400. ;; captured continuations overlap. Oh well; call/cc is strictly less
  401. ;; useful than call-with-prompt anyway.
  402. (define (call-with-current-continuation proc)
  403. (define (unwind-and-call handler)
  404. (abort-to-prompt (default-prompt-tag) handler))
  405. (define (rewind-and-continue captured-continuation)
  406. (define-syntax-rule (reinstate expr)
  407. (captured-continuation (lambda () expr)))
  408. (define (k . args)
  409. (define (rewind-and-return-values discarded-continuation)
  410. (reinstate (apply values args)))
  411. (unwind-and-call rewind-and-return-values))
  412. (reinstate (proc k)))
  413. (let ((thunk (unwind-and-call rewind-and-continue)))
  414. (thunk)))
  415. (define call/cc call-with-current-continuation)
  416. (define-syntax %
  417. (syntax-rules ()
  418. ((_ expr)
  419. (call-with-prompt (default-prompt-tag)
  420. (lambda () expr)
  421. default-prompt-handler))
  422. ((_ expr handler)
  423. (call-with-prompt (default-prompt-tag)
  424. (lambda () expr)
  425. handler))
  426. ((_ tag expr handler)
  427. (call-with-prompt tag
  428. (lambda () expr)
  429. handler))))
  430. (define (default-prompt-handler k proc) (% (proc k)))
  431. (define (dynamic-wind wind body unwind)
  432. (%dynamic-wind wind body unwind))
  433. (define-syntax call-with-values
  434. (lambda (stx)
  435. (syntax-case stx (lambda)
  436. ((_ producer (lambda args body0 body ...))
  437. #'(%call-with-values producer (lambda args body0 body ...)))
  438. (id (identifier? #'id)
  439. #'(lambda (producer consumer)
  440. (let ((p producer) (c consumer))
  441. (%call-with-values p (lambda args (apply c args)))))))))
  442. (define (pair? p) (%pair? p))
  443. (define (cons x y) (%cons x y))
  444. (define (car x) (%car x))
  445. (define (cdr x) (%cdr x))
  446. (define (caar x) (%car (%car x)))
  447. (define (cadr x) (%car (%cdr x)))
  448. (define (cdar x) (%cdr (%car x)))
  449. (define (cddr x) (%cdr (%cdr x)))
  450. (define (caaar x) (%car (%car (%car x))))
  451. (define (cadar x) (%car (%cdr (%car x))))
  452. (define (caadr x) (%car (%car (%cdr x))))
  453. (define (caddr x) (%car (%cdr (%cdr x))))
  454. (define (cdaar x) (%cdr (%car (%car x))))
  455. (define (cddar x) (%cdr (%cdr (%car x))))
  456. (define (cdadr x) (%cdr (%car (%cdr x))))
  457. (define (cdddr x) (%cdr (%cdr (%cdr x))))
  458. (define (caaaar x) (%car (%car (%car (%car x)))))
  459. (define (caadar x) (%car (%car (%cdr (%car x)))))
  460. (define (caaadr x) (%car (%car (%car (%cdr x)))))
  461. (define (caaddr x) (%car (%car (%cdr (%cdr x)))))
  462. (define (cadaar x) (%car (%cdr (%car (%car x)))))
  463. (define (caddar x) (%car (%cdr (%cdr (%car x)))))
  464. (define (cadadr x) (%car (%cdr (%car (%cdr x)))))
  465. (define (cadddr x) (%car (%cdr (%cdr (%cdr x)))))
  466. (define (cdaaar x) (%cdr (%car (%car (%car x)))))
  467. (define (cdadar x) (%cdr (%car (%cdr (%car x)))))
  468. (define (cdaadr x) (%cdr (%car (%car (%cdr x)))))
  469. (define (cdaddr x) (%cdr (%car (%cdr (%cdr x)))))
  470. (define (cddaar x) (%cdr (%cdr (%car (%car x)))))
  471. (define (cdddar x) (%cdr (%cdr (%cdr (%car x)))))
  472. (define (cddadr x) (%cdr (%cdr (%car (%cdr x)))))
  473. (define (cddddr x) (%cdr (%cdr (%cdr (%cdr x)))))
  474. (define (set-car! x y) (%set-car! x y))
  475. (define (set-cdr! x y) (%set-cdr! x y))
  476. (define* (%debug message #:optional (val '(missing)))
  477. (cond
  478. ((eq? val '(missing))
  479. (%inline-wasm
  480. '(func (param $str (ref string))
  481. (call $debug-str (local.get $str)))
  482. message))
  483. (else
  484. (%inline-wasm
  485. '(func (param $str (ref string)) (param $val (ref eq))
  486. (call $debug-str-scm (local.get $str) (local.get $val)))
  487. message val))))
  488. (define* (pk v . v*)
  489. (match (reverse (cons v v*))
  490. ((val . vals)
  491. (for-each (lambda (v) (%debug "pk_" v)) (reverse vals))
  492. (%debug "pkv" val)
  493. val)))
  494. (define (length l)
  495. (let lp ((len 0) (l l))
  496. (if (%null? l) len (lp (%+ len 1) (%cdr l)))))
  497. (define (list-ref l n)
  498. (let lp ((l l) (n n))
  499. (if (zero? n)
  500. (car l)
  501. (lp (cdr l) (1- n)))))
  502. (define (list-set! l n x)
  503. (let lp ((l l) (n n))
  504. (if (zero? n)
  505. (set-car! l x)
  506. (lp (cdr l) (1- n)))))
  507. (define (list-tail l n)
  508. (let lp ((l l) (n n))
  509. (if (zero? n)
  510. l
  511. (lp (cdr l) (1- n)))))
  512. (define (list? l)
  513. (let lp ((l l))
  514. (match l
  515. (() #t)
  516. ((_ . l) (lp l))
  517. (_ #f))))
  518. (define (make-list n init)
  519. (let lp ((n n) (out '()))
  520. (if (zero? n)
  521. out
  522. (lp (1- n) (cons init out)))))
  523. (define (null? x) (%null? x))
  524. (define (reverse l)
  525. (let lp ((out '()) (l l))
  526. (match l
  527. (() out)
  528. ((head . tail) (lp (cons head out) tail)))))
  529. (define append
  530. (case-lambda
  531. (() '())
  532. ((x) x)
  533. ((x y) (%append x y))
  534. ((x y . z) (%append x (apply append y z)))))
  535. (define (list-copy l)
  536. (append l '()))
  537. (define-syntax-rule (define-member+assoc member assoc compare optarg ...)
  538. (begin
  539. (define* (member v l optarg ...)
  540. (let lp ((l l))
  541. (cond
  542. ((null? l) #f)
  543. ((compare v (car l)) l)
  544. (else (lp (cdr l))))))
  545. (define* (assoc v l optarg ...)
  546. (let lp ((l l))
  547. (and (not (null? l))
  548. (let ((head (car l)))
  549. (if (compare v (car head))
  550. head
  551. (lp (cdr l)))))))))
  552. (define-member+assoc memq assq eq?)
  553. (define-member+assoc memv assv eqv?)
  554. (define-member+assoc member assoc compare #:optional (compare equal?))
  555. (define* (make-bytevector len #:optional (init 0))
  556. (check-size len (1- (ash 1 29)) 'make-bytevector)
  557. (check-range init -128 255 'make-bytevector)
  558. (%inline-wasm
  559. '(func (param $len i32) (param $init i32)
  560. (result (ref eq))
  561. (struct.new
  562. $mutable-bytevector
  563. (i32.const 0)
  564. (array.new $raw-bytevector (local.get $init) (local.get $len))))
  565. len init))
  566. (define (bytevector-length bv) (%bytevector-length bv))
  567. (define (bytevector-u8-ref bv i) (%bytevector-u8-ref bv i))
  568. (define (bytevector-u8-set! bv i x) (%bytevector-u8-set! bv i x))
  569. (define (bytevector-s8-ref bv i) (%bytevector-s8-ref bv i))
  570. (define (bytevector-s8-set! bv i x) (%bytevector-s8-set! bv i x))
  571. (define (bytevector-u16-native-ref bv i) (%bytevector-u16-native-ref bv i))
  572. (define (bytevector-u16-native-set! bv i x) (%bytevector-u16-native-set! bv i x))
  573. (define (bytevector-s16-native-ref bv i) (%bytevector-s16-native-ref bv i))
  574. (define (bytevector-s16-native-set! bv i x) (%bytevector-s16-native-set! bv i x))
  575. (define (bytevector-u32-native-ref bv i) (%bytevector-u32-native-ref bv i))
  576. (define (bytevector-u32-native-set! bv i x) (%bytevector-u32-native-set! bv i x))
  577. (define (bytevector-s32-native-ref bv i) (%bytevector-s32-native-ref bv i))
  578. (define (bytevector-s32-native-set! bv i x) (%bytevector-s32-native-set! bv i x))
  579. (define (bytevector-u64-native-ref bv i) (%bytevector-u64-native-ref bv i))
  580. (define (bytevector-u64-native-set! bv i x) (%bytevector-u64-native-set! bv i x))
  581. (define (bytevector-s64-native-ref bv i) (%bytevector-s64-native-ref bv i))
  582. (define (bytevector-s64-native-set! bv i x) (%bytevector-s64-native-set! bv i x))
  583. (define (bytevector-ieee-single-native-ref bv i) (%bytevector-ieee-single-native-ref bv i))
  584. (define (bytevector-ieee-single-native-set! bv i x) (%bytevector-ieee-single-native-set! bv i x))
  585. (define (bytevector-ieee-double-native-ref bv i) (%bytevector-ieee-double-native-ref bv i))
  586. (define (bytevector-ieee-double-native-set! bv i x) (%bytevector-ieee-double-native-set! bv i x))
  587. (define (bytevector? x) (%bytevector? x))
  588. (define (bytevector . inits)
  589. (let* ((len (length inits))
  590. (bv (make-bytevector len)))
  591. (let lp ((i 0) (inits inits))
  592. (when (< i len)
  593. (bytevector-u8-set! bv i (car inits))
  594. (lp (1+ i) (cdr inits))))
  595. bv))
  596. (define (bytevector-concatenate bv*)
  597. (match bv*
  598. (() #vu8())
  599. ((bv) bv)
  600. (bv*
  601. (let* ((len (fold (lambda (bv len) (+ (bytevector-length bv) len)) 0 bv*))
  602. (flattened (make-bytevector len 0)))
  603. (let lp ((bv* bv*) (cur 0))
  604. (match bv*
  605. (() flattened)
  606. ((bv . bv*)
  607. (bytevector-copy! flattened cur bv)
  608. (lp bv* (+ cur (bytevector-length bv))))))))))
  609. (define (bytevector-concatenate-reverse bv*)
  610. (match bv*
  611. (() #vu8())
  612. ((bv) bv)
  613. (bv*
  614. (let* ((len (fold (lambda (bv len) (+ (bytevector-length bv) len)) 0 bv*))
  615. (flattened (make-bytevector len 0)))
  616. (let lp ((bv* bv*) (cur len))
  617. (match bv*
  618. (() flattened)
  619. ((bv . bv*)
  620. (let ((cur (- cur (bytevector-length bv))))
  621. (bytevector-copy! flattened cur bv)
  622. (lp bv* cur)))))))))
  623. (define (bytevector-append . args)
  624. (bytevector-concatenate args))
  625. (define* (bytevector-copy x #:optional (start 0) (end (bytevector-length x)))
  626. (check-type x bytevector? 'bytevector-copy)
  627. (check-range start 0 (bytevector-length x) 'bytevector-copy)
  628. (check-range end start (bytevector-length x) 'bytevector-copy)
  629. (%inline-wasm
  630. '(func (param $src (ref $bytevector)) (param $start i32) (param $end i32)
  631. (result (ref eq))
  632. (local $i0 i32)
  633. (local $vu0 (ref $raw-bytevector))
  634. (local.set $i0 (i32.sub (local.get $end) (local.get $start)))
  635. (local.set $vu0 (array.new_default $raw-bytevector (local.get $i0)))
  636. (array.copy $raw-bytevector $raw-bytevector
  637. (local.get $vu0) (i32.const 0)
  638. (struct.get $bytevector $vals (local.get $src))
  639. (local.get $start) (local.get $i0))
  640. (struct.new $bytevector (i32.const 0) (local.get $vu0)))
  641. x start end))
  642. (define* (bytevector-copy! to at from #:optional
  643. (start 0) (end (bytevector-length from)))
  644. ;; FIXME: check that `to` is mutable
  645. (check-type to bytevector? 'bytevector-copy!)
  646. (check-range at 0 (bytevector-length to) 'bytevector-copy!)
  647. (check-type from bytevector? 'bytevector-copy!)
  648. (check-range start 0 (bytevector-length from) 'bytevector-copy!)
  649. (check-range end start (bytevector-length from) 'bytevector-copy!)
  650. (%inline-wasm
  651. '(func (param $to (ref $mutable-bytevector)) (param $at i32)
  652. (param $from (ref $bytevector)) (param $start i32) (param $end i32)
  653. (array.copy $raw-bytevector $raw-bytevector
  654. (struct.get $mutable-bytevector $vals (local.get $to))
  655. (local.get $at)
  656. (struct.get $bytevector $vals (local.get $from))
  657. (local.get $start)
  658. (i32.sub (local.get $end) (local.get $start))))
  659. to at from start end))
  660. (define-associative-eta-expansion * %*)
  661. (define-associative-eta-expansion + %+)
  662. (define-syntax-rule (define-sub/div-eta-expansion f %f zero)
  663. (begin
  664. (define (%generic y . tail)
  665. (if (null? tail)
  666. (%f zero y)
  667. (let lp ((y y) (tail tail))
  668. (let ((y (%f y (car tail)))
  669. (tail (cdr tail)))
  670. (if (null? tail)
  671. y
  672. (lp y tail))))))
  673. (define-syntax f
  674. (lambda (stx)
  675. (syntax-case stx ()
  676. ((_ . x) #'(%f . x))
  677. (f (identifier? #'f) #'%generic))))))
  678. (define-sub/div-eta-expansion - %- 0)
  679. (define-sub/div-eta-expansion / %/ 1)
  680. (define-syntax-rule (define-comparison-expansion f %f)
  681. (begin
  682. (define (%generic x y . tail)
  683. (and (%f x y)
  684. (or (null? tail)
  685. (apply %generic y tail))))
  686. (define-syntax f
  687. (lambda (stx)
  688. (syntax-case stx ()
  689. ((_ x y . z) #'(%f x y . z))
  690. (f (identifier? #'f) #'%generic))))))
  691. (define-comparison-expansion < %<)
  692. (define-comparison-expansion <= %<=)
  693. (define-comparison-expansion = %=)
  694. (define-comparison-expansion >= %>=)
  695. (define-comparison-expansion > %>)
  696. (define (abs x) (%abs x))
  697. (define (floor x) (%floor x))
  698. (define (ceiling x) (%ceiling x))
  699. (define (round x) (%floor (+ x 0.5)))
  700. (define (truncate x)
  701. (check-type x real? 'truncate)
  702. (if (exact? x)
  703. (if (integer? x)
  704. x
  705. (truncate-quotient (numerator x) (denominator x)))
  706. (%inline-wasm
  707. '(func (param $x f64) (result f64)
  708. (f64.trunc (local.get $x)))
  709. x)))
  710. (define (number? x) (%number? x))
  711. (define (complex? x) (%complex? x))
  712. (define (real? x) (%real? x))
  713. (define (rational? x) (%rational? x))
  714. (define (integer? x) (%integer? x))
  715. (define (exact-integer? x) (%exact-integer? x))
  716. (define (exact? x) (%exact? x))
  717. (define (inexact? x) (%inexact? x))
  718. ;; (scheme inexact)
  719. (define (finite? z)
  720. (define (%inf? x)
  721. (or (= x +inf.0) (= x -inf.0)))
  722. (define (%nan? x)
  723. (not (= x x)))
  724. (if (real? z)
  725. (and (not (%inf? z)) (not (%nan? z)))
  726. (let ((r (real-part z))
  727. (i (imag-part z)))
  728. (and (not (%inf? r)) (not (%nan? r))
  729. (not (%inf? i)) (not (%nan? i))))))
  730. (define (infinite? z)
  731. (define (%inf? x)
  732. (or (= x +inf.0) (= x -inf.0)))
  733. (if (real? z)
  734. (%inf? z)
  735. (or (%inf? (real-part z))
  736. (%inf? (imag-part z)))))
  737. (define (nan? z)
  738. (define (%nan? x)
  739. (not (= x x)))
  740. (if (real? z)
  741. (not (= z z))
  742. (let ((r (real-part z))
  743. (i (imag-part z)))
  744. (or (not (= r r)) (not (= i i))))))
  745. (define (inexact x) (%inexact x))
  746. (define (exact x)
  747. (cond
  748. ((exact? x) x)
  749. (else
  750. (check-type x real? 'exact)
  751. (check-type x finite? 'exact)
  752. (%inline-wasm
  753. '(func (param $x f64)
  754. (result (ref eq))
  755. (call $f64->exact (local.get $x)))
  756. x))))
  757. (define (quotient x y) (%quotient x y))
  758. (define (remainder x y) (%remainder x y))
  759. (define (modulo x y) (%modulo x y))
  760. (define (even? x) (zero? (logand x 1)))
  761. (define (odd? x) (not (even? x)))
  762. (define (numerator x)
  763. (cond
  764. ((exact-integer? x) x)
  765. ((exact? x)
  766. (%inline-wasm
  767. '(func (param $x (ref $fraction))
  768. (result (ref eq))
  769. (struct.get $fraction $num (local.get $x)))
  770. x))
  771. (else (inexact (numerator (exact x))))))
  772. (define (denominator x)
  773. (cond
  774. ((exact-integer? x) 1)
  775. ((exact? x)
  776. (%inline-wasm
  777. '(func (param $x (ref $fraction))
  778. (result (ref eq))
  779. (struct.get $fraction $denom (local.get $x)))
  780. x))
  781. (else (inexact (denominator (exact x))))))
  782. (define (exact-integer-sqrt n)
  783. ;; FIXME: There's a compiler bug that makes this procedure return
  784. ;; junk when this exact-integer? check is enabled.
  785. ;;
  786. ;; (check-type n exact-integer? 'exact-integer-sqrt)
  787. (assert (>= n 0) 'exact-integer-sqrt)
  788. (let loop ((x n) (y (quotient (+ n 1) 2)))
  789. (if (< y x)
  790. (loop y (quotient (+ y (quotient n y)) 2))
  791. (values x (- n (* x x))))))
  792. (define (floor/ x y)
  793. (values (floor-quotient x y) (floor-remainder x y)))
  794. ;; Adapted from the SRFI-141 reference implementation
  795. (define (floor-quotient x y)
  796. (check-type x integer? 'floor-quotient)
  797. (check-type y integer? 'floor-quotient)
  798. (cond
  799. ((and (negative? x) (negative? y))
  800. (quotient (- x) (- y)))
  801. ((negative? x)
  802. (let ((x (- x)))
  803. (call-with-values (lambda () (truncate/ x y))
  804. (lambda (q r)
  805. (if (zero? r)
  806. (- q)
  807. (1- (- q)))))))
  808. ((negative? y)
  809. (let ((y (- y)))
  810. (call-with-values (lambda () (truncate/ x y))
  811. (lambda (q r)
  812. (if (zero? r)
  813. (- q)
  814. (1- (- q)))))))
  815. (else (quotient x y))))
  816. (define (floor-remainder x y) (modulo x y))
  817. (define (truncate/ x y)
  818. (values (truncate-quotient x y)
  819. (truncate-remainder x y)))
  820. (define (truncate-quotient x y) (quotient x y))
  821. (define (truncate-remainder x y) (remainder x y))
  822. (define (%binary-gcd x y)
  823. (check-type x integer? 'gcd)
  824. (check-type y integer? 'gcd)
  825. (let ((result
  826. (%inline-wasm
  827. '(func (param $x (ref eq)) (param $y (ref eq))
  828. (result (ref eq))
  829. (call $gcd (local.get $x) (local.get $y)))
  830. (exact x)
  831. (exact y))))
  832. (if (or (inexact? x) (inexact? y))
  833. (inexact result)
  834. result)))
  835. (define-syntax %gcd
  836. (syntax-rules ()
  837. ((_) 0)
  838. ((_ x) x)
  839. ((_ x y) (%binary-gcd x y))))
  840. (define (%binary-lcm x y)
  841. (check-type x integer? 'lcm)
  842. (check-type y integer? 'lcm)
  843. (let* ((exact-x (exact x))
  844. (exact-y (exact y))
  845. (result (if (and (eqv? exact-x 0) (eqv? exact-y 0))
  846. 0
  847. (quotient (abs (* exact-x exact-y))
  848. (gcd exact-x exact-y)))))
  849. (if (or (inexact? x) (inexact? y))
  850. (inexact result)
  851. result)))
  852. (define-syntax %lcm
  853. (syntax-rules ()
  854. ((_) 1)
  855. ((_ x) x)
  856. ((_ x y) (%binary-lcm x y))))
  857. (define-associative-eta-expansion gcd %gcd)
  858. (define-associative-eta-expansion lcm %lcm)
  859. (define max
  860. (case-lambda
  861. ((x) x)
  862. ((x y) (if (> x y) x y))
  863. ((x y . z) (apply max (max x y) z))))
  864. (define min
  865. (case-lambda
  866. ((x) x)
  867. ((x y) (if (< x y) x y))
  868. ((x y . z) (apply min (min x y) z))))
  869. (define (negative? x) (< x 0))
  870. (define (positive? x) (> x 0))
  871. (define (zero? x) (= x 0))
  872. (define (sin x) (%sin x))
  873. (define (cos x) (%cos x))
  874. (define (tan x) (%tan x))
  875. (define (asin x) (%asin x))
  876. (define (acos x) (%acos x))
  877. ;; FIXME: optargs
  878. (define (%generic-atan x . y)
  879. (if (null? y)
  880. (%atan x)
  881. (%atan x (car y))))
  882. (define-syntax atan
  883. (lambda (stx)
  884. (syntax-case stx ()
  885. ((_ x) #'(%atan x))
  886. ((_ x y) #'(%atan x y))
  887. (f (identifier? #'f) #'%generic-atan))))
  888. (define (sqrt x) (%sqrt x))
  889. (define* (log x #:optional y)
  890. (define (%log x)
  891. (%inline-wasm
  892. '(func (param $x (ref eq)) (result (ref eq))
  893. (call $log (local.get $x)))
  894. x))
  895. (if y
  896. (/ (%log x)
  897. (%log y))
  898. (%log x)))
  899. (define (exp x)
  900. (define (%exp x)
  901. (%inline-wasm
  902. '(func (param $x (ref eq)) (result (ref eq))
  903. (call $exp (local.get $x)))
  904. x))
  905. (%exp x))
  906. (define* (number->string n #:optional (radix 10))
  907. (cond
  908. ((exact-integer? n)
  909. (if (zero? n)
  910. "0"
  911. (let* ((mag (if (< n 0) (- n) n))
  912. (digits
  913. (case radix
  914. ((2) (let lp ((mag mag) (out '()))
  915. (if (zero? mag)
  916. out
  917. (lp (ash mag -1)
  918. (cons (integer->char
  919. (+ (char->integer #\0)
  920. (logand mag 1)))
  921. out)))))
  922. ((8) (let lp ((mag mag) (out '()))
  923. (if (zero? mag)
  924. out
  925. (lp (ash mag -3)
  926. (cons (integer->char
  927. (+ (char->integer #\0)
  928. (logand mag 7)))
  929. out)))))
  930. ((10) (let lp ((mag mag) (out '()))
  931. (if (zero? mag)
  932. out
  933. (lp (quotient mag 10)
  934. (cons (integer->char
  935. (+ (char->integer #\0)
  936. (remainder mag 10)))
  937. out)))))
  938. ((16) (let lp ((mag mag) (out '()))
  939. (if (zero? mag)
  940. out
  941. (lp (ash mag -4)
  942. (cons (integer->char
  943. (let ((digit (logand mag 15)))
  944. (+ (if (< digit 10)
  945. (char->integer #\0)
  946. (char->integer #\a))
  947. digit)))
  948. out))))))))
  949. (list->string (if (negative? n) (cons #\- digits) digits)))))
  950. ((exact? n)
  951. (string-append (number->string (numerator n) radix)
  952. "/"
  953. (number->string (denominator n) radix)))
  954. ((real? n)
  955. (assert (eqv? radix 10) 'number->string)
  956. (%inline-wasm
  957. '(func (param $n f64)
  958. (result (ref eq))
  959. (struct.new $string
  960. (i32.const 0)
  961. (call $flonum->string (local.get $n))))
  962. n))
  963. (else
  964. (string-append (number->string (real-part n) radix)
  965. "/"
  966. (number->string (imag-part n) radix)
  967. "i"))))
  968. (define* (string->number str #:optional (radix 10))
  969. (let ((port (open-input-string str)))
  970. (define (read-bin-digit)
  971. (case (peek-char port)
  972. ((#\0 #\1)
  973. (- (char->integer (read-char port)) (char->integer #\0)))
  974. (else #f)))
  975. (define (read-oct-digit)
  976. (case (peek-char port)
  977. ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7)
  978. (- (char->integer (read-char port)) (char->integer #\0)))
  979. (else #f)))
  980. (define (read-dec-digit)
  981. (case (peek-char port)
  982. ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)
  983. (- (char->integer (read-char port)) (char->integer #\0)))
  984. (else #f)))
  985. (define (read-hex-digit)
  986. (case (peek-char port)
  987. ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)
  988. (- (char->integer (read-char port)) (char->integer #\0)))
  989. ((#\a #\b #\c #\d #\e #\f)
  990. (+ 10 (- (char->integer (read-char port)) (char->integer #\a))))
  991. ((#\A #\B #\C #\D #\E #\F)
  992. (+ 10 (- (char->integer (read-char port)) (char->integer #\A))))
  993. (else #f)))
  994. (define (read-unsigned-int radix)
  995. (case radix
  996. ((2)
  997. (let ((x (read-bin-digit)))
  998. (and x
  999. (let loop ((x x))
  1000. (let ((y (read-bin-digit)))
  1001. (if y (loop (+ (* x 2) y)) x))))))
  1002. ((8)
  1003. (let ((x (read-oct-digit)))
  1004. (and x
  1005. (let loop ((x x))
  1006. (let ((y (read-oct-digit)))
  1007. (if y (loop (+ (* x 8) y)) x))))))
  1008. ((10)
  1009. (let ((x (read-dec-digit)))
  1010. (and x
  1011. (let loop ((x x))
  1012. (let ((y (read-dec-digit)))
  1013. (if y (loop (+ (* x 10) y)) x))))))
  1014. ((16)
  1015. (let ((x (read-hex-digit)))
  1016. (and x
  1017. (let loop ((x x))
  1018. (let ((y (read-hex-digit)))
  1019. (if y (loop (+ (* x 16) y)) x))))))))
  1020. (define (read-sign)
  1021. (let ((ch (peek-char port)))
  1022. (cond
  1023. ((eof-object? ch) #f)
  1024. ((eqv? ch #\+)
  1025. (read-char port)
  1026. '+)
  1027. ((eqv? ch #\-)
  1028. (read-char port)
  1029. '-)
  1030. (else 'none))))
  1031. (define (read-decimal n exactness)
  1032. (case (peek-char port)
  1033. ;; Decimal point
  1034. ((#\.)
  1035. (read-char port)
  1036. (let ((x (read-dec-digit)))
  1037. (and x
  1038. (let loop ((i -2) (x (* x (expt 10 -1))))
  1039. (let ((y (read-dec-digit)))
  1040. (if y
  1041. (loop (- i 1) (+ x (* y (expt 10 i))))
  1042. (let ((z (+ n x)))
  1043. (or (read-decimal z exactness)
  1044. (if (eq? exactness 'exact) z (inexact z))))))))))
  1045. ;; Exponent
  1046. ((#\e #\E)
  1047. (read-char port)
  1048. (let* ((sign (read-sign))
  1049. (x (read-unsigned-int 10)))
  1050. (and x
  1051. (let ((y (* n (expt 10 (if (eq? sign '-) (- x) x)))))
  1052. (if (eq? exactness 'exact) y (inexact y))))))
  1053. (else #f)))
  1054. (define (read-unsigned radix exactness)
  1055. (let ((ch (peek-char port)))
  1056. (cond
  1057. ((eof-object? ch) #f)
  1058. ;; NaN
  1059. ((or (eqv? ch #\n) (eqv? ch #\N))
  1060. (read-char port)
  1061. (case (read-char port)
  1062. ((#\a #\A)
  1063. (case (read-char port)
  1064. ((#\n #\N)
  1065. (case (read-char port)
  1066. ((#\.)
  1067. (case (read-char port)
  1068. ((#\0) +nan.0)
  1069. (else #f)))
  1070. (else #f)))
  1071. (else #f)))
  1072. (else #f)))
  1073. ;; Infinity
  1074. ((or (eqv? ch #\i) (eqv? ch #\I))
  1075. (read-char port)
  1076. (let ((ch (peek-char port)))
  1077. (cond
  1078. ;; This might be a valid complex number, either '+i' or
  1079. ;; '-i', so back up a char so the caller can check for
  1080. ;; that case.
  1081. ((eof-object? ch)
  1082. (seek port -1 'cur)
  1083. #f)
  1084. ((or (eqv? ch #\n) (eqv? ch #\N))
  1085. (read-char port)
  1086. (case (read-char port)
  1087. ((#\f #\F)
  1088. (case (read-char port)
  1089. ((#\.)
  1090. (case (read-char port)
  1091. ((#\0) +inf.0)
  1092. (else #f)))
  1093. (else #f)))
  1094. (else #f)))
  1095. (else #f))))
  1096. ;; Decimal with no leading digits.
  1097. ((eqv? ch #\.)
  1098. (and (eqv? radix 10) (read-decimal 0 exactness)))
  1099. (else
  1100. (let ((x (read-unsigned-int radix)))
  1101. (and x
  1102. (case (peek-char port)
  1103. ;; Fraction
  1104. ((#\/)
  1105. (read-char port)
  1106. (let ((y (read-unsigned-int radix)))
  1107. (and y
  1108. (let ((z (/ x y)))
  1109. (if (eq? exactness 'inexact) (inexact z) z)))))
  1110. ;; Decimal point or exponent
  1111. ((#\. #\e #\E)
  1112. (and (eqv? radix 10) (read-decimal x exactness)))
  1113. (else
  1114. (if (eq? exactness 'inexact) (inexact x) x)))))))))
  1115. (define (read-complex radix exactness)
  1116. (let ((sign (read-sign)))
  1117. (and sign
  1118. (let ((x (read-unsigned radix exactness)))
  1119. (cond
  1120. ((or (and (not x) (eq? sign 'none))
  1121. ;; Infinities and NaNs need explicit sign.
  1122. (and x (or (infinite? x) (nan? x)) (eq? sign 'none)))
  1123. #f)
  1124. ;; +i and -i cases.
  1125. ((not x)
  1126. (let ((ch (read-char port)))
  1127. (and (or (eqv? ch #\i) (eqv? ch #\I))
  1128. (if (eq? sign '+) +i -i))))
  1129. ;; We've successfully read one real, now to check for
  1130. ;; a polar or imaginary part.
  1131. (else
  1132. (let ((x (if (eq? sign '-) (- x) x)))
  1133. (let ((ch (peek-char port)))
  1134. (cond
  1135. ((eof-object? ch) x)
  1136. ;; Complex number in polar form.
  1137. ((eqv? ch #\@)
  1138. (read-char port)
  1139. (let* ((sign (read-sign))
  1140. (y (read-unsigned radix exactness)))
  1141. (and y (make-polar x (if (eq? sign '-) (- y) y)))))
  1142. ;; Complex number in rectangular form.
  1143. ((or (eqv? ch #\+) (eqv? ch #\-))
  1144. (let ((sign (read-sign))
  1145. (y (or (read-unsigned radix exactness) 1.0)))
  1146. (case (read-char port)
  1147. ((#\i #\I)
  1148. (make-rectangular x (if (eq? sign '-) (- y) y)))
  1149. (else #f))))
  1150. (else #f))))))))))
  1151. (define (read-number)
  1152. ;; First, read the radix and exactness prefix. These could be
  1153. ;; specified in either order (like #x#e or #e#x), one could be
  1154. ;; omitted (just #x or #e), or both could be omitted. When
  1155. ;; exactness is omitted, exactness becomes implicit. For
  1156. ;; example, '1.2' will produce an inexact value.
  1157. (let loop ((radix* #f) (exactness #f))
  1158. (let ((ch (peek-char port)))
  1159. (cond
  1160. ((eof-object? ch) #f)
  1161. ((eqv? ch #\#)
  1162. (read-char port)
  1163. (let ((ch (read-char port)))
  1164. (cond
  1165. ((and (or (eqv? ch #\b) (eqv? ch #\B)) (not radix*))
  1166. (loop 2 exactness))
  1167. ((and (or (eqv? ch #\o) (eqv? ch #\O)) (not radix*))
  1168. (loop 8 exactness))
  1169. ((and (or (eqv? ch #\d) (eqv? ch #\D)) (not radix*))
  1170. (loop 10 exactness))
  1171. ((and (or (eqv? ch #\x) (eqv? ch #\X)) (not radix*))
  1172. (loop 16 exactness))
  1173. ((and (or (eqv? ch #\e) (eqv? ch #\E)) (not exactness))
  1174. (loop radix* 'exact))
  1175. ((and (or (eqv? ch #\i) (eqv? ch #\I)) (not exactness))
  1176. (loop radix* 'inexact))
  1177. (else #f))))
  1178. (else
  1179. (read-complex (or radix* radix) exactness))))))
  1180. (let ((x (read-number)))
  1181. ;; Input should be completely consumed at this point.
  1182. (and (eof-object? (peek-char port)) x))))
  1183. ;; Adapted from the comments for scm_rationalize in libguile's numbers.c
  1184. (define (rationalize x y)
  1185. (check-type x rational? 'rationalize)
  1186. (check-type y rational? 'rationalize)
  1187. (define (exact-rationalize x eps)
  1188. (let ((n1 (if (negative? x) -1 1))
  1189. (x (abs x))
  1190. (eps (abs eps)))
  1191. (let ((lo (- x eps))
  1192. (hi (+ x eps)))
  1193. (if (<= lo 0)
  1194. 0
  1195. (let loop ((nlo (numerator lo)) (dlo (denominator lo))
  1196. (nhi (numerator hi)) (dhi (denominator hi))
  1197. (n1 n1) (d1 0) (n2 0) (d2 1))
  1198. (let-values (((qlo rlo) (floor/ nlo dlo))
  1199. ((qhi rhi) (floor/ nhi dhi)))
  1200. (let ((n0 (+ n2 (* n1 qlo)))
  1201. (d0 (+ d2 (* d1 qlo))))
  1202. (cond ((zero? rlo) (/ n0 d0))
  1203. ((< qlo qhi) (/ (+ n0 n1) (+ d0 d1)))
  1204. (else (loop dhi rhi dlo rlo n0 d0 n1 d1))))))))))
  1205. (if (and (exact? x) (exact? y))
  1206. (exact-rationalize x y)
  1207. (inexact (exact-rationalize (exact x) (exact y)))))
  1208. (define (square x) (* x x))
  1209. (define (expt x y)
  1210. (check-type x number? 'expt)
  1211. (check-type y number? 'expt)
  1212. (cond
  1213. ((eqv? x 0)
  1214. (cond ((zero? y) (if (exact? y) 1 1.0))
  1215. ((positive? y) (if (exact? y) 0 0.0))
  1216. (else +nan.0)))
  1217. ((eqv? x 0.0)
  1218. (cond ((zero? y) 1.0)
  1219. ((positive? y) 0.0)
  1220. (else +nan.0)))
  1221. ((exact-integer? y)
  1222. (if (< y 0)
  1223. (/ 1 (expt x (abs y)))
  1224. (let lp ((y y)
  1225. (result 1))
  1226. (if (= y 0)
  1227. result
  1228. (lp (1- y) (* x result))))))
  1229. (else (exp (* y (log x))))))
  1230. ;; (scheme complex)
  1231. ;; Adapted from Guile's numbers.c
  1232. (define (make-rectangular real imag)
  1233. (check-type real real? 'make-rectangular)
  1234. (check-type imag real? 'make-rectangular)
  1235. (if (eq? imag 0)
  1236. real
  1237. (%inline-wasm
  1238. '(func (param $real f64) (param $imag f64) (result (ref eq))
  1239. (struct.new $complex
  1240. (i32.const 0)
  1241. (local.get $real)
  1242. (local.get $imag)))
  1243. (inexact real) (inexact imag))))
  1244. (define (make-polar mag ang)
  1245. (check-type mag real? 'make-polar)
  1246. (check-type ang real? 'make-polar)
  1247. (cond
  1248. ((eq? mag 0) 0)
  1249. ((eq? ang 0) mag)
  1250. (else
  1251. (%inline-wasm
  1252. '(func (param $mag f64) (param $ang f64) (result (ref eq))
  1253. (local $f0 f64) (local $f1 f64)
  1254. (local.set $f0 (call $fcos (local.get $ang)))
  1255. (local.set $f1 (call $fsin (local.get $ang)))
  1256. ;; If sin/cos are NaN and magnitude is 0, return a complex
  1257. ;; zero.
  1258. (if (ref eq)
  1259. (i32.and (call $f64-is-nan (local.get $f0))
  1260. (call $f64-is-nan (local.get $f1))
  1261. (f64.eq (local.get $mag) (f64.const 0.0)))
  1262. (then (struct.new $complex
  1263. (i32.const 0)
  1264. (f64.const 0.0)
  1265. (f64.const 0.0)))
  1266. (else (struct.new $complex
  1267. (i32.const 0)
  1268. (f64.mul (local.get $mag) (local.get $f0))
  1269. (f64.mul (local.get $mag) (local.get $f1))))))
  1270. (inexact mag) (inexact ang)))))
  1271. (define (magnitude z)
  1272. (cond
  1273. ((real? z) (abs z))
  1274. (else
  1275. (check-type z complex? 'magnitude)
  1276. (let ((r (real-part z))
  1277. (i (imag-part z)))
  1278. (sqrt (+ (* r r) (* i i)))))))
  1279. (define (angle z)
  1280. (cond
  1281. ((real? z)
  1282. (if (negative? z)
  1283. (atan 0.0 -1.0)
  1284. 0.0))
  1285. (else
  1286. (check-type z complex? 'angle)
  1287. (atan (imag-part z) (real-part z)))))
  1288. (define (real-part z)
  1289. (cond
  1290. ((real? z) z)
  1291. (else
  1292. (check-type z complex? 'real-part)
  1293. (%inline-wasm
  1294. '(func (param $z (ref $complex)) (result f64)
  1295. (struct.get $complex $real (local.get $z)))
  1296. z))))
  1297. (define (imag-part z)
  1298. (cond
  1299. ((real? z) 0.0)
  1300. (else
  1301. (check-type z complex? 'real-part)
  1302. (%inline-wasm
  1303. '(func (param $z (ref $complex)) (result f64)
  1304. (struct.get $complex $imag (local.get $z)))
  1305. z))))
  1306. (define (char->integer x) (%char->integer x))
  1307. (define (integer->char x) (%integer->char x))
  1308. (define (char? x) (%char? x))
  1309. (define (char<? . args) (apply < (map char->integer args)))
  1310. (define (char<=? . args) (apply <= (map char->integer args)))
  1311. (define (char=? . args) (apply = (map char->integer args)))
  1312. (define (char>=? . args) (apply >= (map char->integer args)))
  1313. (define (char>? . args) (apply > (map char->integer args)))
  1314. ;; generated (scheme char) procedures:
  1315. ;; char-upcase
  1316. ;; char-downcase
  1317. ;; char-upper-case?
  1318. ;; char-lower-case?
  1319. ;; char-alphabetic?
  1320. ;; char-numeric?
  1321. ;; char-whitespace?
  1322. (include-from-path "hoot/char-prelude")
  1323. (define (char-foldcase char)
  1324. (if (or (eqv? char #\460) (eqv? char #\461))
  1325. char
  1326. (char-downcase (char-upcase char))))
  1327. (define (digit-value char)
  1328. ;; The table can be extracted with:
  1329. ;; awk -F ';' '/ZERO;Nd/ {print "#x"$1}' UnicodeData.txt
  1330. ;; Up to date with Unicode 15.1.0.
  1331. (define *decimal-zeroes*
  1332. '#(#x0030 #x0660 #x06F0 #x07C0 #x0966 #x09E6 #x0A66 #x0AE6 #x0B66
  1333. #x0BE6 #x0C66 #x0CE6 #x0D66 #x0DE6 #x0E50 #x0ED0 #x0F20
  1334. #x1040 #x1090 #x17E0 #x1810 #x1946 #x19D0 #x1A80 #x1A90
  1335. #x1B50 #x1BB0 #x1C40 #x1C50 #xA620 #xA8D0 #xA900 #xA9D0
  1336. #xA9F0 #xAA50 #xABF0 #xFF10 #x104A0 #x10D30 #x11066
  1337. #x110F0 #x11136 #x111D0 #x112F0 #x11450 #x114D0 #x11650
  1338. #x116C0 #x11730 #x118E0 #x11950 #x11C50 #x11D50 #x11DA0
  1339. #x11F50 #x16A60 #x16AC0 #x16B50 #x1D7CE #x1D7D8 #x1D7E2
  1340. #x1D7EC #x1D7F6 #x1E140 #x1E2F0 #x1E4F0 #x1E950 #x1FBF0))
  1341. (let ((cp (char->integer char)))
  1342. (if (<= 0 (- cp (char->integer #\0)) 9)
  1343. ;; Fast case.
  1344. (- cp (char->integer #\0))
  1345. ;; Otherwise, a binary search.
  1346. (let lp ((start 0) (end (vector-length *decimal-zeroes*)))
  1347. (and (< start end)
  1348. (let* ((mid (ash (+ start end) -1))
  1349. (val (- cp (vector-ref *decimal-zeroes* mid))))
  1350. (cond
  1351. ((< val 0) (lp start mid))
  1352. ((< val 10) val)
  1353. (else (lp (1+ mid) end)))))))))
  1354. (define (char-ci<? ch1 ch2 . ch*)
  1355. (apply char<?
  1356. (char-foldcase ch1) (char-foldcase ch2) (map char-foldcase ch*)))
  1357. (define (char-ci<=? ch1 ch2 . ch*)
  1358. (apply char<=?
  1359. (char-foldcase ch1) (char-foldcase ch2) (map char-foldcase ch*)))
  1360. (define (char-ci=? ch1 ch2 . ch*)
  1361. (apply char=?
  1362. (char-foldcase ch1) (char-foldcase ch2) (map char-foldcase ch*)))
  1363. (define (char-ci>=? ch1 ch2 . ch*)
  1364. (apply char>=?
  1365. (char-foldcase ch1) (char-foldcase ch2) (map char-foldcase ch*)))
  1366. (define (char-ci>? ch1 ch2 . ch*)
  1367. (apply char>?
  1368. (char-foldcase ch1) (char-foldcase ch2) (map char-foldcase ch*)))
  1369. (define (string-upcase str)
  1370. (check-type str string? 'string-upcase)
  1371. (%inline-wasm
  1372. '(func (param $str (ref string))
  1373. (result (ref eq))
  1374. (struct.new $string
  1375. (i32.const 0)
  1376. (call $string-upcase (local.get $str))))
  1377. str))
  1378. (define (string-downcase str)
  1379. (check-type str string? 'string-downcase)
  1380. (%inline-wasm
  1381. '(func (param $str (ref string))
  1382. (result (ref eq))
  1383. (struct.new $string
  1384. (i32.const 0)
  1385. (call $string-downcase (local.get $str))))
  1386. str))
  1387. (define (string-foldcase str)
  1388. (string-downcase (string-upcase str)))
  1389. ;; FIXME: We could use Intl.Collator instead of manually folding case.
  1390. (define (string-ci<? . strs) (apply string<? (map string-foldcase strs)))
  1391. (define (string-ci<=? . strs) (apply string<=? (map string-foldcase strs)))
  1392. (define (string-ci=? . strs) (apply string=? (map string-foldcase strs)))
  1393. (define (string-ci>=? . strs) (apply string>=? (map string-foldcase strs)))
  1394. (define (string-ci>? . strs) (apply string>? (map string-foldcase strs)))
  1395. (define (make-box init) (%make-box init))
  1396. (define (box-ref box) (%box-ref box))
  1397. (define (box-set! box val) (%box-set! box val))
  1398. (define (not x) (if x #f #t))
  1399. (define (and-map pred l)
  1400. (or (null? l)
  1401. (and (pred (car l))
  1402. (and-map pred (cdr l)))))
  1403. (define (boolean? x) (match x ((or #f #t) #t) (_ #f)))
  1404. (define boolean=?
  1405. (case-lambda
  1406. ((x y)
  1407. (check-type x boolean? 'boolean=?)
  1408. (check-type y boolean? 'boolean=?)
  1409. (eq? x y))
  1410. ((x y . z)
  1411. (let lp ((z z) (res (boolean=? x y)))
  1412. (match z
  1413. (() res)
  1414. ((y . z)
  1415. (lp z (boolean=? x y))))))))
  1416. ;; R7RS strings
  1417. (define (string? x) (%string? x))
  1418. (define (mutable-string? x)
  1419. (%inline-wasm '(func (param $obj (ref eq))
  1420. (result (ref eq))
  1421. (if (ref eq)
  1422. (ref.test $mutable-string (local.get $obj))
  1423. (then (ref.i31 (i32.const 17)))
  1424. (else (ref.i31 (i32.const 1)))))
  1425. x))
  1426. (define (string-length x) (%string-length x))
  1427. (define (string-ref x i) (%string-ref x i))
  1428. (define (%mutable-string-set-str! x x*)
  1429. (check-type x mutable-string? '%mutable-string-set-str!)
  1430. (check-type x* string? '%mutable-string-set-str!)
  1431. (%inline-wasm '(func (param $s (ref $mutable-string))
  1432. (param $new-s (ref $string))
  1433. (struct.set $mutable-string
  1434. $str
  1435. (local.get $s)
  1436. (struct.get $string
  1437. $str
  1438. (local.get $new-s))))
  1439. x x*)
  1440. (if #f #f))
  1441. (define (string-set! x i v)
  1442. (check-type x mutable-string? 'string-set!)
  1443. (check-range i 0 (1- (string-length x)) 'string-set!)
  1444. (check-type v char? 'string-set!)
  1445. (let ((x* (string-append (string-copy x 0 i)
  1446. (string v)
  1447. (string-copy x (1+ i) (string-length x)))))
  1448. (%mutable-string-set-str! x x*)))
  1449. (define (string . chars) (list->string chars))
  1450. (define* (make-string n #:optional (init #\space))
  1451. (let ((p (open-output-string)))
  1452. (let lp ((n n))
  1453. (unless (zero? n)
  1454. (write-char init p)
  1455. (lp (1- n))))
  1456. (get-output-string p)))
  1457. (define (string-append . strs)
  1458. (let ((p (open-output-string)))
  1459. (for-each (lambda (str) (write-string str p)) strs)
  1460. (get-output-string p)))
  1461. (define* (string-copy str #:optional (start 0) (end (string-length str)))
  1462. (check-type str string? 'string-copy)
  1463. (check-range start 0 (string-length str) 'string-copy)
  1464. (check-range end start (string-length str) 'string-copy)
  1465. (%inline-wasm
  1466. '(func (param $str (ref string))
  1467. (param $start i32)
  1468. (param $end i32)
  1469. (result (ref eq))
  1470. (local $str_iter (ref stringview_iter))
  1471. (local.set $str_iter (string.as_iter (local.get $str)))
  1472. (drop
  1473. (stringview_iter.advance (local.get $str_iter) (local.get $start)))
  1474. (struct.new $mutable-string
  1475. (i32.const 0)
  1476. (stringview_iter.slice (local.get $str_iter)
  1477. (i32.sub (local.get $end)
  1478. (local.get $start)))))
  1479. str start end))
  1480. (define (substring str start end)
  1481. (string-copy str start end))
  1482. (define* (string-copy! to at from #:optional (start 0) (end (string-length from)))
  1483. (check-type to mutable-string? 'string-copy!)
  1484. (check-range at 0 (string-length to) 'string-copy!)
  1485. (check-type from string? 'string-copy!)
  1486. (assert (<= (- end start) (- (string-length to) at)) 'string-copy!)
  1487. (let ((to* (string-append (string-copy to 0 at)
  1488. (string-copy from start end)
  1489. (string-copy to (+ at (- end start))))))
  1490. (%mutable-string-set-str! to to*)))
  1491. (define* (string-fill! string fill
  1492. #:optional (start 0) (end (string-length string)))
  1493. (check-type string mutable-string? 'string-fill!)
  1494. (check-type fill char? 'string-fill!)
  1495. (check-range start 0 (string-length string) 'string-fill!)
  1496. (check-range end start (string-length string) 'string-fill!)
  1497. (let ((string*
  1498. (string-append (string-copy string 0 start)
  1499. (make-string (- end start) fill)
  1500. (string-copy string end (string-length string)))))
  1501. (%mutable-string-set-str! string string*)))
  1502. (define string-for-each
  1503. (case-lambda
  1504. ((f str) (for-each f (string->list str)))
  1505. ((f str . strs)
  1506. (apply for-each f (string->list str) (map string->list strs)))))
  1507. ;; TODO: Support n strings, our 'map' doesn't support n lists yet.
  1508. (define (string-map f str)
  1509. (list->string (map f (string->list str))))
  1510. (define (%string-compare a b)
  1511. (if (eq? a b)
  1512. 0
  1513. (%inline-wasm
  1514. '(func (param $a (ref string))
  1515. (param $b (ref string))
  1516. (result (ref eq))
  1517. (ref.i31 (i32.shl (string.compare (local.get $a) (local.get $b))
  1518. (i32.const 1))))
  1519. a b)))
  1520. (define (%string-compare* ordered? x y strs)
  1521. (check-type x string? 'string-compare)
  1522. (check-type y string? 'string-compare)
  1523. (for-each (lambda (s) (check-type s string? 'string-compare)) strs)
  1524. (define (pred a b) (ordered? (%string-compare a b) 0))
  1525. (and (pred x y)
  1526. (let lp ((y y) (strs strs))
  1527. (match strs
  1528. (() #t)
  1529. ((z . strs) (and (pred y z) (lp z strs)))))))
  1530. (define (string<? x y . strs) (%string-compare* < x y strs))
  1531. (define (string<=? x y . strs) (%string-compare* <= x y strs))
  1532. (define (string=? x y . strs) (%string-compare* = x y strs))
  1533. (define (string>=? x y . strs) (%string-compare* >= x y strs))
  1534. (define (string>? x y . strs) (%string-compare* > x y strs))
  1535. (define (list->string chars)
  1536. (let ((p (open-output-string)))
  1537. (for-each (lambda (ch) (write-char ch p)) chars)
  1538. (get-output-string p)))
  1539. (define* (string->list str #:optional (start 0) (end (string-length str)))
  1540. (check-type str string? 'string->list)
  1541. (check-range start 0 (string-length str) 'string->list)
  1542. (check-range end start (string-length str) 'string->list)
  1543. (%inline-wasm
  1544. '(func (param $s (ref string)) (param $start i32) (param $end i32)
  1545. (result (ref eq))
  1546. (local $str_iter (ref stringview_iter))
  1547. (local $s0 (ref eq))
  1548. (local $i0 i32)
  1549. (local.set $str_iter (string.as_iter (local.get $s)))
  1550. (local.set $s0
  1551. (struct.new $mutable-pair
  1552. (i32.const 0)
  1553. (ref.i31 (i32.const 1))
  1554. (ref.i31 (i32.const 13))))
  1555. (local.set $i0
  1556. (i32.sub (local.get $end) (local.get $start)))
  1557. (drop
  1558. (stringview_iter.advance (local.get $str_iter) (local.get $start)))
  1559. (ref.cast $mutable-pair (local.get $s0))
  1560. (loop $lp
  1561. (if (local.get $i0)
  1562. (then
  1563. (ref.cast $mutable-pair (local.get $s0))
  1564. (local.tee
  1565. $s0
  1566. (struct.new $mutable-pair
  1567. (i32.const 0)
  1568. (ref.i31
  1569. (i32.add
  1570. (i32.shl (stringview_iter.next (local.get $str_iter))
  1571. (i32.const 2))
  1572. (i32.const #b11)))
  1573. (ref.i31 (i32.const 13))))
  1574. (struct.set $mutable-pair $cdr)
  1575. (local.set $i0 (i32.sub (local.get $i0) (i32.const 1)))
  1576. (br $lp))))
  1577. (struct.get $mutable-pair $cdr))
  1578. str start end))
  1579. (define* (string->vector str #:optional (start 0) (end (string-length string)))
  1580. (list->vector (string->list str start end)))
  1581. (define* (vector->string v #:optional (start 0) (end (vector-length v)))
  1582. (list->string (vector->list v start end)))
  1583. (define (string-utf8-length str) (%string-utf8-length str))
  1584. (define string->utf8
  1585. (case-lambda
  1586. ((str) (%string->utf8 str))
  1587. ((str start) (%string->utf8
  1588. (if (zero? start)
  1589. str
  1590. (string-copy str start))))
  1591. ((str start end) (%string->utf8
  1592. (if (and (zero? start) (eq? end (string-length str)))
  1593. str
  1594. (string-copy str start end))))))
  1595. (define utf8->string
  1596. (case-lambda
  1597. ((bv) (%utf8->string bv))
  1598. ((bv start) (%utf8->string
  1599. (if (zero? start)
  1600. bv
  1601. (bytevector-copy bv start))))
  1602. ((bv start end) (%utf8->string
  1603. (if (and (zero? start) (eq? end (bytevector-length bv)))
  1604. bv
  1605. (bytevector-copy bv start end))))))
  1606. (define (symbol? x) (%symbol? x))
  1607. (define (string->symbol str)
  1608. (check-type str string? 'string->symbol)
  1609. (%string->symbol str))
  1610. (define (symbol->string sym)
  1611. (check-type sym symbol? 'symbol->string)
  1612. (%symbol->string sym))
  1613. (define (symbol=? x y . z)
  1614. (check-type x symbol? 'symbol=?)
  1615. (check-type y symbol? 'symbol=?)
  1616. (for-each (lambda (z) (check-type z symbol? 'symbol=?)) z)
  1617. (apply eq? x y z))
  1618. ;; R7RS vectors
  1619. (define (%generic-vector . args) (list->vector args))
  1620. (define-syntax vector
  1621. (lambda (stx)
  1622. (syntax-case stx ()
  1623. ((_ . x) #'(%vector . x))
  1624. (f (identifier? #'f) #'%generic-vector))))
  1625. (define* (make-vector n #:optional init) (%make-vector n init))
  1626. (define (vector? x) (%vector? x))
  1627. (define (vector-length x) (%vector-length x))
  1628. (define (vector-ref x i) (%vector-ref x i))
  1629. (define (vector-set! x i v) (%vector-set! x i v))
  1630. (define* (vector-copy v #:optional (start 0) (end (vector-length v)))
  1631. (check-type v vector? 'vector-copy)
  1632. (check-range start 0 (vector-length v) 'vector-copy)
  1633. (check-range end start (vector-length v) 'vector-copy)
  1634. (%inline-wasm
  1635. '(func (param $src (ref $vector)) (param $start i32) (param $end i32)
  1636. (result (ref eq))
  1637. (local $i0 i32)
  1638. (local $v0 (ref $raw-scmvector))
  1639. (local.set $i0 (i32.sub (local.get $end)
  1640. (local.get $start)))
  1641. (local.set $v0 (array.new $raw-scmvector (ref.i31 (i32.const 0))
  1642. (local.get $i0)))
  1643. (array.copy $raw-scmvector $raw-scmvector
  1644. (local.get $v0) (i32.const 0)
  1645. (struct.get $vector $vals (local.get $src))
  1646. (local.get $start) (local.get $i0))
  1647. (struct.new $mutable-vector (i32.const 0) (local.get $v0)))
  1648. v start end))
  1649. (define* (vector-copy! to at from #:optional (start 0) (end (vector-length from)))
  1650. (check-type to vector? 'vector-copy!)
  1651. (check-range at 0 (vector-length to) 'vector-copy!)
  1652. (check-type from vector? 'vector-copy!)
  1653. (check-range start 0 (vector-length from) 'vector-copy!)
  1654. (check-range end start (vector-length from) 'vector-copy!)
  1655. (%inline-wasm
  1656. '(func (param $to (ref $mutable-vector)) (param $at i32)
  1657. (param $from (ref $vector)) (param $start i32) (param $end i32)
  1658. (array.copy $raw-scmvector $raw-scmvector
  1659. (struct.get $mutable-vector $vals (local.get $to))
  1660. (local.get $at)
  1661. (struct.get $vector $vals (local.get $from))
  1662. (local.get $start)
  1663. (i32.sub (local.get $end) (local.get $start))))
  1664. to at from start end))
  1665. (define* (vector-fill! v fill #:optional (start 0) (end (vector-length v)))
  1666. ;; FIXME: check for mutability
  1667. (check-type v vector? 'vector-fill!)
  1668. (check-range start 0 (vector-length v) 'vector-fill!)
  1669. (check-range end start (vector-length v) 'vector-fill!)
  1670. (%inline-wasm
  1671. '(func (param $dst (ref $mutable-vector)) (param $fill (ref eq))
  1672. (param $start i32) (param $end i32)
  1673. (array.fill $raw-scmvector
  1674. (struct.get $mutable-vector $vals (local.get $dst))
  1675. (local.get $start)
  1676. (local.get $fill)
  1677. (i32.sub (local.get $end) (local.get $start))))
  1678. v fill start end))
  1679. (define* (vector->list v #:optional (start 0) (end (vector-length v)))
  1680. (let lp ((i start))
  1681. (if (< i end)
  1682. (cons (vector-ref v i) (lp (1+ i)))
  1683. '())))
  1684. (define (list->vector elts)
  1685. (let* ((len (length elts))
  1686. (v (make-vector len #f)))
  1687. (let lp ((i 0) (elts elts))
  1688. (match elts
  1689. (() v)
  1690. ((elt . elts)
  1691. (vector-set! v i elt)
  1692. (lp (1+ i) elts))))))
  1693. (define (vector-concatenate v*)
  1694. (match v*
  1695. (() #())
  1696. ((v) v)
  1697. (v*
  1698. (let* ((len (fold (lambda (v len) (+ (vector-length v) len)) 0 v*))
  1699. (flattened (make-vector len 0)))
  1700. (let lp ((v* v*) (cur 0))
  1701. (match v*
  1702. (() flattened)
  1703. ((v . v*)
  1704. (vector-copy! flattened cur v)
  1705. (lp v* (+ cur (vector-length v))))))))))
  1706. (define (vector-append . vectors)
  1707. (vector-concatenate vectors))
  1708. (define (vector-for-each f v . v*)
  1709. (apply for-each f (vector->list v) (map vector->list v*)))
  1710. (define (vector-map f v . v*)
  1711. (list->vector (apply map f (vector->list v) (map vector->list v*))))
  1712. ;; FIXME: kwargs
  1713. ;; FIXME: suspendability
  1714. (define (%make-port read
  1715. write
  1716. input-waiting?
  1717. seek
  1718. close
  1719. truncate
  1720. repr
  1721. file-name
  1722. read-buf-size
  1723. write-buf-size
  1724. r/w-random-access?
  1725. fold-case?
  1726. private-data)
  1727. (when file-name (check-type file-name string? 'make-port))
  1728. (let ((read-buf (and read (vector (make-bytevector read-buf-size 0) 0 0 #f)))
  1729. (write-buf (and write (vector (make-bytevector write-buf-size 0) 0 0))))
  1730. (%inline-wasm
  1731. '(func (param $read (ref eq))
  1732. (param $write (ref eq))
  1733. (param $input-waiting? (ref eq))
  1734. (param $seek (ref eq))
  1735. (param $close (ref eq))
  1736. (param $truncate (ref eq))
  1737. (param $repr (ref eq))
  1738. (param $file-name (ref eq))
  1739. (param $read-buf (ref eq))
  1740. (param $write-buf (ref eq))
  1741. (param $read-buffering (ref eq))
  1742. (param $r/w-random-access? (ref eq))
  1743. (param $fold-case? (ref eq))
  1744. (param $private-data (ref eq))
  1745. (result (ref eq))
  1746. (struct.new $port (i32.const 0)
  1747. (ref.i31 (i32.const 17))
  1748. (local.get $read)
  1749. (local.get $write)
  1750. (local.get $input-waiting?)
  1751. (local.get $seek)
  1752. (local.get $close)
  1753. (local.get $truncate)
  1754. (ref.cast $string (local.get $repr))
  1755. (local.get $file-name)
  1756. (struct.new $mutable-pair
  1757. (i32.const 0)
  1758. (ref.i31 (i32.const 0))
  1759. (ref.i31 (i32.const 0)))
  1760. (local.get $read-buf)
  1761. (local.get $write-buf)
  1762. (local.get $read-buffering)
  1763. (local.get $r/w-random-access?)
  1764. (local.get $fold-case?)
  1765. (local.get $private-data)))
  1766. read write input-waiting? seek close truncate repr file-name
  1767. read-buf write-buf read-buf-size r/w-random-access?
  1768. fold-case? private-data)))
  1769. (define (%set-port-buffer-cur! buf cur) (vector-set! buf 1 cur))
  1770. (define (%set-port-buffer-end! buf end) (vector-set! buf 2 end))
  1771. (define (%set-port-buffer-has-eof?! buf has-eof?) (vector-set! buf 3 has-eof?))
  1772. (define-syntax-rule (%define-simple-port-getter getter $field)
  1773. (define (getter port)
  1774. ;; FIXME: arg type checking
  1775. (%inline-wasm
  1776. '(func (param $port (ref $port)) (result (ref eq))
  1777. (struct.get $port $field (local.get $port)))
  1778. port)))
  1779. (define-syntax-rule (%define-simple-port-setter setter $field)
  1780. (define (setter port val)
  1781. ;; FIXME: arg type checking
  1782. (%inline-wasm
  1783. '(func (param $port (ref $port)) (param $val (ref eq))
  1784. (struct.set $port $field (local.get $port) (local.get $val)))
  1785. port val)))
  1786. (%define-simple-port-getter %port-open? $open?)
  1787. (%define-simple-port-getter %port-read $read)
  1788. (%define-simple-port-getter %port-write $write)
  1789. (%define-simple-port-getter %port-input-waiting? $input-waiting?)
  1790. (%define-simple-port-getter %port-seek $seek)
  1791. (%define-simple-port-getter %port-close $close)
  1792. (%define-simple-port-getter %port-truncate $truncate)
  1793. (%define-simple-port-getter %port-repr $repr)
  1794. (%define-simple-port-getter port-filename $filename)
  1795. (%define-simple-port-getter %port-position $position)
  1796. (%define-simple-port-getter %port-read-buffer $read-buf)
  1797. (%define-simple-port-getter %port-write-buffer $write-buf)
  1798. (%define-simple-port-getter %port-read-buffering $read-buffering)
  1799. (%define-simple-port-getter %port-r/w-random-access? $r/w-random-access?)
  1800. (%define-simple-port-getter %port-fold-case? $fold-case?)
  1801. (%define-simple-port-getter %port-private-data $private-data)
  1802. (%define-simple-port-setter %set-port-open?! $open?)
  1803. (%define-simple-port-setter %set-port-filename! $filename)
  1804. (%define-simple-port-setter %set-port-read-buffer! $read-buf)
  1805. (%define-simple-port-setter %set-port-write-buffer! $write-buf)
  1806. (%define-simple-port-setter %set-port-read-buffering! $read-buffering)
  1807. (%define-simple-port-setter %set-port-fold-case?! $fold-case?)
  1808. (define (port-line port)
  1809. (check-type port port? 'port-line)
  1810. (car (%port-position port)))
  1811. (define (port-column port)
  1812. (check-type port port? 'port-column)
  1813. (cdr (%port-position port)))
  1814. (define* (get-output-bytevector port #:optional (clear-buffer? #f))
  1815. ;; FIXME: How to know it's a bytevector output port?
  1816. (check-type port output-port? 'get-output-bytevector)
  1817. (define accum (%port-private-data port))
  1818. (flush-output-port port)
  1819. (let ((flattened (bytevector-concatenate (box-ref accum))))
  1820. (box-set! accum (if clear-buffer?
  1821. '()
  1822. (list flattened)))
  1823. flattened))
  1824. (define (open-output-bytevector)
  1825. (define accum (make-box '()))
  1826. (define pos #f)
  1827. (define (appending?) (not pos))
  1828. (define default-buffer-size 1024)
  1829. (define (bv-write bv start count) ; write
  1830. (unless (zero? count)
  1831. (cond
  1832. ((appending?)
  1833. (box-set! accum
  1834. (cons (bytevector-copy bv start (+ start count))
  1835. (box-ref accum))))
  1836. (else
  1837. (let* ((dst (get-output-bytevector port))
  1838. (to-copy (min count (- (bytevector-length dst) pos))))
  1839. (bytevector-copy! dst pos bv start to-copy)
  1840. (cond
  1841. ((< to-copy count)
  1842. (box-set!
  1843. accum
  1844. (list (bytevector-copy bv (+ start to-copy) (- count to-copy))
  1845. dst))
  1846. (set! pos #f))
  1847. (else
  1848. (set! pos (+ pos count))))))))
  1849. count)
  1850. (define (bv-seek offset whence) ; seek
  1851. (define len (bytevector-length (get-output-bytevector port)))
  1852. (define base (match whence ('start 0) ('cur (or pos len)) ('end len)))
  1853. (define dst (+ base offset))
  1854. (check-range dst 0 len 'seek)
  1855. (set! pos (if (= pos dst) #f dst))
  1856. dst)
  1857. (define port
  1858. (%make-port #f ; read
  1859. bv-write
  1860. #f ; input-waiting?
  1861. bv-seek
  1862. #f ; close
  1863. #f ; truncate
  1864. "bytevector" ; repr
  1865. #f ; filename
  1866. #f ; read-buf-size
  1867. default-buffer-size ; write-buf-size
  1868. #f ; r/w-random-access
  1869. #f ; fold-case?
  1870. accum ; private data
  1871. ))
  1872. port)
  1873. (define (open-input-bytevector src)
  1874. (check-type src bytevector? 'open-input-bytevector)
  1875. (define pos 0)
  1876. (define default-buffer-size 1024)
  1877. (define (bv-read dst start count)
  1878. (let* ((to-copy (min count (- (bytevector-length src) pos)))
  1879. (end (+ pos to-copy)))
  1880. (bytevector-copy! dst start src pos end)
  1881. (set! pos end)
  1882. to-copy))
  1883. (define (bv-seek offset whence) ; seek
  1884. (define len (bytevector-length src))
  1885. (define base (match whence ('start 0) ('cur pos) ('end len)))
  1886. (define dst (+ base offset))
  1887. (check-range dst 0 len 'seek)
  1888. (set! pos dst)
  1889. dst)
  1890. ;; FIXME: Can we just provide `src` directly as the read buffer?
  1891. (%make-port bv-read
  1892. #f ; write
  1893. #f ; input-waiting?
  1894. bv-seek
  1895. #f ; close
  1896. #f ; truncate
  1897. "bytevector" ; repr
  1898. #f ; filename
  1899. default-buffer-size ; read-buf-size
  1900. #f ; write-buf-size
  1901. #t ; r/w-random-access
  1902. #f ; fold-case?
  1903. #f ; private data
  1904. ))
  1905. ;; FIXME: kwargs
  1906. (define (%make-soft-port repr %read-string %write-string input-waiting? close)
  1907. (check-type repr string? 'make-port)
  1908. (define (make-reader read-string)
  1909. (define buffer #f)
  1910. (define buffer-pos 0)
  1911. (lambda (bv start count)
  1912. (unless (and buffer (< buffer-pos (bytevector-length buffer)))
  1913. (let* ((str (%read-string)))
  1914. (set! buffer (string->utf8 str))
  1915. (set! buffer-pos 0)))
  1916. (let* ((to-copy (min count (- (bytevector-length buffer) buffer-pos)))
  1917. (next-pos (+ buffer-pos to-copy)))
  1918. (bytevector-copy! bv start buffer buffer-pos next-pos)
  1919. (if (= (bytevector-length buffer) next-pos)
  1920. (set! buffer #f)
  1921. (set! buffer-pos next-pos))
  1922. to-copy)))
  1923. (define (make-writer write-string)
  1924. (lambda (bv start count)
  1925. ;; FIXME: If the writer is binary, that could split a codepoint in
  1926. ;; two, resulting in badness. Shouldn't happen with textual
  1927. ;; writers but it's worth noting.
  1928. (%write-string (utf8->string bv start (+ start count)))
  1929. count))
  1930. (define default-buffer-size 1024)
  1931. (%make-port (and read-string (make-reader read-string))
  1932. (and write-string (make-writer write-string))
  1933. input-waiting?
  1934. #f ; seek
  1935. #f ; close
  1936. #f ; truncate
  1937. repr ; repr
  1938. #f ; filename
  1939. default-buffer-size ; read-buf-size
  1940. default-buffer-size ; write-buf-size
  1941. #f ; r/w-random-access
  1942. #f ; fold-case?
  1943. #f ; private data
  1944. ))
  1945. (define (open-input-string str)
  1946. (open-input-bytevector (string->utf8 str)))
  1947. (define (open-output-string) (open-output-bytevector))
  1948. (define* (get-output-string p #:optional (clear-buffer? #f))
  1949. (utf8->string (get-output-bytevector p clear-buffer?)))
  1950. ;; R7RS ports
  1951. (define (eof-object? x) (%eof-object? x))
  1952. (define (eof-object)
  1953. (define-syntax eof-object
  1954. (lambda (stx) #`'#,%the-eof-object))
  1955. (eof-object))
  1956. (define (port? x)
  1957. (%inline-wasm '(func (param $obj (ref eq))
  1958. (result (ref eq))
  1959. (if (ref eq)
  1960. (ref.test $port (local.get $obj))
  1961. (then (ref.i31 (i32.const 17)))
  1962. (else (ref.i31 (i32.const 1)))))
  1963. x))
  1964. (define (input-port? x) (and (port? x) (%port-read x) #t))
  1965. (define (output-port? x) (and (port? x) (%port-write x) #t))
  1966. (define (binary-port? x) (port? x))
  1967. (define (textual-port? x) (port? x))
  1968. (define (input-port-open? x)
  1969. (check-type x input-port? 'input-port-open?)
  1970. (%port-open? x))
  1971. (define (output-port-open? x)
  1972. (check-type x output-port? 'output-port-open?)
  1973. (%port-open? x))
  1974. (define (close-input-port port)
  1975. (check-type port input-port? 'close-input-port)
  1976. ;; FIXME: Allow half-closing of socket-like ports.
  1977. (close-port port))
  1978. (define (close-output-port port)
  1979. (check-type port output-port? 'close-output-port)
  1980. ;; FIXME: Allow half-closing of socket-like ports.
  1981. (close-port port))
  1982. (define (close-port port)
  1983. (check-type port port? 'close-port)
  1984. (when (%port-open? port)
  1985. (when (output-port? port) (flush-output-port port))
  1986. (%set-port-open?! port #f))
  1987. (values))
  1988. (define (call-with-port port proc)
  1989. (check-type port port? 'call-with-port)
  1990. (check-type proc procedure? 'call-with-port)
  1991. (call-with-values (lambda () (proc port))
  1992. (lambda vals
  1993. (close-port port)
  1994. (apply values vals))))
  1995. (define (seek port offset whence)
  1996. (check-type port port? 'seek)
  1997. (check-type offset exact-integer? 'seek)
  1998. (assert (memq whence '(cur start end)) 'seek)
  1999. (define (buffered-bytes buf)
  2000. (define (port-buffer-cur buf) (vector-ref buf 1))
  2001. (define (port-buffer-end buf) (vector-ref buf 2))
  2002. (if (vector? buf)
  2003. (- (port-buffer-end buf) (port-buffer-cur buf))
  2004. 0))
  2005. (cond
  2006. ((%port-seek port)
  2007. => (lambda (%seek)
  2008. (cond
  2009. ((and (eq? whence 'cur) (zero? offset))
  2010. ;; Query current position, adjust for buffering without
  2011. ;; flush.
  2012. (let ((pos (%seek offset whence))
  2013. (buf-in (buffered-bytes (%port-read-buffer port)))
  2014. (buf-out (buffered-bytes (%port-write-buffer port))))
  2015. (+ pos (- buf-in) buf-out)))
  2016. ((not (%port-r/w-random-access? port))
  2017. (raise (%make-not-seekable-error port 'seek)))
  2018. (else
  2019. (when (input-port? port) (flush-input-port port))
  2020. (when (output-port? port) (flush-output-port port))
  2021. (let ((pos (%seek offset whence)))
  2022. (when (input-port? port)
  2023. (%set-port-buffer-has-eof?! (%port-read-buffer port) #f))
  2024. pos)))))
  2025. (else (raise (%make-not-seekable-error port 'seek)))))
  2026. (define (%write-bytes port bv start count)
  2027. (let ((written ((%port-write port) bv start count)))
  2028. (check-range written 0 count '%write-bytes)
  2029. (when (< written count)
  2030. (%write-bytes port bv (+ start written) (- count written)))))
  2031. (define (%read-bytes port bv start count)
  2032. (let ((read ((%port-read port) bv start count)))
  2033. (check-range read 0 count '%read-bytes)
  2034. read))
  2035. (define* (flush-input-port #:optional (port (current-output-port)))
  2036. ;; For buffered input+output ports that are random-access?, it's
  2037. ;; likely that when switching from reading to writing that we will
  2038. ;; have some bytes waiting to be read, and that the underlying
  2039. ;; port-position is ahead. This function discards buffered input and
  2040. ;; seeks back from before the buffered input.
  2041. (check-type port port? 'flush-input-port)
  2042. (match (%port-read-buffer port)
  2043. (#f (raise (%make-type-error port 'flush-input-port 'input-port?)))
  2044. ((and buf #(bv cur end has-eof?))
  2045. (when (< cur end)
  2046. (%set-port-buffer-cur! buf 0)
  2047. (%set-port-buffer-end! buf 0)
  2048. (seek port (- cur end) 'cur)))))
  2049. (define* (flush-output-port #:optional (port (current-output-port)))
  2050. (check-type port port? 'flush-output-port)
  2051. (match (%port-write-buffer port)
  2052. (#f (raise (%make-type-error port 'flush-output-port 'output-port?)))
  2053. ((and buf #(bv cur end))
  2054. (when (< cur end)
  2055. (%set-port-buffer-cur! buf 0)
  2056. (%set-port-buffer-end! buf 0)
  2057. (%write-bytes port bv cur (- end cur))))))
  2058. (define* (u8-ready? #:optional (port (current-input-port)))
  2059. (check-type port port? 'u8-ready?)
  2060. (match (%port-read-buffer port)
  2061. (#f (raise (%make-type-error port 'u8-ready? 'input-port?)))
  2062. (#(bv cur end has-eof?)
  2063. (or (< cur end)
  2064. has-eof?
  2065. (match (%port-input-waiting? port)
  2066. (#f #t)
  2067. (proc (proc)))))))
  2068. (define (%fill-input port buf minimum-buffering)
  2069. (match buf
  2070. (#(bv cur end has-eof?)
  2071. (let ((avail (- end cur)))
  2072. (cond
  2073. ((or has-eof?
  2074. (<= minimum-buffering avail))
  2075. (values buf avail))
  2076. ((< (bytevector-length bv) minimum-buffering)
  2077. (let* ((expanded (make-bytevector minimum-buffering 0))
  2078. (buf (vector expanded 0 (- end cur) #f)))
  2079. (when (< cur end)
  2080. (bytevector-copy! expanded 0 bv cur end))
  2081. (%set-port-read-buffer! port buf)
  2082. (%fill-input port buf minimum-buffering)))
  2083. (else
  2084. (when (< 0 cur)
  2085. (bytevector-copy! bv 0 bv cur end)
  2086. (%set-port-buffer-cur! buf 0))
  2087. (let lp ((end avail))
  2088. (let* ((must-read (- minimum-buffering end))
  2089. ;; precondition: read-buffering <= len(read-buffer)
  2090. ;; precondition: minimum-buffering <= len(read-buffer)
  2091. ;; precondition: end < minimum-buffering
  2092. (count (- (max (%port-read-buffering port)
  2093. minimum-buffering)
  2094. end))
  2095. (read (%read-bytes port bv end count))
  2096. (end (+ end read)))
  2097. (cond
  2098. ((zero? read)
  2099. (%set-port-buffer-end! buf end)
  2100. (%set-port-buffer-has-eof?! buf #t)
  2101. (values buf end))
  2102. ((< end minimum-buffering)
  2103. (lp end))
  2104. (else
  2105. (%set-port-buffer-end! buf end)
  2106. (values buf end)))))))))))
  2107. (define* (peek-u8 #:optional (port (current-input-port)))
  2108. (check-type port port? 'peek-u8)
  2109. (let lp ((buf (%port-read-buffer port)))
  2110. (match buf
  2111. (#f (raise (%make-type-error port 'peek-u8 'input-port?)))
  2112. (#(bv cur end has-eof?)
  2113. (cond
  2114. ((eq? cur end)
  2115. (if has-eof?
  2116. (eof-object)
  2117. (call-with-values (lambda ()
  2118. (%fill-input port buf 1))
  2119. (lambda (buf avail)
  2120. (if (zero? avail)
  2121. (eof-object)
  2122. (lp buf))))))
  2123. (else
  2124. (bytevector-u8-ref bv cur)))))))
  2125. (define* (read-u8 #:optional (port (current-input-port)))
  2126. (check-type port port? 'read-u8)
  2127. (define (read-eof! buf)
  2128. (%set-port-buffer-has-eof?! buf #f)
  2129. (eof-object))
  2130. (let lp ((buf (%port-read-buffer port)))
  2131. (match buf
  2132. (#f (raise (%make-type-error port 'read-u8 'input-port?)))
  2133. (#(bv cur end has-eof?)
  2134. (cond
  2135. ((eq? cur end)
  2136. (if has-eof?
  2137. (read-eof! buf)
  2138. (call-with-values (lambda ()
  2139. (%fill-input port buf 1))
  2140. (lambda (buf avail)
  2141. (if (zero? avail)
  2142. (read-eof! buf)
  2143. (lp buf))))))
  2144. (else
  2145. (%set-port-buffer-cur! buf (1+ cur))
  2146. (bytevector-u8-ref bv cur)))))))
  2147. (define* (read-bytevector k #:optional (port (current-input-port)))
  2148. (check-range k 0 (1- (ash 1 29)) 'read-bytevector)
  2149. (check-type port input-port? 'read-bytevector)
  2150. (call-with-values (lambda ()
  2151. (%fill-input port (%port-read-buffer port) (max k 1)))
  2152. (lambda (buf avail)
  2153. (cond
  2154. ((zero? avail)
  2155. (%set-port-buffer-has-eof?! buf #f)
  2156. (eof-object))
  2157. (else
  2158. (match buf
  2159. (#(src cur end has-eof?)
  2160. (let* ((cur* (min (+ cur k) end))
  2161. (bv (bytevector-copy src cur cur*)))
  2162. (%set-port-buffer-cur! buf cur*)
  2163. bv))))))))
  2164. (define* (read-bytevector! dst #:optional (port (current-input-port))
  2165. (start 0) (end (bytevector-length dst)))
  2166. (check-type dst bytevector? 'read-bytevector!)
  2167. (check-range start 0 (bytevector-length dst) 'read-bytevector!)
  2168. (check-range end start (bytevector-length dst) 'read-bytevector!)
  2169. (check-type port input-port? 'read-bytevector!)
  2170. (let ((count (- start end)))
  2171. (call-with-values (lambda ()
  2172. (%fill-input port (%port-read-buffer port)
  2173. (max count 1)))
  2174. (lambda (buf avail)
  2175. (cond
  2176. ((zero? avail)
  2177. (%set-port-buffer-has-eof?! buf #f)
  2178. (eof-object))
  2179. (else
  2180. (match buf
  2181. (#(src cur end has-eof?)
  2182. (let* ((cur* (min (+ cur count) end))
  2183. (count (- cur* cur)))
  2184. (bytevector-copy! dst start src cur cur*)
  2185. (%set-port-buffer-cur! buf cur*)
  2186. count)))))))))
  2187. (define* (char-ready? #:optional (port (current-input-port)))
  2188. (u8-ready? port))
  2189. (define* (peek-char #:optional (port (current-input-port)))
  2190. (let ((a (peek-u8 port)))
  2191. (cond
  2192. ((eof-object? a) a)
  2193. ((< a #b10000000) (integer->char a))
  2194. (else
  2195. ;; FIXME: This is a sloppy UTF-8 decoder. Need to think more
  2196. ;; about this.
  2197. (let ((len (cond ((< a #b11100000) 2)
  2198. ((< a #b11110000) 3)
  2199. (else 4))))
  2200. (call-with-values (lambda ()
  2201. (%fill-input port (%port-read-buffer port) len))
  2202. (lambda (buf avail)
  2203. (when (< len avail)
  2204. (error "decoding error: partial utf-8 sequence"))
  2205. (match buf
  2206. (#(bv cur end has-eof?)
  2207. (integer->char
  2208. (%inline-wasm
  2209. '(func (param $bv (ref $bytevector))
  2210. (param $cur i32)
  2211. (param $end i32)
  2212. (result i64)
  2213. (i64.extend_i32_s
  2214. (stringview_iter.next
  2215. (string.as_iter
  2216. (string.new_lossy_utf8_array
  2217. (struct.get $bytevector $vals (local.get $bv))
  2218. (local.get $cur)
  2219. (local.get $end))))))
  2220. bv cur (+ cur len))))))))))))
  2221. (define* (read-char #:optional (port (current-input-port)))
  2222. (let ((a (peek-u8 port)))
  2223. (cond
  2224. ((eof-object? a) a)
  2225. ((<= a #x7f)
  2226. (match (%port-read-buffer port)
  2227. ((and buf #(bv cur end has-eof?))
  2228. (%set-port-buffer-cur! buf (1+ cur))
  2229. (integer->char a))))
  2230. (else
  2231. (let ((len (cond ((< a #b11100000) 2)
  2232. ((< a #b11110000) 3)
  2233. (else 4))))
  2234. (call-with-values (lambda ()
  2235. (%fill-input port (%port-read-buffer port) len))
  2236. (lambda (buf avail)
  2237. (when (< len avail)
  2238. (error "decoding error: partial utf-8 sequence"))
  2239. (match buf
  2240. (#(bv cur end has-eof?)
  2241. (%set-port-buffer-cur! buf (+ cur len))
  2242. (integer->char
  2243. (%inline-wasm
  2244. '(func (param $bv (ref $bytevector))
  2245. (param $cur i32)
  2246. (param $end i32)
  2247. (result i64)
  2248. (i64.extend_i32_s
  2249. (stringview_iter.next
  2250. (string.as_iter
  2251. (string.new_lossy_utf8_array
  2252. (struct.get $bytevector $vals (local.get $bv))
  2253. (local.get $cur)
  2254. (local.get $end))))))
  2255. bv cur (+ cur len))))))))))))
  2256. (define* (read-string k #:optional (port (current-input-port)))
  2257. (check-type port input-port? 'read-string)
  2258. (cond
  2259. ;; Call peek-char to ensure we're at the start of some UTF-8.
  2260. ((eof-object? (peek-char port)) (eof-object))
  2261. (else
  2262. (match (%port-read-buffer port)
  2263. ((and buf #(bv cur end has-eof?))
  2264. (define (take-string count cur*)
  2265. (%set-port-buffer-cur! buf cur*)
  2266. (define str (utf8->string bv cur cur*))
  2267. (let ((remaining (- k count)))
  2268. (if (zero? remaining)
  2269. str
  2270. (match (read-string remaining port)
  2271. ((? eof-object?) str)
  2272. (tail (string-append str tail))))))
  2273. ;; Count codepoints in buffer.
  2274. (let count-codepoints ((count 0) (cur cur))
  2275. (if (and (< cur end) (< count k))
  2276. (let* ((u8 (bytevector-u8-ref bv cur))
  2277. (len (cond ((< u8 #b10000000) 1)
  2278. ((< u8 #b11100000) 2)
  2279. ((< u8 #b11110000) 3)
  2280. (else 4))))
  2281. (if (<= (+ cur len) end)
  2282. (count-codepoints (1+ count) (+ cur len))
  2283. (take-string count cur)))
  2284. (take-string count cur))))))))
  2285. (define* (read-line #:optional (port (current-input-port)))
  2286. (check-type port input-port? 'read-line)
  2287. (define bytes '())
  2288. (define (finish)
  2289. (utf8->string (bytevector-concatenate-reverse bytes)))
  2290. (let read-some ((buf (%port-read-buffer port)))
  2291. (match buf
  2292. (#(bv cur end has-eof?)
  2293. (define (accumulate-bytes! end)
  2294. (set! bytes (cons (bytevector-copy bv cur end) bytes)))
  2295. (let scan-for-newline ((pos cur))
  2296. (cond
  2297. ((< pos end)
  2298. (let ((u8 (bytevector-u8-ref bv pos)))
  2299. (cond
  2300. ((or (eq? u8 (char->integer #\newline))
  2301. (eq? u8 (char->integer #\return)))
  2302. (accumulate-bytes! pos)
  2303. (%set-port-buffer-cur! buf (1+ pos))
  2304. (when (and (eq? u8 (char->integer #\return))
  2305. (eq? (peek-u8 port) (char->integer #\newline)))
  2306. (read-u8 port))
  2307. (finish))
  2308. (else
  2309. (scan-for-newline (1+ pos))))))
  2310. ((< cur pos)
  2311. (accumulate-bytes! pos)
  2312. (%set-port-buffer-cur! buf pos)
  2313. (read-some (%fill-input port buf 1)))
  2314. ((not has-eof?)
  2315. (read-some (%fill-input port buf 1)))
  2316. ((null? bytes)
  2317. (%set-port-buffer-has-eof?! buf #f)
  2318. (eof-object))
  2319. (else
  2320. (finish))))))))
  2321. (define* (write-u8 u8 #:optional (port (current-output-port)))
  2322. (check-type port port? 'write-u8)
  2323. (match (%port-write-buffer port)
  2324. (#f (raise (%make-type-error port 'write-u8 'output-port?)))
  2325. ((and buf #(dst cur end))
  2326. (when (and (eq? cur end) (%port-r/w-random-access? port))
  2327. (flush-input-port port))
  2328. (cond
  2329. ((= end (bytevector-length dst))
  2330. ;; Multiple threads racing; race to flush, then retry.
  2331. (flush-output-port port)
  2332. (write-u8 u8 port))
  2333. (else
  2334. (bytevector-u8-set! dst end u8)
  2335. (let ((end (1+ end)))
  2336. (%set-port-buffer-end! buf end)
  2337. (when (= end (bytevector-length dst))
  2338. (flush-output-port port))))))))
  2339. (define* (write-bytevector bv #:optional (port (current-output-port))
  2340. (start 0) (end (bytevector-length bv)))
  2341. (check-type port port? 'write-u8)
  2342. (let ((count (- end start)))
  2343. (match (%port-write-buffer port)
  2344. (#f (raise (%make-type-error port 'write-u8 'output-port?)))
  2345. ((and buf #(dst cur end))
  2346. (when (and (eq? cur end) (%port-r/w-random-access? port))
  2347. (flush-input-port port))
  2348. (let ((size (bytevector-length dst))
  2349. (buffered (- end cur)))
  2350. (cond
  2351. ((<= (+ end count) size)
  2352. ;; Bytes fit in buffer: copy directly.
  2353. (bytevector-copy! dst end bv start (+ start count))
  2354. (let ((end (+ end count)))
  2355. (%set-port-buffer-end! buf end)
  2356. (when (= end size)
  2357. (flush-output-port port))))
  2358. ((< count size)
  2359. ;; Bytes fit in buffer, but we have to flush output first.
  2360. (flush-output-port port)
  2361. (bytevector-copy! dst 0 bv start (+ start count))
  2362. (%set-port-buffer-cur! buf 0)
  2363. (%set-port-buffer-end! buf count)
  2364. (when (= count size)
  2365. (flush-output-port port)))
  2366. (else
  2367. ;; Otherwise flush any buffered output, then make an
  2368. ;; unbuffered write.
  2369. (unless (zero? buffered) (flush-output-port port))
  2370. (%write-bytes port bv start count))))))))
  2371. (define* (write-char x #:optional (port (current-output-port)))
  2372. ;; FIXME: update port position.
  2373. (define (low-six i) (logand i #b111111))
  2374. (let ((i (char->integer x)))
  2375. (cond
  2376. ((<= i #x7f)
  2377. (write-u8 i port))
  2378. ((<= i #x7ff)
  2379. (write-bytevector
  2380. (bytevector (logior #b11000000 (ash i -6))
  2381. (logior #b10000000 (low-six i)))
  2382. port))
  2383. ((<= i #xffff)
  2384. (write-bytevector
  2385. (bytevector (logior #b11100000 (ash i -12))
  2386. (logior #b10000000 (low-six (ash i -6)))
  2387. (logior #b10000000 (low-six i)))
  2388. port))
  2389. (else
  2390. (write-bytevector
  2391. (bytevector (logior #b11110000 (ash i -18))
  2392. (logior #b10000000 (low-six (ash i -12)))
  2393. (logior #b10000000 (low-six (ash i -6)))
  2394. (logior #b10000000 (low-six i)))
  2395. port)))))
  2396. (define* (newline #:optional (port (current-output-port)))
  2397. (write-char #\newline port))
  2398. (define* (write-string str #:optional (port (current-output-port)))
  2399. ;; FIXME: Could avoid the double-copy and encode directly to buffer.
  2400. (write-bytevector (string->utf8 str) port))
  2401. ;; (scheme file); perhaps drop?
  2402. (define (open-binary-input-file filename)
  2403. (raise (%make-unimplemented-error 'open-binary-input-file)))
  2404. (define (open-binary-output-file filename)
  2405. (raise (%make-unimplemented-error 'open-binary-output-file)))
  2406. (define (call-with-input-file filename proc)
  2407. (raise (%make-unimplemented-error 'call-with-input-file)))
  2408. (define (call-with-output-file filename proc)
  2409. (raise (%make-unimplemented-error 'call-with-output-file)))
  2410. (define (delete-file filename)
  2411. (raise (%make-unimplemented-error 'delete-file)))
  2412. (define (file-exists? filename)
  2413. (raise (%make-unimplemented-error 'file-exists?)))
  2414. (define (open-input-file filename)
  2415. (raise (%make-unimplemented-error 'open-input-file)))
  2416. (define (open-output-file filename)
  2417. (raise (%make-unimplemented-error 'open-output-file)))
  2418. (define (with-input-from-file filename thunk)
  2419. (let ((p (open-input-file filename)))
  2420. (parameterize ((current-input-port p))
  2421. (call-with-values thunk
  2422. (lambda vals
  2423. (close-port p)
  2424. (apply values vals))))))
  2425. (define (with-output-to-file filename thunk)
  2426. (let ((p (open-output-file filename)))
  2427. (parameterize ((current-output-port p))
  2428. (call-with-values thunk
  2429. (lambda vals
  2430. (close-port p)
  2431. (apply values vals))))))
  2432. (define-syntax-rule (%make-vtable nfields printer name constructor properties
  2433. parents mutable-fields compare)
  2434. (%inline-wasm
  2435. '(func (param $nfields (ref eq))
  2436. (param $printer (ref eq))
  2437. (param $name (ref eq))
  2438. (param $constructor (ref eq))
  2439. (param $properties (ref eq))
  2440. (param $parents (ref eq))
  2441. (param $mutable-fields (ref eq))
  2442. (param $compare (ref eq))
  2443. (result (ref eq))
  2444. (struct.new $vtable
  2445. (i32.const 0)
  2446. (global.get $root-vtable)
  2447. (local.get $nfields)
  2448. (local.get $printer)
  2449. (local.get $name)
  2450. (local.get $constructor)
  2451. (local.get $properties)
  2452. (local.get $parents)
  2453. (local.get $mutable-fields)
  2454. (local.get $compare)))
  2455. nfields printer name constructor properties parents mutable-fields compare))
  2456. (define (record-type-parents rtd)
  2457. (match (%inline-wasm
  2458. '(func (param $vtable (ref $vtable)) (result (ref eq))
  2459. (struct.get $vtable $parents (local.get $vtable)))
  2460. rtd)
  2461. ((? vector? parentv) parentv)
  2462. (parent
  2463. (let ((grandparents (record-type-parents parent)))
  2464. (define parents (make-vector (1+ (vector-length grandparents)) parent))
  2465. (vector-copy! parents 0 grandparents 0)
  2466. (%inline-wasm
  2467. '(func (param $vtable (ref $vtable)) (param $parentv (ref eq))
  2468. (struct.set $vtable $parents (local.get $vtable)
  2469. (local.get $parentv)))
  2470. rtd parents)
  2471. parents))))
  2472. (define-syntax define-record-type
  2473. (lambda (stx)
  2474. (define (cons a b) (%cons a b))
  2475. (define (pair? a) (%pair? a))
  2476. (define (car a) (%car a))
  2477. (define (cdr a) (%cdr a))
  2478. (define (append a b)
  2479. (if (pair? a)
  2480. (cons (car a) (append (cdr a) b))
  2481. b))
  2482. (define-syntax-rule (list x ...)
  2483. (%cons* x ... '()))
  2484. (define (acons a b c) (cons (cons a b) c))
  2485. (define (eq? x y) (%eq? x y))
  2486. (define (keyword? x) (%keyword? x))
  2487. (define (string? x) (%string? x))
  2488. (define (symbol->string x) (%symbol->string x))
  2489. (define (1+ n) (%+ n 1))
  2490. (define (logior a b) (%logior a b))
  2491. (define (ash x n) (%ash x n))
  2492. (define (length l)
  2493. (let lp ((l l) (len 0))
  2494. (if (pair? l)
  2495. (lp (cdr l) (1+ len))
  2496. len)))
  2497. (define (null? x) (%null? x))
  2498. (define (map f l)
  2499. (if (null? l) '() (cons (f (car l)) (map f (cdr l)))))
  2500. (define-syntax-rule (let-values ((vals expr)) body ...)
  2501. (%call-with-values (lambda () expr) (lambda vals body ...)))
  2502. (define (parse-kwargs args k)
  2503. (let lp ((args args) (kwargs '()))
  2504. (syntax-case args ()
  2505. ((kw val . args) (keyword? (syntax->datum #'kw))
  2506. (lp #'args (append kwargs (list (syntax->datum #'kw) #'val))))
  2507. (args (k #'args kwargs)))))
  2508. (define* (parse-body id body #:key (printer #'#f) (parent #'#f) (uid #'#f)
  2509. (extensible? #'#f) (allow-duplicate-field-names? #'#f)
  2510. (opaque? #'#f))
  2511. (define properties
  2512. (datum->syntax
  2513. #'nothing
  2514. ((syntax-case extensible? ()
  2515. (#t (lambda (props) (acons 'extensible? #t props)))
  2516. (#f (lambda (props) props)))
  2517. ((syntax-case opaque? ()
  2518. (#t (lambda (props) (acons 'opaque? #t props)))
  2519. (#f (lambda (props) props)))
  2520. ((syntax-case uid ()
  2521. (#f (lambda (props) props))
  2522. (_ (? string? (syntax->datum uid))
  2523. (lambda (props) (acons 'uid (syntax->datum uid) props))))
  2524. '())))))
  2525. (define id-str (symbol->string (syntax->datum id)))
  2526. (define-values (parent-count
  2527. parent-fields
  2528. parent-mutable-fields
  2529. parents)
  2530. (syntax-case parent ()
  2531. (#f (values 0 '() 0 #'#()))
  2532. (_
  2533. (let-values (((kind value) (syntax-local-binding parent)))
  2534. (define (err reason)
  2535. (syntax-violation 'define-record-type reason stx parent))
  2536. (unless (and (eq? kind 'macro)
  2537. (procedure-property value 'record-type?))
  2538. (err "expected a record type as #:parent"))
  2539. (unless (procedure-property value 'extensible?)
  2540. (err "parent record type is final"))
  2541. (when (procedure-property value 'opaque?)
  2542. (unless (syntax-case opaque? () (#f #f) (_ #t))
  2543. (err "can't make non-opaque subtype of opaque type")))
  2544. (let ((parent-count (procedure-property value 'parent-count)))
  2545. (values
  2546. (1+ parent-count)
  2547. (procedure-property value 'fields)
  2548. (procedure-property value 'mutable-fields)
  2549. (if (eq? parent-count 0)
  2550. #`(vector #,parent)
  2551. ;; Lazily initialize parentv on first access;
  2552. ;; mentioning all of the vtables would make it
  2553. ;; harder for peval / dce to elide unused vtables.
  2554. parent)))))))
  2555. (define (valid-constructor-args? cfields fields)
  2556. (define (check-parent-fields cfields parent-fields)
  2557. (cond
  2558. ((null? parent-fields)
  2559. (check-fields cfields fields))
  2560. (else
  2561. (syntax-case cfields ()
  2562. (() #f)
  2563. ((cfield . cfields)
  2564. (and (identifier? #'cfield)
  2565. (eq? (syntax->datum #'cfield) (car parent-fields))
  2566. (check-parent-fields #'cfields (cdr parent-fields))))))))
  2567. (define (check-fields cfields fields)
  2568. (syntax-case cfields ()
  2569. (() (syntax-case fields () (() #t) (_ #f)))
  2570. ((cfield . cfields)
  2571. (syntax-case fields ()
  2572. ((field . fields)
  2573. (and (free-identifier=? #'field #'cfield)
  2574. (check-fields #'cfields #'fields)))
  2575. (_ #f)))))
  2576. (check-parent-fields cfields parent-fields))
  2577. (define (compute-mutable-fields setters)
  2578. (let lp ((setters setters) (out parent-mutable-fields)
  2579. (i (length parent-fields)))
  2580. (syntax-case setters ()
  2581. (() out)
  2582. ((() . setters) (lp #'setters out (1+ i)))
  2583. (((_) . setters) (lp #'setters (logior out (ash 1 i)) (1+ i))))))
  2584. (syntax-case body ()
  2585. (((constructor cfield ...) predicate (field getter . setter) ...)
  2586. (and (identifier? #'constructor)
  2587. (identifier? #'predicate)
  2588. (valid-constructor-args? #'(cfield ...) #'(field ...)))
  2589. #`(begin
  2590. (define (constructor cfield ...)
  2591. (%make-struct #,id cfield ...))
  2592. (define-syntax #,id
  2593. (lambda (stx)
  2594. #((record-type? . #t)
  2595. (parent-count . #,parent-count)
  2596. (fields cfield ...)
  2597. (mutable-fields . #,(compute-mutable-fields #'(setter ...)))
  2598. #,@properties)
  2599. (syntax-case stx ()
  2600. (x (identifier? #'x) #'vtable))))
  2601. ;; Note that the procedures stored in record vtables are
  2602. ;; treated as "trusted": they do no type checks. They
  2603. ;; shouldn't be exposed to users because it may be that
  2604. ;; they can apply to objects of different types but the
  2605. ;; same shape.
  2606. (define vtable
  2607. (%make-vtable
  2608. #,(length #'(cfield ...))
  2609. #,(syntax-case printer ()
  2610. (#f
  2611. (syntax-case opaque? ()
  2612. (#t
  2613. #`(lambda (x port write-field)
  2614. (write-string "#<" port)
  2615. (write-string #,id-str port)
  2616. (write-string ">" port)))
  2617. (#f
  2618. #`(lambda (x port write-field)
  2619. (write-string "#<" port)
  2620. (write-string #,id-str port)
  2621. #,@(let lp ((fields (map syntax->datum
  2622. #'(cfield ...)))
  2623. (i 0))
  2624. (cond
  2625. ((null? fields) #'())
  2626. (else
  2627. (let ((name (symbol->string (car fields)))
  2628. (fields (cdr fields)))
  2629. #`((write-string " " port)
  2630. (write-field #,name (%struct-ref x #,i) port)
  2631. . #,(lp fields (1+ i)))))))
  2632. (write-string ">" port)))))
  2633. (_ #`(let ((p #,printer))
  2634. (lambda (x port write-field) (p x port)))))
  2635. '#,id
  2636. (lambda (vtable cfield ...)
  2637. (%make-struct vtable cfield ...))
  2638. '#,properties
  2639. #,parents
  2640. #,(compute-mutable-fields #'(setter ...))
  2641. #,(syntax-case opaque? ()
  2642. (#t
  2643. #`(lambda (x y equal?) #f))
  2644. (#f
  2645. #`(lambda (x y equal?)
  2646. (and . #,(let lp ((fields #'(cfield ...))
  2647. (i 0))
  2648. (syntax-case fields ()
  2649. (() #'())
  2650. ((f . fields)
  2651. #`((equal? (%struct-ref x #,i)
  2652. (%struct-ref y #,i))
  2653. . #,(lp #'fields (1+ i))))))))))))
  2654. (define (predicate x)
  2655. (and (%struct? x)
  2656. #,(syntax-case extensible? ()
  2657. (#f #`(%eq? (%struct-vtable x) #,id))
  2658. (#t
  2659. #`(let ((rtd (%struct-vtable x)))
  2660. (or (%eq? rtd #,id)
  2661. (let ((parents (record-type-parents rtd)))
  2662. (and (< #,parent-count
  2663. (vector-length parents))
  2664. (%eq? (vector-ref parents #,parent-count)
  2665. #,id)))))))))
  2666. .
  2667. #,(let lp ((accessors #'((getter . setter) ...))
  2668. (i (length parent-fields)))
  2669. (syntax-case accessors ()
  2670. (() #'())
  2671. (((get) . accessors)
  2672. #`((define (get x)
  2673. (check-type x predicate 'get)
  2674. (%struct-ref x #,i))
  2675. . #,(lp #'accessors (1+ i))))
  2676. (((get set!) . accessors)
  2677. #`((define (set! obj val)
  2678. (check-type obj predicate 'set!)
  2679. (%struct-set! obj #,i val))
  2680. . #,(lp #'((get) . accessors) i)))))))))
  2681. (syntax-case stx ()
  2682. ((_ id arg ...)
  2683. (parse-kwargs
  2684. #'(arg ...)
  2685. (lambda (tail kwargs)
  2686. (apply parse-body #'id tail kwargs)))))))
  2687. (define (record? x)
  2688. (%struct? x))
  2689. (define (write-record record port write)
  2690. (define printer-field 1)
  2691. (define (write-field name value port)
  2692. (write-string name port)
  2693. (write-string ": " port)
  2694. (write value port))
  2695. (match (%struct-ref (%struct-vtable record) printer-field)
  2696. (#f (write-string "#<record with no printer!>" port))
  2697. (print (print record port write-field))))
  2698. (define (eq? x y) (%eq? x y))
  2699. (define (eqv? x y) (%eqv? x y))
  2700. (define (equal? x y)
  2701. (cond
  2702. ((eqv? x y) #t)
  2703. ((pair? x)
  2704. (and (pair? y)
  2705. (equal? (car x) (car y))
  2706. (equal? (cdr x) (cdr y))))
  2707. ((vector? x)
  2708. (and (vector? y)
  2709. (let ((length (vector-length x)))
  2710. (and (= length (vector-length y))
  2711. (let lp ((i 0))
  2712. (if (= i length)
  2713. #t
  2714. (and (equal? (vector-ref x i) (vector-ref y i))
  2715. (lp (+ i 1)))))))))
  2716. ((string? x)
  2717. (and (string? y)
  2718. (string=? x y)))
  2719. ((bytevector? x)
  2720. (and (bytevector? y)
  2721. (let ((length (bytevector-length x)))
  2722. (and (= length (bytevector-length y))
  2723. (let lp ((i 0))
  2724. (if (= i length)
  2725. #t
  2726. (and (eqv? (bytevector-u8-ref x i)
  2727. (bytevector-u8-ref y i))
  2728. (lp (+ i 1)))))))))
  2729. ((bitvector? x)
  2730. (and (bitvector? y)
  2731. (let ((length (bitvector-length x)))
  2732. (and (= length (bitvector-length y))
  2733. (let lp ((i 0))
  2734. (if (= i length)
  2735. #t
  2736. (and (eqv? (bitvector-ref x i)
  2737. (bitvector-ref y i))
  2738. (lp (+ i 1)))))))))
  2739. ((record? x)
  2740. (define (record-type-compare vtable)
  2741. (%struct-ref vtable 7))
  2742. (and (record? y)
  2743. (let ((vtable (%struct-vtable x)))
  2744. (and (eq? vtable (%struct-vtable y))
  2745. (match (record-type-compare vtable)
  2746. (#f #f)
  2747. (compare (compare x y equal?)))))))
  2748. (else #f)))
  2749. (define (procedure? x) (%procedure? x))
  2750. ;; Temp definitions!
  2751. (define map
  2752. (case-lambda
  2753. ((f l)
  2754. (let lp ((l l))
  2755. (match l
  2756. (() '())
  2757. ((x . l) (cons (f x) (lp l))))))
  2758. ((f l1 l2)
  2759. (let lp ((l1 l1) (l2 l2))
  2760. (match l1
  2761. (() '())
  2762. ((x . l1)
  2763. (match l2
  2764. (() '())
  2765. ((y . l2)
  2766. (cons (f x y) (lp l1 l2))))))))))
  2767. (define for-each
  2768. (case-lambda
  2769. ((f l)
  2770. (let lp ((l l))
  2771. (unless (null? l)
  2772. (f (car l))
  2773. (lp (cdr l)))))
  2774. ((f l1 l2)
  2775. (let lp ((l1 l1) (l2 l2))
  2776. (match l1
  2777. (() (values))
  2778. ((x . l1)
  2779. (match l2
  2780. (() (values))
  2781. ((y . l2)
  2782. (f x y)
  2783. (lp l1 l2)))))))))
  2784. (define (environment . import-specs)
  2785. (raise (%make-unimplemented-error 'environment)))
  2786. (define (interaction-environment)
  2787. (raise (%make-unimplemented-error 'interaction-environment)))
  2788. (define (eval exp env)
  2789. (raise (%make-unimplemented-error 'eval)))
  2790. (define* (load filename #:optional env)
  2791. (raise (%make-unimplemented-error 'load)))
  2792. (define (command-line) '())
  2793. (define (get-environment-variable name) #f)
  2794. (define (get-environment-variables) '())
  2795. (define* (emergency-exit #:optional status)
  2796. (raise (%make-unimplemented-error 'emergency-exit)))
  2797. (define* (exit #:optional status)
  2798. (raise (%make-unimplemented-error 'exit)))
  2799. (define* (%write-datum port x #:optional quote-strings?)
  2800. (define (recur x) (%write-datum port x quote-strings?))
  2801. (cond
  2802. ((eq? x #f) (write-string "#f" port))
  2803. ((eq? x #t) (write-string "#t" port))
  2804. ((eq? x #nil) (write-string "#nil" port))
  2805. ((eq? x '()) (write-string "()" port))
  2806. ((eq? x (if #f #f)) (write-string "#<unspecified>" port))
  2807. ((eof-object? x) (write-string "#<eof>" port))
  2808. ((number? x) (write-string (number->string x) port))
  2809. ((char? x)
  2810. (case x
  2811. ((#\alarm) (write-string "#\\alarm" port))
  2812. ((#\backspace) (write-string "#\\backspace" port))
  2813. ((#\delete) (write-string "#\\delete" port))
  2814. ((#\escape) (write-string "#\\escape" port))
  2815. ((#\newline) (write-string "#\\newline" port))
  2816. ((#\null) (write-string "#\\null" port))
  2817. ((#\return) (write-string "#\\return" port))
  2818. ((#\space) (write-string "#\\space" port))
  2819. ((#\tab) (write-string "#\\tab" port))
  2820. ((#\a #\b #\c #\d #\e #\f #\g #\h #\i #\j #\k #\l #\m
  2821. #\n #\o #\p #\q #\r #\s #\t #\u #\v #\w #\x #\y #\z
  2822. #\A #\B #\C #\D #\E #\F #\G #\H #\I #\J #\K #\L #\M
  2823. #\N #\O #\P #\Q #\R #\S #\T #\U #\V #\W #\X #\Y #\Z
  2824. #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9
  2825. #\` #\~ #\! #\@ #\# #\$ #\% #\^ #\& #\* #\( #\) #\- #\_ #\= #\+
  2826. #\[ #\] #\{ #\} #\\ #\| #\; #\: #\' #\" #\< #\> #\, #\. #\/ #\?)
  2827. (write-char #\# port)
  2828. (write-char #\\ port)
  2829. (write-char x port))
  2830. (else
  2831. (write-char #\# port)
  2832. (write-char #\\ port)
  2833. (write-char #\x port)
  2834. (write-string (number->string (char->integer x) 16) port))))
  2835. ((pair? x)
  2836. (write-char #\( port)
  2837. (recur (car x))
  2838. (let lp ((tail (cdr x)))
  2839. (cond
  2840. ((null? tail)
  2841. (write-char #\) port))
  2842. ((pair? tail)
  2843. (write-char #\space port)
  2844. (recur (car tail))
  2845. (lp (cdr tail)))
  2846. (else
  2847. (write-string " . " port)
  2848. (recur tail)
  2849. (write-char #\) port)))))
  2850. ((string? x)
  2851. (cond
  2852. (quote-strings?
  2853. (write-char #\" port)
  2854. (string-for-each (lambda (ch)
  2855. (case ch
  2856. ((#\newline)
  2857. (write-char #\\ port)
  2858. (write-char #\n port))
  2859. ((#\\ #\")
  2860. (write-char #\\ port)
  2861. (write-char ch port))
  2862. (else
  2863. (write-char ch port))))
  2864. x)
  2865. (write-char #\" port))
  2866. (else
  2867. (write-string x port))))
  2868. ((symbol? x)
  2869. (%write-datum port (symbol->string x) #f))
  2870. ((vector? x)
  2871. (write-char #\# port)
  2872. (recur (vector->list x)))
  2873. ((bytevector? x)
  2874. (write-string "#vu8(" port)
  2875. (let lp ((i 0))
  2876. (when (< i (bytevector-length x))
  2877. (unless (zero? i)
  2878. (write-char #\space port))
  2879. (write-string (number->string (bytevector-u8-ref x i)) port)
  2880. (lp (1+ i))))
  2881. (write-char #\) port))
  2882. ((bitvector? x)
  2883. (write-string "#*" port)
  2884. (let lp ((i 0))
  2885. (when (< i (bitvector-length x))
  2886. (write-char (if (bitvector-ref x i) #\1 #\0) port)
  2887. (lp (1+ i)))))
  2888. ((procedure? x)
  2889. (write-string "#<procedure>" port))
  2890. ((keyword? x)
  2891. (write-string "#:" port)
  2892. (write-string (symbol->string (keyword->symbol x)) port))
  2893. ((record? x)
  2894. (write-record x port write))
  2895. (else
  2896. (recur "unhandled object :("))))
  2897. (define* (display datum #:optional (port (current-output-port)))
  2898. (%write-datum port datum #f))
  2899. (define* (write datum #:optional (port (current-output-port)))
  2900. (%write-datum port datum #t))
  2901. (define* (write-shared datum #:optional (port (current-output-port)))
  2902. (raise (%make-unimplemented-error 'write-shared)))
  2903. (define* (write-simple datum #:optional (port (current-output-port)))
  2904. (write datum port))
  2905. (define (jiffies-per-second)
  2906. (%inline-wasm
  2907. '(func (result i64)
  2908. (i64.extend_i32_u (call $jiffies-per-second)))))
  2909. (define (current-jiffy)
  2910. (%inline-wasm
  2911. '(func (result i64)
  2912. (i64.trunc_f64_u (call $current-jiffy)))))
  2913. (define (current-second)
  2914. (%inline-wasm
  2915. '(func (result f64) (call $current-second))))
  2916. (define (standard-input-port)
  2917. (%make-soft-port "stdin"
  2918. (lambda ()
  2919. (%inline-wasm
  2920. '(func (result (ref eq))
  2921. (struct.new $string
  2922. (i32.const 0)
  2923. (call $read-stdin)))))
  2924. #f #f #f))
  2925. (define (standard-output-port)
  2926. (%make-soft-port "stdout"
  2927. #f
  2928. (lambda (str)
  2929. (%inline-wasm
  2930. '(func (param $str (ref string))
  2931. (call $write-stdout (local.get $str)))
  2932. str))
  2933. #f #f))
  2934. (define (standard-error-port)
  2935. (%make-soft-port "stderr"
  2936. #f
  2937. (lambda (str)
  2938. (%inline-wasm
  2939. '(func (param $str (ref string))
  2940. (call $write-stderr (local.get $str)))
  2941. str))
  2942. #f #f))
  2943. ;; FFI
  2944. (define (external? obj)
  2945. (%inline-wasm
  2946. '(func (param $obj (ref eq)) (result (ref eq))
  2947. (ref.i31
  2948. (if i32
  2949. (ref.test $extern-ref (local.get $obj))
  2950. (then (i32.const 17))
  2951. (else (i32.const 1)))))
  2952. obj))
  2953. (define (external-null? extern)
  2954. (check-type extern external? 'external-null?)
  2955. (%inline-wasm
  2956. '(func (param $extern (ref $extern-ref)) (result (ref eq))
  2957. (if (ref eq)
  2958. (ref.is_null
  2959. (struct.get $extern-ref $val (local.get $extern)))
  2960. (then (ref.i31 (i32.const 17)))
  2961. (else (ref.i31 (i32.const 1)))))
  2962. extern))
  2963. (define (procedure->external proc)
  2964. (check-type proc procedure? 'procedure->external)
  2965. (%inline-wasm
  2966. '(func (param $f (ref $proc)) (result (ref eq))
  2967. (struct.new $extern-ref
  2968. (i32.const 0)
  2969. (call $procedure->extern (local.get $f))))
  2970. proc))
  2971. (define-syntax define-foreign
  2972. (lambda (x)
  2973. (define (cons x y) (%cons x y))
  2974. (define (car x) (%car x))
  2975. (define (cdr x) (%cdr x))
  2976. (define (null? x) (%null? x))
  2977. (define (map proc lst)
  2978. (if (null? lst)
  2979. '()
  2980. (cons (proc (car lst)) (map proc (cdr lst)))))
  2981. (define (type-check exp proc-name)
  2982. (define (check param predicate)
  2983. #`(check-type #,param #,predicate '#,proc-name))
  2984. (syntax-case exp (i32 i64 f32 f64 ref null eq string extern)
  2985. ((x i32) (check #'x #'exact-integer?))
  2986. ((x i64) (check #'x #'exact-integer?))
  2987. ((x f32) (check #'x #'real?))
  2988. ((x f64) (check #'x #'real?))
  2989. ((x (ref eq)) #'#t)
  2990. ((x (ref null extern)) (check #'x #'external?))
  2991. ((x (ref string)) (check #'x #'string?))
  2992. ((x type) (%error "unsupported param type" #'type))))
  2993. (define (import-result-types exp)
  2994. (syntax-case exp (none)
  2995. (none #'())
  2996. (type #'((result type)))))
  2997. (define (result-types exp)
  2998. (syntax-case exp (none i32 i64 f32 f64 ref null string extern)
  2999. (none #'())
  3000. (i32 #'((result i64)))
  3001. (i64 #'((result i64)))
  3002. (f32 #'((result f64)))
  3003. (f64 #'((result f64)))
  3004. ((ref string) #'((result (ref eq))))
  3005. ((ref null extern) #'((result (ref eq))))
  3006. (type (%error "unsupported result type" #'type))))
  3007. (define (lift-result exp)
  3008. (syntax-case exp (none i32 i64 f32 f64 ref null string extern)
  3009. ((x none) #'x)
  3010. ((x i32) #'(i64.extend_i32_s x))
  3011. ((x i64) #'x)
  3012. ((x f32) #'(f64.promote_f32 x))
  3013. ((x f64) #'x)
  3014. ((x (ref string)) #'(struct.new $string (i32.const 0) x))
  3015. ((x (ref null extern)) #'(struct.new $extern-ref (i32.const 0) x))
  3016. (type (%error "unsupported result type" #'type))))
  3017. (define (fresh-wasm-id prefix)
  3018. (datum->syntax x (gensym prefix)))
  3019. (define (fresh-wasm-ids prefix lst)
  3020. (map (lambda (_) (fresh-wasm-id prefix)) lst))
  3021. (syntax-case x (->)
  3022. ((_ proc-name mod name ptype ... -> rtype)
  3023. (with-syntax ((iname (fresh-wasm-id "$import-"))
  3024. ((pname ...) (fresh-wasm-ids "$param-" #'(ptype ...))))
  3025. #`(begin
  3026. (%wasm-import
  3027. '(func iname (import mod name)
  3028. (param ptype) ...
  3029. #,@(import-result-types #'rtype)))
  3030. (define (proc-name pname ...)
  3031. #,@(map (lambda (exp) (type-check exp #'proc-name))
  3032. #'((pname ptype) ...))
  3033. (%inline-wasm
  3034. '(func (param pname ptype) ...
  3035. #,@(result-types #'rtype)
  3036. #,(lift-result
  3037. #'((call iname (local.get pname) ...) rtype)))
  3038. pname ...))))))))
  3039. (cond-expand
  3040. (hoot-main
  3041. (define current-input-port
  3042. (make-parameter (standard-input-port)
  3043. (lambda (val)
  3044. (check-type val input-port? 'current-input-port)
  3045. val)))
  3046. (define current-output-port
  3047. (make-parameter (standard-output-port)
  3048. (lambda (val)
  3049. (check-type val output-port? 'current-output-port)
  3050. val)))
  3051. (define current-error-port
  3052. (make-parameter (standard-error-port)
  3053. (lambda (val)
  3054. (check-type val output-port? 'current-error-port)
  3055. val)))
  3056. (%inline-wasm
  3057. '(func (param $current-input-port (ref eq))
  3058. (param $current-output-port (ref eq))
  3059. (param $current-error-port (ref eq))
  3060. (global.set $current-input-port (local.get $current-input-port))
  3061. (global.set $current-output-port (local.get $current-output-port))
  3062. (global.set $current-error-port (local.get $current-error-port)))
  3063. current-input-port
  3064. current-output-port
  3065. current-error-port))
  3066. (hoot-aux
  3067. (define current-input-port
  3068. (%inline-wasm
  3069. '(func (result (ref eq)) (global.get $current-input-port))))
  3070. (define current-output-port
  3071. (%inline-wasm
  3072. '(func (result (ref eq)) (global.get $current-output-port))))
  3073. (define current-error-port
  3074. (%inline-wasm
  3075. '(func (result (ref eq)) (global.get $current-error-port))))))
  3076. ;; promises
  3077. (define-record-type <promise>
  3078. #:opaque? #t
  3079. (%%make-promise value)
  3080. promise?
  3081. (value %promise-value %set-promise-value!))
  3082. (define (%make-promise eager? val)
  3083. (%%make-promise (cons eager? val)))
  3084. (define (make-promise x)
  3085. (if (promise? x) x (%make-promise #t x)))
  3086. (define (force promise)
  3087. (match (%promise-value promise)
  3088. ((#t . val) val)
  3089. ((#f . thunk)
  3090. (let ((promise* (thunk)))
  3091. (match (%promise-value promise)
  3092. ((and value (#f . _))
  3093. (match (%promise-value promise*)
  3094. ((eager? . data)
  3095. (set-car! value eager?)
  3096. (set-cdr! value data)
  3097. (%set-promise-value! promise* value)
  3098. (force promise))))
  3099. ((#t . val) val))))))
  3100. (define-syntax-rule (delay-force expr) (%make-promise #f (lambda () expr)))
  3101. (define-syntax-rule (delay expr) (delay-force (%make-promise #t expr)))
  3102. (define-record-type &exception
  3103. #:extensible? #t
  3104. (make-&exception)
  3105. simple-exception?)
  3106. (define-record-type &compound-exception
  3107. (make-compound-exception components)
  3108. compound-exception?
  3109. (components compound-exception-components))
  3110. (define (simple-exceptions exception)
  3111. "Return a list of the simple exceptions that compose the exception
  3112. object @var{exception}."
  3113. (cond ((compound-exception? exception)
  3114. (compound-exception-components exception))
  3115. ((simple-exception? exception)
  3116. (list exception))
  3117. (else
  3118. (raise (%make-type-error exception 'exception? 'simple-exceptions)))))
  3119. (define (make-exception . exceptions)
  3120. "Return an exception object composed of @var{exceptions}."
  3121. (define (flatten exceptions)
  3122. (if (null? exceptions)
  3123. '()
  3124. (append (simple-exceptions (car exceptions))
  3125. (flatten (cdr exceptions)))))
  3126. (let ((simple (flatten exceptions)))
  3127. (if (and (pair? simple) (null? (cdr simple)))
  3128. (car simple)
  3129. (make-compound-exception simple))))
  3130. (define (exception? obj)
  3131. "Return true if @var{obj} is an exception object."
  3132. (or (compound-exception? obj) (simple-exception? obj)))
  3133. (define-syntax define-exception-type
  3134. (lambda (stx)
  3135. (syntax-case stx ()
  3136. ((define-exception-type exn parent
  3137. (make-exn arg ...)
  3138. exn?
  3139. (field exn-field)
  3140. ...)
  3141. (with-syntax (((%exn-field ...) (generate-temporaries #'(exn-field ...))))
  3142. #'(begin
  3143. (define-record-type exn
  3144. #:parent parent #:extensible? #t
  3145. (make-exn arg ...)
  3146. %exn?
  3147. (field %exn-field)
  3148. ...)
  3149. (define (exn? x)
  3150. (or (%exn? x)
  3151. (and (compound-exception? x)
  3152. (let lp ((simple (compound-exception-components x)))
  3153. (match simple
  3154. (() #f)
  3155. ((x . simple)
  3156. (or (%exn? x)
  3157. (lp simple))))))))
  3158. (define (exn-field x)
  3159. (if (%exn? x)
  3160. (%exn-field x)
  3161. (let lp ((simple (compound-exception-components x)))
  3162. (match simple
  3163. (() (raise (%make-type-error x 'exn-field 'exn?)))
  3164. ((x . simple)
  3165. (if (%exn? x)
  3166. (%exn-field x)
  3167. (lp simple)))))))
  3168. ...))))))
  3169. (define-exception-type &message &exception
  3170. (make-exception-with-message message)
  3171. exception-with-message?
  3172. (message exception-message))
  3173. (define-exception-type &warning &exception
  3174. (make-warning)
  3175. warning?)
  3176. (define-exception-type &serious &exception
  3177. (make-serious-exception)
  3178. serious-exception?)
  3179. (define-exception-type &error &serious
  3180. (make-error)
  3181. error?)
  3182. (define-exception-type &violation &serious
  3183. (make-violation)
  3184. violation?)
  3185. (define-exception-type &assertion &violation
  3186. (make-assertion-violation)
  3187. assertion-violation?)
  3188. (define-exception-type &arity-violation &violation
  3189. (make-arity-violation)
  3190. arity-violation?)
  3191. (define-exception-type &implementation-restriction &violation
  3192. (make-implementation-restriction-violation)
  3193. implementation-restriction-violation?)
  3194. (define-exception-type &failed-type-check &assertion
  3195. (make-failed-type-check predicate)
  3196. failed-type-check?
  3197. (predicate failed-type-check-predicate))
  3198. (define-exception-type &non-continuable &violation
  3199. (make-non-continuable-violation)
  3200. non-continuable-violation?)
  3201. (define-exception-type &irritants &exception
  3202. (make-exception-with-irritants irritants)
  3203. exception-with-irritants?
  3204. (irritants exception-irritants))
  3205. (define-exception-type &origin &exception
  3206. (make-exception-with-origin origin)
  3207. exception-with-origin?
  3208. (origin exception-origin))
  3209. (define-exception-type &lexical &violation
  3210. (make-lexical-violation)
  3211. lexical-violation?)
  3212. (define-exception-type &i/o &error
  3213. (make-i/o-error)
  3214. i/o-error?)
  3215. (define-exception-type &i/o-line-and-column &i/o
  3216. (make-i/o-line-and-column-error line column)
  3217. i/o-line-and-column-error?
  3218. (line i/o-error-line)
  3219. (column i/o-error-column))
  3220. (define-exception-type &i/o-filename &i/o
  3221. (make-i/o-filename-error filename)
  3222. i/o-filename-error?
  3223. (filename i/o-error-filename))
  3224. (define-exception-type &i/o-not-seekable &i/o
  3225. (make-i/o-not-seekable-error)
  3226. i/o-not-seekable-error?)
  3227. (define-exception-type &i/o-port &i/o
  3228. (make-i/o-port-error port)
  3229. i/o-port-error?
  3230. (port i/o-error-port))
  3231. ;; R7RS.
  3232. (define (error-object? x)
  3233. (and (exception-with-message? x)
  3234. (exception-with-irritants? x)))
  3235. (define error-object-message exception-message)
  3236. (define error-object-irritants exception-irritants)
  3237. (define read-error? lexical-violation?)
  3238. (define file-error? i/o-error?)
  3239. ;; Snarfed from Guile's (ice-9 exceptions). Deviates a bit from R7RS.
  3240. (define-syntax guard
  3241. (lambda (stx)
  3242. (define (dispatch tag exn clauses)
  3243. (define (build-clause test handler clauses)
  3244. #`(let ((t #,test))
  3245. (if t
  3246. (abort-to-prompt #,tag #,handler t)
  3247. #,(dispatch tag exn clauses))))
  3248. (syntax-case clauses (=> else)
  3249. (() #`(raise-continuable #,exn))
  3250. (((test => f) . clauses)
  3251. (build-clause #'test #'(lambda (res) (f res)) #'clauses))
  3252. (((else e e* ...) . clauses)
  3253. (build-clause #'#t #'(lambda (res) e e* ...) #'clauses))
  3254. (((test) . clauses)
  3255. (build-clause #'test #'(lambda (res) res) #'clauses))
  3256. (((test e* ...) . clauses)
  3257. (build-clause #'test #'(lambda (res) e* ...) #'clauses))))
  3258. (syntax-case stx ()
  3259. ((guard (exn clause clause* ...) body body* ...)
  3260. (identifier? #'exn)
  3261. #`(let ((tag (make-prompt-tag)))
  3262. (call-with-prompt
  3263. tag
  3264. (lambda ()
  3265. (with-exception-handler
  3266. (lambda (exn)
  3267. #,(dispatch #'tag #'exn #'(clause clause* ...)))
  3268. (lambda () body body* ...)))
  3269. (lambda (_ h v)
  3270. (h v))))))))
  3271. (define* (read #:optional (port (current-input-port)))
  3272. ;; For read-syntax, we'd define these annotate / strip functions
  3273. ;; differently, to create syntax objects instead.
  3274. (define (annotate line column datum) datum)
  3275. (define (strip-annotation datum) datum)
  3276. (define fold-case? (%port-fold-case? port))
  3277. (define (set-fold-case?! val)
  3278. (set! fold-case? val)
  3279. (%set-port-fold-case?! port val))
  3280. (define (next) (read-char port))
  3281. (define (peek) (peek-char port))
  3282. ;; We are only ever interested in whether an object is a char or not.
  3283. (define (eof-object? x) (not (char? x)))
  3284. (define (input-error msg args)
  3285. (raise
  3286. (make-exception (make-lexical-violation)
  3287. (make-exception-with-origin "read")
  3288. (make-exception-with-message msg)
  3289. (make-exception-with-irritants args)
  3290. (make-i/o-filename-error (port-filename port))
  3291. (make-i/o-line-and-column-error (1+ (port-line port))
  3292. (1+ (port-column port))))))
  3293. (define-syntax-rule (error msg arg ...)
  3294. (let ((args (list arg ...)))
  3295. (input-error msg args)))
  3296. (define (read-semicolon-comment)
  3297. (let ((ch (next)))
  3298. (cond
  3299. ((eof-object? ch) ch)
  3300. ((eqv? ch #\newline) (next))
  3301. (else (read-semicolon-comment)))))
  3302. (define-syntax-rule (take-until first pred)
  3303. (let ((p (open-output-string)))
  3304. (write-char first p)
  3305. (let lp ()
  3306. (let ((ch (peek)))
  3307. (if (or (eof-object? ch) (pred ch))
  3308. (get-output-string p)
  3309. (begin
  3310. (write-char ch p)
  3311. (next)
  3312. (lp)))))))
  3313. (define-syntax-rule (take-while first pred)
  3314. (take-until first (lambda (ch) (not (pred ch)))))
  3315. (define (delimiter? ch)
  3316. (case ch
  3317. ((#\( #\) #\; #\" #\space #\return #\ff #\newline #\tab #\[ #\]) #t)
  3318. (else #f)))
  3319. (define (read-token ch)
  3320. (take-until ch delimiter?))
  3321. (define (read-mixed-case-symbol ch)
  3322. (let ((str (read-token ch)))
  3323. (string->symbol (if fold-case? (string-downcase str) str))))
  3324. (define (read-parenthesized rdelim)
  3325. (let lp ((ch (next-non-whitespace)))
  3326. (when (eof-object? ch)
  3327. (error "unexpected end of input while searching for: ~A"
  3328. rdelim))
  3329. (cond
  3330. ((eqv? ch rdelim) '())
  3331. ((or (eqv? ch #\)) (eqv? ch #\]))
  3332. (error "mismatched close paren: ~A" ch))
  3333. (else
  3334. (let ((expr (read-expr ch)))
  3335. ;; Note that it is possible for scm_read_expression to
  3336. ;; return `.', but not as part of a dotted pair: as in
  3337. ;; #{.}#. Indeed an example is here!
  3338. (if (and (eqv? ch #\.) (eq? (strip-annotation expr) '#{.}#))
  3339. (let* ((tail (read-subexpression "tail of improper list"))
  3340. (close (next-non-whitespace)))
  3341. (unless (eqv? close rdelim)
  3342. (error "missing close paren: ~A" close))
  3343. tail)
  3344. (cons expr (lp (next-non-whitespace)))))))))
  3345. (define (hex-digit ch)
  3346. (case ch
  3347. ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)
  3348. (- (char->integer ch) (char->integer #\0)))
  3349. ((#\a #\b #\c #\d #\e #\f)
  3350. (+ 10 (- (char->integer ch) (char->integer #\a))))
  3351. ((#\A #\B #\C #\D #\E #\F)
  3352. (+ 10 (- (char->integer ch) (char->integer #\A))))
  3353. (else #f)))
  3354. (define (read-r6rs-hex-escape)
  3355. (let ((ch (next)))
  3356. (cond
  3357. ((hex-digit ch) =>
  3358. (lambda (res)
  3359. (let lp ((res res))
  3360. (let ((ch (next)))
  3361. (cond
  3362. ((hex-digit ch) => (lambda (digit) (lp (+ (* 16 res) digit))))
  3363. ((eqv? ch #\;) (integer->char res))
  3364. ((eof-object? ch)
  3365. (error "unexpected end of input in character escape sequence"))
  3366. (else
  3367. (error "invalid character in escape sequence: ~S" ch)))))))
  3368. ((eof-object? ch)
  3369. (error "unexpected end of input in character escape sequence"))
  3370. (else
  3371. (error "invalid character in escape sequence: ~S" ch)))))
  3372. (define (read-fixed-hex-escape len)
  3373. (let lp ((len len) (res 0))
  3374. (if (zero? len)
  3375. (integer->char res)
  3376. (let ((ch (next)))
  3377. (cond
  3378. ((hex-digit ch) =>
  3379. (lambda (digit)
  3380. (lp (1- len) (+ (* res 16) digit))))
  3381. ((eof-object? ch)
  3382. (error "unexpected end of input in character escape sequence"))
  3383. (else
  3384. (error "invalid character in escape sequence: ~S" ch)))))))
  3385. (define (char-intraline-whitespace? ch)
  3386. ;; True for tab and for codepoints whose general category is Zs.
  3387. (case ch
  3388. ((#\tab #\space
  3389. #\240 #\13200
  3390. #\20000 #\20001 #\20002 #\20003 #\20004 #\20005
  3391. #\20006 #\20007 #\20010 #\20011 #\20012
  3392. #\20057
  3393. #\20137
  3394. #\30000) #t)
  3395. (else #f)))
  3396. (define (read-string rdelim)
  3397. (let ((out (open-output-string)))
  3398. (let lp ()
  3399. (let ((ch (next)))
  3400. (cond
  3401. ((eof-object? ch)
  3402. (error "unexpected end of input while reading string"))
  3403. ((eqv? ch rdelim)
  3404. (get-output-string out))
  3405. ((eqv? ch #\\)
  3406. (let ((ch (next)))
  3407. (when (eof-object? ch)
  3408. (error "unexpected end of input while reading string"))
  3409. (cond
  3410. ((eqv? ch #\newline)
  3411. ;; Skip intraline whitespace before continuing.
  3412. (let skip ()
  3413. (let ((ch (peek)))
  3414. (when (and (not (eof-object? ch))
  3415. (char-intraline-whitespace? ch))
  3416. (next)
  3417. (skip))))
  3418. (lp))
  3419. ((eqv? ch rdelim)
  3420. (write-char rdelim out)
  3421. (lp))
  3422. (else
  3423. (write-char
  3424. (case ch
  3425. ;; Accept "\(" for use at the beginning of
  3426. ;; lines in multiline strings to avoid
  3427. ;; confusing emacs lisp modes.
  3428. ((#\| #\\ #\() ch)
  3429. ((#\0) #\nul)
  3430. ((#\f) #\ff)
  3431. ((#\n) #\newline)
  3432. ((#\r) #\return)
  3433. ((#\t) #\tab)
  3434. ((#\a) #\alarm)
  3435. ((#\v) #\vtab)
  3436. ((#\b) #\backspace)
  3437. ;; When faced with the choice between Guile's old
  3438. ;; two-char \xHH escapes and R6RS \xHHH...;
  3439. ;; escapes, prefer R6RS; \xHH is of limited
  3440. ;; utility.
  3441. ((#\x) (read-r6rs-hex-escape))
  3442. ((#\u) (read-fixed-hex-escape 4))
  3443. ((#\U) (read-fixed-hex-escape 6))
  3444. (else
  3445. (error "invalid character in escape sequence: ~S" ch)))
  3446. out)
  3447. (lp)))))
  3448. (else
  3449. (write-char ch out)
  3450. (lp)))))))
  3451. (define (read-character)
  3452. (let ((ch (next)))
  3453. (cond
  3454. ((eof-object? ch)
  3455. (error "unexpected end of input after #\\"))
  3456. ((delimiter? ch)
  3457. ch)
  3458. (else
  3459. (let* ((tok (read-token ch))
  3460. (len (string-length tok)))
  3461. (define dotted-circle #\x25cc)
  3462. (define r5rs-charnames
  3463. '(("space" . #\x20) ("newline" . #\x0a)))
  3464. (define r6rs-charnames
  3465. '(("nul" . #\x00) ("alarm" . #\x07) ("backspace" . #\x08)
  3466. ("tab" . #\x09) ("linefeed" . #\x0a) ("vtab" . #\x0b)
  3467. ("page" . #\x0c) ("return" . #\x0d) ("esc" . #\x1b)
  3468. ("delete" . #\x7f)))
  3469. (define r7rs-charnames
  3470. '(("escape" . #\x1b)))
  3471. (define C0-control-charnames
  3472. '(("nul" . #\x00) ("soh" . #\x01) ("stx" . #\x02)
  3473. ("etx" . #\x03) ("eot" . #\x04) ("enq" . #\x05)
  3474. ("ack" . #\x06) ("bel" . #\x07) ("bs" . #\x08)
  3475. ("ht" . #\x09) ("lf" . #\x0a) ("vt" . #\x0b)
  3476. ("ff" . #\x0c) ("cr" . #\x0d) ("so" . #\x0e)
  3477. ("si" . #\x0f) ("dle" . #\x10) ("dc1" . #\x11)
  3478. ("dc2" . #\x12) ("dc3" . #\x13) ("dc4" . #\x14)
  3479. ("nak" . #\x15) ("syn" . #\x16) ("etb" . #\x17)
  3480. ("can" . #\x18) ("em" . #\x19) ("sub" . #\x1a)
  3481. ("esc" . #\x1b) ("fs" . #\x1c) ("gs" . #\x1d)
  3482. ("rs" . #\x1e) ("us" . #\x1f) ("sp" . #\x20)
  3483. ("del" . #\x7f)))
  3484. (define alt-charnames
  3485. '(("null" . #\x0) ("nl" . #\x0a) ("np" . #\x0c)))
  3486. ;; Although R6RS and R7RS charnames specified as being
  3487. ;; case-sensitive, Guile matches them case-insensitively, like
  3488. ;; other char names.
  3489. (define (named-char tok alist)
  3490. (let ((tok (string-downcase tok)))
  3491. (let lp ((alist alist))
  3492. (match alist
  3493. (() #f)
  3494. (((name . ch) . alist)
  3495. (if (string=? name tok) ch (lp alist)))))))
  3496. (cond
  3497. ((= len 1) ch)
  3498. ((and (= len 2) (eqv? (string-ref tok 1) dotted-circle))
  3499. ;; Ignore dotted circles, which may be used to keep
  3500. ;; combining characters from combining with the backslash in
  3501. ;; #\charname.
  3502. ch)
  3503. ((and (<= (char->integer #\0) (char->integer ch) (char->integer #\7))
  3504. (string->number tok 8))
  3505. ;; Specifying a codepoint as an octal value.
  3506. => integer->char)
  3507. ((and (eqv? ch #\x) (> len 1)
  3508. (string->number (string-copy tok 1) 16))
  3509. ;; Specifying a codepoint as an hexadecimal value. Skip
  3510. ;; initial "x".
  3511. => integer->char)
  3512. ((named-char tok r5rs-charnames))
  3513. ((named-char tok r6rs-charnames))
  3514. ((named-char tok r7rs-charnames))
  3515. ((named-char tok C0-control-charnames))
  3516. ((named-char tok alt-charnames))
  3517. (else
  3518. (error "unknown character name ~a" tok))))))))
  3519. (define (read-vector)
  3520. (list->vector (map strip-annotation (read-parenthesized #\)))))
  3521. (define (read-bytevector)
  3522. (define (expect ch)
  3523. (unless (eqv? (next) ch)
  3524. (error "invalid bytevector prefix" ch)))
  3525. (expect #\u)
  3526. (expect #\8)
  3527. (expect #\()
  3528. (let ((p (open-output-bytevector)))
  3529. (for-each (lambda (datum) (write-u8 (strip-annotation datum) p))
  3530. (read-parenthesized #\)))
  3531. (get-output-bytevector p)))
  3532. ;; FIXME: We should require a terminating delimiter.
  3533. (define (read-bitvector)
  3534. (let lp ((bits '()) (len 0))
  3535. (let ((ch (peek)))
  3536. (case ch
  3537. ((#\0) (next) (lp bits (1+ len)))
  3538. ((#\1) (next) (lp (cons len bits) (1+ len)))
  3539. (else
  3540. (let ((bv (make-bitvector len #f)))
  3541. (for-each (lambda (bit) (bitvector-set-bit! bv bit)) bits)
  3542. bv))))))
  3543. (define (read-true)
  3544. (match (peek)
  3545. ((or (? eof-object?) (? delimiter?))
  3546. #t)
  3547. (_ (match (read-token #\t)
  3548. ((? (lambda (tok) (string=? (string-downcase tok) "true"))) #t)
  3549. (tok (error "unexpected input when reading #true" tok))))))
  3550. (define (read-false)
  3551. (match (peek)
  3552. ((or (? eof-object?) (? delimiter?))
  3553. #f)
  3554. (_ (match (string-downcase (read-token #\f))
  3555. ((? (lambda (tok) (string=? (string-downcase tok) "false"))) #f)
  3556. (tok (error "unexpected input when reading #false" tok))))))
  3557. (define (read-keyword)
  3558. (let ((expr (strip-annotation (read-subexpression "keyword"))))
  3559. (unless (symbol? expr)
  3560. (error "keyword prefix #: not followed by a symbol: ~a" expr))
  3561. (symbol->keyword expr)))
  3562. (define (read-number-and-radix ch)
  3563. (let ((tok (string-append "#" (read-token ch))))
  3564. (or (string->number tok)
  3565. (error "unknown # object: ~S" tok))))
  3566. (define (read-extended-symbol)
  3567. (define (next-not-eof)
  3568. (let ((ch (next)))
  3569. (when (eof-object? ch)
  3570. (error "end of input while reading symbol"))
  3571. ch))
  3572. (let ((out (open-output-string)))
  3573. (let lp ((saw-brace? #f))
  3574. (let lp/inner ((ch (next-not-eof))
  3575. (saw-brace? saw-brace?))
  3576. (cond
  3577. (saw-brace?
  3578. (unless (eqv? ch #\#)
  3579. ;; Don't eat CH, see
  3580. ;; <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=49623>.
  3581. (write-char #\} out)
  3582. (lp/inner ch #f)))
  3583. ((eqv? ch #\})
  3584. (lp #t))
  3585. ((eqv? ch #\\)
  3586. ;; \xH+; => R6RS hex escape
  3587. ;; \C => C otherwise, for any C
  3588. (let* ((ch (next-not-eof))
  3589. (ch (if (eqv? ch #\x)
  3590. (read-r6rs-hex-escape)
  3591. ch)))
  3592. (write-char ch out)
  3593. (lp #f)))
  3594. (else
  3595. (write-char ch out)
  3596. (lp #f)))))
  3597. (string->symbol (get-output-string out))))
  3598. (define (read-nil)
  3599. ;; Have already read "#\n" -- now read "il".
  3600. (match (read-mixed-case-symbol #\n)
  3601. ('nil #nil)
  3602. (id (error "unexpected input while reading #nil: ~a" id))))
  3603. (define (read-sharp)
  3604. (let* ((ch (next)))
  3605. (cond
  3606. ((eof-object? ch)
  3607. (error "unexpected end of input after #"))
  3608. (else
  3609. (case ch
  3610. ((#\\) (read-character))
  3611. ((#\() (read-vector))
  3612. ((#\v) (read-bytevector))
  3613. ((#\*) (read-bitvector))
  3614. ((#\f #\F) (read-false))
  3615. ((#\t #\T) (read-true))
  3616. ((#\:) (read-keyword))
  3617. ((#\i #\e #\b #\B #\o #\O #\d #\D #\x #\X #\I #\E)
  3618. (read-number-and-radix ch))
  3619. ((#\{) (read-extended-symbol))
  3620. ((#\') (list 'syntax (read-subexpression "syntax expression")))
  3621. ((#\`) (list 'quasisyntax
  3622. (read-subexpression "quasisyntax expression")))
  3623. ((#\,)
  3624. (if (eqv? #\@ (peek))
  3625. (begin
  3626. (next)
  3627. (list 'unsyntax-splicing
  3628. (read-subexpression "unsyntax-splicing expression")))
  3629. (list 'unsyntax (read-subexpression "unsyntax expression"))))
  3630. ((#\n) (read-nil))
  3631. (else
  3632. (error "Unknown # object: ~S" (string #\# ch))))))))
  3633. (define (read-number ch)
  3634. (let ((str (read-token ch)))
  3635. (or (string->number str)
  3636. (string->symbol (if fold-case? (string-downcase str) str)))))
  3637. (define (read-expr* ch)
  3638. (case ch
  3639. ((#\[) (read-parenthesized #\]))
  3640. ((#\() (read-parenthesized #\)))
  3641. ((#\") (read-string ch))
  3642. ((#\|) (string->symbol (read-string ch)))
  3643. ((#\') (list 'quote (read-subexpression "quoted expression")))
  3644. ((#\`) (list 'quasiquote (read-subexpression "quasiquoted expression")))
  3645. ((#\,) (cond
  3646. ((eqv? #\@ (peek))
  3647. (next)
  3648. (list 'unquote-splicing (read-subexpression "subexpression of ,@")))
  3649. (else
  3650. (list 'unquote (read-subexpression "unquoted expression")))))
  3651. ;; FIXME: read-sharp should recur if we read a comment
  3652. ((#\#) (read-sharp))
  3653. ((#\)) (error "unexpected \")\""))
  3654. ((#\]) (error "unexpected \"]\""))
  3655. ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\+ #\- #\.) (read-number ch))
  3656. (else (read-mixed-case-symbol ch))))
  3657. (define (read-expr ch)
  3658. (annotate (port-line port)
  3659. (port-column port)
  3660. (read-expr* ch)))
  3661. (define (read-directive)
  3662. (define (directive-char? ch)
  3663. (and (char? ch)
  3664. (or (eqv? ch #\-)
  3665. (char-alphabetic? ch)
  3666. (char-numeric? ch))))
  3667. (let ((ch (peek)))
  3668. (cond
  3669. ((directive-char? ch)
  3670. (next)
  3671. (string->symbol (take-while ch directive-char?)))
  3672. (else
  3673. #f))))
  3674. (define (skip-scsh-comment)
  3675. (let lp ((ch (next)))
  3676. (cond
  3677. ((eof-object? ch)
  3678. (error "unterminated `#! ... !#' comment"))
  3679. ((eqv? ch #\!)
  3680. (let ((ch (next)))
  3681. (if (eqv? ch #\#)
  3682. (next)
  3683. (lp ch))))
  3684. (else
  3685. (lp (next))))))
  3686. (define (process-shebang)
  3687. ;; After having read #!, we complete either with #!r6rs,
  3688. ;; #!fold-case, #!no-fold-case, or a SCSH block comment terminated
  3689. ;; by !#.
  3690. (match (read-directive)
  3691. ('fold-case
  3692. (set-fold-case?! #t)
  3693. (next))
  3694. ((or 'no-fold-case 'r6rs)
  3695. (set-fold-case?! #f)
  3696. (next))
  3697. (_
  3698. (skip-scsh-comment))))
  3699. (define (skip-eol-comment)
  3700. (let ((ch (next)))
  3701. (cond
  3702. ((eof-object? ch) ch)
  3703. ((eq? ch #\newline) (next))
  3704. (else (skip-eol-comment)))))
  3705. ;; Unlike SCSH-style block comments, SRFI-30/R6RS block comments may be
  3706. ;; nested.
  3707. (define (skip-r6rs-block-comment)
  3708. ;; We have read #|, now looking for |#.
  3709. (let ((ch (next)))
  3710. (when (eof-object? ch)
  3711. (error "unterminated `#| ... |#' comment"))
  3712. (cond
  3713. ((and (eqv? ch #\|) (eqv? (peek) #\#))
  3714. ;; Done.
  3715. (next)
  3716. (values))
  3717. ((and (eqv? ch #\#) (eqv? (peek) #\|))
  3718. ;; A nested comment.
  3719. (next)
  3720. (skip-r6rs-block-comment)
  3721. (skip-r6rs-block-comment))
  3722. (else
  3723. (skip-r6rs-block-comment)))))
  3724. (define (read-subexpression what)
  3725. (let ((ch (next-non-whitespace)))
  3726. (when (eof-object? ch)
  3727. (error (string-append "unexpected end of input while reading " what)))
  3728. (read-expr ch)))
  3729. (define (next-non-whitespace)
  3730. (let lp ((ch (next)))
  3731. (case ch
  3732. ((#\;)
  3733. (lp (skip-eol-comment)))
  3734. ((#\#)
  3735. (case (peek)
  3736. ((#\!)
  3737. (next)
  3738. (lp (process-shebang)))
  3739. ((#\;)
  3740. (next)
  3741. (read-subexpression "#; comment")
  3742. (next-non-whitespace))
  3743. ((#\|)
  3744. (next)
  3745. (skip-r6rs-block-comment)
  3746. (next-non-whitespace))
  3747. (else ch)))
  3748. ((#\space #\return #\ff #\newline #\tab)
  3749. (next-non-whitespace))
  3750. (else ch))))
  3751. (let ((ch (next-non-whitespace)))
  3752. (if (eof-object? ch)
  3753. ch
  3754. (read-expr ch))))
  3755. (define (format-exception exception port)
  3756. (display "Scheme error:\n")
  3757. (match (simple-exceptions exception)
  3758. (() (display "Empty exception object" port))
  3759. (components
  3760. (let loop ((i 1) (components components))
  3761. (define (format-numbered-exception exception)
  3762. (display " " port)
  3763. (display i port)
  3764. (display ". " port)
  3765. (write exception port))
  3766. (match components
  3767. ((component)
  3768. (format-numbered-exception component))
  3769. ((component . rest)
  3770. (format-numbered-exception component)
  3771. (newline port)
  3772. (loop (+ i 1) rest)))))))
  3773. ;;;; (rnrs hashtables (6))
  3774. ;;; Constructors
  3775. (define* (make-eq-hashtable #:optional k)
  3776. (%inline-wasm
  3777. '(func (result (ref eq))
  3778. (call $make-hash-table))))
  3779. (define* (make-eqv-hashtable #:optional k)
  3780. (raise (%make-unimplemented-error 'make-eqv-hashtable)))
  3781. (define* (make-hashtable hash-function equiv #:optional k)
  3782. (raise (%make-unimplemented-error 'make-hashtable)))
  3783. ;;; Procedures
  3784. (define (hashtable? hashtable)
  3785. (%inline-wasm
  3786. '(func (param $obj (ref eq)) (result (ref eq))
  3787. (if (ref eq)
  3788. (ref.test $hash-table (local.get $obj))
  3789. (then (ref.i31 (i32.const 17)))
  3790. (else (ref.i31 (i32.const 1)))))
  3791. hashtable))
  3792. (define (hashtable-size hashtable)
  3793. (check-type hashtable hashtable? 'hashtable-size)
  3794. (%inline-wasm
  3795. '(func (param $table (ref $hash-table))
  3796. (result (ref eq))
  3797. (call $i32->fixnum
  3798. (struct.get $hash-table $size (local.get $table))))
  3799. hashtable))
  3800. (define* (hashtable-ref hashtable key #:optional default)
  3801. (check-type hashtable hashtable? 'hashtable-ref)
  3802. (%inline-wasm
  3803. '(func (param $table (ref $hash-table))
  3804. (param $key (ref eq))
  3805. (param $default (ref eq))
  3806. (result (ref eq))
  3807. (call $hashq-ref
  3808. (local.get $table)
  3809. (local.get $key)
  3810. (local.get $default)))
  3811. hashtable key default))
  3812. (define (hashtable-set! hashtable key obj)
  3813. (check-type hashtable hashtable? 'hashtable-set!)
  3814. (%inline-wasm
  3815. '(func (param $table (ref $hash-table))
  3816. (param $key (ref eq))
  3817. (param $val (ref eq))
  3818. (result (ref eq))
  3819. (call $hashq-update
  3820. (local.get $table)
  3821. (local.get $key)
  3822. (local.get $val)
  3823. (local.get $val)))
  3824. hashtable key obj)
  3825. (values))
  3826. (define (hashtable-delete! hashtable key)
  3827. (check-type hashtable hashtable? 'hashtable-delete!)
  3828. (%inline-wasm
  3829. '(func (param $table (ref $hash-table))
  3830. (param $key (ref eq))
  3831. (call $hashq-delete! (local.get $table) (local.get $key)))
  3832. hashtable key)
  3833. (values))
  3834. (define (hashtable-contains? hashtable key)
  3835. (check-type hashtable hashtable? 'hashtable-contains?)
  3836. (pair? (%hashq-get-handle hashtable key)))
  3837. (define (hashtable-update! hashtable key proc default)
  3838. (check-type hashtable hashtable? 'hashtable-update!)
  3839. (check-type proc procedure? 'hashtable-update!)
  3840. (let ((handle (%hashq-get-handle hashtable key)))
  3841. (if (pair? handle)
  3842. (set-cdr! handle (proc (cdr handle)))
  3843. (hashtable-set! hashtable key (proc default))))
  3844. (values))
  3845. (define* (hashtable-copy hashtable #:optional (mutable #t))
  3846. (check-type hashtable hashtable? 'hashtable-copy)
  3847. (unless mutable
  3848. (raise (%make-unimplemented-error 'hashtable-copy)))
  3849. (let ((hashtable* (make-eq-hashtable)))
  3850. (hashtable-for-each (lambda (k v)
  3851. (hashtable-set! hashtable* k v))
  3852. hashtable)
  3853. hashtable*))
  3854. (define* (hashtable-clear! hashtable #:optional k)
  3855. (check-type hashtable hashtable? 'hashtable-clear!)
  3856. (%inline-wasm
  3857. '(func (param $table (ref $hash-table))
  3858. (struct.set $hash-table
  3859. $size
  3860. (local.get $table)
  3861. (i32.const 0))
  3862. (array.fill $raw-scmvector
  3863. (struct.get $hash-table $buckets
  3864. (local.get $table))
  3865. (i32.const 0)
  3866. (ref.i31 (i32.const 13))
  3867. (array.len (struct.get $hash-table $buckets
  3868. (local.get $table)))))
  3869. hashtable)
  3870. (values))
  3871. (define (hashtable-keys hashtable)
  3872. (check-type hashtable hashtable? 'hashtable-keys)
  3873. (list->vector
  3874. (%hash-fold (lambda (k v seed) (cons k seed))
  3875. '()
  3876. hashtable)))
  3877. (define (hashtable-entries hashtable)
  3878. (check-type hashtable hashtable? 'hashtable-entries)
  3879. (list->vector
  3880. (%hash-fold (lambda (k v seed) (cons v seed))
  3881. '()
  3882. hashtable)))
  3883. ;;; Inspection
  3884. ;; TODO: non-eq hashtables
  3885. (define (hashtable-equivalence-function hashtable)
  3886. (check-type hashtable hashtable? 'hashtable-equivalence-function)
  3887. eq?)
  3888. ;; TODO: non-eq hashtables
  3889. (define (hashtable-hash-function hashtable)
  3890. (check-type hashtable hashtable? 'hashtable-hash-function)
  3891. %hashq)
  3892. ;; TODO: implement immutable hashtables
  3893. (define (hashtable-mutable? hashtable)
  3894. (check-type hashtable hashtable? 'hashtable-mutable?)
  3895. #t)
  3896. ;;; Hash functions
  3897. (define (equal-hash obj)
  3898. (raise (%make-unimplemented-error 'equal-hash)))
  3899. (define (string-hash string)
  3900. (raise (%make-unimplemented-error 'string-hash)))
  3901. (define (string-ci-hash string)
  3902. (raise (%make-unimplemented-error 'string-ci-hash)))
  3903. (define (symbol-hash symbol)
  3904. (raise (%make-unimplemented-error 'symbol-hash)))
  3905. ;;; Hoot extensions
  3906. (define (hashtable-for-each proc hashtable)
  3907. (check-type proc procedure? 'hashtable-for-each)
  3908. (check-type hashtable hashtable? 'hashtable-for-each)
  3909. (let ((len (%buckets-length hashtable)))
  3910. (do ((i 0 (1+ i)))
  3911. ((= i len) (values))
  3912. (for-each (lambda (handle)
  3913. (proc (car handle) (cdr handle)))
  3914. (%bucket-ref hashtable i)))))
  3915. ;;; Internal hash-table procedures
  3916. (define (%hashq-get-handle table key)
  3917. (%inline-wasm
  3918. '(func (param $table (ref $hash-table))
  3919. (param $key (ref eq))
  3920. (result (ref eq))
  3921. (call $hashq-lookup/default
  3922. (local.get $table)
  3923. (local.get $key)
  3924. (ref.i31 (i32.const 1))))
  3925. table key))
  3926. (define (%hashq key size)
  3927. (%inline-wasm
  3928. '(func (param $v (ref eq))
  3929. (result (ref eq))
  3930. (call $i32->fixnum (call $hashq (local.get $v))))
  3931. key))
  3932. (define (%buckets-length table)
  3933. (%inline-wasm
  3934. '(func (param $table (ref $hash-table))
  3935. (result (ref eq))
  3936. (call $i32->fixnum
  3937. (array.len (struct.get $hash-table
  3938. $buckets
  3939. (local.get $table)))))
  3940. table))
  3941. (define (%bucket-ref table i)
  3942. (%inline-wasm
  3943. '(func (param $table (ref $hash-table))
  3944. (param $i i32)
  3945. (result (ref eq))
  3946. (array.get $raw-scmvector
  3947. (struct.get $hash-table
  3948. $buckets
  3949. (local.get $table))
  3950. (local.get $i)))
  3951. table i))
  3952. (define (%hash-fold-handles proc init table)
  3953. (let ((len (%buckets-length table)))
  3954. (let loop ((i 0)
  3955. (seed init))
  3956. (if (= i len)
  3957. seed
  3958. (loop (1+ i)
  3959. (fold proc seed (%bucket-ref table i)))))))
  3960. (define (%hash-fold proc init table)
  3961. (%hash-fold-handles (lambda (h seed) (proc (car h) (cdr h) seed))
  3962. init
  3963. table))
  3964. ;; Weak key hashtables
  3965. (define (make-weak-key-hashtable)
  3966. (%inline-wasm
  3967. '(func (result (ref eq))
  3968. (struct.new $weak-table
  3969. (i32.const 0)
  3970. (call $make-weak-map)))))
  3971. (define (weak-key-hashtable? obj)
  3972. (%inline-wasm
  3973. '(func (param $obj (ref eq)) (result (ref eq))
  3974. (if (ref eq)
  3975. (ref.test $weak-table (local.get $obj))
  3976. (then (ref.i31 (i32.const 17)))
  3977. (else (ref.i31 (i32.const 1)))))
  3978. obj))
  3979. (define* (weak-key-hashtable-ref table key #:optional default)
  3980. (check-type table weak-key-hashtable? 'weak-key-hashtable-ref)
  3981. (%inline-wasm
  3982. '(func (param $table (ref eq)) (param $key (ref eq))
  3983. (param $default (ref eq)) (result (ref eq))
  3984. (call $weak-map-get
  3985. (struct.get $weak-table $val
  3986. (ref.cast $weak-table (local.get $table)))
  3987. (local.get $key)
  3988. (local.get $default)))
  3989. table key default))
  3990. (define (weak-key-hashtable-set! table key value)
  3991. (check-type table weak-key-hashtable? 'weak-key-hashtable-set!)
  3992. (%inline-wasm
  3993. '(func (param $table (ref eq)) (param $key (ref eq)) (param $val (ref eq))
  3994. (call $weak-map-set
  3995. (struct.get $weak-table $val
  3996. (ref.cast $weak-table (local.get $table)))
  3997. (local.get $key)
  3998. (local.get $val)))
  3999. table key value))
  4000. (define (weak-key-hashtable-delete! table key)
  4001. (check-type table weak-key-hashtable? 'weak-key-hashtable-delete!)
  4002. (%inline-wasm
  4003. '(func (param $table (ref eq)) (param $key (ref eq))
  4004. (call $weak-map-delete
  4005. (struct.get $weak-table $val
  4006. (ref.cast $weak-table (local.get $table)))
  4007. (local.get $key))
  4008. (drop))
  4009. table key))
  4010. (cond-expand
  4011. (hoot-main
  4012. (define %exception-handler (make-fluid #f))
  4013. (define (fluid-ref* fluid depth)
  4014. (%inline-wasm
  4015. '(func (param $fluid (ref $fluid)) (param $depth i32)
  4016. (result (ref eq))
  4017. (call $fluid-ref* (local.get $fluid) (local.get $depth)))
  4018. fluid depth))
  4019. ;; FIXME: Use #:key instead
  4020. (define* (with-exception-handler handler thunk
  4021. #:optional keyword (unwind? #f))
  4022. #;
  4023. (unless (procedure? handler)
  4024. (error "not a procedure" handler))
  4025. (cond
  4026. (unwind?
  4027. (let ((tag (make-prompt-tag "exception handler")))
  4028. (call-with-prompt
  4029. tag
  4030. (lambda ()
  4031. (with-fluids ((%exception-handler (cons #t tag)))
  4032. (thunk)))
  4033. (lambda (k exn)
  4034. (handler exn)))))
  4035. (else
  4036. (let ((running? (make-fluid #f)))
  4037. (with-fluids ((%exception-handler (cons running? handler)))
  4038. (thunk))))))
  4039. (let ()
  4040. ;; FIXME: Use #:key instead
  4041. (define* (raise-exception exn #:optional keyword continuable?)
  4042. (let lp ((depth 0))
  4043. ;; FIXME: fluid-ref* takes time proportional to depth, which
  4044. ;; makes this loop quadratic.
  4045. (match (fluid-ref* %exception-handler depth)
  4046. (#f
  4047. ;; No exception handlers bound; fall back.
  4048. (let ((port (current-error-port)))
  4049. (format-exception exn port)
  4050. (newline port)
  4051. (flush-output-port port))
  4052. (%inline-wasm
  4053. '(func (param $exn (ref eq))
  4054. (call $die (string.const "uncaught exception")
  4055. (local.get $exn))
  4056. (unreachable))
  4057. exn))
  4058. ((#t . prompt-tag)
  4059. (abort-to-prompt prompt-tag exn)
  4060. (raise (make-non-continuable-violation)))
  4061. ((running? . handler)
  4062. (if (fluid-ref running?)
  4063. (begin
  4064. (lp (1+ depth)))
  4065. (with-fluids ((running? #t))
  4066. (cond
  4067. (continuable?
  4068. (handler exn))
  4069. (else
  4070. (handler exn)
  4071. (raise (make-non-continuable-violation))))))))))
  4072. (define (make-with-irritants exn message origin irritants)
  4073. (make-exception exn
  4074. (make-exception-with-message message)
  4075. (make-exception-with-origin origin)
  4076. (make-exception-with-irritants irritants)))
  4077. (define-syntax-rule (define-exception-constructor (name arg ...) body ...)
  4078. (cond-expand
  4079. ((and) (define (name arg ...) body ...))
  4080. (else (define (name arg ...) (list arg ...)))))
  4081. (define-exception-constructor (make-size-error val max who)
  4082. (make-with-irritants (make-error) "size out of range" who (list val)))
  4083. (define-exception-constructor (make-index-error val size who)
  4084. (make-with-irritants (make-error) "index out of range" who (list val)))
  4085. (define-exception-constructor (make-range-error val min max who)
  4086. (make-with-irritants (make-error) "value out of range" who (list val)))
  4087. (define-exception-constructor (make-start-offset-error val size who)
  4088. (make-with-irritants (make-error) "start offset out of range" who (list val)))
  4089. (define-exception-constructor (make-end-offset-error val size who)
  4090. (make-with-irritants (make-error) "end offset out of range" who (list val)))
  4091. (define-exception-constructor (make-type-error val who what)
  4092. (make-with-irritants (make-failed-type-check what)
  4093. "type check failed"
  4094. who (list val)))
  4095. (define-exception-constructor (make-unimplemented-error who)
  4096. (make-exception (make-implementation-restriction-violation)
  4097. (make-exception-with-message "unimplemented")
  4098. (make-exception-with-origin who)))
  4099. (define-exception-constructor (make-assertion-error expr who)
  4100. (make-with-irritants (make-assertion-violation) "assertion failed"
  4101. who (list expr)))
  4102. (define-exception-constructor (make-not-seekable-error port who)
  4103. (make-exception (make-i/o-not-seekable-error)
  4104. (make-i/o-port-error port)
  4105. (make-exception-with-origin who)))
  4106. (define-exception-constructor (make-runtime-error-with-message msg)
  4107. (make-exception (make-error) (make-exception-with-message msg)))
  4108. (define-exception-constructor (make-runtime-error-with-message+irritants msg irritants)
  4109. (make-exception (make-error)
  4110. (make-exception-with-message msg)
  4111. (make-exception-with-irritants irritants)))
  4112. (define-exception-constructor (make-match-error v)
  4113. (make-exception (make-assertion-violation)
  4114. (make-exception-with-message "value failed to match")
  4115. (make-exception-with-irritants (list v))))
  4116. (define-exception-constructor (make-arity-error v who)
  4117. (define (annotate-with-origin exn)
  4118. (if who
  4119. (make-exception (make-exception-with-origin who) exn)
  4120. exn))
  4121. (annotate-with-origin
  4122. (make-exception (make-arity-violation)
  4123. (make-exception-with-message "wrong number of arguments")
  4124. (make-exception-with-irritants (list v)))))
  4125. (define-syntax-rule (initialize-globals (global type proc) ...)
  4126. (%inline-wasm
  4127. '(func (param global type) ...
  4128. (global.set global (local.get global)) ...)
  4129. proc ...))
  4130. (define-syntax-rule (initialize-proc-globals (global proc) ...)
  4131. (initialize-globals (global (ref $proc) proc) ...))
  4132. (initialize-proc-globals
  4133. ($with-exception-handler with-exception-handler)
  4134. ($raise-exception raise-exception)
  4135. ($make-size-error make-size-error)
  4136. ($make-index-error make-index-error)
  4137. ($make-range-error make-range-error)
  4138. ($make-start-offset-error make-start-offset-error)
  4139. ($make-end-offset-error make-end-offset-error)
  4140. ($make-type-error make-type-error)
  4141. ($make-unimplemented-error make-unimplemented-error)
  4142. ($make-assertion-error make-assertion-error)
  4143. ($make-not-seekable-error make-not-seekable-error)
  4144. ($make-runtime-error-with-message make-runtime-error-with-message)
  4145. ($make-runtime-error-with-message+irritants make-runtime-error-with-message+irritants)
  4146. ($make-match-error make-match-error)
  4147. ($make-arity-error make-arity-error))))
  4148. (hoot-aux
  4149. (define with-exception-handler
  4150. (%inline-wasm
  4151. '(func (result (ref eq))
  4152. (global.get $with-exception-handler))))))
  4153. (%inline-wasm
  4154. '(func (param $append (ref $proc))
  4155. (global.set $append-primitive (local.get $append)))
  4156. (lambda (x z)
  4157. (let lp ((x x))
  4158. (if (null? x)
  4159. z
  4160. (cons (car x) (lp (cdr x)))))))