12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320 |
- ; Soft Scheme -- Copyright (C) 1993, 1994 Andrew K. Wright
- ;
- ; This program is free software; you can redistribute it and/or modify
- ; it under the terms of the GNU General Public License as published by
- ; the Free Software Foundation; either version 2 of the License, or
- ; (at your option) any later version.
- ;
- ; This program is distributed in the hope that it will be useful,
- ; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ; GNU General Public License for more details.
- ;
- ; You should have received a copy of the GNU General Public License
- ; along with this program; if not, write to the Free Software
- ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ;
- ; Packaged as a single file for Larceny by Lars T Hansen.
- ; Modified 2000-02-15 by lth.
- ;
- ; Compilation notes.
- ;
- ; The macro definitions for MATCH in this file depend on the presence of
- ; certain helper functions in the compilation environment, eg. match:andmap.
- ; (That is not a problem when loading this file, but it is an issue when
- ; compiling it.) The easiest way to provide the helper functions during
- ; compilation is to load match.sch into the compilation environment before
- ; compiling.
- ;
- ; Once compiled, this program is self-contained.
- ; The SoftScheme benchmark performs soft typing on a program and prints
- ; a diagnostic report. All screen output is captured in an output
- ; string port, which is subsequently discarded. (There is a moderate
- ; amount of output). No file I/O occurs while the program is running.
- (define (softscheme-benchmark)
- (let ((expr `(begin ,@(readfile "ss-input.scm")))
- (out (open-output-string)))
- (run-benchmark "softscheme"
- (lambda ()
- (with-output-to-port out
- (lambda ()
- (soft-def expr #f)))))
- (newline)
- (display (string-length (get-output-string out)))
- (display " characters of output written.")
- (newline)))
- ;;; Define defmacro, macro?, and macroexpand-1.
- (define *macros* '())
- (define-syntax
- defmacro
- (transformer
- (lambda (exp rename compare)
- (define (arglist? x)
- (or (symbol? x)
- (null? x)
- (and (pair? x)
- (symbol? (car x))
- (arglist? (cdr x)))))
- (if (not (and (list? exp)
- (>= (length exp) 4)
- (symbol? (cadr exp))
- (arglist? (caddr exp))))
- (error "Bad macro definition: " exp))
- (let ((name (cadr exp))
- (args (caddr exp))
- (body (cdddr exp)))
- `(begin
- (define-syntax
- ,name
- (transformer
- (lambda (_defmacro_exp
- _defmacro_rename
- _defmacro_compare)
- (apply (lambda ,args ,@body) (cdr _defmacro_exp)))))
- (set! *macros*
- (cons (cons ',name
- (lambda (_exp)
- (apply (lambda ,args ,@body) (cdr _exp))))
- *macros*))
- )))))
- (define (macroexpand-1 exp)
- (cond ((pair? exp)
- (let ((probe (assq (car exp) *macros*)))
- (if probe ((cdr probe) exp) exp)))
- (else exp)))
- (define (macro? keyword)
- (and (symbol? keyword) (assq keyword *macros*)))
- ;;; Other compatibility hacks
- (define slib:error error)
- (define force-output flush-output-port)
- (define format
- (let ((format format))
- (lambda (port . rest)
- (if (not port)
- (let ((s (open-output-string)))
- (apply format s rest)
- (get-output-string s))
- (apply format port rest)))))
- (define gentemp
- (let ((gensym gensym)) (lambda () (gensym "G"))))
- (define getenv
- (let ((getenv getenv))
- (lambda (x)
- (or (getenv x)
- (if (string=? x "HOME")
- "Ertevann:Desktop folder:"
- #f)))))
- ;;; The rest of the file should be more or less portable.
- (define match-file #f)
- (define installation-directory #f)
- (define customization-file #f)
- (define fastlibrary-file #f)
- (define st:version
- "Larceny Version 0.18, April 21, 1995")
- (define match:version
- "Version 1.18, July 17, 1995")
- (define match:error
- (lambda (val . args)
- (for-each pretty-print args)
- (slib:error "no matching clause for " val)))
- (define match:andmap
- (lambda (f l)
- (if (null? l)
- (and)
- (and (f (car l)) (match:andmap f (cdr l))))))
- (define match:syntax-err
- (lambda (obj msg) (slib:error msg obj)))
- (define match:disjoint-structure-tags '())
- (define match:make-structure-tag
- (lambda (name)
- (if (or (eq? match:structure-control 'disjoint)
- match:runtime-structures)
- (let ((tag (gentemp)))
- (set! match:disjoint-structure-tags
- (cons tag match:disjoint-structure-tags))
- tag)
- (string->symbol
- (string-append "<" (symbol->string name) ">")))))
- (define match:structure?
- (lambda (tag)
- (memq tag match:disjoint-structure-tags)))
- (define match:structure-control 'vector)
- (define match:set-structure-control
- (lambda (v) (set! match:structure-control v)))
- (define match:set-error
- (lambda (v) (set! match:error v)))
- (define match:error-control 'error)
- (define match:set-error-control
- (lambda (v) (set! match:error-control v)))
- (define match:disjoint-predicates
- (cons 'null
- '(pair? symbol?
- boolean?
- number?
- string?
- char?
- procedure?
- vector?)))
- (define match:vector-structures '())
- (define match:expanders
- (letrec ((genmatch
- (lambda (x clauses match-expr)
- (let* ((length>= (gentemp))
- (eb-errf (error-maker match-expr))
- (blist (car eb-errf))
- (plist (map (lambda (c)
- (let* ((x (bound (validate-pattern
- (car c))))
- (p (car x))
- (bv (cadr x))
- (bindings (caddr x))
- (code (gentemp))
- (fail (and (pair? (cdr c))
- (pair? (cadr c))
- (eq? (caadr c) '=>)
- (symbol? (cadadr c))
- (pair? (cdadr c))
- (null? (cddadr c))
- (pair? (cddr c))
- (cadadr c)))
- (bv2 (if fail (cons fail bv) bv))
- (body (if fail (cddr c) (cdr c))))
- (set! blist
- (cons `(,code (lambda ,bv2 ,@body))
- (append bindings blist)))
- (list p
- code
- bv
- (and fail (gentemp))
- #f)))
- clauses))
- (code (gen x
- '()
- plist
- (cdr eb-errf)
- length>=
- (gentemp))))
- (unreachable plist match-expr)
- (inline-let
- `(let ((,length>=
- (lambda (n) (lambda (l) (>= (length l) n))))
- ,@blist)
- ,code)))))
- (genletrec
- (lambda (pat exp body match-expr)
- (let* ((length>= (gentemp))
- (eb-errf (error-maker match-expr))
- (x (bound (validate-pattern pat)))
- (p (car x))
- (bv (cadr x))
- (bindings (caddr x))
- (code (gentemp))
- (plist (list (list p code bv #f #f)))
- (x (gentemp))
- (m (gen x
- '()
- plist
- (cdr eb-errf)
- length>=
- (gentemp)))
- (gs (map (lambda (_) (gentemp)) bv)))
- (unreachable plist match-expr)
- `(letrec ((,length>=
- (lambda (n) (lambda (l) (>= (length l) n))))
- ,@(map (lambda (v) `(,v #f)) bv)
- (,x ,exp)
- (,code
- (lambda ,gs
- ,@(map (lambda (v g) `(set! ,v ,g)) bv gs)
- ,@body))
- ,@bindings
- ,@(car eb-errf))
- ,m))))
- (gendefine
- (lambda (pat exp match-expr)
- (let* ((length>= (gentemp))
- (eb-errf (error-maker match-expr))
- (x (bound (validate-pattern pat)))
- (p (car x))
- (bv (cadr x))
- (bindings (caddr x))
- (code (gentemp))
- (plist (list (list p code bv #f #f)))
- (x (gentemp))
- (m (gen x
- '()
- plist
- (cdr eb-errf)
- length>=
- (gentemp)))
- (gs (map (lambda (_) (gentemp)) bv)))
- (unreachable plist match-expr)
- `(begin
- ,@(map (lambda (v) `(define ,v #f)) bv)
- ,(inline-let
- `(let ((,length>=
- (lambda (n) (lambda (l) (>= (length l) n))))
- (,x ,exp)
- (,code
- (lambda ,gs
- ,@(map (lambda (v g) `(set! ,v ,g)) bv gs)
- (cond (#f #f))))
- ,@bindings
- ,@(car eb-errf))
- ,m))))))
- (pattern-var?
- (lambda (x)
- (and (symbol? x)
- (not (dot-dot-k? x))
- (not (memq x
- '(quasiquote
- quote
- unquote
- unquote-splicing
- ?
- _
- $
- =
- and
- or
- not
- set!
- get!
- ...
- ___))))))
- (dot-dot-k?
- (lambda (s)
- (and (symbol? s)
- (if (memq s '(... ___))
- 0
- (let* ((s (symbol->string s)) (n (string-length s)))
- (and (<= 3 n)
- (memq (string-ref s 0) '(#\. #\_))
- (memq (string-ref s 1) '(#\. #\_))
- (match:andmap
- char-numeric?
- (string->list (substring s 2 n)))
- (string->number (substring s 2 n))))))))
- (error-maker
- (lambda (match-expr)
- (cond ((eq? match:error-control 'unspecified)
- (cons '() (lambda (x) `(cond (#f #f)))))
- ((memq match:error-control '(error fail))
- (cons '() (lambda (x) `(match:error ,x))))
- ((eq? match:error-control 'match)
- (let ((errf (gentemp)) (arg (gentemp)))
- (cons `((,errf
- (lambda (,arg)
- (match:error ,arg ',match-expr))))
- (lambda (x) `(,errf ,x)))))
- (else
- (match:syntax-err
- '(unspecified error fail match)
- "invalid value for match:error-control, legal values are")))))
- (unreachable
- (lambda (plist match-expr)
- (for-each
- (lambda (x)
- (if (not (car (cddddr x)))
- (begin
- (display "Warning: unreachable pattern ")
- (display (car x))
- (display " in ")
- (display match-expr)
- (newline))))
- plist)))
- (validate-pattern
- (lambda (pattern)
- (letrec ((simple?
- (lambda (x)
- (or (string? x)
- (boolean? x)
- (char? x)
- (number? x)
- (null? x))))
- (ordinary
- (lambda (p)
- (let ((g88 (lambda (x y)
- (cons (ordinary x) (ordinary y)))))
- (if (simple? p)
- ((lambda (p) p) p)
- (if (equal? p '_)
- ((lambda () '_))
- (if (pattern-var? p)
- ((lambda (p) p) p)
- (if (pair? p)
- (if (equal? (car p) 'quasiquote)
- (if (and (pair? (cdr p))
- (null? (cddr p)))
- ((lambda (p) (quasi p)) (cadr p))
- (g88 (car p) (cdr p)))
- (if (equal? (car p) 'quote)
- (if (and (pair? (cdr p))
- (null? (cddr p)))
- ((lambda (p) p) p)
- (g88 (car p) (cdr p)))
- (if (equal? (car p) '?)
- (if (and (pair? (cdr p))
- (list? (cddr p)))
- ((lambda (pred ps)
- `(? ,pred
- ,@(map ordinary ps)))
- (cadr p)
- (cddr p))
- (g88 (car p) (cdr p)))
- (if (equal? (car p) '=)
- (if (and (pair? (cdr p))
- (pair? (cddr p))
- (null? (cdddr p)))
- ((lambda (sel p)
- `(= ,sel ,(ordinary p)))
- (cadr p)
- (caddr p))
- (g88 (car p) (cdr p)))
- (if (equal? (car p) 'and)
- (if (and (list? (cdr p))
- (pair? (cdr p)))
- ((lambda (ps)
- `(and ,@(map ordinary
- ps)))
- (cdr p))
- (g88 (car p) (cdr p)))
- (if (equal? (car p) 'or)
- (if (and (list? (cdr p))
- (pair? (cdr p)))
- ((lambda (ps)
- `(or ,@(map ordinary
- ps)))
- (cdr p))
- (g88 (car p) (cdr p)))
- (if (equal? (car p) 'not)
- (if (and (list? (cdr p))
- (pair? (cdr p)))
- ((lambda (ps)
- `(not ,@(map ordinary
- ps)))
- (cdr p))
- (g88 (car p) (cdr p)))
- (if (equal? (car p) '$)
- (if (and (pair? (cdr p))
- (symbol?
- (cadr p))
- (list? (cddr p)))
- ((lambda (r ps)
- `($ ,r
- ,@(map ordinary
- ps)))
- (cadr p)
- (cddr p))
- (g88 (car p) (cdr p)))
- (if (equal?
- (car p)
- 'set!)
- (if (and (pair? (cdr p))
- (pattern-var?
- (cadr p))
- (null? (cddr p)))
- ((lambda (p) p) p)
- (g88 (car p)
- (cdr p)))
- (if (equal?
- (car p)
- 'get!)
- (if (and (pair? (cdr p))
- (pattern-var?
- (cadr p))
- (null? (cddr p)))
- ((lambda (p) p) p)
- (g88 (car p)
- (cdr p)))
- (if (equal?
- (car p)
- 'unquote)
- (g88 (car p)
- (cdr p))
- (if (equal?
- (car p)
- 'unquote-splicing)
- (g88 (car p)
- (cdr p))
- (if (and (pair? (cdr p))
- (dot-dot-k?
- (cadr p))
- (null? (cddr p)))
- ((lambda (p
- ddk)
- `(,(ordinary
- p)
- ,ddk))
- (car p)
- (cadr p))
- (g88 (car p)
- (cdr p)))))))))))))))
- (if (vector? p)
- ((lambda (p)
- (let* ((pl (vector->list p))
- (rpl (reverse pl)))
- (apply vector
- (if (and (not (null? rpl))
- (dot-dot-k?
- (car rpl)))
- (reverse
- (cons (car rpl)
- (map ordinary
- (cdr rpl))))
- (map ordinary pl)))))
- p)
- ((lambda ()
- (match:syntax-err
- pattern
- "syntax error in pattern")))))))))))
- (quasi (lambda (p)
- (let ((g109 (lambda (x y)
- (cons (quasi x) (quasi y)))))
- (if (simple? p)
- ((lambda (p) p) p)
- (if (symbol? p)
- ((lambda (p) `',p) p)
- (if (pair? p)
- (if (equal? (car p) 'unquote)
- (if (and (pair? (cdr p))
- (null? (cddr p)))
- ((lambda (p) (ordinary p))
- (cadr p))
- (g109 (car p) (cdr p)))
- (if (and (pair? (car p))
- (equal?
- (caar p)
- 'unquote-splicing)
- (pair? (cdar p))
- (null? (cddar p)))
- (if (null? (cdr p))
- ((lambda (p) (ordinary p))
- (cadar p))
- ((lambda (p y)
- (append
- (ordlist p)
- (quasi y)))
- (cadar p)
- (cdr p)))
- (if (and (pair? (cdr p))
- (dot-dot-k? (cadr p))
- (null? (cddr p)))
- ((lambda (p ddk)
- `(,(quasi p) ,ddk))
- (car p)
- (cadr p))
- (g109 (car p) (cdr p)))))
- (if (vector? p)
- ((lambda (p)
- (let* ((pl (vector->list p))
- (rpl (reverse pl)))
- (apply vector
- (if (dot-dot-k?
- (car rpl))
- (reverse
- (cons (car rpl)
- (map quasi
- (cdr rpl))))
- (map ordinary pl)))))
- p)
- ((lambda ()
- (match:syntax-err
- pattern
- "syntax error in pattern"))))))))))
- (ordlist
- (lambda (p)
- (cond ((null? p) '())
- ((pair? p)
- (cons (ordinary (car p)) (ordlist (cdr p))))
- (else
- (match:syntax-err
- pattern
- "invalid use of unquote-splicing in pattern"))))))
- (ordinary pattern))))
- (bound (lambda (pattern)
- (letrec ((pred-bodies '())
- (bound (lambda (p a k)
- (cond ((eq? '_ p) (k p a))
- ((symbol? p)
- (if (memq p a)
- (match:syntax-err
- pattern
- "duplicate variable in pattern"))
- (k p (cons p a)))
- ((and (pair? p)
- (eq? 'quote (car p)))
- (k p a))
- ((and (pair? p) (eq? '? (car p)))
- (cond ((not (null? (cddr p)))
- (bound `(and (? ,(cadr p))
- ,@(cddr p))
- a
- k))
- ((or (not (symbol?
- (cadr p)))
- (memq (cadr p) a))
- (let ((g (gentemp)))
- (set! pred-bodies
- (cons `(,g ,(cadr p))
- pred-bodies))
- (k `(? ,g) a)))
- (else (k p a))))
- ((and (pair? p) (eq? '= (car p)))
- (cond ((or (not (symbol?
- (cadr p)))
- (memq (cadr p) a))
- (let ((g (gentemp)))
- (set! pred-bodies
- (cons `(,g ,(cadr p))
- pred-bodies))
- (bound `(= ,g ,(caddr p))
- a
- k)))
- (else
- (bound (caddr p)
- a
- (lambda (p2 a)
- (k `(= ,(cadr p)
- ,p2)
- a))))))
- ((and (pair? p) (eq? 'and (car p)))
- (bound*
- (cdr p)
- a
- (lambda (p a)
- (k `(and ,@p) a))))
- ((and (pair? p) (eq? 'or (car p)))
- (bound (cadr p)
- a
- (lambda (first-p first-a)
- (let or* ((plist (cddr p))
- (k (lambda (plist)
- (k `(or ,first-p
- ,@plist)
- first-a))))
- (if (null? plist)
- (k plist)
- (bound (car plist)
- a
- (lambda (car-p
- car-a)
- (if (not (permutation
- car-a
- first-a))
- (match:syntax-err
- pattern
- "variables of or-pattern differ in"))
- (or* (cdr plist)
- (lambda (cdr-p)
- (k (cons car-p
- cdr-p)))))))))))
- ((and (pair? p) (eq? 'not (car p)))
- (cond ((not (null? (cddr p)))
- (bound `(not (or ,@(cdr p)))
- a
- k))
- (else
- (bound (cadr p)
- a
- (lambda (p2 a2)
- (if (not (permutation
- a
- a2))
- (match:syntax-err
- p
- "no variables allowed in"))
- (k `(not ,p2)
- a))))))
- ((and (pair? p)
- (pair? (cdr p))
- (dot-dot-k? (cadr p)))
- (bound (car p)
- a
- (lambda (q b)
- (let ((bvars (find-prefix
- b
- a)))
- (k `(,q
- ,(cadr p)
- ,bvars
- ,(gentemp)
- ,(gentemp)
- ,(map (lambda (_)
- (gentemp))
- bvars))
- b)))))
- ((and (pair? p) (eq? '$ (car p)))
- (bound*
- (cddr p)
- a
- (lambda (p1 a)
- (k `($ ,(cadr p) ,@p1) a))))
- ((and (pair? p)
- (eq? 'set! (car p)))
- (if (memq (cadr p) a)
- (k p a)
- (k p (cons (cadr p) a))))
- ((and (pair? p)
- (eq? 'get! (car p)))
- (if (memq (cadr p) a)
- (k p a)
- (k p (cons (cadr p) a))))
- ((pair? p)
- (bound (car p)
- a
- (lambda (car-p a)
- (bound (cdr p)
- a
- (lambda (cdr-p a)
- (k (cons car-p
- cdr-p)
- a))))))
- ((vector? p)
- (boundv
- (vector->list p)
- a
- (lambda (pl a)
- (k (list->vector pl) a))))
- (else (k p a)))))
- (boundv
- (lambda (plist a k)
- (let ((g115 (lambda () (k plist a))))
- (if (pair? plist)
- (if (and (pair? (cdr plist))
- (dot-dot-k? (cadr plist))
- (null? (cddr plist)))
- ((lambda () (bound plist a k)))
- (if (null? plist)
- (g115)
- ((lambda (x y)
- (bound x
- a
- (lambda (car-p a)
- (boundv
- y
- a
- (lambda (cdr-p a)
- (k (cons car-p cdr-p)
- a))))))
- (car plist)
- (cdr plist))))
- (if (null? plist)
- (g115)
- (match:error plist))))))
- (bound*
- (lambda (plist a k)
- (if (null? plist)
- (k plist a)
- (bound (car plist)
- a
- (lambda (car-p a)
- (bound*
- (cdr plist)
- a
- (lambda (cdr-p a)
- (k (cons car-p cdr-p) a))))))))
- (find-prefix
- (lambda (b a)
- (if (eq? b a)
- '()
- (cons (car b) (find-prefix (cdr b) a)))))
- (permutation
- (lambda (p1 p2)
- (and (= (length p1) (length p2))
- (match:andmap
- (lambda (x1) (memq x1 p2))
- p1)))))
- (bound pattern
- '()
- (lambda (p a)
- (list p (reverse a) pred-bodies))))))
- (inline-let
- (lambda (let-exp)
- (letrec ((occ (lambda (x e)
- (let loop ((e e))
- (cond ((pair? e)
- (+ (loop (car e)) (loop (cdr e))))
- ((eq? x e) 1)
- (else 0)))))
- (subst (lambda (e old new)
- (let loop ((e e))
- (cond ((pair? e)
- (cons (loop (car e)) (loop (cdr e))))
- ((eq? old e) new)
- (else e)))))
- (const?
- (lambda (sexp)
- (or (symbol? sexp)
- (boolean? sexp)
- (string? sexp)
- (char? sexp)
- (number? sexp)
- (null? sexp)
- (and (pair? sexp)
- (eq? (car sexp) 'quote)
- (pair? (cdr sexp))
- (symbol? (cadr sexp))
- (null? (cddr sexp))))))
- (isval?
- (lambda (sexp)
- (or (const? sexp)
- (and (pair? sexp)
- (memq (car sexp)
- '(lambda quote
- match-lambda
- match-lambda*))))))
- (small?
- (lambda (sexp)
- (or (const? sexp)
- (and (pair? sexp)
- (eq? (car sexp) 'lambda)
- (pair? (cdr sexp))
- (pair? (cddr sexp))
- (const? (caddr sexp))
- (null? (cdddr sexp)))))))
- (let loop ((b (cadr let-exp))
- (new-b '())
- (e (caddr let-exp)))
- (cond ((null? b)
- (if (null? new-b) e `(let ,(reverse new-b) ,e)))
- ((isval? (cadr (car b)))
- (let* ((x (caar b)) (n (occ x e)))
- (cond ((= 0 n) (loop (cdr b) new-b e))
- ((or (= 1 n) (small? (cadr (car b))))
- (loop (cdr b)
- new-b
- (subst e x (cadr (car b)))))
- (else
- (loop (cdr b) (cons (car b) new-b) e)))))
- (else (loop (cdr b) (cons (car b) new-b) e)))))))
- (gen (lambda (x sf plist erract length>= eta)
- (if (null? plist)
- (erract x)
- (let* ((v '())
- (val (lambda (x) (cdr (assq x v))))
- (fail (lambda (sf)
- (gen x sf (cdr plist) erract length>= eta)))
- (success
- (lambda (sf)
- (set-car! (cddddr (car plist)) #t)
- (let* ((code (cadr (car plist)))
- (bv (caddr (car plist)))
- (fail-sym (cadddr (car plist))))
- (if fail-sym
- (let ((ap `(,code
- ,fail-sym
- ,@(map val bv))))
- `(call-with-current-continuation
- (lambda (,fail-sym)
- (let ((,fail-sym
- (lambda ()
- (,fail-sym ,(fail sf)))))
- ,ap))))
- `(,code ,@(map val bv)))))))
- (let next ((p (caar plist))
- (e x)
- (sf sf)
- (kf fail)
- (ks success))
- (cond ((eq? '_ p) (ks sf))
- ((symbol? p)
- (set! v (cons (cons p e) v))
- (ks sf))
- ((null? p) (emit `(null? ,e) sf kf ks))
- ((equal? p ''()) (emit `(null? ,e) sf kf ks))
- ((string? p) (emit `(equal? ,e ,p) sf kf ks))
- ((boolean? p) (emit `(equal? ,e ,p) sf kf ks))
- ((char? p) (emit `(equal? ,e ,p) sf kf ks))
- ((number? p) (emit `(equal? ,e ,p) sf kf ks))
- ((and (pair? p) (eq? 'quote (car p)))
- (emit `(equal? ,e ,p) sf kf ks))
- ((and (pair? p) (eq? '? (car p)))
- (let ((tst `(,(cadr p) ,e)))
- (emit tst sf kf ks)))
- ((and (pair? p) (eq? '= (car p)))
- (next (caddr p) `(,(cadr p) ,e) sf kf ks))
- ((and (pair? p) (eq? 'and (car p)))
- (let loop ((p (cdr p)) (sf sf))
- (if (null? p)
- (ks sf)
- (next (car p)
- e
- sf
- kf
- (lambda (sf) (loop (cdr p) sf))))))
- ((and (pair? p) (eq? 'or (car p)))
- (let ((or-v v))
- (let loop ((p (cdr p)) (sf sf))
- (if (null? p)
- (kf sf)
- (begin
- (set! v or-v)
- (next (car p)
- e
- sf
- (lambda (sf) (loop (cdr p) sf))
- ks))))))
- ((and (pair? p) (eq? 'not (car p)))
- (next (cadr p) e sf ks kf))
- ((and (pair? p) (eq? '$ (car p)))
- (let* ((tag (cadr p))
- (fields (cdr p))
- (rlen (length fields))
- (tst `(,(symbol-append tag '?) ,e)))
- (emit tst
- sf
- kf
- (let rloop ((n 1))
- (lambda (sf)
- (if (= n rlen)
- (ks sf)
- (next (list-ref fields n)
- `(,(symbol-append tag '- n)
- ,e)
- sf
- kf
- (rloop (+ 1 n)))))))))
- ((and (pair? p) (eq? 'set! (car p)))
- (set! v (cons (cons (cadr p) (setter e p)) v))
- (ks sf))
- ((and (pair? p) (eq? 'get! (car p)))
- (set! v (cons (cons (cadr p) (getter e p)) v))
- (ks sf))
- ((and (pair? p)
- (pair? (cdr p))
- (dot-dot-k? (cadr p)))
- (emit `(list? ,e)
- sf
- kf
- (lambda (sf)
- (let* ((k (dot-dot-k? (cadr p)))
- (ks (lambda (sf)
- (let ((bound (list-ref
- p
- 2)))
- (cond ((eq? (car p) '_)
- (ks sf))
- ((null? bound)
- (let* ((ptst (next (car p)
- eta
- sf
- (lambda (sf)
- #f)
- (lambda (sf)
- #t)))
- (tst (if (and (pair? ptst)
- (symbol?
- (car ptst))
- (pair? (cdr ptst))
- (eq? eta
- (cadr ptst))
- (null? (cddr ptst)))
- (car ptst)
- `(lambda (,eta)
- ,ptst))))
- (assm `(match:andmap
- ,tst
- ,e)
- (kf sf)
- (ks sf))))
- ((and (symbol?
- (car p))
- (equal?
- (list (car p))
- bound))
- (next (car p)
- e
- sf
- kf
- ks))
- (else
- (let* ((gloop (list-ref
- p
- 3))
- (ge (list-ref
- p
- 4))
- (fresh (list-ref
- p
- 5))
- (p1 (next (car p)
- `(car ,ge)
- sf
- kf
- (lambda (sf)
- `(,gloop
- (cdr ,ge)
- ,@(map (lambda (b
- f)
- `(cons ,(val b)
- ,f))
- bound
- fresh))))))
- (set! v
- (append
- (map cons
- bound
- (map (lambda (x)
- `(reverse
- ,x))
- fresh))
- v))
- `(let ,gloop
- ((,ge ,e)
- ,@(map (lambda (x)
- `(,x
- '()))
- fresh))
- (if (null? ,ge)
- ,(ks sf)
- ,p1)))))))))
- (case k
- ((0) (ks sf))
- ((1) (emit `(pair? ,e) sf kf ks))
- (else
- (emit `((,length>= ,k) ,e)
- sf
- kf
- ks)))))))
- ((pair? p)
- (emit `(pair? ,e)
- sf
- kf
- (lambda (sf)
- (next (car p)
- (add-a e)
- sf
- kf
- (lambda (sf)
- (next (cdr p)
- (add-d e)
- sf
- kf
- ks))))))
- ((and (vector? p)
- (>= (vector-length p) 6)
- (dot-dot-k?
- (vector-ref p (- (vector-length p) 5))))
- (let* ((vlen (- (vector-length p) 6))
- (k (dot-dot-k?
- (vector-ref p (+ vlen 1))))
- (minlen (+ vlen k))
- (bound (vector-ref p (+ vlen 2))))
- (emit `(vector? ,e)
- sf
- kf
- (lambda (sf)
- (assm `(>= (vector-length ,e) ,minlen)
- (kf sf)
- ((let vloop ((n 0))
- (lambda (sf)
- (cond ((not (= n vlen))
- (next (vector-ref
- p
- n)
- `(vector-ref
- ,e
- ,n)
- sf
- kf
- (vloop (+ 1
- n))))
- ((eq? (vector-ref
- p
- vlen)
- '_)
- (ks sf))
- (else
- (let* ((gloop (vector-ref
- p
- (+ vlen
- 3)))
- (ind (vector-ref
- p
- (+ vlen
- 4)))
- (fresh (vector-ref
- p
- (+ vlen
- 5)))
- (p1 (next (vector-ref
- p
- vlen)
- `(vector-ref
- ,e
- ,ind)
- sf
- kf
- (lambda (sf)
- `(,gloop
- (- ,ind
- 1)
- ,@(map (lambda (b
- f)
- `(cons ,(val b)
- ,f))
- bound
- fresh))))))
- (set! v
- (append
- (map cons
- bound
- fresh)
- v))
- `(let ,gloop
- ((,ind
- (- (vector-length
- ,e)
- 1))
- ,@(map (lambda (x)
- `(,x
- '()))
- fresh))
- (if (> ,minlen
- ,ind)
- ,(ks sf)
- ,p1)))))))
- sf))))))
- ((vector? p)
- (let ((vlen (vector-length p)))
- (emit `(vector? ,e)
- sf
- kf
- (lambda (sf)
- (emit `(equal?
- (vector-length ,e)
- ,vlen)
- sf
- kf
- (let vloop ((n 0))
- (lambda (sf)
- (if (= n vlen)
- (ks sf)
- (next (vector-ref p n)
- `(vector-ref ,e ,n)
- sf
- kf
- (vloop (+ 1
- n)))))))))))
- (else
- (display "FATAL ERROR IN PATTERN MATCHER")
- (newline)
- (error #f "THIS NEVER HAPPENS"))))))))
- (emit (lambda (tst sf kf ks)
- (cond ((in tst sf) (ks sf))
- ((in `(not ,tst) sf) (kf sf))
- (else
- (let* ((e (cadr tst))
- (implied
- (cond ((eq? (car tst) 'equal?)
- (let ((p (caddr tst)))
- (cond ((string? p) `((string? ,e)))
- ((boolean? p)
- `((boolean? ,e)))
- ((char? p) `((char? ,e)))
- ((number? p) `((number? ,e)))
- ((and (pair? p)
- (eq? 'quote (car p)))
- `((symbol? ,e)))
- (else '()))))
- ((eq? (car tst) 'null?) `((list? ,e)))
- ((vec-structure? tst) `((vector? ,e)))
- (else '())))
- (not-imp
- (case (car tst)
- ((list?) `((not (null? ,e))))
- (else '())))
- (s (ks (cons tst (append implied sf))))
- (k (kf (cons `(not ,tst)
- (append not-imp sf)))))
- (assm tst k s))))))
- (assm (lambda (tst f s)
- (cond ((equal? s f) s)
- ((and (eq? s #t) (eq? f #f)) tst)
- ((and (eq? (car tst) 'pair?)
- (memq match:error-control '(unspecified fail))
- (memq (car f) '(cond match:error))
- (guarantees s (cadr tst)))
- s)
- ((and (pair? s)
- (eq? (car s) 'if)
- (equal? (cadddr s) f))
- (if (eq? (car (cadr s)) 'and)
- `(if (and ,tst ,@(cdr (cadr s))) ,(caddr s) ,f)
- `(if (and ,tst ,(cadr s)) ,(caddr s) ,f)))
- ((and (pair? s)
- (equal? (car s) 'call-with-current-continuation)
- (pair? (cdr s))
- (pair? (cadr s))
- (equal? (caadr s) 'lambda)
- (pair? (cdadr s))
- (pair? (cadadr s))
- (null? (cdr (cadadr s)))
- (pair? (cddadr s))
- (pair? (car (cddadr s)))
- (equal? (caar (cddadr s)) 'let)
- (pair? (cdar (cddadr s)))
- (pair? (cadar (cddadr s)))
- (pair? (caadar (cddadr s)))
- (pair? (cdr (caadar (cddadr s))))
- (pair? (cadr (caadar (cddadr s))))
- (equal? (caadr (caadar (cddadr s))) 'lambda)
- (pair? (cdadr (caadar (cddadr s))))
- (null? (cadadr (caadar (cddadr s))))
- (pair? (cddadr (caadar (cddadr s))))
- (pair? (car (cddadr (caadar (cddadr s)))))
- (pair? (cdar (cddadr (caadar (cddadr s)))))
- (null? (cddar (cddadr (caadar (cddadr s)))))
- (null? (cdr (cddadr (caadar (cddadr s)))))
- (null? (cddr (caadar (cddadr s))))
- (null? (cdadar (cddadr s)))
- (pair? (cddar (cddadr s)))
- (null? (cdddar (cddadr s)))
- (null? (cdr (cddadr s)))
- (null? (cddr s))
- (equal? f (cadar (cddadr (caadar (cddadr s))))))
- (let ((k (car (cadadr s)))
- (fail (car (caadar (cddadr s))))
- (s2 (caddar (cddadr s))))
- `(call-with-current-continuation
- (lambda (,k)
- (let ((,fail (lambda () (,k ,f))))
- ,(assm tst `(,fail) s2))))))
- ((and #f
- (pair? s)
- (equal? (car s) 'let)
- (pair? (cdr s))
- (pair? (cadr s))
- (pair? (caadr s))
- (pair? (cdaadr s))
- (pair? (car (cdaadr s)))
- (equal? (caar (cdaadr s)) 'lambda)
- (pair? (cdar (cdaadr s)))
- (null? (cadar (cdaadr s)))
- (pair? (cddar (cdaadr s)))
- (null? (cdddar (cdaadr s)))
- (null? (cdr (cdaadr s)))
- (null? (cdadr s))
- (pair? (cddr s))
- (null? (cdddr s))
- (equal? (caddar (cdaadr s)) f))
- (let ((fail (caaadr s)) (s2 (caddr s)))
- `(let ((,fail (lambda () ,f)))
- ,(assm tst `(,fail) s2))))
- (else `(if ,tst ,s ,f)))))
- (guarantees
- (lambda (code x)
- (let ((a (add-a x)) (d (add-d x)))
- (let loop ((code code))
- (cond ((not (pair? code)) #f)
- ((memq (car code) '(cond match:error)) #t)
- ((or (equal? code a) (equal? code d)) #t)
- ((eq? (car code) 'if)
- (or (loop (cadr code))
- (and (loop (caddr code)) (loop (cadddr code)))))
- ((eq? (car code) 'lambda) #f)
- ((and (eq? (car code) 'let) (symbol? (cadr code)))
- #f)
- (else (or (loop (car code)) (loop (cdr code)))))))))
- (in (lambda (e l)
- (or (member e l)
- (and (eq? (car e) 'list?)
- (or (member `(null? ,(cadr e)) l)
- (member `(pair? ,(cadr e)) l)))
- (and (eq? (car e) 'not)
- (let* ((srch (cadr e))
- (const-class (equal-test? srch)))
- (cond (const-class
- (let mem ((l l))
- (if (null? l)
- #f
- (let ((x (car l)))
- (or (and (equal? (cadr x) (cadr srch))
- (disjoint? x)
- (not (equal?
- const-class
- (car x))))
- (equal?
- x
- `(not (,const-class
- ,(cadr srch))))
- (and (equal? (cadr x) (cadr srch))
- (equal-test? x)
- (not (equal?
- (caddr srch)
- (caddr x))))
- (mem (cdr l)))))))
- ((disjoint? srch)
- (let mem ((l l))
- (if (null? l)
- #f
- (let ((x (car l)))
- (or (and (equal? (cadr x) (cadr srch))
- (disjoint? x)
- (not (equal?
- (car x)
- (car srch))))
- (mem (cdr l)))))))
- ((eq? (car srch) 'list?)
- (let mem ((l l))
- (if (null? l)
- #f
- (let ((x (car l)))
- (or (and (equal? (cadr x) (cadr srch))
- (disjoint? x)
- (not (memq (car x)
- '(list? pair?
- null?))))
- (mem (cdr l)))))))
- ((vec-structure? srch)
- (let mem ((l l))
- (if (null? l)
- #f
- (let ((x (car l)))
- (or (and (equal? (cadr x) (cadr srch))
- (or (disjoint? x)
- (vec-structure? x))
- (not (equal?
- (car x)
- 'vector?))
- (not (equal?
- (car x)
- (car srch))))
- (equal?
- x
- `(not (vector? ,(cadr srch))))
- (mem (cdr l)))))))
- (else #f)))))))
- (equal-test?
- (lambda (tst)
- (and (eq? (car tst) 'equal?)
- (let ((p (caddr tst)))
- (cond ((string? p) 'string?)
- ((boolean? p) 'boolean?)
- ((char? p) 'char?)
- ((number? p) 'number?)
- ((and (pair? p)
- (pair? (cdr p))
- (null? (cddr p))
- (eq? 'quote (car p))
- (symbol? (cadr p)))
- 'symbol?)
- (else #f))))))
- (disjoint?
- (lambda (tst)
- (memq (car tst) match:disjoint-predicates)))
- (vec-structure?
- (lambda (tst)
- (memq (car tst) match:vector-structures)))
- (add-a (lambda (a)
- (let ((new (and (pair? a) (assq (car a) c---rs))))
- (if new (cons (cadr new) (cdr a)) `(car ,a)))))
- (add-d (lambda (a)
- (let ((new (and (pair? a) (assq (car a) c---rs))))
- (if new (cons (cddr new) (cdr a)) `(cdr ,a)))))
- (c---rs
- '((car caar . cdar)
- (cdr cadr . cddr)
- (caar caaar . cdaar)
- (cadr caadr . cdadr)
- (cdar cadar . cddar)
- (cddr caddr . cdddr)
- (caaar caaaar . cdaaar)
- (caadr caaadr . cdaadr)
- (cadar caadar . cdadar)
- (caddr caaddr . cdaddr)
- (cdaar cadaar . cddaar)
- (cdadr cadadr . cddadr)
- (cddar caddar . cdddar)
- (cdddr cadddr . cddddr)))
- (setter
- (lambda (e p)
- (let ((mk-setter
- (lambda (s) (symbol-append 'set- s '!))))
- (cond ((not (pair? e))
- (match:syntax-err p "unnested set! pattern"))
- ((eq? (car e) 'vector-ref)
- `(let ((x ,(cadr e)))
- (lambda (y) (vector-set! x ,(caddr e) y))))
- ((eq? (car e) 'unbox)
- `(let ((x ,(cadr e))) (lambda (y) (set-box! x y))))
- ((eq? (car e) 'car)
- `(let ((x ,(cadr e))) (lambda (y) (set-car! x y))))
- ((eq? (car e) 'cdr)
- `(let ((x ,(cadr e))) (lambda (y) (set-cdr! x y))))
- ((let ((a (assq (car e) get-c---rs)))
- (and a
- `(let ((x (,(cadr a) ,(cadr e))))
- (lambda (y) (,(mk-setter (cddr a)) x y))))))
- (else
- `(let ((x ,(cadr e)))
- (lambda (y) (,(mk-setter (car e)) x y))))))))
- (getter
- (lambda (e p)
- (cond ((not (pair? e))
- (match:syntax-err p "unnested get! pattern"))
- ((eq? (car e) 'vector-ref)
- `(let ((x ,(cadr e)))
- (lambda () (vector-ref x ,(caddr e)))))
- ((eq? (car e) 'unbox)
- `(let ((x ,(cadr e))) (lambda () (unbox x))))
- ((eq? (car e) 'car)
- `(let ((x ,(cadr e))) (lambda () (car x))))
- ((eq? (car e) 'cdr)
- `(let ((x ,(cadr e))) (lambda () (cdr x))))
- ((let ((a (assq (car e) get-c---rs)))
- (and a
- `(let ((x (,(cadr a) ,(cadr e))))
- (lambda () (,(cddr a) x))))))
- (else
- `(let ((x ,(cadr e))) (lambda () (,(car e) x)))))))
- (get-c---rs
- '((caar car . car)
- (cadr cdr . car)
- (cdar car . cdr)
- (cddr cdr . cdr)
- (caaar caar . car)
- (caadr cadr . car)
- (cadar cdar . car)
- (caddr cddr . car)
- (cdaar caar . cdr)
- (cdadr cadr . cdr)
- (cddar cdar . cdr)
- (cdddr cddr . cdr)
- (caaaar caaar . car)
- (caaadr caadr . car)
- (caadar cadar . car)
- (caaddr caddr . car)
- (cadaar cdaar . car)
- (cadadr cdadr . car)
- (caddar cddar . car)
- (cadddr cdddr . car)
- (cdaaar caaar . cdr)
- (cdaadr caadr . cdr)
- (cdadar cadar . cdr)
- (cdaddr caddr . cdr)
- (cddaar cdaar . cdr)
- (cddadr cdadr . cdr)
- (cdddar cddar . cdr)
- (cddddr cdddr . cdr)))
- (symbol-append
- (lambda l
- (string->symbol
- (apply string-append
- (map (lambda (x)
- (cond ((symbol? x) (symbol->string x))
- ((number? x) (number->string x))
- (else x)))
- l)))))
- (rac (lambda (l)
- (if (null? (cdr l)) (car l) (rac (cdr l)))))
- (rdc (lambda (l)
- (if (null? (cdr l))
- '()
- (cons (car l) (rdc (cdr l)))))))
- (list genmatch genletrec gendefine pattern-var?)))
- (defmacro
- match
- args
- (cond ((and (list? args)
- (<= 1 (length args))
- (match:andmap
- (lambda (y) (and (list? y) (<= 2 (length y))))
- (cdr args)))
- (let* ((exp (car args))
- (clauses (cdr args))
- (e (if (symbol? exp) exp (gentemp))))
- (if (symbol? exp)
- ((car match:expanders) e clauses `(match ,@args))
- `(let ((,e ,exp))
- ,((car match:expanders) e clauses `(match ,@args))))))
- (else
- (match:syntax-err
- `(match ,@args)
- "syntax error in"))))
- (defmacro
- match-lambda
- args
- (if (and (list? args)
- (match:andmap
- (lambda (g126)
- (if (and (pair? g126) (list? (cdr g126)))
- (pair? (cdr g126))
- #f))
- args))
- ((lambda ()
- (let ((e (gentemp)))
- `(lambda (,e) (match ,e ,@args)))))
- ((lambda ()
- (match:syntax-err
- `(match-lambda ,@args)
- "syntax error in")))))
- (defmacro
- match-lambda*
- args
- (if (and (list? args)
- (match:andmap
- (lambda (g134)
- (if (and (pair? g134) (list? (cdr g134)))
- (pair? (cdr g134))
- #f))
- args))
- ((lambda ()
- (let ((e (gentemp)))
- `(lambda ,e (match ,e ,@args)))))
- ((lambda ()
- (match:syntax-err
- `(match-lambda* ,@args)
- "syntax error in")))))
- (defmacro
- match-let
- args
- (let ((g158 (lambda (pat exp body)
- `(match ,exp (,pat ,@body))))
- (g154 (lambda (pat exp body)
- (let ((g (map (lambda (x) (gentemp)) pat))
- (vpattern (list->vector pat)))
- `(let ,(map list g exp)
- (match (vector ,@g) (,vpattern ,@body))))))
- (g146 (lambda ()
- (match:syntax-err
- `(match-let ,@args)
- "syntax error in")))
- (g145 (lambda (p1 e1 p2 e2 body)
- (let ((g1 (gentemp)) (g2 (gentemp)))
- `(let ((,g1 ,e1) (,g2 ,e2))
- (match (cons ,g1 ,g2) ((,p1 unquote p2) ,@body))))))
- (g136 (cadddr match:expanders)))
- (if (pair? args)
- (if (symbol? (car args))
- (if (and (pair? (cdr args)) (list? (cadr args)))
- (let g161 ((g162 (cadr args)) (g160 '()) (g159 '()))
- (if (null? g162)
- (if (and (list? (cddr args)) (pair? (cddr args)))
- ((lambda (name pat exp body)
- (if (match:andmap (cadddr match:expanders) pat)
- `(let ,@args)
- `(letrec ((,name (match-lambda* (,pat ,@body))))
- (,name ,@exp))))
- (car args)
- (reverse g159)
- (reverse g160)
- (cddr args))
- (g146))
- (if (and (pair? (car g162))
- (pair? (cdar g162))
- (null? (cddar g162)))
- (g161 (cdr g162)
- (cons (cadar g162) g160)
- (cons (caar g162) g159))
- (g146))))
- (g146))
- (if (list? (car args))
- (if (match:andmap
- (lambda (g167)
- (if (and (pair? g167)
- (g136 (car g167))
- (pair? (cdr g167)))
- (null? (cddr g167))
- #f))
- (car args))
- (if (and (list? (cdr args)) (pair? (cdr args)))
- ((lambda () `(let ,@args)))
- (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
- (if (null? g150)
- (g146)
- (if (and (pair? (car g150))
- (pair? (cdar g150))
- (null? (cddar g150)))
- (g149 (cdr g150)
- (cons (cadar g150) g148)
- (cons (caar g150) g147))
- (g146)))))
- (if (and (pair? (car args))
- (pair? (caar args))
- (pair? (cdaar args))
- (null? (cddaar args)))
- (if (null? (cdar args))
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g158 (caaar args) (cadaar args) (cdr args))
- (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
- (if (null? g150)
- (g146)
- (if (and (pair? (car g150))
- (pair? (cdar g150))
- (null? (cddar g150)))
- (g149 (cdr g150)
- (cons (cadar g150) g148)
- (cons (caar g150) g147))
- (g146)))))
- (if (and (pair? (cdar args))
- (pair? (cadar args))
- (pair? (cdadar args))
- (null? (cdr (cdadar args)))
- (null? (cddar args)))
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g145 (caaar args)
- (cadaar args)
- (caadar args)
- (car (cdadar args))
- (cdr args))
- (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
- (if (null? g150)
- (g146)
- (if (and (pair? (car g150))
- (pair? (cdar g150))
- (null? (cddar g150)))
- (g149 (cdr g150)
- (cons (cadar g150) g148)
- (cons (caar g150) g147))
- (g146)))))
- (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
- (if (null? g150)
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g154 (reverse g147) (reverse g148) (cdr args))
- (g146))
- (if (and (pair? (car g150))
- (pair? (cdar g150))
- (null? (cddar g150)))
- (g149 (cdr g150)
- (cons (cadar g150) g148)
- (cons (caar g150) g147))
- (g146))))))
- (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
- (if (null? g150)
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g154 (reverse g147) (reverse g148) (cdr args))
- (g146))
- (if (and (pair? (car g150))
- (pair? (cdar g150))
- (null? (cddar g150)))
- (g149 (cdr g150)
- (cons (cadar g150) g148)
- (cons (caar g150) g147))
- (g146))))))
- (if (pair? (car args))
- (if (and (pair? (caar args))
- (pair? (cdaar args))
- (null? (cddaar args)))
- (if (null? (cdar args))
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g158 (caaar args) (cadaar args) (cdr args))
- (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
- (if (null? g150)
- (g146)
- (if (and (pair? (car g150))
- (pair? (cdar g150))
- (null? (cddar g150)))
- (g149 (cdr g150)
- (cons (cadar g150) g148)
- (cons (caar g150) g147))
- (g146)))))
- (if (and (pair? (cdar args))
- (pair? (cadar args))
- (pair? (cdadar args))
- (null? (cdr (cdadar args)))
- (null? (cddar args)))
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g145 (caaar args)
- (cadaar args)
- (caadar args)
- (car (cdadar args))
- (cdr args))
- (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
- (if (null? g150)
- (g146)
- (if (and (pair? (car g150))
- (pair? (cdar g150))
- (null? (cddar g150)))
- (g149 (cdr g150)
- (cons (cadar g150) g148)
- (cons (caar g150) g147))
- (g146)))))
- (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
- (if (null? g150)
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g154 (reverse g147) (reverse g148) (cdr args))
- (g146))
- (if (and (pair? (car g150))
- (pair? (cdar g150))
- (null? (cddar g150)))
- (g149 (cdr g150)
- (cons (cadar g150) g148)
- (cons (caar g150) g147))
- (g146))))))
- (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
- (if (null? g150)
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g154 (reverse g147) (reverse g148) (cdr args))
- (g146))
- (if (and (pair? (car g150))
- (pair? (cdar g150))
- (null? (cddar g150)))
- (g149 (cdr g150)
- (cons (cadar g150) g148)
- (cons (caar g150) g147))
- (g146)))))
- (g146))))
- (g146))))
- (defmacro
- match-let*
- args
- (let ((g176 (lambda ()
- (match:syntax-err
- `(match-let* ,@args)
- "syntax error in"))))
- (if (pair? args)
- (if (null? (car args))
- (if (and (list? (cdr args)) (pair? (cdr args)))
- ((lambda (body) `(let* ,@args)) (cdr args))
- (g176))
- (if (and (pair? (car args))
- (pair? (caar args))
- (pair? (cdaar args))
- (null? (cddaar args))
- (list? (cdar args))
- (list? (cdr args))
- (pair? (cdr args)))
- ((lambda (pat exp rest body)
- (if ((cadddr match:expanders) pat)
- `(let ((,pat ,exp)) (match-let* ,rest ,@body))
- `(match ,exp (,pat (match-let* ,rest ,@body)))))
- (caaar args)
- (cadaar args)
- (cdar args)
- (cdr args))
- (g176)))
- (g176))))
- (defmacro
- match-letrec
- args
- (let ((g200 (cadddr match:expanders))
- (g199 (lambda (p1 e1 p2 e2 body)
- `(match-letrec
- (((,p1 unquote p2) (cons ,e1 ,e2)))
- ,@body)))
- (g195 (lambda ()
- (match:syntax-err
- `(match-letrec ,@args)
- "syntax error in")))
- (g194 (lambda (pat exp body)
- `(match-letrec
- ((,(list->vector pat) (vector ,@exp)))
- ,@body)))
- (g186 (lambda (pat exp body)
- ((cadr match:expanders)
- pat
- exp
- body
- `(match-letrec ((,pat ,exp)) ,@body)))))
- (if (pair? args)
- (if (list? (car args))
- (if (match:andmap
- (lambda (g206)
- (if (and (pair? g206)
- (g200 (car g206))
- (pair? (cdr g206)))
- (null? (cddr g206))
- #f))
- (car args))
- (if (and (list? (cdr args)) (pair? (cdr args)))
- ((lambda () `(letrec ,@args)))
- (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
- (if (null? g190)
- (g195)
- (if (and (pair? (car g190))
- (pair? (cdar g190))
- (null? (cddar g190)))
- (g189 (cdr g190)
- (cons (cadar g190) g188)
- (cons (caar g190) g187))
- (g195)))))
- (if (and (pair? (car args))
- (pair? (caar args))
- (pair? (cdaar args))
- (null? (cddaar args)))
- (if (null? (cdar args))
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g186 (caaar args) (cadaar args) (cdr args))
- (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
- (if (null? g190)
- (g195)
- (if (and (pair? (car g190))
- (pair? (cdar g190))
- (null? (cddar g190)))
- (g189 (cdr g190)
- (cons (cadar g190) g188)
- (cons (caar g190) g187))
- (g195)))))
- (if (and (pair? (cdar args))
- (pair? (cadar args))
- (pair? (cdadar args))
- (null? (cdr (cdadar args)))
- (null? (cddar args)))
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g199 (caaar args)
- (cadaar args)
- (caadar args)
- (car (cdadar args))
- (cdr args))
- (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
- (if (null? g190)
- (g195)
- (if (and (pair? (car g190))
- (pair? (cdar g190))
- (null? (cddar g190)))
- (g189 (cdr g190)
- (cons (cadar g190) g188)
- (cons (caar g190) g187))
- (g195)))))
- (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
- (if (null? g190)
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g194 (reverse g187) (reverse g188) (cdr args))
- (g195))
- (if (and (pair? (car g190))
- (pair? (cdar g190))
- (null? (cddar g190)))
- (g189 (cdr g190)
- (cons (cadar g190) g188)
- (cons (caar g190) g187))
- (g195))))))
- (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
- (if (null? g190)
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g194 (reverse g187) (reverse g188) (cdr args))
- (g195))
- (if (and (pair? (car g190))
- (pair? (cdar g190))
- (null? (cddar g190)))
- (g189 (cdr g190)
- (cons (cadar g190) g188)
- (cons (caar g190) g187))
- (g195))))))
- (if (pair? (car args))
- (if (and (pair? (caar args))
- (pair? (cdaar args))
- (null? (cddaar args)))
- (if (null? (cdar args))
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g186 (caaar args) (cadaar args) (cdr args))
- (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
- (if (null? g190)
- (g195)
- (if (and (pair? (car g190))
- (pair? (cdar g190))
- (null? (cddar g190)))
- (g189 (cdr g190)
- (cons (cadar g190) g188)
- (cons (caar g190) g187))
- (g195)))))
- (if (and (pair? (cdar args))
- (pair? (cadar args))
- (pair? (cdadar args))
- (null? (cdr (cdadar args)))
- (null? (cddar args)))
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g199 (caaar args)
- (cadaar args)
- (caadar args)
- (car (cdadar args))
- (cdr args))
- (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
- (if (null? g190)
- (g195)
- (if (and (pair? (car g190))
- (pair? (cdar g190))
- (null? (cddar g190)))
- (g189 (cdr g190)
- (cons (cadar g190) g188)
- (cons (caar g190) g187))
- (g195)))))
- (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
- (if (null? g190)
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g194 (reverse g187) (reverse g188) (cdr args))
- (g195))
- (if (and (pair? (car g190))
- (pair? (cdar g190))
- (null? (cddar g190)))
- (g189 (cdr g190)
- (cons (cadar g190) g188)
- (cons (caar g190) g187))
- (g195))))))
- (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
- (if (null? g190)
- (if (and (list? (cdr args)) (pair? (cdr args)))
- (g194 (reverse g187) (reverse g188) (cdr args))
- (g195))
- (if (and (pair? (car g190))
- (pair? (cdar g190))
- (null? (cddar g190)))
- (g189 (cdr g190)
- (cons (cadar g190) g188)
- (cons (caar g190) g187))
- (g195)))))
- (g195)))
- (g195))))
- (defmacro
- match-define
- args
- (let ((g210 (cadddr match:expanders))
- (g209 (lambda ()
- (match:syntax-err
- `(match-define ,@args)
- "syntax error in"))))
- (if (pair? args)
- (if (g210 (car args))
- (if (and (pair? (cdr args)) (null? (cddr args)))
- ((lambda () `(begin (define ,@args))))
- (g209))
- (if (and (pair? (cdr args)) (null? (cddr args)))
- ((lambda (pat exp)
- ((caddr match:expanders)
- pat
- exp
- `(match-define ,@args)))
- (car args)
- (cadr args))
- (g209)))
- (g209))))
- (define match:runtime-structures #f)
- (define match:set-runtime-structures
- (lambda (v) (set! match:runtime-structures v)))
- (define match:primitive-vector? vector?)
- (defmacro
- defstruct
- args
- (let ((field?
- (lambda (x)
- (if (symbol? x)
- ((lambda () #t))
- (if (and (pair? x)
- (symbol? (car x))
- (pair? (cdr x))
- (symbol? (cadr x))
- (null? (cddr x)))
- ((lambda () #t))
- ((lambda () #f))))))
- (selector-name
- (lambda (x)
- (if (symbol? x)
- ((lambda () x))
- (if (and (pair? x)
- (symbol? (car x))
- (pair? (cdr x))
- (null? (cddr x)))
- ((lambda (s) s) (car x))
- (match:error x)))))
- (mutator-name
- (lambda (x)
- (if (symbol? x)
- ((lambda () #f))
- (if (and (pair? x)
- (pair? (cdr x))
- (symbol? (cadr x))
- (null? (cddr x)))
- ((lambda (s) s) (cadr x))
- (match:error x)))))
- (filter-map-with-index
- (lambda (f l)
- (letrec ((mapi (lambda (l i)
- (cond ((null? l) '())
- ((f (car l) i)
- =>
- (lambda (x)
- (cons x (mapi (cdr l) (+ 1 i)))))
- (else (mapi (cdr l) (+ 1 i)))))))
- (mapi l 1)))))
- (let ((g227 (lambda ()
- (match:syntax-err
- `(defstruct ,@args)
- "syntax error in"))))
- (if (and (pair? args)
- (symbol? (car args))
- (pair? (cdr args))
- (symbol? (cadr args))
- (pair? (cddr args))
- (symbol? (caddr args))
- (list? (cdddr args)))
- (let g229 ((g230 (cdddr args)) (g228 '()))
- (if (null? g230)
- ((lambda (name constructor predicate fields)
- (let* ((selectors (map selector-name fields))
- (mutators (map mutator-name fields))
- (tag (if match:runtime-structures
- (gentemp)
- `',(match:make-structure-tag name)))
- (vectorp
- (cond ((eq? match:structure-control 'disjoint)
- 'match:primitive-vector?)
- ((eq? match:structure-control 'vector)
- 'vector?))))
- (cond ((eq? match:structure-control 'disjoint)
- (if (eq? vector? match:primitive-vector?)
- (set! vector?
- (lambda (v)
- (and (match:primitive-vector? v)
- (or (zero? (vector-length v))
- (not (symbol? (vector-ref v 0)))
- (not (match:structure?
- (vector-ref v 0))))))))
- (if (not (memq predicate match:disjoint-predicates))
- (set! match:disjoint-predicates
- (cons predicate match:disjoint-predicates))))
- ((eq? match:structure-control 'vector)
- (if (not (memq predicate match:vector-structures))
- (set! match:vector-structures
- (cons predicate match:vector-structures))))
- (else
- (match:syntax-err
- '(vector disjoint)
- "invalid value for match:structure-control, legal values are")))
- `(begin
- ,@(if match:runtime-structures
- `((define ,tag (match:make-structure-tag ',name)))
- '())
- (define ,constructor
- (lambda ,selectors (vector ,tag ,@selectors)))
- (define ,predicate
- (lambda (obj)
- (and (,vectorp obj)
- (= (vector-length obj) ,(+ 1 (length selectors)))
- (eq? (vector-ref obj 0) ,tag))))
- ,@(filter-map-with-index
- (lambda (n i)
- `(define ,n (lambda (obj) (vector-ref obj ,i))))
- selectors)
- ,@(filter-map-with-index
- (lambda (n i)
- (and n
- `(define ,n
- (lambda (obj newval)
- (vector-set! obj ,i newval)))))
- mutators))))
- (car args)
- (cadr args)
- (caddr args)
- (reverse g228))
- (if (field? (car g230))
- (g229 (cdr g230) (cons (car g230) g228))
- (g227))))
- (g227)))))
- (defmacro
- define-structure
- args
- (let ((g242 (lambda ()
- (match:syntax-err
- `(define-structure ,@args)
- "syntax error in"))))
- (if (and (pair? args)
- (pair? (car args))
- (list? (cdar args)))
- (if (null? (cdr args))
- ((lambda (name id1)
- `(define-structure (,name ,@id1) ()))
- (caar args)
- (cdar args))
- (if (and (pair? (cdr args)) (list? (cadr args)))
- (let g239 ((g240 (cadr args)) (g238 '()) (g237 '()))
- (if (null? g240)
- (if (null? (cddr args))
- ((lambda (name id1 id2 val)
- (let ((mk-id (lambda (id)
- (if (and (pair? id)
- (equal? (car id) '@)
- (pair? (cdr id))
- (symbol? (cadr id))
- (null? (cddr id)))
- ((lambda (x) x) (cadr id))
- ((lambda () `(! ,id)))))))
- `(define-const-structure
- (,name ,@(map mk-id id1))
- ,(map (lambda (id v) `(,(mk-id id) ,v)) id2 val))))
- (caar args)
- (cdar args)
- (reverse g237)
- (reverse g238))
- (g242))
- (if (and (pair? (car g240))
- (pair? (cdar g240))
- (null? (cddar g240)))
- (g239 (cdr g240)
- (cons (cadar g240) g238)
- (cons (caar g240) g237))
- (g242))))
- (g242)))
- (g242))))
- (defmacro
- define-const-structure
- args
- (let ((field?
- (lambda (id)
- (if (symbol? id)
- ((lambda () #t))
- (if (and (pair? id)
- (equal? (car id) '!)
- (pair? (cdr id))
- (symbol? (cadr id))
- (null? (cddr id)))
- ((lambda () #t))
- ((lambda () #f))))))
- (field-name
- (lambda (x) (if (symbol? x) x (cadr x))))
- (has-mutator? (lambda (x) (not (symbol? x))))
- (filter-map-with-index
- (lambda (f l)
- (letrec ((mapi (lambda (l i)
- (cond ((null? l) '())
- ((f (car l) i)
- =>
- (lambda (x)
- (cons x (mapi (cdr l) (+ 1 i)))))
- (else (mapi (cdr l) (+ 1 i)))))))
- (mapi l 1))))
- (symbol-append
- (lambda l
- (string->symbol
- (apply string-append
- (map (lambda (x)
- (cond ((symbol? x) (symbol->string x))
- ((number? x) (number->string x))
- (else x)))
- l))))))
- (let ((g266 (lambda ()
- (match:syntax-err
- `(define-const-structure ,@args)
- "syntax error in"))))
- (if (and (pair? args)
- (pair? (car args))
- (list? (cdar args)))
- (if (null? (cdr args))
- ((lambda (name id1)
- `(define-const-structure (,name ,@id1) ()))
- (caar args)
- (cdar args))
- (if (symbol? (caar args))
- (let g259 ((g260 (cdar args)) (g258 '()))
- (if (null? g260)
- (if (and (pair? (cdr args)) (list? (cadr args)))
- (let g263 ((g264 (cadr args)) (g262 '()) (g261 '()))
- (if (null? g264)
- (if (null? (cddr args))
- ((lambda (name id1 id2 val)
- (let* ((id1id2 (append id1 id2))
- (raw-constructor
- (symbol-append 'make-raw- name))
- (constructor (symbol-append 'make- name))
- (predicate (symbol-append name '?)))
- `(begin
- (defstruct
- ,name
- ,raw-constructor
- ,predicate
- ,@(filter-map-with-index
- (lambda (arg i)
- (if (has-mutator? arg)
- `(,(symbol-append name '- i)
- ,(symbol-append
- 'set-
- name
- '-
- i
- '!))
- (symbol-append name '- i)))
- id1id2))
- ,(let* ((make-fresh
- (lambda (x)
- (if (eq? '_ x) (gentemp) x)))
- (names1
- (map make-fresh
- (map field-name id1)))
- (names2
- (map make-fresh
- (map field-name id2))))
- `(define ,constructor
- (lambda ,names1
- (let* ,(map list names2 val)
- (,raw-constructor
- ,@names1
- ,@names2)))))
- ,@(filter-map-with-index
- (lambda (field i)
- (if (eq? (field-name field) '_)
- #f
- `(define (unquote
- (symbol-append
- name
- '-
- (field-name field)))
- ,(symbol-append name '- i))))
- id1id2)
- ,@(filter-map-with-index
- (lambda (field i)
- (if (or (eq? (field-name field) '_)
- (not (has-mutator? field)))
- #f
- `(define (unquote
- (symbol-append
- 'set-
- name
- '-
- (field-name field)
- '!))
- ,(symbol-append
- 'set-
- name
- '-
- i
- '!))))
- id1id2))))
- (caar args)
- (reverse g258)
- (reverse g261)
- (reverse g262))
- (g266))
- (if (and (pair? (car g264))
- (field? (caar g264))
- (pair? (cdar g264))
- (null? (cddar g264)))
- (g263 (cdr g264)
- (cons (cadar g264) g262)
- (cons (caar g264) g261))
- (g266))))
- (g266))
- (if (field? (car g260))
- (g259 (cdr g260) (cons (car g260) g258))
- (g266))))
- (g266)))
- (g266)))))
- (define home-directory
- (or (getenv "HOME")
- (error "environment variable HOME is not defined")))
- (defmacro recur args `(let ,@args))
- (defmacro
- rec
- args
- (match args
- (((? symbol? x) v) `(letrec ((,x ,v)) ,x))))
- (defmacro
- parameterize
- args
- (match args ((bindings exp ...) `(begin ,@exp))))
- (define gensym gentemp)
- (define expand-once macroexpand-1)
- (defmacro check-increment-counter args #f)
- (define symbol-append
- (lambda l
- (string->symbol
- (apply string-append
- (map (lambda (x) (format #f "~a" x)) l)))))
- (define gensym gentemp)
- (define andmap
- (lambda (f . lists)
- (cond ((null? (car lists)) (and))
- ((null? (cdr (car lists)))
- (apply f (map car lists)))
- (else
- (and (apply f (map car lists))
- (apply andmap f (map cdr lists)))))))
- (define true-object? (lambda (x) (eq? #t x)))
- (define false-object? (lambda (x) (eq? #f x)))
- (define void (lambda () (cond (#f #f))))
- (defmacro
- when
- args
- (match args
- ((tst body __1)
- `(if ,tst (begin ,@body (void)) (void)))))
- (defmacro
- unless
- args
- (match args
- ((tst body __1)
- `(if ,tst (void) (begin ,@body (void))))))
- (define should-never-reach
- (lambda (form)
- (slib:error "fell off end of " form)))
- (define make-cvector make-vector)
- (define cvector vector)
- (define cvector-length vector-length)
- (define cvector-ref vector-ref)
- (define cvector->list vector->list)
- (define list->cvector list->vector)
- (define-const-structure (record _))
- (defmacro
- record
- args
- (match args
- ((((? symbol? id) exp) ...)
- `(make-record
- (list ,@(map (lambda (i x) `(cons ',i ,x)) id exp))))
- (_ (slib:error "syntax error at " `(record ,@args)))))
- (defmacro
- field
- args
- (match args
- (((? symbol? id) exp)
- `(match ,exp
- (($ record x)
- (match (assq ',id x)
- (#f
- (slib:error
- "no field "
- ,id
- 'in
- (cons 'record (map car x))))
- ((_ . x) x)))
- (_ (slib:error "not a record: " '(field ,id _)))))
- (_ (slib:error "syntax error at " `(field ,@args)))))
- (define-const-structure (module _))
- (defmacro
- module
- args
- (match args
- (((i ...) defs ...)
- `(let ()
- ,@defs
- (make-module
- (record ,@(map (lambda (x) (list x x)) i)))))
- (_ (slib:error "syntax error at " `(module ,@args)))))
- (defmacro
- import
- args
- (match args
- ((((mod defs ...) ...) body __1)
- (let* ((m (map (lambda (_) (gentemp)) mod))
- (newdefs
- (let loop ((mod-names m) (l-defs defs))
- (if (null? mod-names)
- '()
- (append
- (let ((m (car mod-names)))
- (map (match-lambda
- ((? symbol? x) `(,x (field ,x ,m)))
- (((? symbol? i) (? symbol? e))
- `(,i (field ,e ,m)))
- (x (slib:error "ill-formed definition: " x)))
- (car l-defs)))
- (loop (cdr mod-names) (cdr l-defs)))))))
- `(let (unquote
- (map (lambda (m mod)
- `(,m (match ,mod (($ module x) x))))
- m
- mod))
- (let ,newdefs body ...))))))
- (define raise
- (lambda vals
- (slib:error "Unhandled exception " vals)))
- (defmacro
- fluid-let
- args
- (match args
- ((((x val) ...) body __1)
- (let ((old-x (map (lambda (_) (gentemp)) x))
- (swap-x (map (lambda (_) (gentemp)) x))
- (swap (gentemp)))
- `(let ,(map list old-x val)
- (let ((,swap
- (lambda ()
- (let ,(map list swap-x old-x)
- ,@(map (lambda (old x) `(set! ,old ,x)) old-x x)
- ,@(map (lambda (x swap) `(set! ,x ,swap))
- x
- swap-x)))))
- (dynamic-wind ,swap (lambda () ,@body) ,swap)))))
- (_ (slib:error
- "syntax error at "
- `(fluid-let ,@args)))))
- (defmacro
- handle
- args
- (match args
- ((e h)
- (let ((k (gentemp)) (exn (gentemp)))
- `((call-with-current-continuation
- (lambda (k)
- (fluid-let
- ((raise (lambda ,exn (k (lambda () (apply ,h ,exn))))))
- (let ((v ,e)) (lambda () v))))))))
- (_ (slib:error "syntax error in " `(handle ,@args)))))
- (defmacro
- :
- args
- (match args ((typeexp exp) exp)))
- (defmacro
- module:
- args
- (match args
- ((((i type) ...) defs ...)
- `(let ()
- ,@defs
- (make-module
- (record
- ,@(map (lambda (i type) `(,i (: ,type ,i))) i type)))))))
- (defmacro
- define:
- args
- (match args
- ((name type exp) `(define ,name (: ,type ,exp)))))
- (define st:failure
- (lambda (chk fmt . args)
- (slib:error
- (apply format
- #f
- (string-append "~a : " fmt)
- chk
- args))))
- (defmacro
- check-bound
- args
- (match args
- ((var) var)
- (x (st:failure `(check-bound ,@x) "syntax-error"))))
- (defmacro
- clash
- args
- (match args
- ((name info ...) name)
- (x (st:failure `(clash ,@x) "syntax error"))))
- (defmacro
- check-lambda
- args
- (match args
- (((id info ...) (? symbol? args) body __1)
- `(lambda ,args
- (check-increment-counter ,id)
- ,@body))
- (((id info ...) args body __1)
- (let* ((n 0)
- (chk (let loop ((a args) (nargs 0))
- (cond ((pair? a) (loop (cdr a) (+ 1 nargs)))
- ((null? a)
- (set! n nargs)
- `(= ,nargs (length args)))
- (else
- (set! n nargs)
- `(<= ,nargs (length args))))))
- (incr (if (number? id)
- `(check-increment-counter ,id)
- #f)))
- `(let ((lam (lambda ,args ,@body)))
- (lambda args
- ,incr
- (if ,chk
- (apply lam args)
- ,(if (eq? '= (car chk))
- `(st:failure
- '(check-lambda ,id ,@info)
- "requires ~a arguments, passed: ~a"
- ,n
- args)
- `(st:failure
- '(check-lambda ,id ,@info)
- "requires >= ~a arguments, passed: ~a"
- ,n
- args)))))))
- (x (st:failure `(check-lambda ,@x) "syntax error"))))
- (defmacro
- check-ap
- args
- (match args
- (((id info ...) (? symbol? f) args ...)
- `(begin
- (check-increment-counter ,id)
- (if (procedure? ,f)
- (,f ,@args)
- (st:failure
- '(check-ap ,id ,@info)
- "not a procedure: ~a"
- ,f))))
- (((id info ...) f args ...)
- `((lambda (proc . args)
- (check-increment-counter ,id)
- (if (procedure? proc)
- (apply proc args)
- (st:failure
- '(check-ap ,id ,@info)
- "not a procedure: ~a"
- proc)))
- ,f
- ,@args))
- (x (st:failure `(check-ap ,@x) "syntax error"))))
- (defmacro
- check-field
- args
- (match args
- (((id info ...) (? symbol? f) exp)
- `(match ,exp
- (($ record x)
- (match (assq ',f x)
- (#f
- (st:failure
- '(check-field ,id ,@info)
- "no ~a field in (record ~a)"
- ',f
- (map car x)))
- ((_ . x) x)))
- (v (st:failure
- '(check-field ,id ,@info)
- "not a record: ~a"
- v))))
- (x (st:failure `(check-field ,@x) "syntax error"))))
- (defmacro
- check-match
- args
- (match args
- (((id info ...) exp (and clause (pat _ __1)) ...)
- (letrec ((last (lambda (pl)
- (if (null? (cdr pl)) (car pl) (last (cdr pl))))))
- (if (match (last pat)
- ((? symbol?) #t)
- (('and subp ...) (andmap symbol? subp))
- (_ #f))
- `(begin
- (check-increment-counter ,id)
- (match ,exp ,@clause))
- `(begin
- (check-increment-counter ,id)
- (match ,exp
- ,@clause
- (x (st:failure
- '(check-match ,id ,@info)
- "no matching clause for ~a"
- x)))))))
- (x (st:failure `(check-match ,@x) "syntax error"))))
- (defmacro
- check-:
- args
- (match args
- (((id info ...) typeexp exp)
- `(st:failure
- '(check-: ,id ,@info)
- "static type annotation reached"))
- (x (st:failure `(check-: ,@x) "syntax error"))))
- (defmacro
- make-check-typed
- args
- (match args
- ((prim)
- (let ((chkprim (symbol-append 'check- prim)))
- (list 'defmacro
- chkprim
- 'id
- (list 'quasiquote
- `(lambda a
- (check-increment-counter (,'unquote (car id)))
- (if (null? a)
- (,prim)
- (st:failure
- (cons ',chkprim '(,'unquote id))
- "invalid arguments: ~a"
- a)))))))
- ((prim '_)
- (let ((chkprim (symbol-append 'check- prim)))
- (list 'defmacro
- chkprim
- 'id
- (list 'quasiquote
- `(lambda a
- (check-increment-counter (,'unquote (car id)))
- (if (= 1 (length a))
- (,prim (car a))
- (st:failure
- (cons ',chkprim '(,'unquote id))
- "invalid arguments: ~a"
- a)))))))
- ((prim type1)
- (let ((chkprim (symbol-append 'check- prim)))
- (list 'defmacro
- chkprim
- 'id
- (list 'quasiquote
- `(lambda a
- (check-increment-counter (,'unquote (car id)))
- (if (and (= 1 (length a)) (,type1 (car a)))
- (,prim (car a))
- (st:failure
- (cons ',chkprim '(,'unquote id))
- "invalid arguments: ~a"
- a)))))))
- ((prim '_ '_)
- (let ((chkprim (symbol-append 'check- prim)))
- (list 'defmacro
- chkprim
- 'id
- (list 'quasiquote
- `(lambda a
- (check-increment-counter (,'unquote (car id)))
- (if (= 2 (length a))
- (,prim (car a) (cadr a))
- (st:failure
- (cons ',chkprim '(,'unquote id))
- "invalid arguments: ~a"
- a)))))))
- ((prim '_ type2)
- (let ((chkprim (symbol-append 'check- prim)))
- (list 'defmacro
- chkprim
- 'id
- (list 'quasiquote
- `(lambda a
- (check-increment-counter (,'unquote (car id)))
- (if (and (= 2 (length a)) (,type2 (cadr a)))
- (,prim (car a) (cadr a))
- (st:failure
- (cons ',chkprim '(,'unquote id))
- "invalid arguments: ~a"
- a)))))))
- ((prim type1 '_)
- (let ((chkprim (symbol-append 'check- prim)))
- (list 'defmacro
- chkprim
- 'id
- (list 'quasiquote
- `(lambda a
- (check-increment-counter (,'unquote (car id)))
- (if (and (= 2 (length a)) (,type1 (car a)))
- (,prim (car a) (cadr a))
- (st:failure
- (cons ',chkprim '(,'unquote id))
- "invalid arguments: ~a"
- a)))))))
- ((prim type1 type2)
- (let ((chkprim (symbol-append 'check- prim)))
- (list 'defmacro
- chkprim
- 'id
- (list 'quasiquote
- `(lambda a
- (check-increment-counter (,'unquote (car id)))
- (if (and (= 2 (length a))
- (,type1 (car a))
- (,type2 (cadr a)))
- (,prim (car a) (cadr a))
- (st:failure
- (cons ',chkprim '(,'unquote id))
- "invalid arguments: ~a"
- a)))))))
- ((prim types ...)
- (let ((nargs (length types))
- (chkprim (symbol-append 'check- prim))
- (types (map (match-lambda ('_ '(lambda (_) #t)) (x x))
- types)))
- (list 'defmacro
- chkprim
- 'id
- (list 'quasiquote
- `(lambda a
- (check-increment-counter (,'unquote (car id)))
- (if (and (= ,nargs (length a))
- (andmap
- (lambda (f a) (f a))
- (list ,@types)
- a))
- (apply ,prim a)
- (st:failure
- (cons ',chkprim '(,'unquote id))
- "invalid arguments: ~a"
- a)))))))))
- (defmacro
- make-check-selector
- args
- (match args
- ((prim pat)
- (let ((chkprim (symbol-append 'check- prim)))
- (list 'defmacro
- chkprim
- 'id
- (list 'quasiquote
- `(lambda a
- (check-increment-counter (,'unquote (car id)))
- (match a
- ((,pat) x)
- (_ (st:failure
- (cons ',chkprim '(,'unquote id))
- "invalid arguments: ~a"
- a))))))))))
- (make-check-typed number? _)
- (make-check-typed null? _)
- (make-check-typed char? _)
- (make-check-typed symbol? _)
- (make-check-typed string? _)
- (make-check-typed vector? _)
- (make-check-typed box? _)
- (make-check-typed pair? _)
- (make-check-typed procedure? _)
- (make-check-typed eof-object? _)
- (make-check-typed input-port? _)
- (make-check-typed output-port? _)
- (make-check-typed true-object? _)
- (make-check-typed false-object? _)
- (make-check-typed boolean? _)
- (make-check-typed list? _)
- (make-check-typed not _)
- (make-check-typed eqv? _ _)
- (make-check-typed eq? _ _)
- (make-check-typed equal? _ _)
- (make-check-typed cons _ _)
- (make-check-selector car (x . _))
- (make-check-selector cdr (_ . x))
- (make-check-selector caar ((x . _) . _))
- (make-check-selector cadr (_ x . _))
- (make-check-selector cdar ((_ . x) . _))
- (make-check-selector cddr (_ _ . x))
- (make-check-selector caaar (((x . _) . _) . _))
- (make-check-selector caadr (_ (x . _) . _))
- (make-check-selector cadar ((_ x . _) . _))
- (make-check-selector caddr (_ _ x . _))
- (make-check-selector cdaar (((_ . x) . _) . _))
- (make-check-selector cdadr (_ (_ . x) . _))
- (make-check-selector cddar ((_ _ . x) . _))
- (make-check-selector cdddr (_ _ _ . x))
- (make-check-selector
- caaaar
- ((((x . _) . _) . _) . _))
- (make-check-selector
- caaadr
- (_ ((x . _) . _) . _))
- (make-check-selector
- caadar
- ((_ (x . _) . _) . _))
- (make-check-selector caaddr (_ _ (x . _) . _))
- (make-check-selector
- cadaar
- (((_ x . _) . _) . _))
- (make-check-selector cadadr (_ (_ x . _) . _))
- (make-check-selector caddar ((_ _ x . _) . _))
- (make-check-selector cadddr (_ _ _ x . _))
- (make-check-selector
- cdaaar
- ((((_ . x) . _) . _) . _))
- (make-check-selector
- cdaadr
- (_ ((_ . x) . _) . _))
- (make-check-selector
- cdadar
- ((_ (_ . x) . _) . _))
- (make-check-selector cdaddr (_ _ (_ . x) . _))
- (make-check-selector
- cddaar
- (((_ _ . x) . _) . _))
- (make-check-selector cddadr (_ (_ _ . x) . _))
- (make-check-selector cdddar ((_ _ _ . x) . _))
- (make-check-selector cddddr (_ _ _ _ . x))
- (make-check-typed set-car! pair? _)
- (make-check-typed set-cdr! pair? _)
- (defmacro
- check-list
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (apply list a)))
- (make-check-typed length list?)
- (defmacro
- check-append
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (let loop ((b a))
- (match b
- (() #t)
- ((l) #t)
- (((? list?) . y) (loop y))
- (_ (st:failure
- (cons 'check-append ',id)
- "invalid arguments: ~a"
- a))))
- (apply append a)))
- (make-check-typed reverse list?)
- (make-check-typed list-tail list? number?)
- (make-check-typed list-ref list? number?)
- (make-check-typed memq _ list?)
- (make-check-typed memv _ list?)
- (make-check-typed member _ list?)
- (defmacro
- check-assq
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (= 2 (length a))
- (list? (cadr a))
- (andmap pair? (cadr a)))
- (assq (car a) (cadr a))
- (st:failure
- (cons 'check-assq ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-assv
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (= 2 (length a))
- (list? (cadr a))
- (andmap pair? (cadr a)))
- (assv (car a) (cadr a))
- (st:failure
- (cons 'check-assv ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-assoc
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (= 2 (length a))
- (list? (cadr a))
- (andmap pair? (cadr a)))
- (assoc (car a) (cadr a))
- (st:failure
- (cons 'check-assoc ',id)
- "invalid arguments: ~a"
- a))))
- (make-check-typed symbol->string symbol?)
- (make-check-typed string->symbol string?)
- (make-check-typed complex? _)
- (make-check-typed real? _)
- (make-check-typed rational? _)
- (make-check-typed integer? _)
- (make-check-typed exact? number?)
- (make-check-typed inexact? number?)
- (defmacro
- check-=
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (<= 2 (length a)) (andmap number? a))
- (apply = a)
- (st:failure
- (cons 'check-= ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-<
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (<= 2 (length a)) (andmap number? a))
- (apply < a)
- (st:failure
- (cons 'check-< ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check->
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (<= 2 (length a)) (andmap number? a))
- (apply > a)
- (st:failure
- (cons 'check-> ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-<=
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (<= 2 (length a)) (andmap number? a))
- (apply <= a)
- (st:failure
- (cons 'check-<= ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check->=
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (<= 2 (length a)) (andmap number? a))
- (apply >= a)
- (st:failure
- (cons 'check->= ',id)
- "invalid arguments: ~a"
- a))))
- (make-check-typed zero? number?)
- (make-check-typed positive? number?)
- (make-check-typed negative? number?)
- (make-check-typed odd? number?)
- (make-check-typed even? number?)
- (defmacro
- check-max
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (<= 1 (length a)) (andmap number? a))
- (apply max a)
- (st:failure
- (cons 'check-max ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-min
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (<= 1 (length a)) (andmap number? a))
- (apply min a)
- (st:failure
- (cons 'check-min ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-+
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (andmap number? a)
- (apply + a)
- (st:failure
- (cons 'check-+ ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-*
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (andmap number? a)
- (apply * a)
- (st:failure
- (cons 'check-* ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check--
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (<= 1 (length a)) (andmap number? a))
- (apply - a)
- (st:failure
- (cons 'check-- ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-/
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (<= 1 (length a)) (andmap number? a))
- (apply / a)
- (st:failure
- (cons 'check-/ ',id)
- "invalid arguments: ~a"
- a))))
- (make-check-typed abs number?)
- (make-check-typed quotient number? number?)
- (make-check-typed remainder number? number?)
- (make-check-typed modulo number? number?)
- (defmacro
- check-gcd
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (andmap number? a)
- (apply gcd a)
- (st:failure
- (cons 'check-gcd ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-lcm
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (andmap number? a)
- (apply lcm a)
- (st:failure
- (cons 'check-lcm ',id)
- "invalid arguments: ~a"
- a))))
- (make-check-typed numerator number?)
- (make-check-typed denominator number?)
- (make-check-typed floor number?)
- (make-check-typed ceiling number?)
- (make-check-typed truncate number?)
- (make-check-typed round number?)
- (make-check-typed rationalize number? number?)
- (make-check-typed exp number?)
- (make-check-typed log number?)
- (make-check-typed sin number?)
- (make-check-typed cos number?)
- (make-check-typed tan number?)
- (make-check-typed asin number?)
- (make-check-typed acos number?)
- (defmacro
- check-atan
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (andmap number? a)
- (pair? a)
- (>= 2 (length a)))
- (apply atan a)
- (st:failure
- (cons 'check-atan ',id)
- "invalid arguments: ~a"
- a))))
- (make-check-typed sqrt number?)
- (make-check-typed expt number? number?)
- (make-check-typed
- make-rectangular
- number?
- number?)
- (make-check-typed make-polar number? number?)
- (make-check-typed real-part number?)
- (make-check-typed imag-part number?)
- (make-check-typed magnitude number?)
- (make-check-typed angle number?)
- (make-check-typed exact->inexact number?)
- (make-check-typed inexact->exact number?)
- (defmacro
- check-number->string
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (andmap number? a)
- (pair? a)
- (>= 2 (length a)))
- (apply number->string a)
- (st:failure
- (cons 'check-number->string ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-string->number
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (pair? a)
- (string? (car a))
- (>= 2 (length a))
- (or (null? (cdr a)) (number? (cadr a))))
- (apply string->number a)
- (st:failure
- (cons 'check-string->number ',id)
- "invalid arguments: ~a"
- a))))
- (make-check-typed char=? char? char?)
- (make-check-typed char<? char? char?)
- (make-check-typed char>? char? char?)
- (make-check-typed char<=? char? char?)
- (make-check-typed char>=? char? char?)
- (make-check-typed char-ci=? char? char?)
- (make-check-typed char-ci<? char? char?)
- (make-check-typed char-ci>? char? char?)
- (make-check-typed char-ci<=? char? char?)
- (make-check-typed char-ci>=? char? char?)
- (make-check-typed char-alphabetic? char?)
- (make-check-typed char-numeric? char?)
- (make-check-typed char-whitespace? char?)
- (make-check-typed char-upper-case? char?)
- (make-check-typed char-lower-case? char?)
- (make-check-typed char->integer char?)
- (make-check-typed integer->char number?)
- (make-check-typed char-upcase char?)
- (make-check-typed char-downcase char?)
- (defmacro
- check-make-string
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (pair? a)
- (number? (car a))
- (>= 2 (length a))
- (or (null? (cdr a)) (char? (cadr a))))
- (apply make-string a)
- (st:failure
- (cons 'check-make-string ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-string
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (andmap char? a)
- (apply string a)
- (st:failure
- (cons 'check-string ',id)
- "invalid arguments: ~a"
- a))))
- (make-check-typed string-length string?)
- (make-check-typed string-ref string? number?)
- (make-check-typed
- string-set!
- string?
- number?
- char?)
- (make-check-typed string=? string? string?)
- (make-check-typed string<? string? string?)
- (make-check-typed string>? string? string?)
- (make-check-typed string<=? string? string?)
- (make-check-typed string>=? string? string?)
- (make-check-typed string-ci=? string? string?)
- (make-check-typed string-ci<? string? string?)
- (make-check-typed string-ci>? string? string?)
- (make-check-typed string-ci<=? string? string?)
- (make-check-typed string-ci>=? string? string?)
- (make-check-typed
- substring
- string?
- number?
- number?)
- (defmacro
- check-string-append
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (andmap string? a)
- (apply string-append a)
- (st:failure
- (cons 'check-string-append ',id)
- "invalid arguments: ~a"
- a))))
- (make-check-typed string->list string?)
- (defmacro
- check-list->string
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (= 1 (length a))
- (list? (car a))
- (andmap char? (car a)))
- (list->string (car a))
- (st:failure
- (cons 'check-list->string ',id)
- "invalid arguments: ~a"
- a))))
- (make-check-typed string-copy string?)
- (make-check-typed string-fill! string? char?)
- (make-check-typed make-vector number? _)
- (defmacro
- check-vector
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (apply vector a)))
- (make-check-typed vector-length vector?)
- (make-check-typed vector-ref vector? number?)
- (make-check-typed vector-set! vector? number? _)
- (make-check-typed vector->list vector?)
- (make-check-typed list->vector list?)
- (make-check-typed vector-fill! vector? _)
- (defmacro
- check-apply
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (pair? a)
- (let loop ((arg (cdr a)))
- (match arg
- (((? list?)) (apply apply a))
- ((_ . y) (loop y))
- (_ (st:failure
- (cons 'check-apply ',id)
- "invalid arguments: ~a"
- a))))
- (st:failure
- `(check-apply ,@id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-map
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (<= 2 (length a))
- (procedure? (car a))
- (andmap list? (cdr a)))
- (apply map a)
- (st:failure
- (cons 'check-map ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-for-each
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (<= 2 (length a))
- (procedure? (car a))
- (andmap list? (cdr a)))
- (apply for-each a)
- (st:failure
- (cons 'check-for-each ',id)
- "invalid arguments: ~a"
- a))))
- (make-check-typed force procedure?)
- (defmacro
- check-call-with-current-continuation
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (= 1 (length a)) (procedure? (car a)))
- (call-with-current-continuation
- (lambda (k)
- ((car a) (check-lambda (continuation) (x) (k x)))))
- (st:failure
- (cons 'check-call-with-current-continuation ',id)
- "invalid arguments: ~a"
- a))))
- (make-check-typed
- call-with-input-file
- string?
- procedure?)
- (make-check-typed
- call-with-output-file
- string?
- procedure?)
- (make-check-typed input-port? _)
- (make-check-typed output-port? _)
- (make-check-typed current-input-port)
- (make-check-typed current-output-port)
- (make-check-typed
- with-input-from-file
- string?
- procedure?)
- (make-check-typed
- with-output-to-file
- string?
- procedure?)
- (make-check-typed open-input-file string?)
- (make-check-typed open-output-file string?)
- (make-check-typed close-input-port input-port?)
- (make-check-typed close-output-port output-port?)
- (defmacro
- check-read
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (or (null? a)
- (and (= 1 (length a)) (input-port? (car a))))
- (apply read a)
- (st:failure
- (cons 'check-read ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-read-char
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (or (null? a)
- (and (= 1 (length a)) (input-port? (car a))))
- (apply read-char a)
- (st:failure
- (cons 'check-read-char ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-peek-char
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (or (null? a)
- (and (= 1 (length a)) (input-port? (car a))))
- (apply peek-char a)
- (st:failure
- (cons 'check-peek-char ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-char-ready?
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (or (null? a)
- (and (= 1 (length a)) (input-port? (car a))))
- (apply char-ready? a)
- (st:failure
- (cons 'check-char-ready? ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-write
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (pair? a)
- (or (null? (cdr a)) (output-port? (cadr a))))
- (apply write a)
- (st:failure
- (cons 'check-write ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-display
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (pair? a)
- (or (null? (cdr a)) (output-port? (cadr a))))
- (apply display a)
- (st:failure
- (cons 'check-display ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-newline
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (or (null? a) (output-port? (car a)))
- (apply newline a)
- (st:failure
- (cons 'check-newline ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-write-char
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (pair? a)
- (char? (car a))
- (or (null? (cdr a)) (output-port? (cadr a))))
- (apply write-char a)
- (st:failure
- (cons 'check-write-char ',id)
- "invalid arguments: ~a"
- a))))
- (make-check-typed load string?)
- (make-check-typed transcript-on string?)
- (make-check-typed transcript-off)
- (defmacro
- check-symbol-append
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (apply symbol-append a)))
- (make-check-typed box _)
- (make-check-typed unbox box?)
- (make-check-typed set-box! box? _)
- (make-check-typed void)
- (make-check-typed make-module _)
- (defmacro
- check-match:error
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (pair? a)
- (apply match:error a)
- (st:failure
- (cons 'check-match:error ',id)
- "invalid arguments: ~a"
- a))))
- (make-check-typed should-never-reach symbol?)
- (defmacro
- check-make-cvector
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (if (and (pair? a)
- (number? (car a))
- (= 2 (length a)))
- (apply make-cvector a)
- (st:failure
- (cons 'check-make-cvector ',id)
- "invalid arguments: ~a"
- a))))
- (defmacro
- check-cvector
- id
- `(lambda a
- (check-increment-counter ,(car id))
- (apply cvector a)))
- (make-check-typed cvector-length cvector?)
- (make-check-typed cvector-ref cvector? number?)
- (make-check-typed cvector->list cvector?)
- (make-check-typed list->cvector list?)
- (defmacro
- check-define-const-structure
- args
- (let ((field?
- (lambda (x)
- (or (symbol? x)
- (and (pair? x)
- (equal? (car x) '!)
- (pair? (cdr x))
- (symbol? (cadr x))
- (null? (cddr x))))))
- (arg-name
- (lambda (x) (if (symbol? x) x (cadr x))))
- (with-mutator? (lambda (x) (not (symbol? x)))))
- (match args
- ((((? symbol? name) (? field? id1) ...))
- (let ((constructor (symbol-append 'make- name))
- (check-constructor
- (symbol-append 'check-make- name))
- (predicate (symbol-append name '?))
- (access
- (let loop ((l id1))
- (cond ((null? l) '())
- ((eq? '_ (arg-name (car l))) (loop (cdr l)))
- (else
- (cons (symbol-append name '- (arg-name (car l)))
- (loop (cdr l)))))))
- (assign
- (let loop ((l id1))
- (cond ((null? l) '())
- ((eq? '_ (arg-name (car l))) (loop (cdr l)))
- ((not (with-mutator? (car l))) (loop (cdr l)))
- (else
- (cons (symbol-append
- 'set-
- name
- '-
- (arg-name (car l))
- '!)
- (loop (cdr l)))))))
- (nargs (length id1)))
- `(begin
- (define-const-structure (,name ,@id1) ())
- (defmacro
- ,check-constructor
- id
- (lambda a
- (check-increment-counter (,'unquote (car id)))
- (if (= ,nargs (length a))
- (apply ,constructor a)
- (st:failure
- (cons ',check-constructor '(,'unquote id))
- "invalid arguments: ~a"
- a))))
- (make-check-typed ,predicate _)
- ,@(map (lambda (a) `(make-check-typed ,a ,predicate))
- access)
- ,@(map (lambda (a) `(make-check-typed ,a ,predicate _))
- assign))))
- (x (st:failure
- `(check-define-const-structure ,@x)
- "syntax error")))))
- (if (equal? '(match 1) (macroexpand-1 '(match 1)))
- (load "/home/wright/scheme/match/match-slib.scm"))
- (define sprintf
- (lambda args (apply format #f args)))
- (define printf
- (lambda args (apply format #t args)))
- (define disaster
- (lambda (context fmt . args)
- (slib:error
- (apply sprintf
- (string-append "in ~a: " fmt)
- context
- args))))
- (define use-error
- (lambda (fmt . args)
- (slib:error (apply sprintf fmt args))))
- (define syntax-err
- (lambda (context fmt . args)
- (newline)
- (if context (pretty-print context))
- (slib:error
- (apply sprintf
- (string-append "in syntax: " fmt)
- args))))
- (define flush-output force-output)
- (define print-context
- (lambda (obj depth)
- (pretty-print
- (recur loop
- ((obj obj) (n 0))
- (if (pair? obj)
- (if (< n depth)
- (cons (loop (car obj) (+ 1 n))
- (loop (cdr obj) n))
- '(...))
- obj)))))
- (define *box-tag* (gensym))
- (define box (lambda (a) (cons *box-tag* a)))
- (define box?
- (lambda (b)
- (and (pair? b) (eq? (car b) *box-tag*))))
- (define unbox cdr)
- (define box-1 cdr)
- (define set-box! set-cdr!)
- (define sort-list sort)
- (define expand-once-if-macro
- (lambda (e)
- (and (macro? (car e)) (macroexpand-1 e))))
- (define ormap
- (lambda (f . lists)
- (if (null? (car lists))
- (or)
- (or (apply f (map car lists))
- (apply ormap f (map cdr lists))))))
- (define call/cc call-with-current-continuation)
- (define (cpu-time) 0)
- (define (pretty-print x) (display x) (newline))
- (define clock-granularity 1.0e-3)
- (define set-vector! vector-set!)
- (define set-string! string-set!)
- (define maplr
- (lambda (f l)
- (match l
- (() '())
- ((x . y) (let ((v (f x))) (cons v (maplr f y)))))))
- (define maprl
- (lambda (f l)
- (match l
- (() '())
- ((x . y) (let ((v (maprl f y))) (cons (f x) v))))))
- (define foldl
- (lambda (f i l)
- (recur loop
- ((l l) (acc i))
- (match l (() acc) ((x . y) (loop y (f x acc)))))))
- (define foldr
- (lambda (f i l)
- (recur loop
- ((l l))
- (match l (() i) ((x . y) (f x (loop y)))))))
- (define filter
- (lambda (p l)
- (match l
- (() '())
- ((x . y)
- (if (p x) (cons x (filter p y)) (filter p y))))))
- (define filter-map
- (lambda (p l)
- (match l
- (() '())
- ((x . y)
- (match (p x)
- (#f (filter-map p y))
- (x (cons x (filter-map p y))))))))
- (define rac
- (lambda (l)
- (match l ((last) last) ((_ . rest) (rac rest)))))
- (define rdc
- (lambda (l)
- (match l
- ((_) '())
- ((x . rest) (cons x (rdc rest))))))
- (define map-with-n
- (lambda (f l)
- (recur loop
- ((l l) (n 0))
- (match l
- (() '())
- ((x . y)
- (let ((v (f x n))) (cons v (loop y (+ 1 n)))))))))
- (define readfile
- (lambda (f)
- (with-input-from-file
- f
- (letrec ((rf (lambda ()
- (match (read)
- ((? eof-object?) '())
- (sexp (cons sexp (rf)))))))
- rf))))
- (define map2
- (lambda (f a b)
- (match (cons a b)
- ((()) '())
- (((ax . ay) bx . by)
- (let ((v (f ax bx))) (cons v (map2 f ay by))))
- (else (error 'map2 "lists differ in length")))))
- (define for-each2
- (lambda (f a b)
- (match (cons a b)
- ((()) (void))
- (((ax . ay) bx . by)
- (f ax bx)
- (for-each2 f ay by))
- (else (error 'for-each2 "lists differ in length")))))
- (define andmap2
- (lambda (f a b)
- (match (cons a b)
- ((()) (and))
- (((ax) bx) (f ax bx))
- (((ax . ay) bx . by)
- (and (f ax bx) (andmap2 f ay by)))
- (else (error 'andmap2 "lists differ in length")))))
- (define ormap2
- (lambda (f a b)
- (match (cons a b)
- ((()) (or))
- (((ax) bx) (f ax bx))
- (((ax . ay) bx . by)
- (or (f ax bx) (ormap2 f ay by)))
- (else (error 'ormap2 "lists differ in length")))))
- (define empty-set '())
- (define empty-set? null?)
- (define set (lambda l (list->set l)))
- (define list->set
- (match-lambda
- (() '())
- ((x . y)
- (if (memq x y)
- (list->set y)
- (cons x (list->set y))))))
- (define element-of?
- (lambda (x set) (and (memq x set) #t)))
- (define cardinality length)
- (define set<=
- (lambda (a b)
- (foldr (lambda (a-elt acc) (and acc (memq a-elt b) #t))
- (and)
- a)))
- (define set-eq?
- (lambda (a b)
- (and (= (cardinality a) (cardinality b))
- (set<= a b))))
- (define union2
- (lambda (a b)
- (if (null? b)
- a
- (foldr (lambda (x b) (if (memq x b) b (cons x b)))
- b
- a))))
- (define union (lambda l (foldr union2 '() l)))
- (define setdiff2
- (lambda (a b)
- (if (null? b)
- a
- (foldr (lambda (x c) (if (memq x b) c (cons x c)))
- '()
- a))))
- (define setdiff
- (lambda l
- (if (null? l)
- '()
- (setdiff2 (car l) (foldr union2 '() (cdr l))))))
- (define intersect2
- (lambda (a b)
- (if (null? b)
- a
- (foldr (lambda (x c) (if (memq x b) (cons x c) c))
- '()
- a))))
- (define intersect
- (lambda l
- (if (null? l) '() (foldl intersect2 (car l) l))))
- (define-const-structure (some _))
- (define-const-structure (none))
- (define none (make-none))
- (define some make-some)
- (define-const-structure (and exps))
- (define-const-structure (app exp exps))
- (define-const-structure (begin exps))
- (define-const-structure (const val pred))
- (define-const-structure (if exp1 exp2 exp3))
- (define-const-structure (lam names body))
- (define-const-structure (let binds body))
- (define-const-structure (let* binds body))
- (define-const-structure (letr binds body))
- (define-const-structure (or exps))
- (define-const-structure (prim name))
- (define-const-structure (delay exp))
- (define-const-structure (set! (! name) exp))
- (define-const-structure (var (! name)))
- (define-const-structure (vlam names name body))
- (define-const-structure (match exp mclauses))
- (define-const-structure (record binds))
- (define-const-structure (field name exp))
- (define-const-structure (cast type exp))
- (define-const-structure (body defs exps))
- (define-const-structure (bind name exp))
- (define-const-structure (mclause pat body fail))
- (define-const-structure (pvar name))
- (define-const-structure (pany))
- (define-const-structure (pelse))
- (define-const-structure (pconst name pred))
- (define-const-structure (pobj name pats))
- (define-const-structure (ppred name))
- (define-const-structure (pand pats))
- (define-const-structure (pnot pat))
- (define-const-structure (define name (! exp)))
- (define-const-structure
- (defstruct
- tag
- args
- make
- pred
- get
- set
- getn
- setn
- mutable))
- (define-const-structure (datatype _))
- (define-const-structure
- (variant con pred arg-types))
- (define-structure
- (name name
- ty
- timestamp
- occ
- mutated
- gdef
- primitive
- struct
- pure
- predicate
- variant
- selector))
- (define-structure (type ty exp))
- (define-const-structure (shape _ _))
- (define-const-structure (check _ _))
- (define parse-def
- (lambda (def)
- (let ((parse-name
- (match-lambda
- ((? symbol? s)
- (if (keyword? s)
- (syntax-err def "invalid use of keyword ~a" s)
- s))
- (n (syntax-err def "invalid variable at ~a" n)))))
- (match def
- (('extend-syntax ((? symbol? name) . _) . _)
- (printf
- "Note: installing but _not_ checking (extend-syntax (~a) ...)~%"
- name)
- (eval def)
- '())
- (('extend-syntax . _)
- (syntax-err def "invalid syntax"))
- (('defmacro (? symbol? name) . _)
- (printf
- "Note: installing but _not_ checking (defmacro ~a ...)~%"
- name)
- (eval def)
- '())
- (('defmacro . _)
- (syntax-err def "invalid syntax"))
- (('define (? symbol? n) e)
- (list (make-define (parse-name n) (parse-exp e))))
- (('define (n . args) . body)
- (list (make-define
- (parse-name n)
- (parse-exp `(lambda ,args ,@body)))))
- (('define . _) (syntax-err def "at define"))
- (('begin . defs)
- (foldr append '() (smap parse-def defs)))
- (('define-structure (n . args))
- (parse-def `(define-structure (,n ,@args) ())))
- (('define-structure (n . args) inits)
- (let ((m-args (smap (lambda (x) `(! ,x)) args))
- (m-inits
- (smap (match-lambda
- ((x e) `((! ,x) ,e))
- (_ (syntax-err
- def
- "invalid structure initializer")))
- inits)))
- (parse-def
- `(define-const-structure (,n ,@m-args) ,m-inits))))
- (('define-const-structure ((? symbol? n) . args))
- (parse-def
- `(define-const-structure (,n ,@args) ())))
- (('define-const-structure
- ((? symbol? n) . args)
- ())
- (letrec ((smap-with-n
- (lambda (f l)
- (recur loop
- ((l l) (n 0))
- (match l
- (() '())
- ((x . y)
- (let ((v (f x n)))
- (cons v (loop y (+ 1 n)))))
- (_ (syntax-err l "invalid list"))))))
- (parse-arg
- (lambda (a index)
- (match a
- (('! '_)
- (list none
- none
- (some (symbol-append
- n
- '-
- (+ index 1)))
- (some (symbol-append
- 'set-
- n
- '-
- (+ index 1)
- '!))
- #t))
- (('! a)
- (let ((a (parse-name a)))
- (list (some (symbol-append n '- a))
- (some (symbol-append
- 'set-
- n
- '-
- a
- '!))
- (some (symbol-append
- n
- '-
- (+ index 1)))
- (some (symbol-append
- 'set-
- n
- '-
- (+ index 1)
- '!))
- #t)))
- ('_
- (list none
- none
- (some (symbol-append
- n
- '-
- (+ index 1)))
- none
- #f))
- (a (let ((a (parse-name a)))
- (list (some (symbol-append n '- a))
- none
- (some (symbol-append
- n
- '-
- (+ index 1)))
- none
- #f)))))))
- (let* ((arg-info (smap-with-n parse-arg args))
- (get (map car arg-info))
- (set (map cadr arg-info))
- (getn (map caddr arg-info))
- (setn (map cadddr arg-info))
- (mutable
- (map (lambda (x) (car (cddddr x))) arg-info)))
- (list (make-defstruct
- n
- (cons n args)
- (symbol-append 'make- n)
- (symbol-append n '?)
- get
- set
- getn
- setn
- mutable)))))
- (('define-const-structure
- ((? symbol? n) . args)
- inits)
- (syntax-err
- def
- "sorry, structure initializers are not supported"))
- (('datatype . d)
- (let* ((parse-variant
- (match-lambda
- (((? symbol? con) ? list? args)
- (let ((n (parse-name con)))
- (make-variant
- (symbol-append 'make- n)
- (symbol-append n '?)
- (cons con args))))
- (_ (syntax-err def "invalid datatype syntax"))))
- (parse-dt
- (match-lambda
- (((? symbol? type) . variants)
- (cons (list (parse-name type))
- (smap parse-variant variants)))
- ((((? symbol? type) ? list? targs) . variants)
- (cons (cons (parse-name type)
- (smap parse-name targs))
- (smap parse-variant variants)))
- (_ (syntax-err def "invalid datatype syntax")))))
- (list (make-datatype (smap parse-dt d)))))
- (((? symbol? k) . _)
- (cond ((and (not (keyword? k))
- (expand-once-if-macro def))
- =>
- parse-def)
- (else (list (make-define #f (parse-exp def))))))
- (_ (list (make-define #f (parse-exp def))))))))
- (define keep-match #t)
- (define parse-exp
- (lambda (expression)
- (letrec ((n-primitive (string->symbol "#primitive"))
- (parse-exp
- (match-lambda
- (('quote (? symbol? s)) (make-const s 'symbol?))
- ((and m ('quote _)) (parse-exp (quote-tf m)))
- ((and m ('quasiquote _))
- (parse-exp (quasiquote-tf m)))
- ((and m (? box?)) (parse-exp (quote-tf m)))
- ((and m (? vector?)) (parse-exp (quote-tf m)))
- ((and m ('cond . _)) (parse-exp (cond-tf m)))
- ((and m ('case . _)) (parse-exp (case-tf m)))
- ((and m ('do . _)) (parse-exp (do-tf m)))
- ((? symbol? s) (make-var (parse-name s)))
- (#t (make-const #t 'true-object?))
- (#f (make-const #f 'false-object?))
- ((? null? c) (make-const c 'null?))
- ((? number? c) (make-const c 'number?))
- ((? char? c) (make-const c 'char?))
- ((? string? c) (make-const c 'string?))
- ((': ty e1) (make-cast ty (parse-exp e1)))
- ((and exp ('record . bind))
- (let ((bindings (smap parse-bind bind)))
- (no-repeats (map bind-name bindings) exp)
- (make-record bindings)))
- ((and exp ('field name e1))
- (make-field (parse-name name) (parse-exp e1)))
- ((and exp ('match e clause0 . clauses))
- (=> fail)
- (if keep-match
- (let* ((e2 (parse-exp e))
- (parse-clause
- (match-lambda
- ((p ('=> (? symbol? failsym)) . body)
- (make-mclause
- (parse-pat p expression)
- (parse-body
- `((let ((,failsym (lambda () (,failsym))))
- ,@body)))
- failsym))
- ((p . body)
- (make-mclause
- (parse-pat p expression)
- (parse-body body)
- #f))
- (_ (syntax-err exp "invalid match clause")))))
- (make-match
- e2
- (smap parse-clause (cons clause0 clauses))))
- (fail)))
- ((and exp ('lambda bind . body))
- (recur loop
- ((b bind) (names '()))
- (match b
- ((? symbol? n)
- (let ((rest (parse-name n)))
- (no-repeats (cons rest names) exp)
- (make-vlam
- (reverse names)
- rest
- (parse-body body))))
- (()
- (no-repeats names exp)
- (make-lam (reverse names) (parse-body body)))
- ((n . x) (loop x (cons (parse-name n) names)))
- (_ (syntax-err
- exp
- "invalid lambda expression")))))
- (('if e1 e2 e3)
- (make-if
- (parse-exp e1)
- (parse-exp e2)
- (parse-exp e3)))
- ((and if-expr ('if e1 e2))
- (printf "Note: one-armed if: ")
- (print-context if-expr 2)
- (make-if
- (parse-exp e1)
- (parse-exp e2)
- (parse-exp '(void))))
- (('delay e) (make-delay (parse-exp e)))
- (('set! n e)
- (make-set! (parse-name n) (parse-exp e)))
- (('and . args) (make-and (smap parse-exp args)))
- (('or . args) (make-or (smap parse-exp args)))
- ((and exp ('let (? symbol? n) bind . body))
- (let* ((nb (parse-name n))
- (bindings (smap parse-bind bind)))
- (no-repeats (map bind-name bindings) exp)
- (make-app
- (make-letr
- (list (make-bind
- nb
- (make-lam
- (map bind-name bindings)
- (parse-body body))))
- (make-body '() (list (make-var nb))))
- (map bind-exp bindings))))
- ((and exp ('let bind . body))
- (let ((bindings (smap parse-bind bind)))
- (no-repeats (map bind-name bindings) exp)
- (make-let bindings (parse-body body))))
- (('let* bind . body)
- (make-let*
- (smap parse-bind bind)
- (parse-body body)))
- ((and exp ('letrec bind . body))
- (let ((bindings (smap parse-bind bind)))
- (no-repeats (map bind-name bindings) exp)
- (make-letr bindings (parse-body body))))
- (('begin e1 . rest)
- (make-begin (smap parse-exp (cons e1 rest))))
- (('define . _)
- (syntax-err
- expression
- "invalid context for internal define"))
- (('define-structure . _)
- (syntax-err
- expression
- "invalid context for internal define-structure"))
- (('define-const-structure . _)
- (syntax-err
- expression
- "invalid context for internal define-const-structure"))
- ((and m (f . args))
- (cond ((and (eq? f n-primitive)
- (match args
- (((? symbol? p)) (make-prim p))
- (_ #f))))
- ((and (symbol? f)
- (not (keyword? f))
- (expand-once-if-macro m))
- =>
- parse-exp)
- (else
- (make-app (parse-exp f) (smap parse-exp args)))))
- (x (syntax-err
- expression
- "invalid expression at ~a"
- x))))
- (parse-name
- (match-lambda
- ((? symbol? s)
- (when (keyword? s)
- (syntax-err
- expression
- "invalid use of keyword ~a"
- s))
- s)
- (n (syntax-err
- expression
- "invalid variable at ~a"
- n))))
- (parse-bind
- (match-lambda
- ((x e) (make-bind (parse-name x) (parse-exp e)))
- (b (syntax-err expression "invalid binding at ~a" b))))
- (parse-body
- (lambda (body)
- (recur loop
- ((b body) (defs '()))
- (match b
- (((and d ('define . _)) . rest)
- (loop rest (append defs (parse-def d))))
- (((and d ('define-structure . _)) . rest)
- (loop rest (append defs (parse-def d))))
- (((and d ('define-const-structure . _)) . rest)
- (loop rest (append defs (parse-def d))))
- ((('begin) . rest) (loop rest defs))
- (((and beg ('begin ('define . _) . _)) . rest)
- (loop rest (append defs (parse-def beg))))
- (((and beg ('begin ('define-structure . _) . _))
- .
- rest)
- (loop rest (append defs (parse-def beg))))
- (((and beg
- ('begin
- ('define-const-structure . _)
- .
- _))
- .
- rest)
- (loop rest (append defs (parse-def beg))))
- ((_ . _) (make-body defs (smap parse-exp b)))
- (_ (syntax-err
- expression
- "invalid body at ~a"
- b))))))
- (no-repeats
- (lambda (l exp)
- (match l
- (() #f)
- ((_) #f)
- ((x . l)
- (if (memq x l)
- (syntax-err exp "name ~a repeated" x)
- (no-repeats l exp)))))))
- (parse-exp expression))))
- (define parse-pat
- (lambda (pat expression)
- (letrec ((parse-pat
- (match-lambda
- (#f (make-ppred 'false-object?))
- (#t (make-ppred 'true-object?))
- (() (make-ppred 'null?))
- ((? number? c) (make-pconst c 'number?))
- ((? char? c) (make-pconst c 'char?))
- ((? string? c) (make-pconst c 'string?))
- (('quote x) (parse-quote x))
- ('_ (make-pany))
- ('else (make-pelse))
- ((? symbol? n) (make-pvar (parse-pname n)))
- (('not . pats)
- (syntax-err
- expression
- "not patterns are not supported"))
- (('or . pats)
- (syntax-err
- expression
- "or patterns are not supported"))
- (('get! . pats)
- (syntax-err
- expression
- "get! patterns are not supported"))
- (('set! . pats)
- (syntax-err
- expression
- "set! patterns are not supported"))
- (('and . pats)
- (let* ((pats (smap parse-pat pats))
- (p (make-flat-pand pats))
- (non-var?
- (match-lambda
- ((? pvar?) #f)
- ((? pany?) #f)
- (_ #t))))
- (match p
- (($ pand pats)
- (when (< 1 (length (filter non-var? pats)))
- (syntax-err
- expression
- "~a has conflicting subpatterns"
- (ppat p))))
- (_ #f))
- p))
- (('? (? symbol? pred) p)
- (parse-pat `(and (? ,pred) ,p)))
- (('? (? symbol? pred))
- (if (keyword? pred)
- (syntax-err
- expression
- "invalid use of keyword ~a"
- pred)
- (make-ppred pred)))
- (('$ (? symbol? c) . args)
- (if (memq c '(? _ $))
- (syntax-err
- expression
- "invalid use of pattern keyword ~a"
- c)
- (make-pobj
- (symbol-append c '?)
- (smap parse-pat args))))
- ((? box? cb)
- (make-pobj 'box? (list (parse-pat (unbox cb)))))
- ((x . y)
- (make-pobj
- 'pair?
- (list (parse-pat x) (parse-pat y))))
- ((? vector? v)
- (make-pobj
- 'vector?
- (map parse-pat (vector->list v))))
- (m (syntax-err expression "invalid pattern at ~a" m))))
- (parse-quote
- (match-lambda
- (#f (make-pobj 'false-object? '()))
- (#t (make-pobj 'true-object? '()))
- (() (make-pobj 'null? '()))
- ((? number? c) (make-pconst c 'number?))
- ((? char? c) (make-pconst c 'char?))
- ((? string? c) (make-pconst c 'string?))
- ((? symbol? s) (make-pconst s 'symbol?))
- ((? box? cb)
- (make-pobj 'box? (list (parse-quote (unbox cb)))))
- ((x . y)
- (make-pobj
- 'pair?
- (list (parse-quote x) (parse-quote y))))
- ((? vector? v)
- (make-pobj
- 'vector?
- (map parse-quote (vector->list v))))
- (m (syntax-err expression "invalid pattern at ~a" m))))
- (parse-pname
- (match-lambda
- ((? symbol? s)
- (cond ((keyword? s)
- (syntax-err
- expression
- "invalid use of keyword ~a"
- s))
- ((memq s '(? _ else $ and or not set! get! ...))
- (syntax-err
- expression
- "invalid use of pattern keyword ~a"
- s))
- (else s)))
- (n (syntax-err
- expression
- "invalid pattern variable at ~a"
- n)))))
- (parse-pat pat))))
- (define smap
- (lambda (f l)
- (match l
- (() '())
- ((x . r) (let ((v (f x))) (cons v (smap f r))))
- (_ (syntax-err l "invalid list")))))
- (define primitive
- (lambda (p)
- (list (string->symbol "#primitive") p)))
- (define keyword?
- (lambda (s)
- (or (memq s
- '(=> and
- begin
- case
- cond
- do
- define
- delay
- if
- lambda
- let
- let*
- letrec
- or
- quasiquote
- quote
- set!
- unquote
- unquote-splicing
- define-structure
- define-const-structure
- record
- field
- :
- datatype))
- (and keep-match (eq? s 'match)))))
- (define make-flat-pand
- (lambda (pats)
- (let* ((l (foldr (lambda (p plist)
- (match p
- (($ pand pats) (append pats plist))
- (_ (cons p plist))))
- '()
- pats))
- (concrete?
- (match-lambda
- ((? pconst?) #t)
- ((? pobj?) #t)
- ((? ppred?) #t)
- (_ #f)))
- (sorted
- (append
- (filter concrete? l)
- (filter (lambda (x) (not (concrete? x))) l))))
- (match sorted ((p) p) (_ (make-pand sorted))))))
- (define never-counter 0)
- (define reinit-macros!
- (lambda () (set! never-counter 0)))
- (define cond-tf
- (lambda (cond-expr)
- (recur loop
- ((e (cdr cond-expr)))
- (match e
- (()
- (begin
- (set! never-counter (+ 1 never-counter))
- `(,(primitive 'should-never-reach)
- '(cond ,never-counter))))
- ((('else b1 . body)) `(begin ,b1 ,@body))
- ((('else . _) . _)
- (syntax-err cond-expr "invalid cond expression"))
- (((test '=> proc) . rest)
- (let ((g (gensym)))
- `(let ((,g ,test))
- (if ,g (,proc ,g) ,(loop rest)))))
- (((#t b1 . body)) `(begin ,b1 ,@body))
- (((test) . rest) `(or ,test ,(loop rest)))
- (((test . body) . rest)
- `(if ,test (begin ,@body) ,(loop rest)))
- (_ (syntax-err cond-expr "invalid cond expression"))))))
- (define scheme-cond-tf
- (lambda (cond-expr)
- (recur loop
- ((e (cdr cond-expr)))
- (match e
- (() `(,(primitive 'void)))
- ((('else b1 . body)) `(begin ,b1 ,@body))
- ((('else . _) . _)
- (syntax-err cond-expr "invalid cond expression"))
- (((test '=> proc) . rest)
- (let ((g (gensym)))
- `(let ((,g ,test))
- (if ,g (,proc ,g) ,(loop rest)))))
- (((#t b1 . body)) `(begin ,b1 ,@body))
- (((test) . rest) `(or ,test ,(loop rest)))
- (((test . body) . rest)
- `(if ,test (begin ,@body) ,(loop rest)))
- (_ (syntax-err cond-expr "invalid cond expression"))))))
- (define case-tf
- (lambda (case-expr)
- (recur loop
- ((e (cdr case-expr)))
- (match e
- ((exp) `(begin ,exp (,(primitive 'void))))
- ((exp ('else b1 . body)) `(begin ,b1 ,@body))
- ((exp ('else . _) . _)
- (syntax-err case-expr "invalid case expression"))
- (((? symbol? exp)
- ((? list? test) b1 . body)
- .
- rest)
- `(if (,(primitive 'memv) ,exp ',test)
- (begin ,b1 ,@body)
- ,(loop (cons exp rest))))
- (((? symbol? exp) (test b1 . body) . rest)
- `(if (,(primitive 'memv) ,exp '(,test))
- (begin ,b1 ,@body)
- ,(loop (cons exp rest))))
- ((exp . rest)
- (if (not (symbol? exp))
- (let ((g (gensym)))
- `(let ((,g ,exp)) ,(loop (cons g rest))))
- (syntax-err case-expr "invalid case expression")))
- (_ (syntax-err case-expr "invalid case expression"))))))
- (define conslimit 8)
- (define quote-tf
- (lambda (exp)
- (letrec ((qloop (match-lambda
- ((? box? q)
- `(,(primitive qbox) ,(qloop (unbox q))))
- ((? symbol? q) `',q)
- ((? null? q) q)
- ((? list? q)
- (if (< (length q) conslimit)
- `(,(primitive qcons)
- ,(qloop (car q))
- ,(qloop (cdr q)))
- `(,(primitive qlist) ,@(map qloop q))))
- ((x . y)
- `(,(primitive qcons) ,(qloop x) ,(qloop y)))
- ((? vector? q)
- `(,(primitive qvector)
- ,@(map qloop (vector->list q))))
- ((? boolean? q) q)
- ((? number? q) q)
- ((? char? q) q)
- ((? string? q) q)
- (q (syntax-err
- exp
- "invalid quote expression at ~a"
- q)))))
- (match exp
- (('quote q) (qloop q))
- ((? vector? q) (qloop q))
- ((? box? q) (qloop q))))))
- (define quasiquote-tf
- (lambda (exp)
- (letrec ((make-cons
- (lambda (x y)
- (cond ((null? y) `(,(primitive 'list) ,x))
- ((and (pair? y)
- (equal? (car y) (primitive 'list)))
- (cons (car y) (cons x (cdr y))))
- (else `(,(primitive 'cons) ,x ,y)))))
- (qloop (lambda (e n)
- (match e
- (('quasiquote e)
- (make-cons 'quasiquote (qloop `(,e) (+ 1 n))))
- (('unquote e)
- (if (zero? n)
- e
- (make-cons 'unquote (qloop `(,e) (- n 1)))))
- (('unquote-splicing e)
- (if (zero? n)
- e
- (make-cons
- 'unquote-splicing
- (qloop `(,e) (- n 1)))))
- ((('unquote-splicing e) . y)
- (=> fail)
- (if (zero? n)
- (if (null? y)
- e
- `(,(primitive 'append) ,e ,(qloop y n)))
- (fail)))
- ((? box? q)
- `(,(primitive 'box) ,(qloop (unbox q) n)))
- ((? symbol? q)
- (if (memq q
- '(quasiquote unquote unquote-splicing))
- (syntax-err
- exp
- "invalid use of ~a inside quasiquote"
- q)
- `',q))
- ((? null? q) q)
- ((x . y) (make-cons (qloop x n) (qloop y n)))
- ((? vector? q)
- `(,(primitive 'vector)
- ,@(map (lambda (z) (qloop z n))
- (vector->list q))))
- ((? boolean? q) q)
- ((? number? q) q)
- ((? char? q) q)
- ((? string? q) q)
- (q (syntax-err
- exp
- "invalid quasiquote expression at ~a"
- q))))))
- (match exp (('quasiquote q) (qloop q 0))))))
- (define do-tf
- (lambda (do-expr)
- (recur loop
- ((e (cdr do-expr)))
- (match e
- (((? list? vis) (e0 ? list? e1) ? list? c)
- (if (andmap (match-lambda ((_ _ . _) #t) (_ #f)) vis)
- (let* ((var (map car vis))
- (init (map cadr vis))
- (step (map cddr vis))
- (step (map (lambda (v s)
- (match s
- (() v)
- ((e) e)
- (_ (syntax-err
- do-expr
- "invalid do expression"))))
- var
- step)))
- (let ((doloop (gensym)))
- (match e1
- (()
- `(let ,doloop
- ,(map list var init)
- (if (not ,e0)
- (begin ,@c (,doloop ,@step) (void))
- (void))))
- ((body0 ? list? body)
- `(let ,doloop
- ,(map list var init)
- (if ,e0
- (begin ,body0 ,@body)
- (begin ,@c (,doloop ,@step)))))
- (_ (syntax-err
- do-expr
- "invalid do expression")))))
- (syntax-err do-expr "invalid do expression")))
- (_ (syntax-err do-expr "invalid do expression"))))))
- (define empty-env '())
- (define lookup
- (lambda (env x)
- (match (assq x env)
- (#f (disaster 'lookup "no binding for ~a" x))
- ((_ . b) b))))
- (define lookup?
- (lambda (env x)
- (match (assq x env) (#f #f) ((_ . b) b))))
- (define bound?
- (lambda (env x)
- (match (assq x env) (#f #f) (_ #t))))
- (define extend-env
- (lambda (env x v) (cons (cons x v) env)))
- (define extend-env*
- (lambda (env xs vs)
- (append (map2 cons xs vs) env)))
- (define join-env
- (lambda (env newenv) (append newenv env)))
- (define populated #t)
- (define pseudo #f)
- (define global-error #f)
- (define share #f)
- (define matchst #f)
- (define fullsharing #t)
- (define dump-depths #f)
- (define flags #t)
- (define-structure
- (c depth kind fsym pres args next))
- (define-structure
- (v depth kind name vis split inst))
- (define-structure (ts type n-gen))
- (define-structure (k name order args))
- (define top (box 'top))
- (define bot (box 'bot))
- (define generic? (lambda (d) (< d 0)))
- (define new-type
- (lambda (s d)
- (let ((t (box s)))
- (vector-set!
- types
- d
- (cons t (vector-ref types d)))
- t)))
- (define generate-counter
- (lambda ()
- (let ((n 0)) (lambda () (set! n (+ 1 n)) n))))
- (define var-counter (generate-counter))
- (define make-raw-tvar
- (lambda (d k) (make-v d k var-counter #t #f #f)))
- (define make-tvar
- (lambda (d k) (new-type (make-raw-tvar d k) d)))
- (define ord? (lambda (k) (eq? 'ord k)))
- (define abs? (lambda (k) (eq? 'abs k)))
- (define pre? (lambda (k) (eq? 'pre k)))
- (define ord-depth 2)
- (define depth ord-depth)
- (define types (make-vector 16 '()))
- (define reset-types!
- (lambda ()
- (set! depth ord-depth)
- (set! types (make-vector 16 '()))))
- (define push-level
- (lambda ()
- (set! depth (+ depth 1))
- (when (< (vector-length types) (+ 1 depth))
- (set! types
- (let ((l (vector->list types)))
- (list->vector
- (append l (map (lambda (_) '()) l))))))))
- (define pop-level
- (lambda ()
- (vector-set! types depth '())
- (set! depth (- depth 1))))
- (define v-ord (lambda () (make-tvar depth 'ord)))
- (define v-abs (lambda () (make-tvar depth 'abs)))
- (define v-pre (lambda () (make-tvar depth 'pre)))
- (define tvar v-ord)
- (define out1tvar
- (lambda () (make-tvar (- depth 1) 'ord)))
- (define monotvar
- (lambda () (make-tvar ord-depth 'ord)))
- (define pvar
- (match-lambda
- (($ box (and x ($ v d k _ vis _ _)))
- (unless
- (number? (v-name x))
- (set-v-name! x ((v-name x))))
- (string->symbol
- (sprintf
- "~a~a~a"
- (match k
- ('ord
- (if (generic? d)
- (if vis "X" "x")
- (if vis "Z" "z")))
- ('abs (if vis "A" "a"))
- ('pre (if vis "P" "p")))
- (v-name x)
- (if dump-depths (sprintf ".~a" d) ""))))))
- (define make-tvar-like
- (match-lambda
- (($ box ($ v d k _ _ _ _)) (make-tvar d k))))
- (define ind*
- (lambda (t)
- (match (unbox t)
- ((? box? u)
- (let ((v (ind* u))) (set-box! t v) v))
- (_ t))))
- (define type-check?
- (match-lambda
- ((abs def inexhaust once _)
- (cond (((if once check-abs1? check-abs?) abs)
- (if (and def (definite? def)) 'def #t))
- (inexhaust 'inexhaust)
- (else #f)))))
- (define type-check1?
- (match-lambda
- ((abs def inexhaust _ _)
- (cond ((check-abs1? abs)
- (if (and def (definite? def)) 'def #t))
- (inexhaust 'inexhaust)
- (else #f)))))
- (define check-abs?
- (lambda (vlist)
- (letrec ((seen '())
- (labs? (lambda (t)
- (match t
- (($ box ($ v _ _ _ _ _ inst))
- (and inst
- (not (memq t seen))
- (begin
- (set! seen (cons t seen))
- (ormap (match-lambda ((t . _) (labs? t)))
- inst))))
- (($ box ($ c _ _ _ p _ n))
- (or (labs? p) (labs? n)))
- (($ box (? symbol?)) #t)
- (($ box i) (labs? i))))))
- (ormap labs? vlist))))
- (define check-abs1?
- (lambda (vlist)
- (letrec ((labs1?
- (lambda (t)
- (match t
- (($ box (? v?)) #f)
- (($ box ($ c _ _ _ p _ n))
- (or (labs1? p) (labs1? n)))
- (($ box (? symbol?)) #t)
- (($ box i) (labs1? i))))))
- (ormap labs1? vlist))))
- (define check-sources
- (lambda (info)
- (letrec ((seen '())
- (lsrcs (lambda (t source)
- (match t
- (($ box ($ v _ k _ _ _ inst))
- (union (if (and inst (not (memq t seen)))
- (begin
- (set! seen (cons t seen))
- (foldr union
- empty-set
- (map (match-lambda
- ((t . s) (lsrcs t s)))
- inst)))
- empty-set)))
- (($ box ($ c _ _ _ p _ n))
- (union (lsrcs p source) (lsrcs n source)))
- (($ box (? symbol?))
- (if source (set source) empty-set))
- (($ box i) (lsrcs i source))))))
- (match-let
- (((abs _ _ _ _) info))
- (if (eq? #t abs)
- empty-set
- (foldr union
- empty-set
- (map (lambda (t) (lsrcs t #f)) abs)))))))
- (define check-local-sources
- (match-lambda ((_ _ _ _ component) component)))
- (define mk-definite-prim
- (match-lambda
- (($ box ($ c _ _ x p a n))
- (if (eq? (k-name x) '?->)
- (let ((seen '()))
- (recur lprim
- ((t (car a)))
- (match t
- (($ box ($ c _ _ x p a n))
- (if (memq t seen)
- '()
- (begin
- (set! seen (cons t seen))
- (match (k-name x)
- ('noarg (cons p (lprim n)))
- ('arg
- (let ((args (recur argloop
- ((a (car a)))
- (match a
- (($ box
- ($ c
- _
- _
- _
- p
- _
- n))
- (cons p
- (argloop
- n)))
- (($ box
- ($ v
- _
- k
- _
- _
- _
- _))
- (if (ord? k)
- (list a)
- '()))
- (($ box
- (? symbol?))
- '())
- (($ box i)
- (argloop i))))))
- (cons (list p args (lprim (cadr a)))
- (lprim n))))))))
- (($ box ($ v _ k _ _ _ _))
- (if (ord? k) (list t) '()))
- (($ box (? symbol?)) '())
- (($ box i) (lprim i)))))
- (mk-definite-prim n)))
- (($ box (? v?)) '())
- (($ box (? symbol?)) '())
- (($ box i) (mk-definite-prim i))))
- (define mk-definite-app
- (match-lambda
- (($ box ($ c _ _ _ p _ _)) (list p))))
- (define mk-definite-lam
- (match-lambda
- (($ box ($ c _ _ x p a n))
- (if (eq? (k-name x) '?->)
- (let ((seen '()))
- (recur llam
- ((t (car a)))
- (match t
- (($ box ($ c _ _ x p a n))
- (if (memq t seen)
- '()
- (begin
- (set! seen (cons t seen))
- (match (k-name x)
- ('noarg (cons p (llam n)))
- ('arg
- (let ((args (list top)))
- (cons (list p args (llam (cadr a)))
- (llam n))))))))
- (($ box ($ v _ k _ _ _ _))
- (if (ord? k) (list t) '()))
- (($ box (? symbol?)) '())
- (($ box i) (llam i)))))
- (mk-definite-lam n)))
- (($ box (? v?)) '())
- (($ box (? symbol?)) '())
- (($ box i) (mk-definite-lam i))))
- (define definite?
- (lambda (def-info)
- (letrec ((non-empty?
- (lambda (t)
- (let ((seen '()))
- (recur ldef
- ((t t))
- (match t
- (($ box ($ c _ _ _ p _ n))
- (or (ldef p) (ldef n)))
- (($ box ($ v d k _ _ _ inst))
- (if (or global-error (abs? k))
- (and inst
- (generic? d)
- (not (memq t seen))
- (begin
- (set! seen (cons t seen))
- (ormap (match-lambda
- ((t . _) (ldef t)))
- inst)))
- (generic? d)))
- (($ box 'top) #t)
- (($ box 'bot) #f)
- (($ box i) (ldef i)))))))
- (ok (lambda (l)
- (ormap (match-lambda
- ((? box? t) (non-empty? t))
- ((p arg rest)
- (and (non-empty? p)
- (ormap non-empty? arg)
- (ok rest))))
- l))))
- (not (ok def-info)))))
- (define close
- (lambda (t-list) (close-type t-list #f)))
- (define closeall
- (lambda (t) (car (close-type (list t) #t))))
- (define for
- (lambda (from to f)
- (cond ((= from to) (f from))
- ((< from to)
- (begin (f from) (for (+ from 1) to f)))
- (else #f))))
- (define close-type
- (lambda (t-list all?)
- (let* ((sorted (make-vector (+ depth 1) '()))
- (sort (lambda (t)
- (match t
- (($ box ($ c d _ _ _ _ _))
- (vector-set!
- sorted
- d
- (cons t (vector-ref sorted d))))
- (($ box ($ v d _ _ _ _ _))
- (vector-set!
- sorted
- d
- (cons t (vector-ref sorted d))))
- (_ #f))))
- (prop-d
- (lambda (down)
- (letrec ((pr (match-lambda
- (($ box (and x ($ v d _ _ _ _ _)))
- (when (< down d) (set-v-depth! x down)))
- (($ box (and x ($ c d _ _ p a n)))
- (when (< down d)
- (set-c-depth! x down)
- (pr p)
- (for-each pr a)
- (pr n)))
- (($ box (? symbol?)) #f)
- (z (pr (ind* z))))))
- (match-lambda
- (($ box (and x ($ c d _ _ p a n)))
- (when (<= down d) (pr p) (for-each pr a) (pr n)))
- (_ #f)))))
- (prop-k
- (lambda (t)
- (let ((pk (lambda (kind)
- (rec pr
- (match-lambda
- (($ box (and x ($ v _ k _ _ _ _)))
- (when (kind< kind k) (set-v-kind! x kind)))
- (($ box (and x ($ c _ k _ p a n)))
- (when (kind< kind k)
- (set-c-kind! x kind)
- (pr p)
- (unless populated (for-each pr a))
- (pr n)))
- (($ box (? symbol?)) #f)
- (z (pr (ind* z))))))))
- (match t
- (($ box (and x ($ c _ k _ p a n)))
- (when (not (ord? k))
- (let ((prop (pk k)))
- (prop p)
- (unless populated (for-each prop a))
- (prop n))))
- (_ #f)))))
- (might-be-generalized?
- (match-lambda
- (($ box ($ v d k _ _ _ _))
- (and (<= depth d) (or populated (ord? k) all?)))
- (($ box ($ c d k _ _ _ _))
- (and (<= depth d) (or populated (ord? k) all?)))
- (($ box (? symbol?)) #f)))
- (leaves '())
- (depth-of
- (match-lambda
- (($ box ($ v d _ _ _ _ _)) d)
- (($ box ($ c d _ _ _ _ _)) d)))
- (vector-grow
- (lambda (v)
- (let* ((n (vector-length v))
- (v2 (make-vector (* n 2) '())))
- (recur loop
- ((i 0))
- (when (< i n)
- (vector-set! v2 i (vector-ref v i))
- (loop (+ 1 i))))
- v2)))
- (parents (make-vector 64 '()))
- (parent-index 0)
- (parents-of
- (lambda (t)
- (let ((d (depth-of t)))
- (if (< depth d)
- (vector-ref parents (- (- d depth) 1))
- '()))))
- (xtnd-parents!
- (lambda (t parent)
- (match t
- (($ box (and x ($ v d _ _ _ _ _)))
- (when (= d depth)
- (set! parent-index (+ 1 parent-index))
- (set-v-depth! x (+ depth parent-index))
- (when (< (vector-length parents) parent-index)
- (set! parents (vector-grow parents)))
- (set! d (+ depth parent-index)))
- (vector-set!
- parents
- (- (- d depth) 1)
- (cons parent
- (vector-ref parents (- (- d depth) 1)))))
- (($ box (and x ($ c d _ _ _ _ _)))
- (when (= d depth)
- (set! parent-index (+ 1 parent-index))
- (set-c-depth! x (+ depth parent-index))
- (when (< (vector-length parents) parent-index)
- (set! parents (vector-grow parents)))
- (set! d (+ depth parent-index)))
- (vector-set!
- parents
- (- (- d depth) 1)
- (cons parent
- (vector-ref parents (- (- d depth) 1))))))))
- (needs-cleanup '())
- (revtype
- (rec revtype
- (lambda (parent t)
- (let ((t (ind* t)))
- (cond ((not (might-be-generalized? t)) #f)
- ((null? (parents-of t))
- (xtnd-parents! t parent)
- (set! needs-cleanup (cons t needs-cleanup))
- (match t
- (($ box (? v?))
- (set! leaves (cons t leaves)))
- (($ box ($ c _ _ _ p a n))
- (let ((rev (lambda (q) (revtype t q))))
- (rev p)
- (for-each rev a)
- (rev n)))))
- ((not (memq parent (parents-of t)))
- (xtnd-parents! t parent))
- (else #f))))))
- (generic-index 0)
- (gen (rec gen
- (lambda (t)
- (let ((t (ind* t)))
- (when (might-be-generalized? t)
- (set! generic-index (- generic-index 1))
- (let ((parents (parents-of t)))
- (match t
- (($ box (and x ($ v _ k _ _ _ _)))
- (set-v-depth! x generic-index)
- (when (and populated
- (or global-error
- (abs? k)
- (pre? k))
- (not all?))
- (set-v-inst! x '())))
- (($ box (? c? x))
- (set-c-depth! x generic-index)))
- (for-each gen parents)))))))
- (cleanup
- (match-lambda
- (($ box (and x ($ v d _ _ _ _ _)))
- (unless (< d 0) (set-v-depth! x (- depth 1))))
- (($ box (and x ($ c d _ _ _ _ _)))
- (unless (< d 0) (set-c-depth! x (- depth 1))))))
- (gen2 (rec gen
- (lambda (t)
- (let ((t (ind* t)))
- (when (might-be-generalized? t)
- (set! generic-index (- generic-index 1))
- (match t
- (($ box (and x ($ v _ k _ _ _ _)))
- (set-v-depth! x generic-index)
- (when (and populated
- (or global-error
- (abs? k)
- (pre? k))
- (not all?))
- (set-v-inst! x '())))
- (($ box (and x ($ c _ _ _ p a n)))
- (set-c-depth! x generic-index)
- (gen p)
- (for-each gen a)
- (gen n))))))))
- (upd (lambda (t)
- (let ((d (depth-of t)))
- (when (< 0 d)
- (vector-set!
- types
- d
- (cons t (vector-ref types d))))))))
- (for-each sort (vector-ref types depth))
- (for 0
- (- depth 1)
- (lambda (i)
- (for-each (prop-d i) (vector-ref sorted i))))
- (for-each prop-k (vector-ref types depth))
- (vector-set! types depth '())
- (if fullsharing
- (begin
- (for-each (lambda (t) (revtype t t)) t-list)
- (for-each gen leaves)
- (for-each cleanup needs-cleanup))
- (for-each gen2 t-list))
- (for 0
- depth
- (lambda (i) (for-each upd (vector-ref sorted i))))
- (if (null? t-list)
- '()
- (match-let*
- ((n-gen (- generic-index))
- ((t-list n-gen)
- (if (and pseudo flags (not all?))
- (pseudo t-list n-gen)
- (list t-list n-gen))))
- (visible t-list n-gen)
- (map (lambda (t) (make-ts t n-gen)) t-list))))))
- (define visible-time 0)
- (define visible
- (lambda (t-list n-gen)
- (let* ((before (cpu-time))
- (valences (make-vector n-gen '()))
- (namer (generate-counter))
- (lvis (rec lvis
- (lambda (t pos rcd)
- (match t
- (($ box ($ c d _ x p a n))
- (when (and (generic? d)
- (not (element-of?
- pos
- (vector-ref
- valences
- (- (- d) 1)))))
- (let ((u (union (vector-ref
- valences
- (- (- d) 1))
- (set pos))))
- (vector-set! valences (- (- d) 1) u))
- (lvis p pos rcd)
- (match (k-name x)
- ('?->
- (lvis (car a) (not pos) #f)
- (lvis (cadr a) pos #f))
- ('record (lvis (car a) pos #t))
- (_ (for-each
- (lambda (x) (lvis x pos #f))
- a)))
- (lvis n pos rcd)))
- (($ box (and x ($ v d k _ _ _ _)))
- (when (and (generic? d)
- (not (element-of?
- pos
- (vector-ref
- valences
- (- (- d) 1)))))
- (let ((u (union (vector-ref
- valences
- (- (- d) 1))
- (set pos))))
- (vector-set! valences (- (- d) 1) u)
- (set-v-name! x namer)
- (cond ((abs? k) #f)
- ((= 2 (cardinality u))
- (set-v-split! x #t)
- (set-v-vis! x #t))
- ((eq? pos rcd) (set-v-vis! x #t))
- (else (set-v-vis! x #f))))))
- (($ box (? symbol?)) #f)
- (($ box i) (lvis i pos rcd)))))))
- (for-each (lambda (t) (lvis t #t #f)) t-list)
- (set! visible-time
- (+ visible-time (- (cpu-time) before))))))
- (define visible?
- (match-lambda
- (($ box ($ v _ k _ vis _ _))
- (or (pre? k) (and vis (not (abs? k)))))
- (($ box 'top) #t)
- (($ box 'bot) #f)
- (($ box i) (visible? i))))
- (define instantiate
- (lambda (ts syntax)
- (match ts
- (($ ts t n-gen)
- (let* ((absv '())
- (seen (make-vector n-gen #f))
- (t2 (recur linst
- ((t t))
- (match t
- (($ box (and y ($ v d k _ _ _ inst)))
- (cond ((not (generic? d)) t)
- ((vector-ref seen (- (- d) 1)))
- (else
- (let ((u (make-tvar depth k)))
- (vector-set! seen (- (- d) 1) u)
- (when inst
- (set-v-inst!
- y
- (cons (cons u syntax)
- inst)))
- (when (or (abs? k) (pre? k))
- (set! absv (cons u absv)))
- u))))
- (($ box ($ c d _ x p a n))
- (cond ((not (generic? d)) t)
- ((vector-ref seen (- (- d) 1)))
- (else
- (let ((u (new-type
- '**fix**
- depth)))
- (vector-set! seen (- (- d) 1) u)
- (set-box!
- u
- (make-c
- depth
- 'ord
- x
- (if flags (linst p) top)
- (map linst a)
- (linst n)))
- u))))
- (($ box (? symbol?)) t)
- (($ box i) (linst i))))))
- (list t2 absv))))))
- (define pseudo-subtype
- (lambda (t-list n-gen)
- (let* ((valences (make-vector n-gen '()))
- (valence-of
- (lambda (d) (vector-ref valences (- (- d) 1))))
- (set-valence
- (lambda (d v)
- (vector-set! valences (- (- d) 1) v)))
- (find (rec find
- (lambda (t pos mutable)
- (match t
- (($ box ($ v d _ _ _ _ _))
- (when (generic? d)
- (cond (mutable
- (set-valence d (set #t #f)))
- ((not (element-of?
- pos
- (valence-of d)))
- (set-valence
- d
- (union (valence-of d)
- (set pos))))
- (else #f))))
- (($ box ($ c d _ x p a n))
- (when (generic? d)
- (cond ((= 2 (cardinality (valence-of d)))
- #f)
- (mutable
- (set-valence d (set #t #f))
- (for-each2
- (lambda (t m)
- (find t pos mutable))
- a
- (k-args x))
- (find n pos mutable))
- ((not (element-of?
- pos
- (valence-of d)))
- (set-valence
- d
- (union (valence-of d)
- (set pos)))
- (if (eq? '?-> (k-name x))
- (begin
- (find (car a)
- (not pos)
- mutable)
- (find (cadr a) pos mutable))
- (for-each2
- (lambda (t m)
- (find t pos (or m mutable)))
- a
- (k-args x)))
- (find n pos mutable))
- (else #f))))
- (($ box (? symbol?)) #f)
- (($ box i) (find i pos mutable))))))
- (seen (make-vector n-gen #f))
- (new-generic-var
- (lambda ()
- (set! n-gen (+ 1 n-gen))
- (box (make-raw-tvar (- n-gen) 'ord))))
- (copy (rec copy
- (lambda (t)
- (match t
- (($ box ($ v d k _ _ _ _))
- (if (generic? d)
- (or (vector-ref seen (- (- d) 1))
- (let ((u (if (and (abs? k)
- (equal?
- (valence-of d)
- '(#t)))
- (new-generic-var)
- t)))
- (vector-set! seen (- (- d) 1) u)
- u))
- t))
- (($ box ($ c d k x p a n))
- (if (generic? d)
- (or (vector-ref seen (- (- d) 1))
- (let* ((u (box '**fix**))
- (_ (vector-set!
- seen
- (- (- d) 1)
- u))
- (new-p (if (and (eq? (ind* p) top)
- (equal?
- (valence-of d)
- '(#f)))
- (new-generic-var)
- (copy p)))
- (new-a (map copy a))
- (new-n (copy n)))
- (set-box!
- u
- (make-c d 'ord x new-p new-a new-n))
- u))
- t))
- (($ box (? symbol?)) t)
- (($ box i) (copy i))))))
- (t-list
- (map (lambda (t) (find t #t #f) (copy t)) t-list)))
- (list t-list n-gen))))
- (set! pseudo pseudo-subtype)
- (define unify
- (letrec ((uni (lambda (u v)
- (unless
- (eq? u v)
- (match (cons u v)
- ((($ box (and us ($ c ud uk ux up ua un)))
- $
- box
- (and vs ($ c vd vk vx vp va vn)))
- (if (eq? ux vx)
- (begin
- (if (< ud vd)
- (begin
- (set-box! v u)
- (when (kind< vk uk) (set-c-kind! us vk)))
- (begin
- (set-box! u v)
- (when (kind< uk vk) (set-c-kind! vs uk))))
- (uni un vn)
- (for-each2 uni ua va)
- (uni up vp))
- (let* ((next (tvar))
- (k (if (kind< uk vk) uk vk)))
- (if (< ud vd)
- (begin
- (when (< vd ud) (set-c-depth! us vd))
- (when (kind< vk uk) (set-c-kind! us vk))
- (set-box! v u))
- (begin
- (when (< ud vd) (set-c-depth! vs ud))
- (when (kind< uk vk) (set-c-kind! vs uk))
- (set-box! u v)))
- (uni (new-type
- (make-c depth k ux up ua next)
- depth)
- vn)
- (uni un
- (new-type
- (make-c depth k vx vp va next)
- depth)))))
- ((($ box (and x ($ v ud uk _ _ _ _)))
- $
- box
- ($ v vd vk _ _ _ _))
- (set-v-depth! x (min ud vd))
- (set-v-kind! x (if (kind< uk vk) uk vk))
- (set-box! v u))
- ((($ box ($ v ud uk _ _ _ _))
- $
- box
- (and x ($ c vd vk _ _ _ _)))
- (when (< ud vd) (set-c-depth! x ud))
- (when (kind< uk vk) (set-c-kind! x uk))
- (set-box! u v))
- ((($ box (and x ($ c ud uk _ _ _ _)))
- $
- box
- ($ v vd vk _ _ _ _))
- (when (< vd ud) (set-c-depth! x vd))
- (when (kind< vk uk) (set-c-kind! x vk))
- (set-box! v u))
- ((($ box ($ v _ _ _ _ _ _)) $ box (? symbol?))
- (set-box! u v))
- ((($ box (? symbol?)) $ box ($ v _ _ _ _ _ _))
- (set-box! v u))
- ((($ box 'bot) $ box ($ c _ _ _ p _ n))
- (set-box! v u)
- (uni u p)
- (uni u n))
- ((($ box ($ c _ _ _ p _ n)) $ box 'bot)
- (set-box! u v)
- (uni v p)
- (uni v n))
- (_ (uni (ind* u) (ind* v))))))))
- uni))
- (define kind<
- (lambda (k1 k2) (and (ord? k2) (not (ord? k1)))))
- (define r+-
- (lambda (flag+ flag- tail+- absent- pos env type)
- (letrec ((absent+ v-ord)
- (tvars '())
- (fvars '())
- (absv '())
- (make-flag
- (lambda (pos)
- (cond ((not flags) top)
- (pos (flag+))
- (else (flag-)))))
- (typevar?
- (lambda (v)
- (and (symbol? v)
- (not (bound? env v))
- (not (memq v
- '(_ bool
- mu
- list
- &list
- &optional
- &rest
- arglist
- +
- not
- rec
- *tidy))))))
- (parse-type
- (lambda (t pos)
- (match t
- (('mu a t)
- (unless
- (typevar? a)
- (raise 'type "invalid type syntax at ~a" t))
- (when (assq a tvars)
- (raise 'type "~a is defined more than once" a))
- (let* ((fix (new-type '**fix** depth))
- (_ (set! tvars (cons (list a fix '()) tvars)))
- (t (parse-type t pos)))
- (when (eq? t fix)
- (raise 'type
- "recursive type is not contractive"))
- (set-box! fix t)
- (ind* t)))
- (('rec (? list? bind) t2)
- (for-each
- (match-lambda
- ((a _)
- (unless
- (typevar? a)
- (raise 'type "invalid type syntax at ~a" t))
- (when (assq a tvars)
- (raise 'type
- "~a is defined more than once"
- a))
- (set! tvars
- (cons (list a (new-type '**fix** depth) '())
- tvars)))
- (_ (raise 'type "invalid type syntax at ~a" t)))
- bind)
- (for-each
- (match-lambda
- ((a t)
- (match (assq a tvars)
- ((_ fix _)
- (let ((t (parse-type t '?)))
- (when (eq? t fix)
- (raise 'type
- "type is not contractive"))
- (set-box! fix t))))))
- bind)
- (parse-type t2 pos))
- ('bool (parse-type '(+ false true) pos))
- ('s-exp
- (let ((v (gensym)))
- (parse-type
- `(mu ,v
- (+ num
- nil
- false
- true
- char
- sym
- str
- (vec ,v)
- (box ,v)
- (cons ,v ,v)))
- pos)))
- (('list t)
- (let ((u (gensym)))
- (parse-type `(mu ,u (+ nil (cons ,t ,u))) pos)))
- (('arglist t)
- (let ((u (gensym)))
- (parse-type `(mu ,u (+ noarg (arg ,t ,u))) pos)))
- (('+ ? list? union) (parse-union union pos))
- (t (parse-union (list t) pos)))))
- (parse-union
- (lambda (t pos)
- (letrec ((sort-cs
- (lambda (cs)
- (sort-list
- cs
- (lambda (x y) (k< (c-fsym x) (c-fsym y))))))
- (link (lambda (c t)
- (set-c-next! c t)
- (new-type c depth))))
- (recur loop
- ((t t) (cs '()))
- (match t
- (()
- (foldr link
- (if pos
- (absent+)
- (let ((v (absent-)))
- (set! absv (cons v absv))
- v))
- (sort-cs cs)))
- (((? box? t)) (foldr link t (sort-cs cs)))
- (('_) (foldr link (tail+-) (sort-cs cs)))
- (((? symbol? a))
- (=> fail)
- (unless (typevar? a) (fail))
- (let* ((cs (sort-cs cs))
- (ks (map c-fsym cs)))
- (foldr link
- (match (assq a tvars)
- ((_ f aks)
- (unless
- (equal? ks aks)
- (raise 'type
- "variable ~a is not tidy"
- a))
- f)
- (#f
- (let ((v (tail+-)))
- (set! tvars
- (cons (list a v ks)
- tvars))
- v)))
- cs)))
- ((k . rest)
- (loop rest (cons (parse-k k pos) cs))))))))
- (parse-k
- (lambda (k pos)
- (cond ((and (list? k)
- (let ((n (length k)))
- (and (<= 2 n) (eq? '-> (list-ref k (- n 2))))))
- (let* ((rk (reverse k))
- (arg (reverse (cddr rk)))
- (res (car rk)))
- (letrec ((mkargs
- (match-lambda
- (() 'noarg)
- ((('&rest x)) x)
- ((('&list x))
- (let ((u (gensym)))
- `(mu ,u (+ noarg (arg ,x ,u)))))
- ((('&optional x))
- `(+ noarg (arg ,x noarg)))
- ((x . y) `(arg ,x ,(mkargs y)))
- (_ (raise 'type
- "invalid type syntax")))))
- (make-c
- depth
- 'ord
- (lookup env '?->)
- (make-flag pos)
- (let ((a (parse-type (mkargs arg) (flip pos)))
- (r (parse-type res pos)))
- (list a r))
- '**fix**))))
- (else
- (match k
- ((arg '?-> res)
- (make-c
- depth
- 'ord
- (lookup env '?->)
- (make-flag pos)
- (let ((a (parse-type arg (flip pos)))
- (r (parse-type res pos)))
- (list a r))
- '**fix**))
- (('record ? list? fields)
- (make-c
- depth
- 'ord
- (lookup env 'record)
- (make-flag pos)
- (list (recur loop
- ((fields fields))
- (match fields
- (() (if pos bot (v-ord)))
- ((((? symbol? f) ftype)
- .
- rest)
- (new-type
- (make-c
- depth
- 'ord
- (new-field! f)
- (if pos
- (v-ord)
- (let ((v (v-pre)))
- (set! absv
- (cons v absv))
- v))
- (list (parse-type
- ftype
- pos))
- (loop rest))
- depth)))))
- '**fix**))
- (('not (? k? k))
- (make-c
- depth
- 'ord
- k
- (if pos
- (absent+)
- (let ((v (absent-)))
- (set! absv (cons v absv))
- v))
- (map (lambda (x) (tail+-)) (k-args k))
- '**fix**))
- (('not c)
- (unless
- (bound? env c)
- (raise 'type "invalid type syntax at ~a" k))
- (let ((k (lookup env c)))
- (make-c
- depth
- 'ord
- k
- (if pos
- (absent+)
- (let ((v (absent-)))
- (set! absv (cons v absv))
- v))
- (map (lambda (x) (tail+-)) (k-args k))
- '**fix**)))
- (('*tidy c (? symbol? f))
- (unless
- (bound? env c)
- (raise 'type "invalid type syntax at ~a" k))
- (let ((k (lookup env c)))
- (make-c
- depth
- 'ord
- k
- (match (assq f fvars)
- ((_ . f) f)
- (#f
- (let ((v (tail+-)))
- (set! fvars
- (cons (cons f v) fvars))
- v)))
- (map (lambda (x) (parse-type '(+) pos))
- (k-args k))
- '**fix**)))
- (((? k? k) ? list? arg)
- (unless
- (= (length arg) (length (k-args k)))
- (raise 'type
- "~a requires ~a arguments"
- (k-name k)
- (length (k-args k))))
- (make-c
- depth
- 'ord
- k
- (make-flag pos)
- (smap (lambda (x) (parse-type x pos)) arg)
- '**fix**))
- ((c ? list? arg)
- (unless
- (bound? env c)
- (raise 'type "invalid type syntax at ~a" k))
- (let ((k (lookup env c)))
- (unless
- (= (length arg) (length (k-args k)))
- (raise 'type
- "~a requires ~a arguments"
- c
- (length (k-args k))))
- (make-c
- depth
- 'ord
- k
- (make-flag pos)
- (smap (lambda (x) (parse-type x pos)) arg)
- '**fix**)))
- (c (unless
- (bound? env c)
- (raise 'type
- "invalid type syntax at ~a"
- k))
- (let ((k (lookup env c)))
- (unless
- (= 0 (length (k-args k)))
- (raise 'type
- "~a requires ~a arguments"
- c
- (length (k-args k))))
- (make-c
- depth
- 'ord
- k
- (make-flag pos)
- '()
- '**fix**))))))))
- (flip (match-lambda ('? '?) (#t #f) (#f #t))))
- (let ((t (parse-type type pos))) (list t absv)))))
- (define v-top (lambda () top))
- (define r+
- (lambda (env t)
- (car (r+- v-top v-ord v-ord v-abs #t env t))))
- (define r-
- (lambda (env t)
- (car (r+- v-top v-ord v-ord v-abs #f env t))))
- (define r++
- (lambda (env t)
- (car (r+- v-top v-ord v-ord v-ord #t env t))))
- (define r+collect
- (lambda (env t)
- (r+- v-top v-ord v-ord v-abs #t env t)))
- (define r-collect
- (lambda (env t)
- (r+- v-top v-ord v-ord v-abs #f env t)))
- (define r (lambda (t) (r+ initial-type-env t)))
- (define r-match
- (lambda (t)
- (close '())
- '(pretty-print `(fixing ,(ptype t)))
- (fix-pat-abs! t)
- (list t (collect-abs t))))
- (define collect-abs
- (lambda (t)
- (let ((seen '()))
- (recur loop
- ((t t))
- (match t
- (($ box ($ v _ k _ _ _ _))
- (if (abs? k) (set t) empty-set))
- (($ box ($ c _ _ _ p a n))
- (if (memq t seen)
- empty-set
- (begin
- (set! seen (cons t seen))
- (foldr union
- (union (loop p) (loop n))
- (map loop a)))))
- (($ box (? symbol?)) empty-set)
- (($ box i) (loop i)))))))
- (define fix-pat-abs!
- (lambda (t)
- (let ((seen '()))
- (recur loop
- ((t t))
- (match t
- (($ box (and x ($ v d _ _ _ _ _)))
- (when (= d depth) (set-v-kind! x 'abs)))
- (($ box (and c ($ c _ _ _ p a n)))
- (unless
- (memq t seen)
- (set! seen (cons t seen))
- (loop p)
- (when (and matchst flags (eq? (ind* p) top))
- (set-c-pres! c (v-ord)))
- (for-each loop a)
- (loop n)))
- (($ box (? symbol?)) t)
- (($ box i) (loop i)))))))
- (define pat-var-bind
- (lambda (t)
- (let ((seen '()))
- (recur loop
- ((t t))
- (match t
- (($ box ($ v d _ _ _ _ _))
- (if (< d depth)
- t
- (match (assq t seen)
- ((_ . new) new)
- (#f
- (let* ((new (v-ord)))
- (set! seen (cons (cons t new) seen))
- new)))))
- (($ box ($ c d k x p a n))
- (match (assq t seen)
- ((_ . new) new)
- (#f
- (let* ((fix (new-type '**fix** depth))
- (fixbox (box fix))
- (_ (set! seen (cons (cons t fixbox) seen)))
- (new-p (if flags (loop p) top))
- (new-a (map2 (lambda (mutable a)
- (if mutable a (loop a)))
- (k-args x)
- a))
- (new-n (loop n)))
- (if (and (eq? new-p p)
- (eq? new-n n)
- (andmap eq? new-a a))
- (begin (set-box! fixbox t) t)
- (begin
- (set-box!
- fix
- (make-c d k x new-p new-a new-n))
- fix))))))
- (($ box (? symbol?)) t)
- (($ box i) (loop i)))))))
- (define fields '())
- (define new-field!
- (lambda (x)
- (match (assq x fields)
- (#f
- (let ((k (make-k x (+ 1 (length fields)) '(#f))))
- (set! fields (cons (cons x k) fields))
- k))
- ((_ . k) k))))
- (define k<
- (lambda (x y) (< (k-order x) (k-order y))))
- (define k-counter 0)
- (define bind-tycon
- (lambda (x args covers fail-thunk)
- (when (memq x
- '(_ bool
- mu
- list
- &list
- &optional
- &rest
- arglist
- +
- not
- rec
- *tidy))
- (fail-thunk "invalid type constructor ~a" x))
- (set! k-counter (+ 1 k-counter))
- (make-k
- (if covers
- (symbol-append x "." (- k-counter 100))
- x)
- k-counter
- args)))
- (define initial-type-env '())
- (define init-types!
- (lambda ()
- (set! k-counter 0)
- (set! var-counter (generate-counter))
- (set! initial-type-env
- (foldl (lambda (l env)
- (extend-env
- env
- (car l)
- (bind-tycon
- (car l)
- (cdr l)
- #f
- (lambda x (apply disaster 'init x)))))
- empty-env
- initial-type-info))
- (set! k-counter 100)
- (reset-types!)))
- (define reinit-types!
- (lambda ()
- (set! var-counter (generate-counter))
- (set! k-counter 100)
- (set! fields '())
- (set-cons-mutability! #t)
- (reset-types!)))
- (define deftype
- (lambda (tag mutability)
- (set! initial-type-env
- (extend-env
- initial-type-env
- tag
- (make-k
- tag
- (+ 1 (length initial-type-env))
- mutability)))))
- (define initial-type-info
- '((?-> #f #f)
- (arg #f #f)
- (noarg)
- (num)
- (nil)
- (false)
- (true)
- (char)
- (sym)
- (str)
- (void)
- (iport)
- (oport)
- (eof)
- (vec #t)
- (box #t)
- (cons #t #t)
- (cvec #f)
- (promise #t)
- (record #f)
- (module #f)))
- (define cons-is-mutable #f)
- (define set-cons-mutability!
- (lambda (m)
- (set! cons-is-mutable m)
- (set-k-args!
- (lookup initial-type-env 'cons)
- (list m m))))
- (define tidy?
- (lambda (t)
- (let ((seen '()))
- (recur loop
- ((t t) (label '()))
- (match t
- (($ box (? v?))
- (match (assq t seen)
- (#f (set! seen (cons (cons t label) seen)) #t)
- ((_ . l2) (equal? label l2))))
- (($ box ($ c _ _ x _ a n))
- (match (assq t seen)
- ((_ . l2) (equal? label l2))
- (#f
- (set! seen (cons (cons t label) seen))
- (and (loop n (sort-list (cons x label) k<))
- (andmap (lambda (t) (loop t '())) a)))))
- (($ box (? symbol?)) #t)
- (($ box i) (loop i label)))))))
- (define tidy
- (match-lambda
- (($ ts t _)
- (tidy-print t print-union assemble-union #f))
- (t (tidy-print t print-union assemble-union #f))))
- (define ptype
- (match-lambda
- (($ ts t _)
- (tidy-print
- t
- print-raw-union
- assemble-raw-union
- #t))
- (t (tidy-print
- t
- print-raw-union
- assemble-raw-union
- #t))))
- (define tidy-print
- (lambda (t print assemble top)
- (let* ((share (shared-unions t top))
- (bindings
- (map-with-n
- (lambda (t n)
- (list t
- (box #f)
- (box #f)
- (symbol-append "Y" (+ 1 n))))
- share))
- (body (print t (print-binding bindings)))
- (let-bindings
- (filter-map
- (match-lambda
- ((_ _ ($ box #f) _) #f)
- ((_ ($ box t) ($ box x) _) (list x t)))
- bindings)))
- (assemble let-bindings body))))
- (define print-binding
- (lambda (bindings)
- (lambda (ty share-wrapper var-wrapper render)
- (match (assq ty bindings)
- (#f (render))
- ((_ box-tprint box-name nprint)
- (var-wrapper
- (or (unbox box-name)
- (begin
- (set-box! box-name nprint)
- (set-box! box-tprint (share-wrapper (render)))
- nprint))))))))
- (define shared-unions
- (lambda (t all)
- (let ((seen '()))
- (recur loop
- ((t t) (top #t))
- (match t
- (($ box (? v?)) #f)
- (($ box ($ c _ _ _ _ a n))
- (match (and top (assq t seen))
- (#f
- (set! seen (cons (cons t (box 1)) seen))
- (for-each (lambda (x) (loop x #t)) a)
- (loop n all))
- ((_ . b) (set-box! b (+ 1 (unbox b))))))
- (($ box (? symbol?)) #f)
- (($ box i) (loop i top))))
- (reverse
- (filter-map
- (match-lambda ((_ $ box 1) #f) ((t . _) t))
- seen)))))
- (define print-raw-union
- (lambda (t print-share)
- (recur loop
- ((t t))
- (match t
- (($ box ($ v _ _ _ _ split _))
- (if (and share split)
- (string->symbol (sprintf "~a#" (pvar t)))
- (pvar t)))
- (($ box ($ c d k x p a n))
- (print-share
- t
- (lambda (x) x)
- (lambda (x) x)
- (lambda ()
- (let* ((name (if (abs? k)
- (symbol-append '~ (k-name x))
- (k-name x)))
- (name (if dump-depths
- (symbol-append d '! name)
- name))
- (pr-x `(,name ,@(maplr loop (cons p a)))))
- (cons pr-x (loop n))))))
- (($ box 'top) '+)
- (($ box 'bot) '-)
- (($ box i) (loop i))))))
- (define assemble-raw-union
- (lambda (bindings body)
- (if (null? bindings) body `(rec ,bindings ,body))))
- (define print-union
- (lambda (t print-share)
- (add-+ (recur loop
- ((t t) (tailvis (visible? (tailvar t))))
- (match t
- (($ box (? v?))
- (if (visible? t) (list (pvar t)) '()))
- (($ box ($ c _ _ x p a n))
- (print-share
- t
- add-+
- list
- (lambda ()
- (cond ((visible? p)
- (let* ((split-flag
- (and share
- (match (ind* p)
- (($ box
- ($ v
- _
- _
- _
- _
- split
- _))
- split)
- (_ #f))))
- (kname (if split-flag
- (string->symbol
- (sprintf
- "~a#~a"
- (k-name x)
- (pvar p)))
- (k-name x))))
- (cons (cond ((null? a) kname)
- ((eq? '?-> (k-name x))
- (let ((arg (add-+ (loop (car a)
- (visible?
- (tailvar
- (car a))))))
- (res (add-+ (loop (cadr a)
- (visible?
- (tailvar
- (cadr a)))))))
- (decode-arrow
- kname
- (lambda ()
- (if split-flag
- (string->symbol
- (sprintf
- "->#~a"
- (pvar p)))
- '->))
- arg
- res)))
- ((eq? 'record (k-name x))
- `(,kname
- ,@(loop (car a) #f)))
- (else
- `(,kname
- ,@(maplr (lambda (x)
- (add-+ (loop x
- (visible?
- (tailvar
- x)))))
- a))))
- (loop n tailvis))))
- ((not tailvis) (loop n tailvis))
- (else
- (cons `(not ,(k-name x))
- (loop n tailvis)))))))
- (($ box 'bot) '())
- (($ box i) (loop i tailvis)))))))
- (define assemble-union
- (lambda (bindings body)
- (subst-small-type
- (map clean-binding bindings)
- body)))
- (define add-+
- (match-lambda
- (() 'empty)
- ((t) t)
- (x (cons '+ x))))
- (define tailvar
- (lambda (t)
- (match t
- (($ box (? v?)) t)
- (($ box ($ c _ _ _ _ _ n)) (tailvar n))
- (($ box 'bot) t)
- (($ box i) (tailvar i)))))
- (define decode-arrow
- (lambda (kname thunk-> arg res)
- (let ((args (recur loop
- ((l arg))
- (match l
- ('noarg '())
- (('arg a b) `(,a ,@(loop b)))
- (('+ ('arg a b) 'noarg . _)
- `((&optional ,a) ,@(loop b)))
- (('+ 'noarg ('arg a b) . _)
- `((&optional ,a) ,@(loop b)))
- ((? symbol? z)
- (if (rectypevar? z) `(,z) `((&rest ,z))))
- (('+ 'noarg z) (loop z))
- (('+ ('arg a b) z)
- (loop `(+ (arg ,a ,b) noarg ,z)))))))
- `(,@args ,(thunk->) ,res))))
- (define rectypevar?
- (lambda (s)
- (memq (string-ref (symbol->string s) 0) '(#\Y))))
- (define typevar?
- (lambda (s)
- (memq (string-ref (symbol->string s) 0)
- '(#\X #\Z))))
- (define clean-binding
- (lambda (binding)
- (match binding
- ((u ('+ 'nil ('cons a v)))
- (if (and (equal? u v) (not (memq* u a)))
- (list u `(list ,a))
- binding))
- ((u ('+ ('cons a v) 'nil))
- (if (and (equal? u v) (not (memq* u a)))
- (list u `(list ,a))
- binding))
- ((u ('+ 'nil ('cons a v) (? symbol? z)))
- (if (and (equal? u v) (not (memq* u a)) (typevar? z))
- (list u `(list* ,a ,z))
- binding))
- ((u ('+ ('cons a v) 'nil (? symbol? z)))
- (if (and (equal? u v) (not (memq* u a)) (typevar? z))
- (list u `(list* ,a ,z))
- binding))
- ((u ('+ 'noarg ('arg a v)))
- (if (and (equal? u v) (not (memq* u a)))
- (list u `(&list ,a))
- binding))
- ((u ('+ ('arg a v) 'noarg))
- (if (and (equal? u v) (not (memq* u a)))
- (list u `(&list ,a))
- binding))
- (x x))))
- (define memq*
- (lambda (v t)
- (recur loop
- ((t t))
- (match t
- ((x . y) (or (loop x) (loop y)))
- (_ (eq? v t))))))
- (define subst-type
- (lambda (new old t)
- (match new
- (('list elem) (subst-list elem old t))
- (_ (subst* new old t)))))
- (define subst-list
- (lambda (elem old t)
- (match t
- ((? symbol?) (if (eq? old t) `(list ,elem) t))
- (('+ 'nil ('cons a (? symbol? b)))
- (if (and (eq? b old) (equal? elem a))
- `(list ,elem)
- `(+ nil (cons ,(subst-list elem old a) ,b))))
- (('+ ('cons a (? symbol? b)) 'nil)
- (if (and (eq? b old) (equal? elem a))
- `(list ,elem)
- `(+ nil (cons ,(subst-list elem old a) ,b))))
- ((a . b)
- (cons (subst-list elem old a)
- (subst-list elem old b)))
- (z z))))
- (define subst*
- (lambda (new old t)
- (cond ((eq? old t) new)
- ((pair? t)
- (cons (subst* new old (car t))
- (subst* new old (cdr t))))
- (else t))))
- (define subst-small-type
- (lambda (bindings body)
- (recur loop
- ((bindings bindings) (newb '()) (body body))
- (match bindings
- (()
- (let ((newb (filter
- (match-lambda
- ((name type) (not (equal? name type))))
- newb)))
- (if (null? newb)
- body
- `(rec ,(reverse newb) ,body))))
- (((and b (name type)) . rest)
- (if (and (not (memq* name type)) (small-type? type))
- (loop (subst-type type name rest)
- (subst-type type name newb)
- (subst-type type name body))
- (loop rest (cons b newb) body)))))))
- (define small-type?
- (lambda (t)
- (>= 8
- (recur loop
- ((t t))
- (match t
- ('+ 0)
- ((? symbol? s) 1)
- ((? number? n) 0)
- ((x . y) (+ (loop x) (loop y)))
- (() 0))))))
- (define qop
- (lambda (s)
- (string->symbol (string-append "# " s))))
- (define qcons (qop "cons"))
- (define qbox (qop "box"))
- (define qlist (qop "list"))
- (define qvector (qop "vector"))
- (define initial-info
- `((not (a -> bool))
- (eqv? (a a -> bool))
- (eq? (a a -> bool))
- (equal? (a a -> bool))
- (cons (a b -> (cons a b)) (ic))
- (car ((cons a b) -> a) (s (x . _)))
- (cdr ((cons b a) -> a) (s (_ . x)))
- (caar ((cons (cons a b) c) -> a)
- (s ((x . _) . _)))
- (cadr ((cons c (cons a b)) -> a) (s (_ x . _)))
- (cdar ((cons (cons b a) c) -> a)
- (s ((_ . x) . _)))
- (cddr ((cons c (cons b a)) -> a) (s (_ _ . x)))
- (caaar ((cons (cons (cons a b) c) d) -> a)
- (s (((x . _) . _) . _)))
- (caadr ((cons d (cons (cons a b) c)) -> a)
- (s (_ (x . _) . _)))
- (cadar ((cons (cons c (cons a b)) d) -> a)
- (s ((_ x . _) . _)))
- (caddr ((cons d (cons c (cons a b))) -> a)
- (s (_ _ x . _)))
- (cdaar ((cons (cons (cons b a) c) d) -> a)
- (s (((_ . x) . _) . _)))
- (cdadr ((cons d (cons (cons b a) c)) -> a)
- (s (_ (_ . x) . _)))
- (cddar ((cons (cons c (cons b a)) d) -> a)
- (s ((_ _ . x) . _)))
- (cdddr ((cons d (cons c (cons b a))) -> a)
- (s (_ _ _ . x)))
- (caaaar
- ((cons (cons (cons (cons a b) c) d) e) -> a)
- (s ((((x . _) . _) . _) . _)))
- (caaadr
- ((cons e (cons (cons (cons a b) c) d)) -> a)
- (s (_ ((x . _) . _) . _)))
- (caadar
- ((cons (cons d (cons (cons a b) c)) e) -> a)
- (s ((_ (x . _) . _) . _)))
- (caaddr
- ((cons e (cons d (cons (cons a b) c))) -> a)
- (s (_ _ (x . _) . _)))
- (cadaar
- ((cons (cons (cons c (cons a b)) d) e) -> a)
- (s (((_ x . _) . _) . _)))
- (cadadr
- ((cons e (cons (cons c (cons a b)) d)) -> a)
- (s (_ (_ x . _) . _)))
- (caddar
- ((cons (cons d (cons c (cons a b))) e) -> a)
- (s ((_ _ x . _) . _)))
- (cadddr
- ((cons e (cons d (cons c (cons a b)))) -> a)
- (s (_ _ _ x . _)))
- (cdaaar
- ((cons (cons (cons (cons b a) c) d) e) -> a)
- (s ((((_ . x) . _) . _) . _)))
- (cdaadr
- ((cons e (cons (cons (cons b a) c) d)) -> a)
- (s (_ ((_ . x) . _) . _)))
- (cdadar
- ((cons (cons d (cons (cons b a) c)) e) -> a)
- (s ((_ (_ . x) . _) . _)))
- (cdaddr
- ((cons e (cons d (cons (cons b a) c))) -> a)
- (s (_ _ (_ . x) . _)))
- (cddaar
- ((cons (cons (cons c (cons b a)) d) e) -> a)
- (s (((_ _ . x) . _) . _)))
- (cddadr
- ((cons e (cons (cons c (cons b a)) d)) -> a)
- (s (_ (_ _ . x) . _)))
- (cdddar
- ((cons (cons d (cons c (cons b a))) e) -> a)
- (s ((_ _ _ . x) . _)))
- (cddddr
- ((cons e (cons d (cons c (cons b a)))) -> a)
- (s (_ _ _ _ . x)))
- (set-car! ((cons a b) a -> void))
- (set-cdr! ((cons a b) b -> void))
- (list ((&list a) -> (list a)) (ic))
- (length ((list a) -> num))
- (append ((&list (list a)) -> (list a)) (ic) (d))
- (reverse ((list a) -> (list a)) (ic))
- (list-tail ((list a) num -> (list a)) (c))
- (list-ref ((list a) num -> a) (c))
- (memq (a (list a) -> (+ false (cons a (list a)))))
- (memv (a (list a) -> (+ false (cons a (list a)))))
- (member
- (a (list a) -> (+ false (cons a (list a)))))
- (assq (a (list (cons a c)) -> (+ false (cons a c))))
- (assv (a (list (cons a c)) -> (+ false (cons a c))))
- (assoc (a (list (cons a c)) -> (+ false (cons a c))))
- (symbol->string (sym -> str))
- (string->symbol (str -> sym))
- (complex? (a -> bool))
- (real? (a -> bool))
- (rational? (a -> bool))
- (integer? (a -> bool))
- (exact? (num -> bool))
- (inexact? (num -> bool))
- (= (num num (&list num) -> bool))
- (< (num num (&list num) -> bool))
- (> (num num (&list num) -> bool))
- (<= (num num (&list num) -> bool))
- (>= (num num (&list num) -> bool))
- (zero? (num -> bool))
- (positive? (num -> bool))
- (negative? (num -> bool))
- (odd? (num -> bool))
- (even? (num -> bool))
- (max (num (&list num) -> num))
- (min (num (&list num) -> num))
- (+ ((&list num) -> num))
- (* ((&list num) -> num))
- (- (num (&list num) -> num))
- (/ (num (&list num) -> num))
- (abs (num -> num))
- (quotient (num num -> num))
- (remainder (num num -> num))
- (modulo (num num -> num))
- (gcd ((&list num) -> num))
- (lcm ((&list num) -> num))
- (numerator (num -> num))
- (denominator (num -> num))
- (floor (num -> num))
- (ceiling (num -> num))
- (truncate (num -> num))
- (round (num -> num))
- (rationalize (num num -> num))
- (exp (num -> num))
- (log (num -> num))
- (sin (num -> num))
- (cos (num -> num))
- (tan (num -> num))
- (asin (num -> num))
- (acos (num -> num))
- (atan (num (&optional num) -> num))
- (sqrt (num -> num))
- (expt (num num -> num))
- (make-rectangular (num num -> num))
- (make-polar (num num -> num))
- (real-part (num -> num))
- (imag-part (num -> num))
- (magnitude (num -> num))
- (angle (num -> num))
- (exact->inexact (num -> num))
- (inexact->exact (num -> num))
- (number->string (num (&optional num) -> str))
- (string->number (str (&optional num) -> num))
- (char=? (char char -> bool))
- (char<? (char char -> bool))
- (char>? (char char -> bool))
- (char<=? (char char -> bool))
- (char>=? (char char -> bool))
- (char-ci=? (char char -> bool))
- (char-ci<? (char char -> bool))
- (char-ci>? (char char -> bool))
- (char-ci<=? (char char -> bool))
- (char-ci>=? (char char -> bool))
- (char-alphabetic? (char -> bool))
- (char-numeric? (char -> bool))
- (char-whitespace? (char -> bool))
- (char-upper-case? (char -> bool))
- (char-lower-case? (char -> bool))
- (char->integer (char -> num))
- (integer->char (num -> char))
- (char-upcase (char -> char))
- (char-downcase (char -> char))
- (make-string (num (&optional char) -> str))
- (string ((&list char) -> str))
- (string-length (str -> num))
- (string-ref (str num -> char))
- (string-set! (str num char -> void))
- (string=? (str str -> bool))
- (string<? (str str -> bool))
- (string>? (str str -> bool))
- (string<=? (str str -> bool))
- (string>=? (str str -> bool))
- (string-ci=? (str str -> bool))
- (string-ci<? (str str -> bool))
- (string-ci>? (str str -> bool))
- (string-ci<=? (str str -> bool))
- (string-ci>=? (str str -> bool))
- (substring (str num num -> str))
- (string-append ((&list str) -> str))
- (string->list (str -> (list char)) (ic))
- (list->string ((list char) -> str))
- (string-copy (str -> str))
- (string-fill! (str char -> void))
- (make-vector (num a -> (vec a)) (i))
- (vector ((&list a) -> (vec a)) (i))
- (vector-length ((vec a) -> num))
- (vector-ref ((vec a) num -> a))
- (vector-set! ((vec a) num a -> void))
- (vector->list ((vec a) -> (list a)) (ic))
- (list->vector ((list a) -> (vec a)) (i))
- (vector-fill! ((vec a) a -> void))
- (apply (((&list a) -> b) (list a) -> b) (i) (d))
- (map ((a -> b) (list a) -> (list b)) (i) (d))
- (for-each ((a -> b) (list a) -> void) (i) (d))
- (force ((promise a) -> a) (i))
- (call-with-current-continuation
- (((a -> b) -> a) -> a)
- (i))
- (call-with-input-file
- (str (iport -> a) -> a)
- (i))
- (call-with-output-file
- (str (oport -> a) -> a)
- (i))
- (input-port? (a -> bool))
- (output-port? (a -> bool))
- (current-input-port (-> iport))
- (current-output-port (-> oport))
- (with-input-from-file (str (-> a) -> a) (i))
- (with-output-to-file (str (-> a) -> a) (i))
- (open-input-file (str -> iport))
- (open-output-file (str -> oport))
- (close-input-port (iport -> void))
- (close-output-port (oport -> void))
- (read ((&optional iport)
- ->
- (+ eof
- num
- nil
- false
- true
- char
- sym
- str
- (box (mu sexp
- (+ num
- nil
- false
- true
- char
- sym
- str
- (vec sexp)
- (cons sexp sexp)
- (box sexp))))
- (cons sexp sexp)
- (vec sexp)))
- (i))
- (read-char
- ((&optional iport) -> (+ char eof))
- (i))
- (peek-char
- ((&optional iport) -> (+ char eof))
- (i))
- (char-ready? ((&optional iport) -> bool) (i))
- (write (a (&optional oport) -> void) (i))
- (display (a (&optional oport) -> void) (i))
- (newline ((&optional oport) -> void) (i))
- (write-char (char (&optional oport) -> void) (i))
- (load (str -> void))
- (transcript-on (str -> void))
- (transcript-off (-> void))
- (symbol-append ((&rest a) -> sym))
- (box (a -> (box a)) (i))
- (unbox ((box a) -> a) (s boxx))
- (set-box! ((box a) a -> void))
- (void (-> void))
- (make-module (a -> (module a)))
- (raise ((&rest a) -> b))
- (match:error (a (&rest b) -> c))
- (should-never-reach (a -> b))
- (make-cvector (num a -> (cvec a)))
- (cvector ((&list a) -> (cvec a)))
- (cvector-length ((cvec a) -> num))
- (cvector-ref ((cvec a) num -> a))
- (cvector->list ((cvec a) -> (list a)) (ic))
- (list->cvector ((list a) -> (cvec a)))
- (,qcons (a b -> (cons a b)) (ic) (n))
- (,qvector ((&list a) -> (vec a)) (i) (n))
- (,qbox (a -> (box a)) (i) (n))
- (,qlist ((&list a) -> (list a)) (ic) (n))
- (number? ((+ num x) -> bool) (p (num)))
- (null? ((+ nil x) -> bool) (p (nil)))
- (char? ((+ char x) -> bool) (p (char)))
- (symbol? ((+ sym x) -> bool) (p (sym)))
- (string? ((+ str x) -> bool) (p (str)))
- (vector? ((+ (vec a) x) -> bool) (p (vec a)))
- (cvector? ((+ (cvec a) x) -> bool) (p (cvec a)))
- (box? ((+ (box a) x) -> bool) (p (box a)))
- (pair? ((+ (cons a b) x) -> bool) (p (cons a b)))
- (procedure?
- ((+ ((&rest a) -> b) x) -> bool)
- (p (?-> a b)))
- (eof-object? ((+ eof x) -> bool) (p (eof)))
- (input-port? ((+ iport x) -> bool) (p (iport)))
- (output-port? ((+ oport x) -> bool) (p (oport)))
- (true-object? ((+ true x) -> bool) (p (true)))
- (false-object? ((+ false x) -> bool) (p (false)))
- (module?
- ((+ (module a) x) -> bool)
- (p (module a)))
- (boolean? ((+ true false x) -> bool) (p #t))
- (list? ((mu u (+ nil (cons y u) x)) -> bool)
- (p #t))))
- (define initial-env '())
- (define init-env!
- (lambda ()
- (set! initial-env
- (foldr init-prim empty-env initial-info))))
- (define init-prim
- (lambda (l env)
- (letrec ((build-selector
- (match-lambda
- ('x (lambda (x) x))
- ('_ (lambda (x) (make-pany)))
- ('boxx
- (let ((c (lookup env 'box?)))
- (lambda (x) (make-pobj c (list x)))))
- ((x . y)
- (let ((c (lookup env 'pair?))
- (lx (build-selector x))
- (ly (build-selector y)))
- (lambda (x) (make-pobj c (list (lx x) (ly x)))))))))
- (match l
- ((name type . attr)
- (let* ((pure (cond ((assq 'i attr) #f)
- ((assq 'ic attr) 'cons)
- (else #t)))
- (def (assq 'd attr))
- (check (assq 'c attr))
- (nocheck (assq 'n attr))
- (pred (match (assq 'p attr)
- (#f #f)
- ((_ #t) #t)
- ((_ (tag . args))
- (cons (lookup initial-type-env tag) args))))
- (sel (match (assq 's attr)
- (#f #f)
- ((_ s) (build-selector s))))
- (env1 (extend-env
- env
- name
- (make-name
- name
- (closeall (r+ initial-type-env type))
- #f
- 0
- #f
- #f
- (cond (nocheck 'nocheck)
- (check 'check)
- (def 'imprecise)
- (else #t))
- #f
- pure
- pred
- #f
- sel)))
- (env2 (extend-env
- env1
- (symbol-append 'check- name)
- (make-name
- (symbol-append 'check- name)
- (closeall (r++ initial-type-env type))
- #f
- 0
- #f
- #f
- #t
- #f
- pure
- pred
- #f
- sel))))
- env2))))))
- (define defprim
- (lambda (name type mode)
- (handle
- (r+ initial-type-env type)
- (match-lambda*
- (('type . args) (apply syntax-err type args))
- (x (apply raise x))))
- (let* ((attr (match mode
- ('impure '((i)))
- ('pure '())
- ('pure-if-cons-is '((ic)))
- ('mutates-cons
- (set! cons-mutators (cons name cons-mutators))
- '())
- (x (use-error
- "invalid attribute ~a for st:defprim"
- x))))
- (info `(,name ,type ,@attr)))
- (unless
- (equal? info (assq name initial-info))
- (set! initial-info (cons info initial-info))
- (set! initial-env (init-prim info initial-env))))))
- (init-types!)
- (init-env!)
- (define %not (lookup initial-env 'not))
- (define %list (lookup initial-env 'list))
- (define %cons (lookup initial-env 'cons))
- (define %should-never-reach
- (lookup initial-env 'should-never-reach))
- (define %false-object?
- (lookup initial-env 'false-object?))
- (define %eq? (lookup initial-env 'eq?))
- (define %eqv? (lookup initial-env 'eqv?))
- (define %equal? (lookup initial-env 'equal?))
- (define %null? (lookup initial-env 'null?))
- (define %vector? (lookup initial-env 'vector?))
- (define %cvector? (lookup initial-env 'cvector?))
- (define %list? (lookup initial-env 'list?))
- (define %boolean? (lookup initial-env 'boolean?))
- (define %procedure?
- (lookup initial-env 'procedure?))
- (define n-unbound 0)
- (define bind-defs
- (lambda (defs env0 tenv0 old-unbound timestamp)
- (letrec ((cons-mutable #f)
- (unbound '())
- (use-var
- (lambda (x env context mk-node)
- (match (lookup? env x)
- (#f
- (let* ((b (bind-var x)) (n (mk-node b)))
- (set-name-timestamp! b context)
- (set! unbound (cons n unbound))
- n))
- (b (when (and (name-primitive b)
- (memq x cons-mutators))
- (set! cons-mutable #t))
- (set-name-occ! b (+ 1 (name-occ b)))
- (mk-node b)))))
- (bind-var
- (lambda (x)
- (make-name
- x
- #f
- timestamp
- 0
- #f
- #f
- #f
- #f
- #f
- #f
- #f
- #f)))
- (bind (lambda (e env tenv context)
- (let ((bind-cur (lambda (x) (bind x env tenv context))))
- (match e
- (($ var x) (use-var x env context make-var))
- (($ prim x)
- (use-var x initial-env context make-var))
- (($ const c pred)
- (use-var
- pred
- initial-env
- context
- (lambda (p) (make-const c p))))
- (($ lam args e2)
- (let* ((b-args (map bind-var args))
- (newenv (extend-env* env args b-args)))
- (make-lam
- b-args
- (bind e2 newenv tenv context))))
- (($ vlam args rest e2)
- (let* ((b-args (map bind-var args))
- (b-rest (bind-var rest))
- (newenv
- (extend-env*
- env
- (cons rest args)
- (cons b-rest b-args))))
- (make-vlam
- b-args
- b-rest
- (bind e2 newenv tenv context))))
- (($ match e1 clauses)
- (make-match
- (bind-cur e1)
- (map (lambda (x)
- (bind-mclause x env tenv context))
- clauses)))
- (($ app e1 args)
- (make-app (bind-cur e1) (map bind-cur args)))
- (($ begin exps) (make-begin (map bind-cur exps)))
- (($ and exps) (make-and (map bind-cur exps)))
- (($ or exps) (make-or (map bind-cur exps)))
- (($ if test then els)
- (make-if
- (bind-cur test)
- (bind-cur then)
- (bind-cur els)))
- (($ delay e2) (make-delay (bind-cur e2)))
- (($ set! x e2)
- (use-var
- x
- env
- context
- (lambda (b)
- (when (name-struct b)
- (syntax-err
- (pexpr e)
- "define-structure identifier ~a may not be assigned"
- x))
- (when (name-primitive b)
- (syntax-err
- (pexpr e)
- "(set! ~a ...) requires (define ~a ...)"
- x
- x))
- (when (and (not (name-mutated b))
- (not (= (name-timestamp b)
- timestamp)))
- (syntax-err
- (pexpr e)
- "(set! ~a ...) missing from compilation unit defining ~a"
- x
- x))
- (set-name-mutated! b #t)
- (make-set! b (bind-cur e2)))))
- (($ let args e2)
- (let* ((b-args
- (map (match-lambda
- (($ bind x e)
- (make-bind
- (bind-var x)
- (bind-cur e))))
- args))
- (newenv
- (extend-env*
- env
- (map bind-name args)
- (map bind-name b-args))))
- (make-let
- b-args
- (bind e2 newenv tenv context))))
- (($ let* args e2)
- (recur loop
- ((args args) (b-args '()) (env env))
- (match args
- ((($ bind x e) . rest)
- (let ((b (bind-var x)))
- (loop rest
- (cons (make-bind
- b
- (bind e
- env
- tenv
- context))
- b-args)
- (extend-env env x b))))
- (()
- (make-let*
- (reverse b-args)
- (bind e2 env tenv context))))))
- (($ letr args e2)
- (let* ((b-args
- (map (match-lambda
- (($ bind x e)
- (make-bind (bind-var x) e)))
- args))
- (newenv
- (extend-env*
- env
- (map bind-name args)
- (map bind-name b-args)))
- (b-args
- (map (match-lambda
- (($ bind b e)
- (let* ((n (name-occ b))
- (e2 (bind e
- newenv
- tenv
- context)))
- (set-name-occ! b n)
- (make-bind b e2))))
- b-args)))
- (make-letr
- b-args
- (bind e2 newenv tenv context))))
- (($ body defs exps)
- (match-let*
- (((defs newenv newtenv)
- (bind-defn defs env tenv #f)))
- (make-body
- defs
- (map (lambda (x)
- (bind x newenv newtenv context))
- exps))))
- (($ record args)
- (make-record
- (map (match-lambda
- (($ bind x e)
- (new-field! x)
- (make-bind x (bind-cur e))))
- args)))
- (($ field x e2)
- (new-field! x)
- (make-field x (bind-cur e2)))
- (($ cast ty e2)
- (match-let
- (((t absv)
- (handle
- (r+collect
- tenv
- (match ty
- (('rec bind ty2)
- `(rec ,bind (,ty2 -> ,ty2)))
- (_ `(,ty -> ,ty))))
- (match-lambda*
- (('type . args)
- (apply syntax-err ty args))
- (x (apply raise x))))))
- (make-cast
- (list ty t absv)
- (bind-cur e2))))))))
- (bind-mclause
- (lambda (clause env tenv context)
- (match-let*
- ((($ mclause pattern body failsym) clause)
- (patenv empty-env)
- (bp (recur loop
- ((p pattern))
- (match p
- (($ pvar x)
- (when (bound? patenv x)
- (syntax-err
- (ppat pattern)
- "pattern variable ~a repeated"
- x))
- (let ((b (bind-var x)))
- (set! patenv (extend-env patenv x b))
- (make-pvar b)))
- (($ pobj c args)
- (use-var
- c
- env
- context
- (lambda (b)
- (cond ((boolean? (name-predicate b))
- (syntax-err
- (ppat pattern)
- "~a is not a predicate"
- c))
- ((and (not (eq? b %vector?))
- (not (eq? b %cvector?))
- (not (= (length
- (cdr (name-predicate
- b)))
- (length args))))
- (syntax-err
- (ppat pattern)
- "~a requires ~a sub-patterns"
- c
- (length
- (cdr (name-predicate
- b)))))
- (else
- (make-pobj
- b
- (map loop args)))))))
- (($ pand pats)
- (make-pand (map loop pats)))
- (($ pnot pat) (make-pnot (loop pat)))
- (($ ppred pred)
- (use-var
- pred
- env
- context
- (lambda (b)
- (unless
- (name-predicate b)
- (syntax-err
- (ppat pattern)
- "~a is not a predicate"
- pred))
- (make-ppred b))))
- (($ pany) p)
- (($ pelse) p)
- (($ pconst c pred)
- (use-var
- pred
- initial-env
- context
- (lambda (p) (make-pconst c p))))))))
- (if failsym
- (let ((b (bind-var failsym)))
- (when (bound? patenv failsym)
- (syntax-err
- (ppat pattern)
- "fail symbol ~a repeated"
- failsym))
- (set! patenv (extend-env patenv failsym b))
- (make-mclause
- bp
- (bind body (join-env env patenv) tenv context)
- b))
- (make-mclause
- bp
- (bind body (join-env env patenv) tenv context)
- #f)))))
- (bind-defn
- (lambda (defs env tenv glob)
- (let* ((newenv empty-env)
- (newtenv empty-env)
- (struct-def
- (lambda (x pure)
- (when (or (bound? newenv x)
- (and glob (bound? initial-env x)))
- (syntax-err
- #f
- "~a defined more than once"
- x))
- (let ((b (bind-var x)))
- (set-name-primitive! b #t)
- (set-name-struct! b #t)
- (set-name-pure! b pure)
- (set! newenv (extend-env newenv x b))
- b)))
- (bind1 (match-lambda
- ((and z ($ define x e))
- (cond ((not x) z)
- ((bound? newenv x)
- (if glob
- (make-define #f (make-set! x e))
- (syntax-err
- #f
- "~a defined more than once"
- x)))
- (else
- (let ((b (bind-var x)))
- (set-name-gdef! b glob)
- (set! newenv
- (extend-env newenv x b))
- (make-define b e)))))
- ((and d
- ($ defstruct
- tag
- args
- make
- pred
- get
- set
- getn
- setn
- mutable))
- (let* ((make (struct-def
- make
- (map not mutable)))
- (pred (struct-def pred #t))
- (bind-get
- (lambda (name n)
- (match name
- (($ some x)
- (let ((b (struct-def
- x
- #t)))
- (set-name-selector!
- b
- (lambda (x)
- (make-pobj
- pred
- (map-with-n
- (lambda (_ m)
- (if (= m n)
- x
- (make-pany)))
- get))))
- (some b)))
- (none none))))
- (bind-set
- (match-lambda
- (($ some x)
- (some (struct-def x #t)))
- (none none)))
- (get (map-with-n bind-get get))
- (getn (map-with-n bind-get getn))
- (set (map bind-set set))
- (setn (map bind-set setn))
- (_ (when (bound? newtenv tag)
- (syntax-err
- (pdef d)
- "type constructor ~a defined more than once"
- tag)))
- (tc (bind-tycon
- tag
- mutable
- (bound? tenv tag)
- (lambda args
- (apply syntax-err
- (cons (pdef d)
- args))))))
- (set! newtenv (extend-env newtenv tag tc))
- (set-name-predicate!
- pred
- `(,tc ,@(map (lambda (_) (gensym)) get)))
- (make-defstruct
- tc
- args
- make
- pred
- get
- set
- getn
- setn
- mutable)))
- ((and d ($ datatype dt))
- (make-datatype
- (maplr (match-lambda
- (((tag . args) . bindings)
- (when (bound? newtenv tag)
- (syntax-err
- (pdef d)
- "type constructor ~a defined more than once"
- tag))
- (let ((tc (bind-tycon
- tag
- (map (lambda (_) #f)
- args)
- (bound? tenv tag)
- (lambda args
- (apply syntax-err
- (cons (pdef d)
- args))))))
- (set! newtenv
- (extend-env newtenv tag tc))
- (cons (cons tc args)
- (maplr (match-lambda
- (($ variant
- con
- pred
- arg-types)
- (let ((make (struct-def
- con
- #t))
- (pred (struct-def
- pred
- #t)))
- (set-name-predicate!
- pred
- (cons tc
- args))
- (set-name-variant!
- pred
- arg-types)
- (make-variant
- make
- pred
- arg-types))))
- bindings)))))
- dt)))))
- (defs2 (maplr bind1 defs))
- (newenv2 (join-env env newenv))
- (newtenv2 (join-env tenv newtenv))
- (bind2 (match-lambda
- ((and ($ define (? name? x) ($ var y)))
- (=> fail)
- (if (eq? (name-name x) y)
- (if (bound? initial-env y)
- (make-define
- x
- (make-var (lookup initial-env y)))
- (begin
- (printf
- "Warning: (define ~a ~a) but ~a is not a primitive~%"
- y
- y
- y)
- (fail)))
- (fail)))
- ((and ($ define x e2) context)
- (when (and glob
- (name? x)
- (bound?
- initial-env
- (name-name x)))
- (printf
- "Note: (define ~a ...) hides primitive ~a~%"
- (name-name x)
- (name-name x)))
- (make-define
- (or x
- (let ((b (bind-var x)))
- (set-name-gdef! b glob)
- b))
- (bind e2 newenv2 newtenv2 context)))
- (d d))))
- (list (maplr bind2 defs2) newenv2 newtenv2))))
- (bind-old
- (lambda (e env)
- (match e
- (($ var x)
- (match (lookup? env (name-name x))
- (#f (set! unbound (cons e unbound)))
- (b (when (and (name-primitive b)
- (memq x cons-mutators))
- (set! cons-mutable #t))
- (set-name-occ! b (+ 1 (name-occ b)))
- (set-var-name! e b))))
- (($ set! x _)
- (match (lookup? env (name-name x))
- (#f (set! unbound (cons e unbound)))
- (b (when (name-struct b)
- (syntax-err
- (pexpr e)
- "define-structure identifier ~a may not be assigned"
- x))
- (when (name-primitive b)
- (syntax-err
- (pexpr e)
- "(set! ~a ...) requires (define ~a ...)"
- x
- x))
- (when (and (not (name-mutated b))
- (not (= (name-timestamp b)
- timestamp)))
- (syntax-err
- (pexpr e)
- "(set! ~a ...) missing from compilation unit defining ~a"
- x
- x))
- (set-name-mutated! b #t)
- (set-name-occ! b (+ 1 (name-occ b)))
- (set-set!-name! e b))))))))
- (match-let
- (((defs env tenv) (bind-defn defs env0 tenv0 #t)))
- (for-each
- (lambda (x) (bind-old x env))
- old-unbound)
- (set-cons-mutability! cons-mutable)
- (set! n-unbound (length unbound))
- (list defs env tenv unbound)))))
- (define rebind-var
- (lambda (b)
- (make-name
- (name-name b)
- (name-ty b)
- (name-timestamp b)
- (name-occ b)
- (name-mutated b)
- #f
- #f
- #f
- #f
- #f
- #f
- #f)))
- (define warn-unbound
- (lambda (l)
- (let* ((names '())
- (node->name
- (match-lambda
- (($ var x) x)
- (($ set! x _) x)
- (($ pobj x _) x)
- (($ ppred x) x)))
- (warn (lambda (b)
- (unless
- (memq (name-name b) names)
- (set! names (cons (name-name b) names))
- (printf
- "Warning: ~a is unbound in "
- (name-name b))
- (print-context (pexpr (name-timestamp b)) 2)))))
- (for-each (lambda (x) (warn (node->name x))) l))))
- (define name-unbound?
- (lambda (x) (not (number? (name-timestamp x)))))
- (define improve-defs
- (lambda (defs)
- (map (match-lambda
- (($ define x e2) (make-define x (improve e2)))
- (x x))
- defs)))
- (define improve
- (match-lambda
- (($ match e clauses) (improve-match e clauses))
- (($ if tst thn els) (improve-if tst thn els))
- ((? var? e) e)
- ((? const? e) e)
- (($ lam args e2) (make-lam args (improve e2)))
- (($ vlam args rest e2)
- (make-vlam args rest (improve e2)))
- (($ app (and e1 ($ var x)) args)
- (let ((args (map improve args)))
- (if (and (eq? x %list) (< (length args) conslimit))
- (foldr (lambda (a rest)
- (make-app (make-var %cons) (list a rest)))
- (make-const '() %null?)
- args)
- (make-app e1 args))))
- (($ app e1 args)
- (make-app (improve e1) (map improve args)))
- (($ begin exps) (make-begin (map improve exps)))
- (($ and exps) (make-and (map improve exps)))
- (($ or exps) (make-or (map improve exps)))
- (($ delay e2) (make-delay (improve e2)))
- (($ set! x e2) (make-set! x (improve e2)))
- (($ let args e2)
- (let ((args (map (match-lambda
- (($ bind x e) (make-bind x (improve e))))
- args)))
- (make-let args (improve e2))))
- (($ let* args e2)
- (let ((args (map (match-lambda
- (($ bind x e) (make-bind x (improve e))))
- args)))
- (make-let* args (improve e2))))
- (($ letr args e2)
- (let ((args (map (match-lambda
- (($ bind x e) (make-bind x (improve e))))
- args)))
- (make-letr args (improve e2))))
- (($ body defs exps)
- (let ((defs (improve-defs defs)))
- (make-body defs (map improve exps))))
- (($ record args)
- (make-record
- (map (match-lambda
- (($ bind x e) (make-bind x (improve e))))
- args)))
- (($ field x e2) (make-field x (improve e2)))
- (($ cast ty e2) (make-cast ty (improve e2)))))
- (define improve-if
- (lambda (tst thn els)
- (let ((if->match
- (lambda (x p mk-s thn els)
- (let ((else-pat
- (match els
- (($ app ($ var q) _)
- (if (eq? q %should-never-reach)
- (make-pelse)
- (make-pany)))
- (_ (make-pany)))))
- (make-match
- (make-var x)
- (list (make-mclause
- (mk-s (make-ppred p))
- (make-body '() (list thn))
- #f)
- (make-mclause
- (mk-s else-pat)
- (make-body '() (list els))
- #f)))))))
- (match tst
- (($ app ($ var v) (e))
- (=> fail)
- (if (eq? v %not) (improve-if e els thn) (fail)))
- (($ app ($ var eq) (($ const #f _) val))
- (=> fail)
- (if (or (eq? eq %eq?)
- (eq? eq %eqv?)
- (eq? eq %equal?))
- (improve-if val els thn)
- (fail)))
- (($ app ($ var eq) (val ($ const #f _)))
- (=> fail)
- (if (or (eq? eq %eq?)
- (eq? eq %eqv?)
- (eq? eq %equal?))
- (improve-if val els thn)
- (fail)))
- (($ app ($ var v) (($ var x)))
- (=> fail)
- (if (and (name-predicate v) (not (name-mutated x)))
- (improve (if->match x v (lambda (x) x) thn els))
- (fail)))
- (($ app ($ var v) (($ app ($ var s) (($ var x)))))
- (=> fail)
- (if (and (name-predicate v)
- (name-selector s)
- (not (name-mutated x)))
- (improve
- (if->match x v (name-selector s) thn els))
- (fail)))
- (($ app ($ var v) (($ var x)))
- (=> fail)
- (if (and (name-selector v) (not (name-mutated x)))
- (improve
- (if->match
- x
- %false-object?
- (name-selector v)
- els
- thn))
- (fail)))
- (($ var v)
- (=> fail)
- (if (not (name-mutated v))
- (improve
- (if->match
- v
- %false-object?
- (lambda (x) x)
- els
- thn))
- (fail)))
- (_ (make-if
- (improve tst)
- (improve thn)
- (improve els)))))))
- (define improve-match
- (lambda (e clauses)
- (let ((clauses
- (map (match-lambda
- (($ mclause p body fail)
- (make-mclause p (improve body) fail)))
- clauses)))
- (match e
- (($ var x)
- (if (not (name-mutated x))
- (let ((fix-clause
- (match-lambda
- ((and c ($ mclause p e fail))
- (if (not (uses-x? e x))
- c
- (let ((y (rebind-var x)))
- (make-mclause
- (make-flat-pand (list p (make-pvar y)))
- (sub e x y)
- fail)))))))
- (make-match e (map fix-clause clauses)))
- (make-match e clauses)))
- (_ (make-match (improve e) clauses))))))
- (define uses-x?
- (lambda (e x)
- (recur loop
- ((e e))
- (match e
- (($ and exps) (ormap loop exps))
- (($ app fun args)
- (or (loop fun) (ormap loop args)))
- (($ begin exps) (ormap loop exps))
- (($ if e1 e2 e3)
- (or (loop e1) (loop e2) (loop e3)))
- (($ lam names body) (loop body))
- (($ let bindings body)
- (or (ormap (match-lambda (($ bind _ b) (loop b)))
- bindings)
- (loop body)))
- (($ let* bindings body)
- (or (ormap (match-lambda (($ bind _ b) (loop b)))
- bindings)
- (loop body)))
- (($ letr bindings body)
- (or (ormap (match-lambda (($ bind _ b) (loop b)))
- bindings)
- (loop body)))
- (($ or exps) (ormap loop exps))
- (($ delay e2) (loop e2))
- (($ set! name exp) (or (eq? x name) (loop exp)))
- (($ var name) (eq? x name))
- (($ vlam names name body) (loop body))
- (($ match exp clauses)
- (or (loop exp)
- (ormap (match-lambda
- (($ mclause p b _) (or (loop p) (loop b))))
- clauses)))
- (($ body defs exps)
- (or (ormap loop defs) (ormap loop exps)))
- (($ record bindings)
- (ormap (match-lambda (($ bind _ b) (loop b)))
- bindings))
- (($ field _ e) (loop e))
- (($ cast _ e) (loop e))
- (($ define _ e) (loop e))
- ((? defstruct?) #f)
- ((? datatype?) #f)
- (($ pand pats) (ormap loop pats))
- (($ pnot pat) (loop pat))
- (($ pobj c args) (ormap loop args))
- (($ ppred pred) (eq? x pred))
- (_ #f)))))
- (define sub
- (lambda (e x to)
- (let ((dos (lambda (y) (if (eq? x y) to y))))
- (recur sub
- ((e e))
- (match e
- (($ define x e) (make-define x (sub e)))
- ((? defstruct?) e)
- ((? datatype?) e)
- (($ match e clauses)
- (let ((clauses
- (map (match-lambda
- (($ mclause p e fail)
- (make-mclause p (sub e) fail)))
- clauses)))
- (make-match (sub e) clauses)))
- (($ if tst thn els)
- (make-if (sub tst) (sub thn) (sub els)))
- (($ var x) (make-var (dos x)))
- ((? const? e) e)
- (($ lam args e2) (make-lam args (sub e2)))
- (($ vlam args rest e2)
- (make-vlam args rest (sub e2)))
- (($ app e1 args)
- (make-app (sub e1) (map sub args)))
- (($ begin exps) (make-begin (map sub exps)))
- (($ and exps) (make-and (map sub exps)))
- (($ or exps) (make-or (map sub exps)))
- (($ delay e2) (make-delay (sub e2)))
- (($ set! x e2) (make-set! (dos x) (sub e2)))
- (($ let args e2)
- (let ((args (map (match-lambda
- (($ bind x e) (make-bind x (sub e))))
- args)))
- (make-let args (sub e2))))
- (($ let* args e2)
- (let ((args (map (match-lambda
- (($ bind x e) (make-bind x (sub e))))
- args)))
- (make-let* args (sub e2))))
- (($ letr args e2)
- (let ((args (map (match-lambda
- (($ bind x e) (make-bind x (sub e))))
- args)))
- (make-letr args (sub e2))))
- (($ body defs exps)
- (make-body (map sub defs) (map sub exps)))
- (($ record args)
- (make-record
- (map (match-lambda
- (($ bind x e) (make-bind x (sub e))))
- args)))
- (($ field x e) (make-field x (sub e)))
- (($ cast ty e) (make-cast ty (sub e))))))))
- (define improve-clauses
- (lambda (clauses)
- (recur loop
- ((clauses clauses))
- (match clauses
- (() '())
- ((_) clauses)
- (((and m1 ($ mclause p _ fail)) . rest)
- (cons m1
- (if fail
- (loop rest)
- (recur loop2
- ((clauses (loop rest)))
- (match clauses
- (() '())
- (((and m ($ mclause p2 body2 fail2))
- .
- r)
- (match (improve-by-pattern p2 p)
- (('stop . p)
- (cons (make-mclause
- p
- body2
- fail2)
- r))
- (('redundant . p)
- (unless
- (null? r)
- (printf
- "Warning: redundant pattern ~a~%"
- (ppat p2)))
- (cons (make-mclause
- p
- body2
- fail2)
- r))
- (('continue . p)
- (cons (make-mclause
- p
- body2
- fail2)
- (loop2 r))))))))))))))
- (define improve-by-pattern
- (lambda (p2 p1)
- (call-with-current-continuation
- (lambda (k)
- (let* ((reject (lambda () (k (cons 'continue p2))))
- (p1covers #t)
- (p2covers #t)
- (p3 (recur m
- ((p1 p1) (p2 p2))
- '(printf "(M ~a ~a)~%" (ppat p1) (ppat p2))
- (match (cons p1 p2)
- ((($ pand (a . _)) . p2) (m a p2))
- ((p1 $ pand (a . b))
- (make-flat-pand (cons (m p1 a) b)))
- ((($ pvar _) . _)
- (unless
- (or (pvar? p2) (pany? p2))
- (set! p2covers #f))
- p2)
- ((($ pany) . _)
- (unless
- (or (pvar? p2) (pany? p2))
- (set! p2covers #f))
- p2)
- ((($ pelse) . _)
- '(unless
- (or (pvar? p2) (pany? p2))
- (set! p2covers #f))
- p2)
- ((_ $ pvar _)
- (unless p1covers (reject))
- (set! p1covers #f)
- (make-flat-pand (list p2 (make-pnot p1))))
- ((_ $ pany)
- (unless p1covers (reject))
- (set! p1covers #f)
- (make-flat-pand (list p2 (make-pnot p1))))
- ((_ $ pelse)
- (unless p1covers (reject))
- (set! p1covers #f)
- (make-flat-pand (list p2 (make-pnot p1))))
- ((($ pconst a _) $ pconst b _)
- (unless (equal? a b) (reject))
- p2)
- ((($ pobj tag1 a) $ pobj tag2 b)
- (unless (eq? tag1 tag2) (reject))
- (make-pobj tag1 (map2 m a b)))
- ((($ ppred tag1) $ ppred tag2)
- (unless (eq? tag1 tag2) (reject))
- p2)
- ((($ ppred tag1) $ pobj tag2 _)
- (unless (eq? tag1 tag2) (reject))
- (set! p2covers #f)
- p2)
- ((($ ppred tag1) $ pconst c tag2)
- (unless (eq? tag1 tag2) (reject))
- (set! p2covers #f)
- p2)
- (_ (reject))))))
- (cond (p1covers (cons 'redundant p2))
- (p2covers (cons 'stop p3))
- (else (cons 'continue p3))))))))
- (define improve-by-noisily
- (lambda (p2 p1)
- (let ((r (improve-by-pattern p2 p1)))
- (printf
- "~a by ~a returns ~a ~a~%"
- (ppat p2)
- (ppat p1)
- (car r)
- (ppat (cdr r))))))
- (define make-components
- (lambda (d)
- (let* ((structs
- (filter-map
- (match-lambda ((? define?) #f) (x x))
- d))
- (defs (filter-map
- (match-lambda ((? define? x) x) (_ #f))
- d))
- (name-of (match-lambda (($ define x _) x)))
- (ref-of
- (match-lambda
- (($ define _ e) (references e name-gdef))))
- (comp (top-sort defs name-of ref-of)))
- (when #f
- (printf "Components:~%")
- (pretty-print
- (map (lambda (c)
- (map (match-lambda
- (($ define x _) (and x (name-name x))))
- c))
- comp)))
- (append structs comp))))
- (define make-body-components
- (lambda (d)
- (let* ((structs
- (filter-map
- (match-lambda ((? define?) #f) (x x))
- d))
- (defs (filter-map
- (match-lambda ((? define? x) x) (_ #f))
- d))
- (name-of (match-lambda (($ define x _) x)))
- (bound (map name-of defs))
- (ref-of
- (match-lambda
- (($ define _ e)
- (references e (lambda (x) (memq x bound))))))
- (comp (top-sort defs name-of ref-of)))
- (when #f
- (printf "Components:~%")
- (pretty-print
- (map (lambda (c)
- (map (match-lambda
- (($ define x _) (and x (name-name x))))
- c))
- comp)))
- (append structs comp))))
- (define make-letrec-components
- (lambda (bindings)
- (let* ((name-of bind-name)
- (bound (map name-of bindings))
- (ref-of
- (match-lambda
- (($ bind _ e)
- (references e (lambda (x) (memq x bound))))))
- (comp (top-sort bindings name-of ref-of)))
- (when #f
- (printf "Letrec Components:~%")
- (pretty-print
- (map (lambda (c)
- (map (match-lambda (($ bind x _) (pname x))) c))
- comp)))
- comp)))
- (define references
- (lambda (e ref?)
- (recur loop
- ((e e))
- (match e
- (($ define x e)
- (if (and x (name-mutated x))
- (union (set x) (loop e))
- (loop e)))
- ((? defstruct?) empty-set)
- ((? datatype?) empty-set)
- ((? const?) empty-set)
- (($ var x) (if (ref? x) (set x) empty-set))
- (($ lam _ e1) (loop e1))
- (($ vlam _ _ e1) (loop e1))
- (($ app e0 args)
- (foldr union2 (loop e0) (map loop args)))
- (($ let b e2)
- (let ((do-bind (match-lambda (($ bind _ e) (loop e)))))
- (foldr union2 (loop e2) (map do-bind b))))
- (($ let* b e2)
- (let ((do-bind (match-lambda (($ bind _ e) (loop e)))))
- (foldr union2 (loop e2) (map do-bind b))))
- (($ letr b e2)
- (let ((do-bind (match-lambda (($ bind _ e) (loop e)))))
- (foldr union2 (loop e2) (map do-bind b))))
- (($ body defs exps)
- (foldr union2
- empty-set
- (map loop (append defs exps))))
- (($ record b)
- (let ((do-bind (match-lambda (($ bind _ e) (loop e)))))
- (foldr union2 empty-set (map do-bind b))))
- (($ field _ e) (loop e))
- (($ cast _ e) (loop e))
- (($ and exps)
- (foldr union2 empty-set (map loop exps)))
- (($ or exps)
- (foldr union2 empty-set (map loop exps)))
- (($ begin exps)
- (foldr union2 empty-set (map loop exps)))
- (($ if test then els)
- (union (loop test) (loop then) (loop els)))
- (($ delay e) (loop e))
- (($ set! x body)
- (union (if (ref? x) (set x) empty-set)
- (loop body)))
- (($ match exp clauses)
- (foldr union2
- (loop exp)
- (map (match-lambda (($ mclause _ exp _) (loop exp)))
- clauses)))))))
- (define top-sort
- (lambda (graph name-of references-of)
- (let* ((adj assq)
- (g (map (lambda (x)
- (list (name-of x)
- (box (references-of x))
- (box #f)
- x))
- graph))
- (gt (let ((gt (map (match-lambda
- ((n _ _ name)
- (list n (box empty-set) (box #f) n)))
- g)))
- (for-each
- (match-lambda
- ((n nay _ _)
- (for-each
- (lambda (v)
- (match (adj v gt)
- (#f #f)
- ((_ b _ _) (set-box! b (cons n (unbox b))))))
- (unbox nay))))
- g)
- gt))
- (visit (lambda (vg)
- (letrec ((visit (lambda (g l)
- (match g
- (#f l)
- ((n nay mark name)
- (if (unbox mark)
- l
- (begin
- (set-box! mark #t)
- (cons name
- (foldr (lambda (v l)
- (visit (adj v
- vg)
- l))
- l
- (unbox nay))))))))))
- visit)))
- (visit-gt (visit gt))
- (visit-g (visit g))
- (post (foldr visit-gt '() gt))
- (pre (foldl (lambda (gg l)
- (match (visit-g (adj gg g) '())
- (() l)
- (c (cons c l))))
- '()
- post)))
- (reverse pre))))
- (define genlet #t)
- (define genmatch #t)
- (define letonce #f)
- (define type-defs
- (lambda (d)
- (for-each
- (match-lambda
- ((? defstruct? b) (type-structure b))
- ((? datatype? b) (type-structure b))
- (c (type-component c #t)))
- (make-components d))
- (close '())))
- (define type-structure
- (match-lambda
- (($ defstruct
- x
- _
- make
- pred
- get
- set
- getn
- setn
- mutable)
- (let* ((vars (map (lambda (_) (gensym)) get))
- (make-get-type
- (lambda (getter v)
- (match getter
- (($ some b)
- (set-name-ty!
- b
- (closeall
- (r+ initial-type-env `((,x ,@vars) -> ,v)))))
- (_ #f))))
- (make-set-type
- (lambda (setter v)
- (match setter
- (($ some b)
- (set-name-ty!
- b
- (closeall
- (r+ initial-type-env `((,x ,@vars) ,v -> void)))))
- (_ #f)))))
- (set-name-ty!
- make
- (closeall
- (r+ initial-type-env `(,@vars -> (,x ,@vars)))))
- (set-name-ty!
- pred
- (closeall
- (r+ initial-type-env
- `((+ (,x ,@vars) y) -> bool))))
- (for-each2 make-get-type get vars)
- (for-each2 make-set-type set vars)
- (for-each2 make-get-type getn vars)
- (for-each2 make-set-type setn vars)))
- (($ datatype dt)
- (for-each
- (match-lambda
- ((type . variants)
- (for-each
- (match-lambda
- (($ variant con pred arg-types)
- (set-name-ty!
- con
- (closeall
- (r+ initial-type-env
- `(,@(cdr arg-types) -> ,type))))
- (set-name-ty!
- pred
- (closeall
- (r+ initial-type-env
- `((+ ,(name-predicate pred) x) -> bool))))))
- variants)))
- dt))))
- (define type-component
- (lambda (component top)
- (when verbose
- (let ((cnames
- (filter-map
- (match-lambda (($ define b _) (name-name b)))
- component)))
- (unless
- (null? cnames)
- (printf "Typing ~a~%" cnames))))
- (let* ((f (match-lambda (($ define b e) (make-bind b e))))
- (bindings (map f component))
- (names (map (match-lambda (($ define b _) (pname b)))
- component))
- (f1 (match-lambda
- (($ define b _) (set-name-ty! b (tvar)))))
- (f2 (match-lambda
- ((and d ($ define b e))
- (set-define-exp! d (w e names)))))
- (f3 (match-lambda
- (($ define b e) (unify (name-ty b) (typeof e)))))
- (f4 (match-lambda (($ define b _) (name-ty b))))
- (f5 (lambda (d ts)
- (match d (($ define b _) (set-name-ty! b ts))))))
- (push-level)
- (for-each f1 component)
- (for-each f2 component)
- (for-each f3 component)
- (for-each limit-expansive component)
- (for-each
- f5
- component
- (close (map f4 component)))
- (pop-level))))
- (define w
- (lambda (e component)
- (match e
- (($ const _ pred)
- (make-type
- (r+ initial-type-env (name-predicate pred))
- e))
- (($ var x)
- (unless
- (name-ty x)
- (set-name-ty!
- x
- (if (name-mutated x)
- (monotvar)
- (let* ((_1 (push-level))
- (t (closeall (tvar)))
- (_2 (pop-level)))
- t))))
- (if (ts? (name-ty x))
- (match-let*
- ((tynode (make-type #f #f))
- ((t absv) (instantiate (name-ty x) tynode)))
- (set-type-ty! tynode t)
- (set-type-exp!
- tynode
- (match (name-primitive x)
- ('imprecise
- (make-check (list absv #f #f #f component) e))
- ('check
- (make-check
- (list (cons top absv) #f #f #f component)
- e))
- ('nocheck e)
- (#t
- (make-check
- (list absv (mk-definite-prim t) #f #f component)
- e))
- (#f
- (make-check (list absv #f #f #t component) e))))
- tynode)
- e))
- (($ lam x e1)
- (for-each (lambda (b) (set-name-ty! b (tvar))) x)
- (match-let*
- ((body (w e1 component))
- ((t absv)
- (r+collect
- initial-type-env
- `(,@(map name-ty x) -> ,(typeof body)))))
- (make-type
- t
- (make-check
- (list absv (mk-definite-lam t) #f #f component)
- (make-lam x body)))))
- (($ vlam x rest e1)
- (for-each (lambda (b) (set-name-ty! b (tvar))) x)
- (match-let*
- ((z (tvar))
- (_ (set-name-ty!
- rest
- (r+ initial-type-env `(list ,z))))
- (body (w e1 component))
- ((t absv)
- (r+collect
- initial-type-env
- `(,@(map name-ty x) (&list ,z) -> ,(typeof body)))))
- (make-type
- t
- (make-check
- (list absv (mk-definite-lam t) #f #f component)
- (make-vlam x rest body)))))
- (($ app e0 args)
- (match-let*
- ((t0 (w e0 component))
- (targs (maplr (lambda (e) (w e component)) args))
- (a* (map (lambda (_) (tvar)) args))
- (b (tvar))
- ((t absv)
- (r-collect initial-type-env `(,@a* -> ,b)))
- (definf (mk-definite-app t)))
- (unify (typeof t0) t)
- (for-each2 unify (map typeof targs) a*)
- (if (syntactically-a-procedure? t0)
- (make-type b (make-app t0 targs))
- (make-type
- b
- (make-check
- (list absv definf #f #f component)
- (make-app t0 targs))))))
- (($ let b e2)
- (let* ((do-bind
- (match-lambda
- (($ bind b e)
- (if genlet
- (let* ((_ (push-level))
- (e (w e (list (pname b))))
- (bind (make-bind b e)))
- (limit-expansive bind)
- (set-name-ty! b (car (close (list (typeof e)))))
- (pop-level)
- bind)
- (let ((e (w e component)))
- (set-name-ty! b (typeof e))
- (make-bind b e))))))
- (tb (map do-bind b))
- (body (w e2 component)))
- (make-let tb body)))
- (($ let* b e2)
- (let* ((do-bind
- (match-lambda
- (($ bind b e)
- (if genlet
- (let* ((_ (push-level))
- (e (w e (list (pname b))))
- (bind (make-bind b e)))
- (limit-expansive bind)
- (set-name-ty! b (car (close (list (typeof e)))))
- (pop-level)
- bind)
- (let ((e (w e component)))
- (set-name-ty! b (typeof e))
- (make-bind b e))))))
- (tb (maplr do-bind b))
- (body (w e2 component)))
- (make-let* tb body)))
- (($ letr b e2)
- (let* ((do-comp
- (lambda (b)
- (if genlet
- (let* ((f1 (match-lambda
- (($ bind b _) (set-name-ty! b (tvar)))))
- (names (map (match-lambda
- (($ bind b _) (pname b)))
- b))
- (f2 (match-lambda
- (($ bind b e)
- (make-bind b (w e names)))))
- (f3 (match-lambda
- (($ bind b e)
- (unify (name-ty b) (typeof e))
- (name-ty b))))
- (f4 (lambda (bind ts)
- (match bind
- (($ bind b _)
- (set-name-ty! b ts)))))
- (_1 (push-level))
- (_2 (for-each f1 b))
- (tb (maplr f2 b))
- (_3 (for-each limit-expansive tb))
- (ts-list (close (maplr f3 tb))))
- (pop-level)
- (for-each2 f4 tb ts-list)
- tb)
- (let* ((f1 (match-lambda
- (($ bind b _) (set-name-ty! b (tvar)))))
- (f2 (match-lambda
- (($ bind b e)
- (make-bind b (w e component)))))
- (f3 (match-lambda
- (($ bind b e)
- (unify (name-ty b) (typeof e)))))
- (_1 (for-each f1 b))
- (tb (maplr f2 b)))
- (for-each f3 tb)
- tb))))
- (comps (make-letrec-components b))
- (tb (foldr append '() (maplr do-comp comps))))
- (make-letr tb (w e2 component))))
- (($ body defs exps)
- (for-each
- (match-lambda
- ((? defstruct? b) (type-structure b))
- ((? datatype? b) (type-structure b))
- (c (type-component c #f)))
- (make-body-components defs))
- (let ((texps (maplr (lambda (x) (w x component)) exps)))
- (make-body defs texps)))
- (($ and exps)
- (let* ((texps (maplr (lambda (x) (w x component)) exps))
- (t (match texps
- (() (r+ initial-type-env 'true))
- ((e) (typeof e))
- (_ (let ((a (r+ initial-type-env 'false)))
- (unify (typeof (rac texps)) a)
- a)))))
- (make-type t (make-and texps))))
- (($ or exps)
- (let* ((texps (maplr (lambda (x) (w x component)) exps))
- (t (match texps
- (() (r+ initial-type-env 'false))
- ((e) (typeof e))
- (_ (let* ((t-last (typeof (rac texps)))
- (but-last (rdc texps))
- (a (tvar)))
- (for-each
- (lambda (e)
- (unify (typeof e)
- (r+ initial-type-env
- `(+ (not false) ,a))))
- but-last)
- (unify t-last
- (r+ initial-type-env
- `(+ (not false) ,a)))
- t-last)))))
- (make-type t (make-or texps))))
- (($ begin exps)
- (let ((texps (maplr (lambda (x) (w x component)) exps)))
- (make-begin texps)))
- (($ if test then els)
- (let ((ttest (w test component))
- (tthen (w then component))
- (tels (w els component))
- (a (tvar)))
- (unify (typeof tthen) a)
- (unify (typeof tels) a)
- (make-type a (make-if ttest tthen tels))))
- (($ delay e2)
- (let ((texp (w e2 component)))
- (make-type
- (r+ initial-type-env `(promise ,(typeof texp)))
- (make-delay texp))))
- (($ set! x body)
- (unless (name-ty x) (set-name-ty! x (monotvar)))
- (let* ((body (w body component))
- (t (if (ts? (name-ty x))
- (car (instantiate (name-ty x) #f))
- (name-ty x))))
- (unify t (typeof body))
- (make-type
- (r+ initial-type-env 'void)
- (make-set! x body))))
- (($ record bind)
- (let* ((tbind (map (match-lambda
- (($ bind name exp)
- (make-bind name (w exp component))))
- bind))
- (t (r+ initial-type-env
- `(record
- ,@(map (match-lambda
- (($ bind name exp)
- (list name (typeof exp))))
- tbind)))))
- (make-type t (make-record tbind))))
- (($ field name exp)
- (match-let*
- ((texp (w exp component))
- (a (tvar))
- ((t absv)
- (r-collect initial-type-env `(record (,name ,a)))))
- (unify (typeof texp) t)
- (make-type
- a
- (make-check
- (list absv #f #f #f component)
- (make-field name texp)))))
- (($ cast (ty t absv) exp)
- (let ((texp (w exp component)) (a (tvar)))
- (unify (r+ initial-type-env `(,(typeof texp) -> ,a))
- t)
- (make-type
- a
- (make-check
- (list absv #f #f #f component)
- (make-cast (list ty t absv) texp)))))
- (($ match exp clauses)
- (for-each
- (match-lambda
- (($ mclause p _ (? name? fail))
- (set-name-ty!
- fail
- (r+ initial-type-env '(a ?-> b))))
- (_ #f))
- clauses)
- (match-let*
- ((iclauses
- (improve-clauses
- (append
- clauses
- (list (make-mclause (make-pelse) #f #f)))))
- ((tmatch absv precise)
- (w-match (rdc iclauses) (rac iclauses)))
- (texp (w exp component))
- (_ (unify (typeof texp) tmatch))
- (tclauses
- (maplr (match-lambda
- (($ mclause p e fail)
- (make-mclause p (w e component) fail)))
- clauses))
- (a (tvar)))
- (for-each
- (match-lambda
- (($ mclause _ e _) (unify (typeof e) a)))
- tclauses)
- (make-type
- a
- (make-check
- (list absv #f (not precise) #f component)
- (make-match texp tclauses))))))))
- (define w-match
- (lambda (clauses last)
- (letrec ((bindings '())
- (encode
- (match-lambda
- (($ pand pats) (encode* pats))
- (x (encode* (list x)))))
- (encode*
- (lambda (pats)
- (let* ((concrete?
- (lambda (p)
- (or (pconst? p) (pobj? p) (ppred? p) (pelse? p))))
- (var? (lambda (p) (or (pvar? p) (pany? p))))
- (not-var?
- (lambda (p)
- (and (not (pvar? p)) (not (pany? p)))))
- (t (match (filter concrete? pats)
- ((p)
- (r+ initial-type-env
- (match (template p)
- ((x) x)
- (x `(+ ,@x)))))
- (()
- (r+ initial-type-env
- `(+ ,@(apply append
- (map template
- (filter
- not-var?
- pats)))
- ,@(if (null? (filter var? pats))
- '()
- (list (out1tvar)))))))))
- (for-each
- (match-lambda
- (($ pvar b)
- (set! bindings (cons b bindings))
- (set-name-ty! b (pat-var-bind t))))
- (filter pvar? pats))
- t)))
- (template
- (match-lambda
- ((? pelse?) '())
- (($ pconst _ pred) (list (name-predicate pred)))
- ((and pat ($ pobj c args))
- (list (cond ((or (eq? %vector? c) (eq? %cvector? c))
- (cons (if (eq? %vector? c) 'vec 'cvec)
- (match (maplr encode args)
- (() (list (out1tvar)))
- ((first . rest)
- (list (foldr (lambda (x y)
- (unify x y)
- y)
- first
- rest))))))
- (else
- (cons (car (name-predicate c))
- (maplr encode args))))))
- (($ ppred pred)
- (cond ((eq? pred %boolean?) (list 'true 'false))
- ((eq? pred %list?) (list `(list ,(out1tvar))))
- (else
- (list (cons (car (name-predicate pred))
- (maplr (lambda (_) (out1tvar))
- (cdr (name-predicate pred))))))))
- (($ pnot (? pconst?)) '())
- (($ pnot ($ ppred pred))
- (cond ((eq? pred %boolean?) '((not true) (not false)))
- ((eq? pred %procedure?) '((not ?->)))
- ((eq? pred %list?) '())
- (else `((not ,(car (name-predicate pred)))))))
- (($ pnot ($ pobj pred pats))
- (let ((m (foldr + 0 (map non-triv pats))))
- (case m
- ((0) `((not ,(car (name-predicate pred)))))
- ((1)
- `((,(car (name-predicate pred))
- ,@(map (match-lambda
- (($ pobj pred _)
- `(+ (not ,(car (name-predicate pred)))
- ,(out1tvar)))
- (($ ppred pred)
- `(+ (not ,(car (name-predicate pred)))
- ,(out1tvar)))
- (_ (out1tvar)))
- pats))))
- (else '()))))))
- (non-triv
- (match-lambda
- ((? pvar?) 0)
- ((? pany?) 0)
- ((? pelse?) 0)
- ((? pconst?) 2)
- (($ pobj _ pats) (foldr + 1 (map non-triv pats)))
- (_ 1)))
- (precise
- (match-lambda
- ((? pconst?) #f)
- (($ pand pats) (andmap precise pats))
- (($ pnot pat) (precise pat))
- (($ pobj pred pats)
- (let ((m (foldr + 0 (map non-triv pats))))
- (case m
- ((0) #t)
- ((1) (andmap precise pats))
- (else #f))))
- (($ ppred pred) (not (eq? pred %list?)))
- (_ #t))))
- (push-level)
- (match-let*
- ((precise-match
- (and (andmap
- (match-lambda (($ mclause _ _ fail) (not fail)))
- clauses)
- (match last (($ mclause p _ _) (precise p)))))
- (types (maplr (match-lambda (($ mclause p _ _) (encode p)))
- clauses))
- ((t absv)
- (r-match
- (foldr (lambda (x y) (unify x y) y) (tvar) types))))
- (unify (out1tvar) t)
- (for-each limit-name bindings)
- (for-each2
- set-name-ty!
- bindings
- (close (map name-ty bindings)))
- (pop-level)
- '(pretty-print
- `(match-input
- ,@(map (match-lambda (($ mclause p _ _) (ppat p)))
- clauses)))
- '(pretty-print
- `(match-type
- ,(ptype t)
- ,@(map (lambda (b) (list (pname b) (ptype (name-ty b))))
- bindings)))
- (list t absv precise-match)))))
- (define syntactically-a-procedure?
- (match-lambda
- (($ type _ e) (syntactically-a-procedure? e))
- (($ check _ e) (syntactically-a-procedure? e))
- (($ var x) (name-primitive x))
- ((? lam?) #t)
- ((? vlam?) #t)
- (($ let _ body)
- (syntactically-a-procedure? body))
- (($ let* _ body)
- (syntactically-a-procedure? body))
- (($ letr _ body)
- (syntactically-a-procedure? body))
- (($ if _ e2 e3)
- (and (syntactically-a-procedure? e2)
- (syntactically-a-procedure? e3)))
- (($ begin exps)
- (syntactically-a-procedure? (rac exps)))
- (($ body _ exps)
- (syntactically-a-procedure? (rac exps)))
- (_ #f)))
- (define typeof
- (match-lambda
- (($ type t _) t)
- (($ check _ e) (typeof e))
- (($ let _ body) (typeof body))
- (($ let* _ body) (typeof body))
- (($ letr _ body) (typeof body))
- (($ body _ exps) (typeof (rac exps)))
- (($ begin exps) (typeof (rac exps)))
- (($ var x) (name-ty x))))
- (define limit-name
- (lambda (n)
- (when (name-mutated n)
- (unify (name-ty n) (out1tvar)))))
- (define limit-expansive
- (letrec ((limit! (lambda (t) (unify t (out1tvar))))
- (expansive-pattern?
- (match-lambda
- ((? pconst?) #f)
- (($ pvar x) (name-mutated x))
- (($ pobj _ pats) (ormap expansive-pattern? pats))
- ((? pany?) #f)
- ((? pelse?) #f)
- (($ pand pats) (ormap expansive-pattern? pats))
- (($ ppred x) (name-mutated x))
- (($ pnot pat) (expansive-pattern? pat))))
- (limit-expr
- (match-lambda
- (($ bind b e)
- (if (name-mutated b)
- (limit! (typeof e))
- (limit-expr e)))
- ((? defstruct?) #f)
- ((? datatype?) #f)
- (($ define x e)
- (if (and x (name-mutated x))
- (limit! (typeof e))
- (limit-expr e)))
- (($ type
- t
- ($ app ($ type _ ($ check _ ($ var x))) exps))
- (cond ((list? (name-pure x))
- (if (= (length (name-pure x)) (length exps))
- (for-each2
- (lambda (pure e)
- (if pure (limit-expr e) (limit! (typeof e))))
- (name-pure x)
- exps)
- (limit! t)))
- ((or (eq? #t (name-pure x))
- (and (eq? 'cons (name-pure x))
- (not cons-is-mutable)))
- (for-each limit-expr exps))
- (else (limit! t))))
- (($ type t ($ app _ _)) (limit! t))
- (($ type t ($ check _ ($ app _ _))) (limit! t))
- (($ delay _) #f)
- (($ type t ($ set! _ _)) (limit! t))
- (($ var _) #f)
- ((? const?) #f)
- (($ lam _ _) #f)
- (($ vlam _ _ _) #f)
- (($ let bind body)
- (limit-expr body)
- (for-each limit-expr bind))
- (($ let* bind body)
- (limit-expr body)
- (for-each limit-expr bind))
- (($ letr bind body)
- (limit-expr body)
- (for-each limit-expr bind))
- (($ body defs exps)
- (for-each limit-expr defs)
- (for-each limit-expr exps))
- (($ and exps) (for-each limit-expr exps))
- (($ or exps) (for-each limit-expr exps))
- (($ begin exps) (for-each limit-expr exps))
- (($ if e1 e2 e3)
- (limit-expr e1)
- (limit-expr e2)
- (limit-expr e3))
- (($ record bind)
- (for-each
- (match-lambda (($ bind _ e) (limit-expr e)))
- bind))
- (($ field _ exp) (limit-expr exp))
- (($ cast _ exp) (limit-expr exp))
- (($ match exp clauses)
- (limit-expr exp)
- (for-each
- (match-lambda
- (($ mclause pat body fail)
- (if (or (and fail (name-mutated fail))
- (expansive-pattern? pat))
- (limit! (typeof body))
- (limit-expr body))))
- clauses))
- (($ type _ e1) (limit-expr e1))
- (($ check _ e1) (limit-expr e1)))))
- limit-expr))
- (define unparse
- (lambda (e check-action)
- (letrec ((pbind (match-lambda
- (($ bind n e) (list (pname n) (pexpr e)))))
- (pexpr (match-lambda
- ((and x ($ type _ (? check?)))
- (check-action x pexpr))
- (($ type _ exp) (pexpr exp))
- (($ shape t exp) (pexpr exp))
- (($ define x e)
- (if (or (not x) (and (name? x) (not (name-name x))))
- (pexpr e)
- `(define ,(pname x) ,(pexpr e))))
- (($ defstruct _ args _ _ _ _ _ _ _)
- `(check-define-const-structure ,args))
- (($ datatype d)
- `(datatype
- ,@(map (match-lambda
- (((tag . args) . bindings)
- (cons (cons (ptag tag) args)
- (map (match-lambda
- (($ variant _ _ types) types))
- bindings))))
- d)))
- (($ and exps) `(and ,@(maplr pexpr exps)))
- (($ or exps) `(or ,@(maplr pexpr exps)))
- (($ begin exps) `(begin ,@(maplr pexpr exps)))
- (($ var x) (pname x))
- (($ prim x) (pname x))
- (($ const x _) (pconst x))
- (($ lam x e1)
- `(lambda ,(maplr pname x) ,@(pexpr e1)))
- (($ vlam x rest e1)
- `(lambda ,(append (maplr pname x) (pname rest))
- ,@(pexpr e1)))
- (($ match e1 clauses)
- (let* ((pclause
- (match-lambda
- (($ mclause p #f #f)
- `(,(ppat p) <last clause>))
- (($ mclause p exp fail)
- (if fail
- `(,(ppat p)
- (=> ,(pname fail))
- ,@(pexpr exp))
- `(,(ppat p) ,@(pexpr exp))))))
- (p1 (pexpr e1)))
- `(match ,p1 ,@(maplr pclause clauses))))
- (($ app e1 args)
- (let* ((p1 (pexpr e1))
- (pargs (maplr pexpr args))
- (unkwote
- (match-lambda
- (('quote x) x)
- ((? boolean? x) x)
- ((? number? x) x)
- ((? char? x) x)
- ((? string? x) x)
- ((? null? x) x)
- ((? box? x) x)
- ((? vector? x) x))))
- (cond ((eq? p1 qlist) `',(maplr unkwote pargs))
- ((eq? p1 qcons)
- (let ((unq (maplr unkwote pargs)))
- `',(cons (car unq) (cadr unq))))
- ((eq? p1 qbox) (box (unkwote (car pargs))))
- ((eq? p1 qvector)
- (list->vector (maplr unkwote pargs)))
- (else (cons p1 pargs)))))
- (($ let b e2)
- (let ((pb (maplr pbind b)))
- `(let ,pb ,@(pexpr e2))))
- (($ let* b e2)
- (let ((pb (maplr pbind b)))
- `(let* ,pb ,@(pexpr e2))))
- (($ letr b e2)
- (let ((pb (maplr pbind b)))
- `(letrec ,pb ,@(pexpr e2))))
- (($ body defs exps)
- (let ((pdefs (maplr pexpr defs)))
- (append pdefs (maplr pexpr exps))))
- (($ if e1 e2 e3)
- (let* ((p1 (pexpr e1)) (p2 (pexpr e2)) (p3 (pexpr e3)))
- `(if ,p1 ,p2 ,p3)))
- (($ record bindings)
- `(record ,@(maplr pbind bindings)))
- (($ field x e2) `(field ,x ,(pexpr e2)))
- (($ cast (ty . _) e2) `(: ,ty ,(pexpr e2)))
- (($ delay e) `(delay ,(pexpr e)))
- (($ set! x e) `(set! ,(pname x) ,(pexpr e))))))
- (pexpr e))))
- (define pexpr
- (lambda (ex)
- (unparse
- ex
- (lambda (e pexpr)
- (match e
- (($ type _ ($ check _ exp)) (pexpr exp)))))))
- (define pdef pexpr)
- (define ppat
- (match-lambda
- (($ pconst x _) (pconst x))
- (($ pvar x) (pname x))
- (($ pany) '_)
- (($ pelse) 'else)
- (($ pnot pat) `(not ,(ppat pat)))
- (($ pand pats) `(and ,@(maplr ppat pats)))
- (($ ppred pred)
- (match (pname pred)
- ('false-object? #f)
- ('true-object? #t)
- ('null? '())
- (x `(? ,x))))
- (($ pobj tag args)
- (match (cons (pname tag) args)
- (('box? x) (box (ppat x)))
- (('pair? x y) (cons (ppat x) (ppat y)))
- (('vector? . x) (list->vector (maplr ppat x)))
- ((tg . _) `($ ,(strip-? tg) ,@(maplr ppat args)))))))
- (define strip-?
- (lambda (s)
- (let* ((str (symbol->string s))
- (n (string-length str)))
- (if (or (zero? n)
- (not (char=? #\? (string-ref str (- n 1)))))
- s
- (string->symbol (substring str 0 (- n 1)))))))
- (define pname
- (match-lambda
- ((? name? x) (or (name-name x) '<expr>))
- ((? symbol? x) x)))
- (define ptag
- (match-lambda
- ((? k? k) (k-name k))
- ((? symbol? x) x)))
- (define pconst
- (match-lambda
- ((? symbol? x) `',x)
- ((? boolean? x) x)
- ((? number? x) x)
- ((? char? x) x)
- ((? string? x) x)
- ((? null? x) `',x)))
- (define check
- (lambda (file)
- (output-checked file '() type-check?)))
- (define profcheck
- (lambda (file)
- (output-checked #f '() type-check?)
- (output-checked
- #f
- (make-counters total-possible)
- type-check?)))
- (define fullcheck
- (lambda (file)
- (let ((check? (lambda (_) #t)))
- (output-checked #f '() check?)
- (output-checked
- #f
- (make-counters total-possible)
- check?))))
- (define make-counters
- (lambda (n)
- (let* ((init `(define check-counters (make-vector ,n 0)))
- (sum '(define check-total
- (lambda ()
- (let ((foldr (lambda (f i l)
- (recur loop
- ((l l))
- (match l
- (() i)
- ((x . y) (f x (loop y))))))))
- (foldr + 0 (vector->list check-counters))))))
- (incr '(extend-syntax
- (check-increment-counter)
- ((check-increment-counter c)
- (vector-set!
- check-counters
- c
- (+ 1 (vector-ref check-counters c)))))))
- (list init sum incr))))
- (define output-checked
- (lambda (file header check-test)
- (set! summary '())
- (set! total-possible 0)
- (set! total-cast 0)
- (set! total-err 0)
- (set! total-any 0)
- (let ((doit (lambda ()
- (when (string? file)
- (printf
- ";; Generated by Soft Scheme ~a~%"
- st:version)
- (printf ";; (st:control")
- (for-each
- (lambda (x) (printf " '~a" x))
- (show-controls))
- (printf ")~%")
- (unless
- (= 0 n-unbound)
- (printf
- ";; CAUTION: ~a unbound references, this code is not safe~%"
- n-unbound))
- (printf "~%")
- (for-each pretty-print header))
- (for-each
- (lambda (exp)
- (match exp
- (($ define x _)
- (set! n-possible 0)
- (set! n-clash 0)
- (set! n-err 0)
- (set! n-match 0)
- (set! n-inexhaust 0)
- (set! n-prim 0)
- (set! n-lam 0)
- (set! n-app 0)
- (set! n-field 0)
- (set! n-cast 0)
- (if file
- (pretty-print (pcheck exp check-test))
- (pcheck exp check-test))
- (make-summary-line x)
- (set! total-possible
- (+ total-possible n-possible))
- (set! total-cast (+ total-cast n-cast))
- (set! total-err (+ total-err n-err))
- (set! total-any
- (+ total-any
- n-match
- n-inexhaust
- n-prim
- n-lam
- n-app
- n-field
- n-cast)))
- (_ (when file
- (pretty-print
- (pcheck exp check-test))))))
- tree)
- (when (string? file)
- (newline)
- (newline)
- (print-summary "; ")))))
- (if (string? file)
- (begin
- (delete-file file)
- (with-output-to-file file doit))
- (doit)))))
- (define total-possible 0)
- (define total-err 0)
- (define total-cast 0)
- (define total-any 0)
- (define n-possible 0)
- (define n-clash 0)
- (define n-err 0)
- (define n-match 0)
- (define n-inexhaust 0)
- (define n-prim 0)
- (define n-lam 0)
- (define n-app 0)
- (define n-field 0)
- (define n-cast 0)
- (define summary '())
- (define make-summary-line
- (lambda (x)
- (let ((total (+ n-match
- n-inexhaust
- n-prim
- n-lam
- n-app
- n-field
- n-cast)))
- (unless
- (= 0 total)
- (let* ((s (sprintf
- "~a~a "
- (padr (pname x) 16)
- (padl total 2)))
- (s (cond ((< 0 n-inexhaust)
- (sprintf
- "~a (~a match ~a inexhaust)"
- s
- n-match
- n-inexhaust))
- ((< 0 n-match)
- (sprintf "~a (~a match)" s n-match))
- (else s)))
- (s (if (< 0 n-prim)
- (sprintf "~a (~a prim)" s n-prim)
- s))
- (s (if (< 0 n-field)
- (sprintf "~a (~a field)" s n-field)
- s))
- (s (if (< 0 n-lam)
- (sprintf "~a (~a lambda)" s n-lam)
- s))
- (s (if (< 0 n-app) (sprintf "~a (~a ap)" s n-app) s))
- (s (if (< 0 n-err)
- (sprintf "~a (~a ERROR)" s n-err)
- s))
- (s (if (< 0 n-cast)
- (sprintf "~a (~a TYPE)" s n-cast)
- s)))
- (set! summary (cons s summary)))))))
- (define print-summary
- (lambda (hdr)
- (for-each
- (lambda (s) (printf "~a~a~%" hdr s))
- (reverse summary))
- (printf
- "~a~a~a "
- hdr
- (padr "TOTAL CHECKS" 16)
- (padl total-any 2))
- (printf
- " (of ~s is ~s%)"
- total-possible
- (if (= 0 total-possible)
- 0
- (string->number
- (chop-number
- (exact->inexact
- (* (/ total-any total-possible) 100))
- 4))))
- (when (< 0 total-err)
- (printf " (~s ERROR)" total-err))
- (when (< 0 total-cast)
- (printf " (~s TYPE)" total-cast))
- (printf "~%")))
- (define padl
- (lambda (arg n)
- (let ((s (sprintf "~a" arg)))
- (recur loop
- ((s s))
- (if (< (string-length s) n)
- (loop (string-append " " s))
- s)))))
- (define padr
- (lambda (arg n)
- (let ((s (sprintf "~a" arg)))
- (recur loop
- ((s s))
- (if (< (string-length s) n)
- (loop (string-append s " "))
- s)))))
- (define chop-number
- (lambda (x n)
- (substring
- (sprintf "~s00000000000000000000" x)
- 0
- (- n 1))))
- (define pcheck
- (lambda (ex check-test)
- (unparse
- ex
- (lambda (e pexpr)
- (match e
- ((and z ($ type _ ($ check inf ($ var x))))
- (cond ((name-primitive x)
- (set! n-possible (+ 1 n-possible))
- (match (check-test inf)
- (#f (pname x))
- ('def
- (set! n-err (+ 1 n-err))
- (set! n-prim (+ 1 n-prim))
- `(,(symbol-append "CHECK-" (pname x))
- ,(tree-index z)
- ',(string->symbol "ERROR")))
- (_ (set! n-prim (+ 1 n-prim))
- `(,(symbol-append "CHECK-" (pname x))
- ,(tree-index z)))))
- ((name-unbound? x) `(check-bound ,(pname x)))
- (else
- (if (check-test inf)
- (begin
- (set! n-clash (+ 1 n-clash))
- `(,(string->symbol "CLASH")
- ,(pname x)
- ,(tree-index z)))
- (pname x)))))
- ((and z
- ($ type _ ($ check inf (and m ($ lam x e1)))))
- (set! n-possible (+ 1 n-possible))
- (match (check-test inf)
- (#f (pexpr m))
- ('def
- (set! n-err (+ 1 n-err))
- (set! n-lam (+ 1 n-lam))
- `(,(string->symbol "CHECK-lambda")
- (,(tree-index z) ',(string->symbol "ERROR"))
- ,(map pname x)
- ,@(pexpr e1)))
- (_ (set! n-lam (+ 1 n-lam))
- `(,(string->symbol "CHECK-lambda")
- (,(tree-index z))
- ,(map pname x)
- ,@(pexpr e1)))))
- ((and z
- ($ type
- _
- ($ check inf (and m ($ vlam x rest e1)))))
- (set! n-possible (+ 1 n-possible))
- (match (check-test inf)
- (#f (pexpr m))
- ('def
- (set! n-err (+ 1 n-err))
- (set! n-lam (+ 1 n-lam))
- `(,(string->symbol "CHECK-lambda")
- (,(tree-index z) ',(string->symbol "ERROR"))
- ,(append (map pname x) (pname rest))
- ,@(pexpr e1)))
- (_ (set! n-lam (+ 1 n-lam))
- `(,(string->symbol "CHECK-lambda")
- (,(tree-index z))
- ,(append (map pname x) (pname rest))
- ,@(pexpr e1)))))
- ((and z
- ($ type _ ($ check inf (and m ($ app e1 args)))))
- (set! n-possible (+ 1 n-possible))
- (match (check-test inf)
- (#f (pexpr m))
- ('def
- (set! n-err (+ 1 n-err))
- (set! n-app (+ 1 n-app))
- `(,(string->symbol "CHECK-ap")
- (,(tree-index z) ',(string->symbol "ERROR"))
- ,(pexpr e1)
- ,@(map pexpr args)))
- (_ (set! n-app (+ 1 n-app))
- (let ((p1 (pexpr e1)))
- `(,(string->symbol "CHECK-ap")
- (,(tree-index z))
- ,p1
- ,@(map pexpr args))))))
- ((and z
- ($ type _ ($ check inf (and m ($ field x e1)))))
- (set! n-possible (+ 1 n-possible))
- (match (check-test inf)
- (#f (pexpr m))
- ('def
- (set! n-err (+ 1 n-err))
- (set! n-field (+ 1 n-field))
- `(,(string->symbol "CHECK-field")
- (,(tree-index z) ',(string->symbol "ERROR"))
- ,x
- ,(pexpr e1)))
- (_ (set! n-field (+ 1 n-field))
- `(,(string->symbol "CHECK-field")
- (,(tree-index z))
- ,x
- ,(pexpr e1)))))
- ((and z
- ($ type
- _
- ($ check inf (and m ($ cast (x . _) e1)))))
- (set! n-possible (+ 1 n-possible))
- (match (check-test inf)
- (#f (pexpr m))
- (_ (set! n-cast (+ 1 n-cast))
- `(,(string->symbol "CHECK-:")
- (,(tree-index z))
- ,x
- ,(pexpr e1)))))
- ((and z
- ($ type
- _
- ($ check inf (and m ($ match e1 clauses)))))
- (set! n-possible (+ 1 n-possible))
- (match (check-test inf)
- (#f (pexpr m))
- (inx (let* ((pclause
- (match-lambda
- (($ mclause p exp fail)
- (if fail
- `(,(ppat p)
- (=> ,(pname fail))
- ,@(pexpr exp))
- `(,(ppat p) ,@(pexpr exp))))))
- (p1 (pexpr e1)))
- (if (eq? 'inexhaust inx)
- (begin
- (set! n-inexhaust (+ 1 n-inexhaust))
- `(,(string->symbol "CHECK-match")
- (,(tree-index z)
- ,(string->symbol "INEXHAUST"))
- ,p1
- ,@(maplr pclause clauses)))
- (begin
- (set! n-match (+ 1 n-match))
- `(,(string->symbol "CHECK-match")
- (,(tree-index z))
- ,p1
- ,@(maplr pclause clauses)))))))))))))
- (define tree-index-list '())
- (define reinit-output!
- (lambda () (set! tree-index-list '())))
- (define tree-index
- (lambda (syntax)
- (match (assq syntax tree-index-list)
- (#f
- (let ((n (length tree-index-list)))
- (set! tree-index-list
- (cons (cons syntax n) tree-index-list))
- n))
- ((_ . n) n))))
- (define tree-unindex
- (lambda (n)
- (let ((max (length tree-index-list)))
- (when (<= max n)
- (use-error "Invalid CHECK number ~a" n))
- (car (list-ref tree-index-list (- (- max 1) n))))))
- (define cause
- (lambda ()
- (for-each
- (lambda (def)
- (for-each pretty-print (exp-cause def)))
- tree)))
- (define cause*
- (lambda names
- (if (null? names)
- (for-each
- (lambda (def)
- (for-each pretty-print (exp-cause def)))
- tree)
- (for-each
- (match-lambda
- ((? symbol? dname)
- (for-each
- pretty-print
- (exp-cause (find-global dname)))))
- names))))
- (define exp-cause
- (let ((sum (lambda (exps)
- (foldr (lambda (x y) (append (exp-cause x) y))
- '()
- exps)))
- (src (lambda (inf)
- (let ((nonlocal (map tree-index (check-sources inf))))
- (if (type-check1? inf)
- (cons (check-local-sources inf) nonlocal)
- nonlocal)))))
- (match-lambda
- ((and z ($ type ty ($ check inf ($ var x))))
- (if (name-primitive x)
- (if (type-check? inf)
- (list `((,(symbol-append 'check- (pname x))
- ,(tree-index z))
- ,@(src inf)))
- '())
- (if (type-check1? inf)
- (list `((clash ,(pname x) ,(tree-index z)) ,@(src inf)))
- '())))
- ((and z ($ type ty ($ check inf ($ lam x e1))))
- (append
- (if (type-check? inf)
- (list `((check-lambda ,(tree-index z) ,(map pname x) ...)
- ,@(src inf)))
- '())
- (exp-cause e1)))
- ((and z
- ($ type ty ($ check inf ($ vlam x rest e1))))
- (append
- (if (type-check? inf)
- (list `((check-lambda
- ,(tree-index z)
- ,(append (map pname x) (pname rest))
- ...)
- ,@(src inf)))
- '())
- (exp-cause e1)))
- ((and z ($ type _ ($ check inf ($ app e1 args))))
- (append
- (if (type-check? inf)
- (list `((check-ap ,(tree-index z)) ,@(src inf)))
- '())
- (exp-cause e1)
- (sum args)))
- ((and z ($ type _ ($ check inf ($ field x e1))))
- (append
- (if (type-check? inf)
- (list `((check-field ,(tree-index z) ,x ...)
- ,@(src inf)))
- '())
- (exp-cause e1)))
- ((and z
- ($ type _ ($ check inf ($ cast (x . _) e1))))
- (append
- (if (type-check? inf)
- (list `((check-: ,(tree-index z) ,x ...) ,@(src inf)))
- '())
- (exp-cause e1)))
- ((and z
- ($ type
- _
- ($ check inf (and m ($ match e1 clauses)))))
- (append
- (if (type-check? inf)
- (list `((check-match ,(tree-index z) ...) ,@(src inf)))
- '())
- (exp-cause m)))
- (($ define _ e) (exp-cause e))
- ((? defstruct?) '())
- ((? datatype?) '())
- (($ app e1 args) (sum (cons e1 args)))
- (($ match exp clauses)
- (foldr (lambda (x y)
- (append
- (match x (($ mclause _ e _) (exp-cause e)))
- y))
- (exp-cause exp)
- clauses))
- (($ var _) '())
- (($ and exps) (sum exps))
- (($ begin exps) (sum exps))
- ((? const?) '())
- (($ if test then els)
- (append
- (exp-cause test)
- (exp-cause then)
- (exp-cause els)))
- (($ let bindings body)
- (foldr (lambda (x y)
- (append (match x (($ bind _ e) (exp-cause e))) y))
- (exp-cause body)
- bindings))
- (($ let* bindings body)
- (foldr (lambda (x y)
- (append (match x (($ bind _ e) (exp-cause e))) y))
- (exp-cause body)
- bindings))
- (($ letr bindings body)
- (foldr (lambda (x y)
- (append (match x (($ bind _ e) (exp-cause e))) y))
- (exp-cause body)
- bindings))
- (($ body defs exps) (sum (append defs exps)))
- (($ or exps) (sum exps))
- (($ delay e) (exp-cause e))
- (($ set! var body) (exp-cause body))
- (($ record bindings)
- (foldr (lambda (x y)
- (append (match x (($ bind _ e) (exp-cause e))) y))
- '()
- bindings))
- (($ type _ exp) (exp-cause exp)))))
- (define display-type tidy)
- (define type
- (lambda names
- (if (null? names)
- (for-each globaldef tree)
- (for-each
- (match-lambda
- ((? symbol? x)
- (match (lookup? global-env x)
- (#f (use-error "~a is not defined" x))
- (ty (pretty-print
- `(,x : ,(display-type (name-ty ty)))))))
- ((? number? n)
- (let* ((ty (check-type (tree-unindex n)))
- (type (display-type ty)))
- (pretty-print `(,n : ,type))))
- (_ (use-error
- "arguments must be identifiers or CHECK numbers")))
- names))))
- (define localtype
- (lambda names
- (if (null? names)
- (for-each localdef tree)
- (for-each
- (lambda (x) (localdef (find-global x)))
- names))))
- (define find-global
- (lambda (name)
- (let ((d (ormap (match-lambda
- ((and d ($ define x _))
- (and (eq? name (name-name x)) d))
- (_ #f))
- tree)))
- (unless d (use-error "~a is not defined" name))
- d)))
- (define globaldef
- (lambda (e)
- (match e
- (($ define x _)
- (let ((type (display-type (name-ty x))))
- (pretty-print `(,(pname x) : ,type))))
- (_ #f))))
- (define localdef
- (lambda (e) (pretty-print (expdef e))))
- (define expdef
- (let* ((show (lambda (x)
- `(,(pname x) : ,(display-type (name-ty x)))))
- (pbind (match-lambda
- (($ bind x e) `(,(show x) ,(expdef e))))))
- (match-lambda
- (($ define x e)
- (if (or (not x) (and (name? x) (not (name-name x))))
- (expdef e)
- `(define ,(show x) ,(expdef e))))
- ((? defstruct? d) (pdef d))
- ((? datatype? d) (pdef d))
- (($ and exps) `(and ,@(maplr expdef exps)))
- (($ app fun args)
- `(,(expdef fun) ,@(maplr expdef args)))
- (($ begin exps) `(begin ,@(maplr expdef exps)))
- (($ const c _) (pconst c))
- (($ if test then els)
- `(if ,(expdef test) ,(expdef then) ,(expdef els)))
- (($ lam params body)
- `(lambda ,(map show params) ,@(expdef body)))
- (($ vlam params rest body)
- `(lambda ,(append (map show params) (show rest))
- ,@(expdef body)))
- (($ let bindings body)
- `(let ,(map pbind bindings) ,@(expdef body)))
- (($ let* bindings body)
- `(let* ,(map pbind bindings) ,@(expdef body)))
- (($ letr bindings body)
- `(letrec ,(map pbind bindings) ,@(expdef body)))
- (($ body defs exps)
- (let ((pdefs (maplr expdef defs)))
- (append pdefs (maplr expdef exps))))
- (($ record bindings)
- `(record ,@(maplr pbind bindings)))
- (($ field x e) `(field ,x ,(expdef e)))
- (($ cast (ty . _) e) `(: ,ty ,(expdef e)))
- (($ or exps) `(or ,@(maplr expdef exps)))
- (($ delay e) `(delay ,(expdef e)))
- (($ set! x body)
- `(set! ,(pname x) ,(expdef body)))
- (($ var x) (pname x))
- (($ match e1 clauses)
- (let* ((pclause
- (match-lambda
- (($ mclause p exp fail)
- (if fail
- `(,(expdef p) (=> ,(pname fail)) ,@(expdef exp))
- `(,(expdef p) ,@(expdef exp))))))
- (p1 (expdef e1)))
- `(match ,p1 ,@(maplr pclause clauses))))
- (($ pconst x _) (pconst x))
- (($ pvar x) (show x))
- (($ pany) '_)
- (($ pelse) 'else)
- (($ pnot pat) `(not ,(expdef pat)))
- (($ pand pats) `(and ,@(maplr expdef pats)))
- (($ ppred pred)
- (match (pname pred)
- ('false-object? #f)
- ('true-object? #t)
- ('null? '())
- (x `(? ,x))))
- (($ pobj tag args)
- (match (cons (pname tag) args)
- (('pair? x y) (cons (expdef x) (expdef y)))
- (('box? x) (box (expdef x)))
- (('vector? . x) (list->vector (maplr expdef x)))
- ((tg . _)
- `($ ,(strip-? tg) ,@(maplr expdef args)))))
- (($ type _ exp) (expdef exp))
- (($ check _ exp) (expdef exp)))))
- (define check-type
- (match-lambda
- (($ type ty ($ check inf ($ var x))) ty)
- (($ type ty ($ check inf ($ lam x e1))) ty)
- (($ type ty ($ check inf ($ vlam x rest e1))) ty)
- (($ type _ ($ check inf ($ app e1 args)))
- (typeof e1))
- (($ type _ ($ check inf ($ field x e1)))
- (typeof e1))
- (($ type _ ($ check inf ($ cast (x . _) e1)))
- (typeof e1))
- (($ type _ ($ check inf ($ match e1 clauses)))
- (typeof e1))))
- (define tree '())
- (define global-env empty-env)
- (define verbose #f)
- (define times #t)
- (define benchmarking #f)
- (define cons-mutators '(set-car! set-cdr!))
- (define st:check
- (lambda args
- (parameterize
- ((print-level #f)
- (print-length #f)
- (pretty-maximum-lines #f))
- (let ((output (apply do-soft args)))
- (when output
- (printf
- "Typed program written to file ~a~%"
- output))))))
- (define st:run
- (lambda (file)
- (parameterize
- ((optimize-level 3))
- (when benchmarking
- (printf "Reloading slow CHECKs...~%")
- (load (string-append
- installation-directory
- "checklib.scm"))
- (set! benchmarking #f))
- (load file))))
- (define st:bench
- (lambda (file)
- (parameterize
- ((optimize-level 3))
- (unless
- benchmarking
- (unless
- fastlibrary-file
- (use-error
- "No benchmarking mode in this version"))
- (printf "Reloading fast CHECKs...~%")
- (load (string-append
- installation-directory
- fastlibrary-file))
- (set! benchmarking #t))
- (load file))))
- (define st:
- (lambda args
- (parameterize
- ((print-level #f)
- (print-length #f)
- (pretty-maximum-lines #f))
- (let ((output (apply do-soft args)))
- (cond ((not output)
- (use-error "Output file name required to run"))
- ((= 0 n-unbound)
- (printf
- "Typed program written to file ~a, executing ...~%"
- output)
- (flush-output)
- (st:run output))
- (else
- (printf
- "Typed program written to file ~a, not executing (unbound refs)~%"
- output)))))))
- (define do-soft
- (match-lambda*
- ((input (? string? output))
- (when (strip-suffix output)
- (use-error
- "output file name cannot end in .ss or .scm"))
- (cond ((string? input)
- (soft-files (list input) output)
- output)
- ((and (list? input) (andmap string? input))
- (soft-files input output)
- output)
- (else (soft-def input output) output)))
- ((input #f)
- (cond ((string? input) (soft-files (list input) #f) #f)
- ((and (list? input) (andmap string? input))
- (soft-files input #f)
- #f)
- (else (soft-def input #f) #f)))
- ((input)
- (cond ((string? input)
- (let ((o (string-append
- (or (strip-suffix input) input)
- ".soft")))
- (soft-files (list input) o)
- o))
- ((and (list? input) (andmap string? input))
- (use-error "Output file name required"))
- (else (soft-def input #t) #f)))
- (else (use-error
- "Input must be a file name or list of file names"))))
- (define rawmode #f)
- (define st:control
- (lambda args
- (let ((dbg (match-lambda
- ('raw
- (set! display-type ptype)
- (set! rawmode #t))
- ('!raw
- (set! display-type tidy)
- (set! rawmode #f))
- ('verbose (set! verbose #t))
- ('!verbose (set! verbose #f))
- ('times (set! times #t))
- ('!times (set! times #f))
- ('partial (set! fullsharing #f))
- ('!partial (set! fullsharing #t))
- ('pseudo (set! pseudo pseudo-subtype))
- ('!pseudo (set! pseudo #f))
- ('populated (set! populated #t))
- ('!populated (set! populated #f))
- ('matchst (set! matchst #t))
- ('!matchst (set! matchst #f))
- ('genmatch (set! genmatch #t))
- ('!genmatch (set! genmatch #f))
- ('letonce (set! letonce #t))
- ('!letonce (set! letonce #f))
- ('global-error (set! global-error #t))
- ('!global-error (set! global-error #f))
- ('share (set! share #t))
- ('!share (set! share #f))
- ('flags (set! flags #t))
- ('!flags (set! flags #f))
- ('depths (set! dump-depths #t))
- ('!depths (set! dump-depths #f))
- ('match (set! keep-match #t))
- ('!match (set! keep-match #f))
- (x (printf "Error: unknown debug switch ~a~%" x)
- (st:control)))))
- (if (null? args)
- (begin
- (printf "Current values:")
- (for-each
- (lambda (x) (printf " ~a" x))
- (show-controls))
- (printf "~%"))
- (for-each dbg args)))))
- (define show-controls
- (lambda ()
- (list (if rawmode 'raw '!raw)
- (if verbose 'verbose '!verbose)
- (if times 'times '!times)
- (if share 'share '!share)
- (if flags 'flags '!flags)
- (if dump-depths 'depths '!depths)
- (if fullsharing '!partial 'partial)
- (if pseudo 'pseudo '!pseudo)
- (if populated 'populated '!populated)
- (if letonce 'letonce '!letonce)
- (if matchst 'matchst '!matchst)
- (if genmatch 'genmatch '!genmatch)
- (if global-error 'global-error '!global-error)
- (if keep-match 'match '!match))))
- (define soft-def
- (lambda (exp output)
- (reinit-macros!)
- (reinit-types!)
- (reinit-output!)
- (set! visible-time 0)
- (match-let*
- ((before-parse (cpu-time))
- (defs (parse-def exp))
- (before-bind (cpu-time))
- ((defs env tenv unbound)
- (bind-defs
- defs
- initial-env
- initial-type-env
- '()
- 0))
- (_ (warn-unbound unbound))
- (_ (if cons-is-mutable
- (printf
- "Note: use of ~a, treating cons as MUTABLE~%"
- cons-mutators)
- (printf
- "Note: no use of ~a, treating cons as immutable~%"
- cons-mutators)))
- (before-improve (cpu-time))
- (defs (improve-defs defs))
- (before-typecheck (cpu-time))
- (_ (type-check defs))
- (_ (set! global-env env))
- (before-output (cpu-time))
- (_ (check output))
- (_ (print-summary ""))
- (before-end (cpu-time)))
- (when times
- (printf
- "~a seconds parsing,~%"
- (exact->inexact
- (* (- before-bind before-parse)
- clock-granularity)))
- (printf
- "~a seconds binding,~%"
- (exact->inexact
- (* (- before-improve before-bind)
- clock-granularity)))
- (printf
- "~a seconds improving,~%"
- (exact->inexact
- (* (- before-typecheck before-improve)
- clock-granularity)))
- (printf
- "~a seconds type checking,~%"
- (exact->inexact
- (* (- (- before-output before-typecheck)
- visible-time)
- clock-granularity)))
- (printf
- "~a seconds setting visibility,~%"
- (exact->inexact
- (* visible-time clock-granularity)))
- (printf
- "~a seconds writing output,~%"
- (exact->inexact
- (* (- before-end before-output)
- clock-granularity)))
- (printf
- "~a seconds in total.~%"
- (exact->inexact
- (* (- before-end before-parse) clock-granularity)))))))
- (define type-check
- (lambda (defs)
- (set! tree defs)
- (type-defs defs)
- defs))
- (define soft-files
- (lambda (files output)
- (let ((contents
- (map (lambda (f) `(begin ,@(readfile f))) files)))
- (soft-def `(begin ,@contents) output))))
- (define strip-suffix
- (lambda (name)
- (let ((n (string-length name)))
- (or (and (<= 3 n)
- (equal? ".ss" (substring name (- n 3) n))
- (substring name 0 (- n 3)))
- (and (<= 4 n)
- (equal? ".scm" (substring name (- n 4) n))
- (substring name 0 (- n 4)))))))
- (define st:deftype
- (match-lambda*
- (((? symbol? x) ? list? mutability)
- (=> fail)
- (if (andmap boolean? mutability)
- (deftype x mutability)
- (fail)))
- (args (use-error
- "Invalid command ~a"
- `(st:deftype ,@args)))))
- (define st:defprim
- (match-lambda*
- (((? symbol? x) type) (defprim x type 'impure))
- (((? symbol? x) type (? symbol? mode))
- (defprim x type mode))
- (args (use-error
- "Invalid command ~a"
- `(st:defprim ,@args)))))
- (define st:help
- (lambda ()
- (printf
- "Commands for Soft Scheme (~a)~%"
- st:version)
- (printf
- " (st: file (output)) type check file and execute~%")
- (printf
- " (st:type (name)) print types of global defs~%")
- (printf
- " (st:check file (output)) type check file~%")
- (printf
- " (st:run file) execute type checked file~%")
- (printf
- " (st:bench file) execute type checked file fast~%")
- (printf
- " (st:ltype (name)) print types of local defs~%")
- (printf
- " (st:cause) print cause of CHECKs~%")
- (printf
- " (st:summary) print summary of CHECKs~%")
- (printf
- " (st:help) prints this message~%")
- (printf
- " (st:defprim name type (mode)) define a new primitive~%")
- (printf
- " (st:deftype name bool ...) define a new type constructor~%")
- (printf
- " (st:control flag ...) set internal flags~%")
- (printf
- "For more info, see ftp://ftp.nj.nec.com/pub/wright/ssmanual/softscheme.html~%")
- (printf
- "Copyright (c) 1993, 1994, 1995 by Andrew K. Wright under the~%")
- (printf
- "terms of the Gnu Public License. No warranties of any kind apply.~%")))
- (define st:type type)
- (define st:ltype localtype)
- (define st:cause cause)
- (define st:summary
- (lambda () (print-summary "")))
- (define init!
- (lambda ()
- (when customization-file
- (load (string-append
- installation-directory
- customization-file)))
- (let ((softrc
- (string-append home-directory "/.softschemerc")))
- (when (file-exists? softrc) (load softrc)))
- (set! global-env initial-env)
- (st:help)))
- (init!)
|