1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062(**************************************************************************)(* *)(* OCaml *)(* *)(* Zesen Qian, Jane Street, London *)(* *)(* Copyright 2024 Jane Street Group LLC *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)(* warn on fragile matches *)[@@@warning"+4"](* Merlin-specific: change some module paths to match the compiler *)moduleMisc=structincludeMiscmoduleStdlib=Misc_stdlibincludeMisc_stdlibendopenAllowanceopenSolveropenMode_intfmoduleHint=Mode_hintmoduleFmt=Format_docmoduleHint_for_solver(* : Solver_intf.Hint *)=structmodulePinpoint=structtypet=Hint.pinpointletunknown:t=Location.none,UnknownendmoduleMorph=structtype'dt='dHint.morphletunknown:_t=Unknownletid:_t=Skipletleft_adjoint:typel.Hint.pinpoint->(l*allowed)t->Hint.pinpoint*(allowed*disallowed)t=funppt->matchtwith|Skip->pp,Skip|Is_closed_by(Monadic,co)->co.closure,Close_over(Monadic,co)|Is_closed_by(Comonadic,co)->co.closure,Close_over(Comonadic,co)|Captured_by_partial_application->(Location.none,Expression),Adj_captured_by_partial_application|Crossing->pp,Crossing|Unknown->(Location.none,Unknown),Unknown|Allocation_rloc->pp,Allocation_lloc|Contains_r(Comonadic,{containing;contained})->contained,Is_contained_by(Comonadic,{containing;container=pp})|Contains_l(Monadic,{containing;contained})->contained,Is_contained_by(Monadic,{containing;container=pp})|Is_contained_by(Comonadic,{containing;container})->container,Contains_l(Comonadic,{containing;contained=pp})|Is_contained_by(Monadic,{containing;container})->container,Contains_r(Monadic,{containing;contained=pp})letright_adjoint:typer.Hint.pinpoint->(allowed*r)t->Hint.pinpoint*(disallowed*allowed)t=funppt->matchtwith|Skip->pp,Skip|Close_over(Monadic,co)->co.closed,Is_closed_by(Monadic,co)|Close_over(Comonadic,co)->co.closed,Is_closed_by(Comonadic,co)|Adj_captured_by_partial_application->(Location.none,Expression),Captured_by_partial_application|Crossing->pp,Crossing|Unknown->(Location.none,Unknown),Unknown|Allocation_lloc->pp,Allocation_rloc|Contains_l(Comonadic,{containing;contained})->contained,Is_contained_by(Comonadic,{containing;container=pp})|Contains_r(Monadic,{containing;contained})->contained,Is_contained_by(Monadic,{containing;container=pp})|Is_contained_by(Comonadic,{containing;container})->container,Contains_r(Comonadic,{containing;contained=pp})|Is_contained_by(Monadic,{containing;container})->container,Contains_l(Monadic,{containing;contained=pp})includeMagic_allow_disallow(structtype(_,_,'d)sided='dtconstraint'd='l*'rletallow_left:typelr.(allowed*r)t->(l*r)t=fun(typelr)(h:(allowed*r)t):(l*r)t->matchhwith|Skip->Skip|Unknown->Unknown|Close_over(Monadic,x)->Close_over(Monadic,x)|Close_over(Comonadic,x)->Close_over(Comonadic,x)|Adj_captured_by_partial_application->Adj_captured_by_partial_application|Crossing->Crossing|Allocation_lloc->Allocation_lloc|Contains_l(Comonadic,x)->Contains_l(Comonadic,x)|Contains_r(Monadic,x)->Contains_r(Monadic,x)|Is_contained_by(Comonadic,x)->Is_contained_by(Comonadic,x)|Is_contained_by(Monadic,x)->Is_contained_by(Monadic,x)letallow_right:typelr.(l*allowed)t->(l*r)t=fun(typelr)(h:(l*allowed)t):(l*r)t->matchhwith|Skip->Skip|Unknown->Unknown|Is_closed_by(Monadic,x)->Is_closed_by(Monadic,x)|Is_closed_by(Comonadic,x)->Is_closed_by(Comonadic,x)|Captured_by_partial_application->Captured_by_partial_application|Crossing->Crossing|Allocation_rloc->Allocation_rloc|Contains_r(Comonadic,x)->Contains_r(Comonadic,x)|Contains_l(Monadic,x)->Contains_l(Monadic,x)|Is_contained_by(Comonadic,x)->Is_contained_by(Comonadic,x)|Is_contained_by(Monadic,x)->Is_contained_by(Monadic,x)letdisallow_left:typelr.(l*r)t->(disallowed*r)t=fun(typelr)(h:(l*r)t):(disallowed*r)t->matchhwith|Skip->Skip|Unknown->Unknown|Close_over(Monadic,x)->Close_over(Monadic,x)|Close_over(Comonadic,x)->Close_over(Comonadic,x)|Is_closed_by(Monadic,x)->Is_closed_by(Monadic,x)|Is_closed_by(Comonadic,x)->Is_closed_by(Comonadic,x)|Captured_by_partial_application->Captured_by_partial_application|Adj_captured_by_partial_application->Adj_captured_by_partial_application|Crossing->Crossing|Allocation_rloc->Allocation_rloc|Allocation_lloc->Allocation_lloc|Contains_r(Comonadic,x)->Contains_r(Comonadic,x)|Contains_l(Monadic,x)->Contains_l(Monadic,x)|Is_contained_by(Comonadic,x)->Is_contained_by(Comonadic,x)|Is_contained_by(Monadic,x)->Is_contained_by(Monadic,x)|Contains_r(Monadic,x)->Contains_r(Monadic,x)|Contains_l(Comonadic,x)->Contains_l(Comonadic,x)letdisallow_right:typelr.(l*r)t->(l*disallowed)t=fun(typelr)(h:(l*r)t):(l*disallowed)t->matchhwith|Skip->Skip|Unknown->Unknown|Close_over(Monadic,x)->Close_over(Monadic,x)|Close_over(Comonadic,x)->Close_over(Comonadic,x)|Is_closed_by(Monadic,x)->Is_closed_by(Monadic,x)|Is_closed_by(Comonadic,x)->Is_closed_by(Comonadic,x)|Captured_by_partial_application->Captured_by_partial_application|Adj_captured_by_partial_application->Adj_captured_by_partial_application|Crossing->Crossing|Allocation_lloc->Allocation_lloc|Allocation_rloc->Allocation_rloc|Contains_l(Comonadic,x)->Contains_l(Comonadic,x)|Contains_r(Monadic,x)->Contains_r(Monadic,x)|Is_contained_by(Comonadic,x)->Is_contained_by(Comonadic,x)|Is_contained_by(Monadic,x)->Is_contained_by(Monadic,x)|Contains_l(Monadic,x)->Contains_l(Monadic,x)|Contains_r(Comonadic,x)->Contains_r(Comonadic,x)end)endmoduleConst=structtype'dt='dHint.constletunknown:_t=Unknownletmax:_t=Unknownletmin:_t=UnknownincludeMagic_allow_disallow(structtype(_,_,'d)sided='dtconstraint'd='l*'rletallow_left:typelr.(allowed*r)t->(l*r)t=fun(typelr)(h:(allowed*r)t):(l*r)t->matchhwith|Unknown->Unknown|Legacyx->Legacyx|Stack_expression->Stack_expression|Mutable_readm->Mutable_readm|Mutable_writem->Mutable_writem|Lazy_forced->Lazy_forced|Borrowed(loc,Comonadic)->Borrowed(loc,Comonadic)|Borrowed(loc,Monadic)->Borrowed(loc,Monadic)letallow_right:typelr.(l*allowed)t->(l*r)t=fun(typelr)(h:(l*allowed)t):(l*r)t->matchhwith|Unknown->Unknown|Legacyx->Legacyx|Lazy_allocated_on_heap->Lazy_allocated_on_heap|Tailcall_function->Tailcall_function|Tailcall_argument->Tailcall_argument|Function_return->Function_return|Module_allocated_on_heap->Module_allocated_on_heap|Is_used_inpp->Is_used_inpp|Always_dynamicx->Always_dynamicx|Branching->Branching|Borrowed(loc,Monadic)->Borrowed(loc,Monadic)|Borrowed(loc,Comonadic)->Borrowed(loc,Comonadic)|Escape_regionx->Escape_regionxletdisallow_left:typelr.(l*r)t->(disallowed*r)t=fun(typelr)(h:(l*r)t):(disallowed*r)t->matchhwith|Unknown->Unknown|Lazy_allocated_on_heap->Lazy_allocated_on_heap|Legacyx->Legacyx|Tailcall_function->Tailcall_function|Tailcall_argument->Tailcall_argument|Mutable_readm->Mutable_readm|Mutable_writem->Mutable_writem|Lazy_forced->Lazy_forced|Function_return->Function_return|Stack_expression->Stack_expression|Module_allocated_on_heap->Module_allocated_on_heap|Is_used_inpp->Is_used_inpp|Always_dynamicx->Always_dynamicx|Branching->Branching|Borrowed(loc,Monadic)->Borrowed(loc,Monadic)|Borrowed(loc,Comonadic)->Borrowed(loc,Comonadic)|Escape_regionx->Escape_regionxletdisallow_right:typelr.(l*r)t->(l*disallowed)t=fun(typelr)(h:(l*r)t):(l*disallowed)t->matchhwith|Unknown->Unknown|Lazy_allocated_on_heap->Lazy_allocated_on_heap|Legacyx->Legacyx|Tailcall_function->Tailcall_function|Tailcall_argument->Tailcall_argument|Mutable_readm->Mutable_readm|Mutable_writem->Mutable_writem|Lazy_forced->Lazy_forced|Function_return->Function_return|Stack_expression->Stack_expression|Module_allocated_on_heap->Module_allocated_on_heap|Is_used_inpp->Is_used_inpp|Always_dynamicx->Always_dynamicx|Branching->Branching|Borrowed(loc,Monadic)->Borrowed(loc,Monadic)|Borrowed(loc,Comonadic)->Borrowed(loc,Comonadic)|Escape_regionx->Escape_regionxend)endendtypenonrecallowed=allowedtypenonrecdisallowed=disallowedtypenonrecequate_step=equate_stepmoduletypeHeyting=sig(** Extend the [Lattice] interface with operations of Heyting algebras *)includeLattice(** [imply c] is the right adjoint of [meet c]; That is, for any [a] and [b],
[meet c a <= b] iff [a <= imply c b] *)valimply:t->t->tendmoduletypeCoHeyting=sig(** Extend the [Lattice] interface with operations of co-Heyting algebras *)includeLattice(** [subtract _ c] is the left adjoint of [join c]. That is, for any [a] and
[b], [subtract a c <= b] iff [a <= join c b] *)valsubtract:t->t->tend(* Even though our lattices are all bi-heyting algebras, that knowledge is
internal to this module. Externally they are seen as normal lattices. *)moduleLattices=structmoduletypeTotal=sig(** A lattice is total order, if for any [a] [b], [a <= b] or [b <= a].
If it's also finite, then the ordering can be represented as a monotone
injection [ord] into [int], where [a <= b] iff [ord a <= ord b]. *)typetvalord:t->intvalmin:tvalmax:tendmoduleTotal(L:Total)=structletmin=L.minletmax=L.maxletleab=L.orda<=L.ordbletequalab=L.orda=L.ordbletjoinab=ifL.orda>L.ordbthenaelsebletmeetab=ifL.orda<L.ordbthenaelseb(* A total lattice has a co-heyting structure.
Prove the [subtract] below is the left adjoint of [join].
- If [subtract a c <= b], by the definition of [subtract] below,
that could mean one of two things:
- Took the branch [a <= c], and [min <= b]. In this case, we have [a <= c <= join c b].
- Took the other branch, and [a <= b]. In this case, we have [a <= b <= join c b].
- In the other direction: Given [a <= join c b], compare [c] and [b]:
- if [c <= b], then [a <= join c b = b], and:
- either [a <= c], then [subtract a c = min <= b]
- or the other branch, then [subtract a c = a <= b]
- if [b <= c], then [a <= join c b = c], then [subtract a c = min <= b]
*)letsubtractac=ifleacthenL.minelsea(* A total lattice has a heyting structure. The proof for [imply] is dual
and omitted. *)letimplycb=iflecbthenL.maxelsebend[@@inline](* Make the type of [Locality] and [Regionality] below distinguishable,
so that we can be sure [Comonadic_with] is applied correctly. *)moduletypeAreality=sigincludeConstincludeHeytingwithtypet:=tval_is_areality:unitendmoduleLocality=structtypet=|Global|LocalincludeTotal(structtypenonrect=tletmin=Globalletmax=Localletord=functionGlobal->0|Local->1end)letlegacy=Globalletprintppf=function|Global->Fmt.fprintfppf"global"|Local->Fmt.fprintfppf"local"let_is_areality=()endmoduleRegionality=structtypet=|Global|Regional|LocalincludeTotal(structtypenonrect=tletmin=Globalletmax=Localletord=functionGlobal->0|Regional->1|Local->2end)letlegacy=Globalletprintppf=function|Global->Fmt.fprintfppf"global"|Regional->Fmt.fprintfppf"regional"|Local->Fmt.fprintfppf"local"let_is_areality=()endmoduleUniqueness=structtypet=|Unique|AliasedincludeTotal(structtypenonrect=tletmin=Uniqueletmax=Aliasedletord=functionUnique->0|Aliased->1end)letlegacy=Aliasedletprintppf=function|Aliased->Fmt.fprintfppf"aliased"|Unique->Fmt.fprintfppf"unique"endmoduleLinearity=structtypet=|Many|OnceincludeTotal(structtypenonrect=tletmin=Manyletmax=Onceletord=functionMany->0|Once->1end)letlegacy=Manyletprintppf=function|Once->Fmt.fprintfppf"once"|Many->Fmt.fprintfppf"many"endmodulePortability=structtypet=|Portable|Shareable|NonportableincludeTotal(structtypenonrect=tletmin=Portableletmax=Nonportableletord=functionPortable->0|Shareable->1|Nonportable->2end)letlegacy=Nonportableletprintppf=function|Portable->Fmt.fprintfppf"portable"|Shareable->Fmt.fprintfppf"shareable"|Nonportable->Fmt.fprintfppf"nonportable"endmoduleContention=structtypet=|Uncontended|Shared|ContendedincludeTotal(structtypenonrect=tletmin=Uncontendedletmax=Contendedletord=functionUncontended->0|Shared->1|Contended->2end)letlegacy=Uncontendedletprintppf=function|Contended->Fmt.fprintfppf"contended"|Shared->Fmt.fprintfppf"shared"|Uncontended->Fmt.fprintfppf"uncontended"endmoduleForkable=structtypet=|Forkable|UnforkableincludeTotal(structtypenonrect=tletmin=Forkableletmax=Unforkableletord=functionForkable->0|Unforkable->1end)letlegacy=Forkableletprintppf=function|Unforkable->Fmt.fprintfppf"unforkable"|Forkable->Fmt.fprintfppf"forkable"endmoduleYielding=structtypet=|Unyielding|YieldingincludeTotal(structtypenonrect=tletmin=Unyieldingletmax=Yieldingletord=functionUnyielding->0|Yielding->1end)letlegacy=Unyieldingletprintppf=function|Yielding->Fmt.fprintfppf"yielding"|Unyielding->Fmt.fprintfppf"unyielding"endmoduleStatefulness=structtypet=|Stateless|Observing|StatefulincludeTotal(structtypenonrect=tletmin=Statelessletmax=Statefulletord=functionStateless->0|Observing->1|Stateful->2end)letlegacy=Statefulletprintppf=function|Stateless->Fmt.fprintfppf"stateless"|Observing->Fmt.fprintfppf"observing"|Stateful->Fmt.fprintfppf"stateful"endmoduleVisibility=structtypet=|Read_write|Read|ImmutableincludeTotal(structtypenonrect=tletmin=Read_writeletmax=Immutableletord=functionRead_write->0|Read->1|Immutable->2end)letlegacy=Read_writeletprintppf=function|Immutable->Fmt.fprintfppf"immutable"|Read->Fmt.fprintfppf"read"|Read_write->Fmt.fprintfppf"read_write"endmoduleStaticity=structtypet=|Static|DynamicincludeTotal(structtypenonrect=tletmin=Staticletmax=Dynamicletord=functionStatic->0|Dynamic->1end)letlegacy=Dynamicletprintppf=function|Dynamic->Fmt.fprintfppf"dynamic"|Static->Fmt.fprintfppf"static"endtypemonadic={uniqueness:Uniqueness.t;contention:Contention.t;visibility:Visibility.t;staticity:Staticity.t}moduleMonadic=structtypet=monadicletmin=letuniqueness=Uniqueness.mininletcontention=Contention.mininletvisibility=Visibility.mininletstaticity=Staticity.minin{uniqueness;contention;visibility;staticity}letmax=letuniqueness=Uniqueness.maxinletcontention=Contention.maxinletvisibility=Visibility.maxinletstaticity=Staticity.maxin{uniqueness;contention;visibility;staticity}letlegacy=letuniqueness=Uniqueness.legacyinletcontention=Contention.legacyinletvisibility=Visibility.legacyinletstaticity=Staticity.legacyin{uniqueness;contention;visibility;staticity}letlem1m2=let{uniqueness=uniqueness1;contention=contention1;visibility=visibility1;staticity=staticity1}=m1inlet{uniqueness=uniqueness2;contention=contention2;visibility=visibility2;staticity=staticity2}=m2inUniqueness.leuniqueness1uniqueness2&&Contention.lecontention1contention2&&Visibility.levisibility1visibility2&&Staticity.lestaticity1staticity2letequalm1m2=let{uniqueness=uniqueness1;contention=contention1;visibility=visibility1;staticity=staticity1}=m1inlet{uniqueness=uniqueness2;contention=contention2;visibility=visibility2;staticity=staticity2}=m2inUniqueness.equaluniqueness1uniqueness2&&Contention.equalcontention1contention2&&Visibility.equalvisibility1visibility2&&Staticity.equalstaticity1staticity2letjoinm1m2=letuniqueness=Uniqueness.joinm1.uniquenessm2.uniquenessinletcontention=Contention.joinm1.contentionm2.contentioninletvisibility=Visibility.joinm1.visibilitym2.visibilityinletstaticity=Staticity.joinm1.staticitym2.staticityin{uniqueness;contention;visibility;staticity}letmeetm1m2=letuniqueness=Uniqueness.meetm1.uniquenessm2.uniquenessinletcontention=Contention.meetm1.contentionm2.contentioninletvisibility=Visibility.meetm1.visibilitym2.visibilityinletstaticity=Staticity.meetm1.staticitym2.staticityin{uniqueness;contention;visibility;staticity}letsubtractm1m2=letuniqueness=Uniqueness.subtractm1.uniquenessm2.uniquenessinletcontention=Contention.subtractm1.contentionm2.contentioninletvisibility=Visibility.subtractm1.visibilitym2.visibilityinletstaticity=Staticity.subtractm1.staticitym2.staticityin{uniqueness;contention;visibility;staticity}letprintppfm=Fmt.fprintfppf"%a,%a,%a,%a"Uniqueness.printm.uniquenessContention.printm.contentionVisibility.printm.visibilityStaticity.printm.staticityendtype'arealitycomonadic_with={areality:'areality;linearity:Linearity.t;portability:Portability.t;forkable:Forkable.t;yielding:Yielding.t;statefulness:Statefulness.t}moduleComonadic_with(Areality:Areality)=structtypet=Areality.tcomonadic_withletmin=letareality=Areality.mininletlinearity=Linearity.mininletportability=Portability.mininletforkable=Forkable.mininletyielding=Yielding.mininletstatefulness=Statefulness.minin{areality;linearity;portability;forkable;yielding;statefulness}letmax=letareality=Areality.maxinletlinearity=Linearity.maxinletportability=Portability.maxinletforkable=Forkable.maxinletyielding=Yielding.maxinletstatefulness=Statefulness.maxin{areality;linearity;portability;forkable;yielding;statefulness}letlegacy=letareality=Areality.legacyinletlinearity=Linearity.legacyinletportability=Portability.legacyinletforkable=Forkable.legacyinletyielding=Yielding.legacyinletstatefulness=Statefulness.legacyin{areality;linearity;portability;forkable;yielding;statefulness}letlem1m2=let{areality=areality1;linearity=linearity1;portability=portability1;forkable=forkable1;yielding=yielding1;statefulness=statefulness1}=m1inlet{areality=areality2;linearity=linearity2;portability=portability2;forkable=forkable2;yielding=yielding2;statefulness=statefulness2}=m2inAreality.leareality1areality2&&Linearity.lelinearity1linearity2&&Portability.leportability1portability2&&Forkable.leforkable1forkable2&&Yielding.leyielding1yielding2&&Statefulness.lestatefulness1statefulness2letequalm1m2=let{areality=areality1;linearity=linearity1;portability=portability1;forkable=forkable1;yielding=yielding1;statefulness=statefulness1}=m1inlet{areality=areality2;linearity=linearity2;portability=portability2;forkable=forkable2;yielding=yielding2;statefulness=statefulness2}=m2inAreality.equalareality1areality2&&Linearity.equallinearity1linearity2&&Portability.equalportability1portability2&&Forkable.equalforkable1forkable2&&Yielding.equalyielding1yielding2&&Statefulness.equalstatefulness1statefulness2letjoinm1m2=letareality=Areality.joinm1.arealitym2.arealityinletlinearity=Linearity.joinm1.linearitym2.linearityinletportability=Portability.joinm1.portabilitym2.portabilityinletforkable=Forkable.joinm1.forkablem2.forkableinletyielding=Yielding.joinm1.yieldingm2.yieldinginletstatefulness=Statefulness.joinm1.statefulnessm2.statefulnessin{areality;linearity;portability;forkable;yielding;statefulness}letmeetm1m2=letareality=Areality.meetm1.arealitym2.arealityinletlinearity=Linearity.meetm1.linearitym2.linearityinletportability=Portability.meetm1.portabilitym2.portabilityinletforkable=Forkable.meetm1.forkablem2.forkableinletyielding=Yielding.meetm1.yieldingm2.yieldinginletstatefulness=Statefulness.meetm1.statefulnessm2.statefulnessin{areality;linearity;portability;forkable;yielding;statefulness}letimplym1m2=letareality=Areality.implym1.arealitym2.arealityinletlinearity=Linearity.implym1.linearitym2.linearityinletportability=Portability.implym1.portabilitym2.portabilityinletforkable=Forkable.implym1.forkablem2.forkableinletyielding=Yielding.implym1.yieldingm2.yieldinginletstatefulness=Statefulness.implym1.statefulnessm2.statefulnessin{areality;linearity;portability;forkable;yielding;statefulness}letprintppfm=Fmt.fprintfppf"%a,%a,%a,%a,%a,%a"Areality.printm.arealityLinearity.printm.linearityPortability.printm.portabilityForkable.printm.forkableYielding.printm.yieldingStatefulness.printm.statefulnessend[@@inline]moduleOpposite(L:CoHeyting):Heytingwithtypet=L.t=structtypet=L.tletmin=L.maxletmax=L.minlet[@inline]leab=L.lebaletequal=L.equalletjoin=L.meetletmeet=L.joinletprint=L.printletimplyab=L.subtractbaend[@@inline](* Notes on flipping
Our lattices are split into two opposite fragments: monadic and comonadic.
Moreover:
- Morphisms between lattices in the same fragment are always monotone.
- Morphisms between lattices from opposite fragments are always antitone.
[Solver_mono] only supports monotone morphisms. Due to this limitation,
here, we flip all lattices in the monadic fragment, which makes morphisms
between opposite fragments monotone. We submit this category of lattices
(original comonadic lattices + flipped monadic lattices) to [Solver_mono].
The resulted interface given by [Solver_mono] therefore has the monadic
lattices flipped. We build on top of that and provide an interface to the
downstream code where monadic lattices are flipped back to its original
ordering. See [module Monadic_gen] and [module Monadic].
*)moduleUniqueness_op=Opposite(Uniqueness)moduleContention_op=Opposite(Contention)moduleVisibility_op=Opposite(Visibility)moduleStaticity_op=Opposite(Staticity)moduleMonadic_op=Opposite(Monadic)moduleComonadic_with_locality=Comonadic_with(Locality)moduleComonadic_with_regionality=Comonadic_with(Regionality)type'aobj=|Locality:Locality.tobj|Regionality:Regionality.tobj|Uniqueness_op:Uniqueness_op.tobj|Linearity:Linearity.tobj|Portability:Portability.tobj|Forkable:Forkable.tobj|Yielding:Yielding.tobj|Statefulness:Statefulness.tobj|Contention_op:Contention_op.tobj|Visibility_op:Visibility_op.tobj|Staticity_op:Staticity_op.tobj|Monadic_op:Monadic_op.tobj|Comonadic_with_regionality:Comonadic_with_regionality.tobj|Comonadic_with_locality:Comonadic_with_locality.tobjletis_opposite:typea.aobj->bool=function|Locality->false|Regionality->false|Uniqueness_op->true|Linearity->false|Portability->false|Forkable->false|Yielding->false|Statefulness->false|Contention_op->true|Visibility_op->true|Staticity_op->true|Monadic_op->true|Comonadic_with_locality->false|Comonadic_with_regionality->falseletprint_obj:typea._->aobj->unit=funppf->function|Locality->Fmt.fprintfppf"Locality"|Regionality->Fmt.fprintfppf"Regionality"|Uniqueness_op->Fmt.fprintfppf"Uniqueness_op"|Linearity->Fmt.fprintfppf"Linearity"|Portability->Fmt.fprintfppf"Portability"|Forkable->Fmt.fprintfppf"Forkable"|Yielding->Fmt.fprintfppf"Yielding"|Statefulness->Fmt.fprintfppf"Statefulness"|Contention_op->Fmt.fprintfppf"Contention_op"|Visibility_op->Fmt.fprintfppf"Visibility_op"|Staticity_op->Fmt.fprintfppf"Staticity_op"|Monadic_op->Fmt.fprintfppf"Monadic_op"|Comonadic_with_locality->Fmt.fprintfppf"Comonadic_with_locality"|Comonadic_with_regionality->Fmt.fprintfppf"Comonadic_with_regionality"letmin:typea.aobj->a=function|Locality->Locality.min|Regionality->Regionality.min|Uniqueness_op->Uniqueness_op.min|Contention_op->Contention_op.min|Visibility_op->Visibility_op.min|Forkable->Forkable.min|Yielding->Yielding.min|Statefulness->Statefulness.min|Linearity->Linearity.min|Portability->Portability.min|Staticity_op->Staticity_op.min|Monadic_op->Monadic_op.min|Comonadic_with_locality->Comonadic_with_locality.min|Comonadic_with_regionality->Comonadic_with_regionality.minletmax:typea.aobj->a=function|Locality->Locality.max|Regionality->Regionality.max|Uniqueness_op->Uniqueness_op.max|Contention_op->Contention_op.max|Visibility_op->Visibility_op.max|Linearity->Linearity.max|Portability->Portability.max|Forkable->Forkable.max|Yielding->Yielding.max|Statefulness->Statefulness.max|Staticity_op->Staticity_op.max|Monadic_op->Monadic_op.max|Comonadic_with_locality->Comonadic_with_locality.max|Comonadic_with_regionality->Comonadic_with_regionality.maxletle:typea.aobj->a->a->bool=funobjab->matchobjwith|Locality->Locality.leab|Regionality->Regionality.leab|Uniqueness_op->Uniqueness_op.leab|Contention_op->Contention_op.leab|Visibility_op->Visibility_op.leab|Linearity->Linearity.leab|Portability->Portability.leab|Forkable->Forkable.leab|Yielding->Yielding.leab|Statefulness->Statefulness.leab|Staticity_op->Staticity_op.leab|Monadic_op->Monadic_op.leab|Comonadic_with_locality->Comonadic_with_locality.leab|Comonadic_with_regionality->Comonadic_with_regionality.leabletjoin:typea.aobj->a->a->a=funobjab->matchobjwith|Locality->Locality.joinab|Regionality->Regionality.joinab|Uniqueness_op->Uniqueness_op.joinab|Contention_op->Contention_op.joinab|Visibility_op->Visibility_op.joinab|Linearity->Linearity.joinab|Portability->Portability.joinab|Forkable->Forkable.joinab|Yielding->Yielding.joinab|Statefulness->Statefulness.joinab|Staticity_op->Staticity_op.joinab|Monadic_op->Monadic_op.joinab|Comonadic_with_locality->Comonadic_with_locality.joinab|Comonadic_with_regionality->Comonadic_with_regionality.joinabletmeet:typea.aobj->a->a->a=funobjab->matchobjwith|Locality->Locality.meetab|Regionality->Regionality.meetab|Uniqueness_op->Uniqueness_op.meetab|Contention_op->Contention_op.meetab|Visibility_op->Visibility_op.meetab|Linearity->Linearity.meetab|Portability->Portability.meetab|Forkable->Forkable.meetab|Yielding->Yielding.meetab|Statefulness->Statefulness.meetab|Staticity_op->Staticity_op.meetab|Monadic_op->Monadic_op.meetab|Comonadic_with_locality->Comonadic_with_locality.meetab|Comonadic_with_regionality->Comonadic_with_regionality.meetabletimply:typea.aobj->a->a->a=funobjab->matchobjwith|Locality->Locality.implyab|Regionality->Regionality.implyab|Uniqueness_op->Uniqueness_op.implyab|Contention_op->Contention_op.implyab|Visibility_op->Visibility_op.implyab|Linearity->Linearity.implyab|Portability->Portability.implyab|Forkable->Forkable.implyab|Yielding->Yielding.implyab|Statefulness->Statefulness.implyab|Staticity_op->Staticity_op.implyab|Comonadic_with_locality->Comonadic_with_locality.implyab|Comonadic_with_regionality->Comonadic_with_regionality.implyab|Monadic_op->Monadic_op.implyab(* not hotpath, Ok to curry *)letprint:typea.aobj->_->a->unit=function|Locality->Locality.print|Regionality->Regionality.print|Uniqueness_op->Uniqueness_op.print|Contention_op->Contention_op.print|Visibility_op->Visibility_op.print|Linearity->Linearity.print|Portability->Portability.print|Forkable->Forkable.print|Yielding->Yielding.print|Statefulness->Statefulness.print|Staticity_op->Staticity_op.print|Monadic_op->Monadic_op.print|Comonadic_with_locality->Comonadic_with_locality.print|Comonadic_with_regionality->Comonadic_with_regionality.printmoduleEqual_obj=Magic_equal(structtype('a,_,'d)t='aobjconstraint'd='l*'rletequal:typeab.aobj->bobj->(a,b)Misc.eqoption=funab->matcha,bwith|Locality,Locality->SomeRefl|Regionality,Regionality->SomeRefl|Uniqueness_op,Uniqueness_op->SomeRefl|Contention_op,Contention_op->SomeRefl|Visibility_op,Visibility_op->SomeRefl|Linearity,Linearity->SomeRefl|Portability,Portability->SomeRefl|Yielding,Yielding->SomeRefl|Forkable,Forkable->SomeRefl|Statefulness,Statefulness->SomeRefl|Monadic_op,Monadic_op->SomeRefl|Staticity_op,Staticity_op->SomeRefl|Comonadic_with_locality,Comonadic_with_locality->SomeRefl|Comonadic_with_regionality,Comonadic_with_regionality->SomeRefl|((Locality|Regionality|Uniqueness_op|Contention_op|Visibility_op|Linearity|Portability|Forkable|Yielding|Statefulness|Staticity_op|Monadic_op|Comonadic_with_locality|Comonadic_with_regionality),_)->Noneend)leteq_obj=Equal_obj.equalendmoduleLattices_mono=structincludeLatticesmoduleAxis=structtype('t,'r)t=|Areality:('acomonadic_with,'a)t|Forkable:('arealitycomonadic_with,Forkable.t)t|Yielding:('arealitycomonadic_with,Yielding.t)t|Linearity:('arealitycomonadic_with,Linearity.t)t|Statefulness:('arealitycomonadic_with,Statefulness.t)t|Portability:('arealitycomonadic_with,Portability.t)t|Uniqueness:(Monadic_op.t,Uniqueness_op.t)t|Visibility:(Monadic_op.t,Visibility_op.t)t|Contention:(Monadic_op.t,Contention_op.t)t|Staticity:(Monadic_op.t,Staticity_op.t)t(* Index must reflect implication order: if A implies B, then index A <
index B. This is needed by the implication logic in [typemode]. *)letindex:typepr.(p,r)t->int=function|Areality->0|Forkable->1|Yielding->2|Linearity->3|Statefulness->4|Portability->5|Uniqueness->6|Visibility->7|Contention->8|Staticity->9letcompareab=indexa-indexbletprint:typepr._->(p,r)t->unit=funppf->function|Areality->Fmt.fprintfppf"locality"|Linearity->Fmt.fprintfppf"linearity"|Portability->Fmt.fprintfppf"portability"|Uniqueness->Fmt.fprintfppf"uniqueness"|Contention->Fmt.fprintfppf"contention"|Forkable->Fmt.fprintfppf"forkable"|Yielding->Fmt.fprintfppf"yielding"|Statefulness->Fmt.fprintfppf"statefulness"|Visibility->Fmt.fprintfppf"visibility"|Staticity->Fmt.fprintfppf"staticity"leteq:typepr0r1.(p,r0)t->(p,r1)t->(r0,r1)Misc.eqoption=funax0ax1->matchax0,ax1with|Areality,Areality->SomeRefl|Linearity,Linearity->SomeRefl|Portability,Portability->SomeRefl|Uniqueness,Uniqueness->SomeRefl|Contention,Contention->SomeRefl|Forkable,Forkable->SomeRefl|Yielding,Yielding->SomeRefl|Statefulness,Statefulness->SomeRefl|Visibility,Visibility->SomeRefl|Staticity,Staticity->SomeRefl|((Areality|Linearity|Uniqueness|Portability|Contention|Forkable|Yielding|Statefulness|Visibility|Staticity),_)->Noneletproj:typepr.(p,r)t->p->r=funaxt->matchaxwith|Areality->t.areality|Linearity->t.linearity|Portability->t.portability|Forkable->t.forkable|Yielding->t.yielding|Statefulness->t.statefulness|Uniqueness->t.uniqueness|Contention->t.contention|Visibility->t.visibility|Staticity->t.staticityletset:typepr.(p,r)t->r->p->p=funaxrt->matchaxwith|Areality->{twithareality=r}|Linearity->{twithlinearity=r}|Portability->{twithportability=r}|Forkable->{twithforkable=r}|Yielding->{twithyielding=r}|Statefulness->{twithstatefulness=r}|Uniqueness->{twithuniqueness=r}|Contention->{twithcontention=r}|Visibility->{twithvisibility=r}|Staticity->{twithstaticity=r}endtype('a,'b,'d)morph=|Id:('a,'a,'l*'r)morph(** identity morphism *)|Meet_with:'a->('a,'a,'l*'r)morph(** Meet the input with the parameter *)|Imply:'a->('a,'a,disallowed*'r)morph(** The right adjoint of [Meet_with] *)|Proj:'tobj*('t,'r_)Axis.t->('t,'r_,'l*'r)morph(** Project from a product to an axis *)|Max_with:('t,'r_)Axis.t->('r_,'t,disallowed*'r)morph(** Combine an axis with maxima along other axes *)|Min_with:('t,'r_)Axis.t->('r_,'t,'l*disallowed)morph(** Combine an axis with minima along other axes *)|Map_comonadic:('a0,'a1,'l*'r)morph->('a0comonadic_with,'a1comonadic_with,'l*'r)morph(** Lift an morphism on areality to a morphism on the comonadic fragment
*)|Monadic_to_comonadic_min:(Monadic_op.t,'acomonadic_with,'l*disallowed)morph(** Dualize the monadic fragment to the comonadic fragment. The areality
is set to min. *)|Comonadic_to_monadic_min:'acomonadic_withobj->('acomonadic_with,Monadic_op.t,'l*disallowed)morph(** Dualize the comonadic fragment to the monadic fragment. The
staticity_op is set to min. *)|Monadic_to_comonadic_max:(Monadic_op.t,'acomonadic_with,disallowed*'r)morph(** Dualize the monadic fragment to the comonadic fragment. The areality
is set to max. *)|Comonadic_to_monadic_max:'acomonadic_withobj->('acomonadic_with,Monadic_op.t,disallowed*'r)morph(** Dualize the comonadic fragment to the monadic fragment. The
staticity_op is set to max. *)(* Following is a chain of adjunction (complete and cannot extend in
either direction) *)|Local_to_regional:(Locality.t,Regionality.t,'l*disallowed)morph(** Maps local to regional, global to global *)|Regional_to_local:(Regionality.t,Locality.t,'l*'r)morph(** Maps regional to local, identity otherwise *)|Locality_as_regionality:(Locality.t,Regionality.t,'l*'r)morph(** Inject locality into regionality *)|Regional_to_global:(Regionality.t,Locality.t,'l*'r)morph(** Maps regional to global, identity otherwise *)|Global_to_regional:(Locality.t,Regionality.t,disallowed*'r)morph(** Maps global to regional, local to local *)|Compose:('b,'c,'l*'r)morph*('a,'b,'l*'r)morph->('a,'c,'l*'r)morph(** Compoistion of two morphisms *)constraint'd=_*_[@@ocaml.warning"-62"]includeMagic_allow_disallow(structtype('a,'b,'d)sided=('a,'b,'d)morphconstraint'd='l*'rletrecallow_left:typeablr.(a,b,allowed*r)morph->(a,b,l*r)morph=function|Id->Id|Proj(src,ax)->Proj(src,ax)|Min_withax->Min_withax|Meet_withc->Meet_withc|Compose(f,g)->letf=allow_leftfinletg=allow_leftginCompose(f,g)|Monadic_to_comonadic_min->Monadic_to_comonadic_min|Comonadic_to_monadic_mina->Comonadic_to_monadic_mina|Local_to_regional->Local_to_regional|Locality_as_regionality->Locality_as_regionality|Regional_to_local->Regional_to_local|Regional_to_global->Regional_to_global|Map_comonadicf->letf=allow_leftfinMap_comonadicfletrecallow_right:typeablr.(a,b,l*allowed)morph->(a,b,l*r)morph=function|Id->Id|Proj(src,ax)->Proj(src,ax)|Max_withax->Max_withax|Meet_withc->Meet_withc|Implyc->Implyc|Compose(f,g)->letf=allow_rightfinletg=allow_rightginCompose(f,g)|Comonadic_to_monadic_maxa->Comonadic_to_monadic_maxa|Monadic_to_comonadic_max->Monadic_to_comonadic_max|Global_to_regional->Global_to_regional|Locality_as_regionality->Locality_as_regionality|Regional_to_local->Regional_to_local|Regional_to_global->Regional_to_global|Map_comonadicf->letf=allow_rightfinMap_comonadicfletrecdisallow_left:typeablr.(a,b,l*r)morph->(a,b,disallowed*r)morph=function|Id->Id|Proj(src,ax)->Proj(src,ax)|Min_withax->Min_withax|Max_withax->Max_withax|Meet_withc->Meet_withc|Implyc->Implyc|Compose(f,g)->letf=disallow_leftfinletg=disallow_leftginCompose(f,g)|Monadic_to_comonadic_min->Monadic_to_comonadic_min|Comonadic_to_monadic_mina->Comonadic_to_monadic_mina|Monadic_to_comonadic_max->Monadic_to_comonadic_max|Comonadic_to_monadic_maxa->Comonadic_to_monadic_maxa|Local_to_regional->Local_to_regional|Global_to_regional->Global_to_regional|Locality_as_regionality->Locality_as_regionality|Regional_to_local->Regional_to_local|Regional_to_global->Regional_to_global|Map_comonadicf->letf=disallow_leftfinMap_comonadicfletrecdisallow_right:typeablr.(a,b,l*r)morph->(a,b,l*disallowed)morph=function|Id->Id|Proj(src,ax)->Proj(src,ax)|Min_withax->Min_withax|Max_withax->Max_withax|Meet_withc->Meet_withc|Implyc->Implyc|Compose(f,g)->letf=disallow_rightfinletg=disallow_rightginCompose(f,g)|Monadic_to_comonadic_min->Monadic_to_comonadic_min|Comonadic_to_monadic_mina->Comonadic_to_monadic_mina|Monadic_to_comonadic_max->Monadic_to_comonadic_max|Comonadic_to_monadic_maxa->Comonadic_to_monadic_maxa|Local_to_regional->Local_to_regional|Global_to_regional->Global_to_regional|Locality_as_regionality->Locality_as_regionality|Regional_to_local->Regional_to_local|Regional_to_global->Regional_to_global|Map_comonadicf->letf=disallow_rightfinMap_comonadicfend)letset_areality:typea0a1.a1->a0comonadic_with->a1comonadic_with=funrt->{twithareality=r}letproj_obj:typetr.(t,r)Axis.t->tobj->robj=funaxobj->matchax,objwith|Areality,Comonadic_with_locality->Locality|Areality,Comonadic_with_regionality->Regionality|Linearity,Comonadic_with_locality->Linearity|Linearity,Comonadic_with_regionality->Linearity|Portability,Comonadic_with_locality->Portability|Portability,Comonadic_with_regionality->Portability|Forkable,Comonadic_with_locality->Forkable|Forkable,Comonadic_with_regionality->Forkable|Yielding,Comonadic_with_locality->Yielding|Yielding,Comonadic_with_regionality->Yielding|Statefulness,Comonadic_with_locality->Statefulness|Statefulness,Comonadic_with_regionality->Statefulness|Uniqueness,Monadic_op->Uniqueness_op|Contention,Monadic_op->Contention_op|Visibility,Monadic_op->Visibility_op|Staticity,Monadic_op->Staticity_opletcomonadic_with_obj:typea.aobj->acomonadic_withobj=funa0->matcha0with|Locality->Comonadic_with_locality|Regionality->Comonadic_with_regionality|Uniqueness_op|Linearity|Monadic_op|Comonadic_with_regionality|Comonadic_with_locality|Contention_op|Visibility_op|Portability|Forkable|Yielding|Statefulness|Staticity_op->assertfalseletrecsrc:typeablr.bobj->(a,b,l*r)morph->aobj=fundstf->matchfwith|Id->dst|Proj(src,_)->src|Max_withax->proj_objaxdst|Min_withax->proj_objaxdst|Meet_with_->dst|Imply_->dst|Compose(f,g)->letmid=srcdstfinsrcmidg|Monadic_to_comonadic_min->Monadic_op|Comonadic_to_monadic_minsrc->src|Comonadic_to_monadic_maxsrc->src|Monadic_to_comonadic_max->Monadic_op|Local_to_regional->Locality|Locality_as_regionality->Locality|Global_to_regional->Locality|Regional_to_local->Regionality|Regional_to_global->Regionality|Map_comonadicf->letdst0=proj_objArealitydstinletsrc0=srcdst0fincomonadic_with_objsrc0moduleEqual_morph=Magic_equal(structtype('a,'b,'d)t=('a,'b,'d)morphconstraint'd='l*'rletrecequal:typea0l0r0a1bl1r1.(a0,b,l0*r0)morph->(a1,b,l1*r1)morph->(a0,a1)Misc.eqoption=funf0f1->matchf0,f1with|Id,Id->SomeRefl|Proj(src0,ax0),Proj(src1,ax1)->(matcheq_objsrc0src1with|SomeRefl->(matchAxis.eqax0ax1withNone->None|SomeRefl->SomeRefl)|None->None)|Max_withax0,Max_withax1->(matchAxis.eqax0ax1withSomeRefl->SomeRefl|None->None)|Min_withax0,Min_withax1->(matchAxis.eqax0ax1withSomeRefl->SomeRefl|None->None)|Meet_withc0,Meet_withc1->(* This polymorphic equality is correct only if runtime representation
uniquely identifies a constant, which could be false. For example,
the lattice of rational number would be represented as the tuple of
numerator and denominator, and (9,4) and (18, 8) means the same
thing. However, even in that case, it's not unsound, as [eq_morph] is
not requird to be complete: i.e., it's allowed to return [None] when
it should return [Some]. It would cause duplication but not error. *)ifc0=c1thenSomeReflelseNone|Implyc0,Implyc1->ifc0=c1thenSomeReflelseNone|Monadic_to_comonadic_min,Monadic_to_comonadic_min->SomeRefl|Comonadic_to_monadic_mina0,Comonadic_to_monadic_mina1->(matcheq_obja0a1withNone->None|SomeRefl->SomeRefl)|Comonadic_to_monadic_maxa0,Comonadic_to_monadic_maxa1->(matcheq_obja0a1withNone->None|SomeRefl->SomeRefl)|Monadic_to_comonadic_max,Monadic_to_comonadic_max->SomeRefl|Local_to_regional,Local_to_regional->SomeRefl|Locality_as_regionality,Locality_as_regionality->SomeRefl|Global_to_regional,Global_to_regional->SomeRefl|Regional_to_local,Regional_to_local->SomeRefl|Regional_to_global,Regional_to_global->SomeRefl|Compose(f0,g0),Compose(f1,g1)->(matchequalf0f1with|None->None|SomeRefl->(matchequalg0g1withNone->None|SomeRefl->SomeRefl))|Map_comonadicf,Map_comonadicg->(matchequalfgwithSomeRefl->SomeRefl|None->None)|((Id|Proj_|Max_with_|Min_with_|Meet_with_|Monadic_to_comonadic_min|Comonadic_to_monadic_min_|Comonadic_to_monadic_max_|Monadic_to_comonadic_max|Local_to_regional|Locality_as_regionality|Global_to_regional|Regional_to_local|Regional_to_global|Compose_|Map_comonadic_|Imply_),_)->Noneend)leteq_morph=Equal_morph.equalletrecprint_morph:typeablr.bobj->Fmt.formatter->(a,b,l*r)morph->unit=fundstppf->function|Id->Fmt.fprintfppf"id"|Meet_withc->Fmt.fprintfppf"meet(%a)"(printdst)c|Implyc->Fmt.fprintfppf"imply(%a)"(printdst)c|Proj(_,ax)->Fmt.fprintfppf"proj_%a"Axis.printax|Max_withax->Fmt.fprintfppf"max_with_%a"Axis.printax|Min_withax->Fmt.fprintfppf"min_with_%a"Axis.printax|Map_comonadicf->letdst0=proj_objArealitydstinFmt.fprintfppf"map_comonadic(%a)"(print_morphdst0)f|Monadic_to_comonadic_min->Fmt.fprintfppf"monadic_to_comonadic_min"|Comonadic_to_monadic_min_->Fmt.fprintfppf"comonadic_to_monadic_min"|Comonadic_to_monadic_max_->Fmt.fprintfppf"comonadic_to_monadic_max"|Monadic_to_comonadic_max->Fmt.fprintfppf"monadic_to_comonadic_max"|Local_to_regional->Fmt.fprintfppf"local_to_regional"|Regional_to_local->Fmt.fprintfppf"regional_to_local"|Locality_as_regionality->Fmt.fprintfppf"locality_as_regionality"|Regional_to_global->Fmt.fprintfppf"regional_to_global"|Global_to_regional->Fmt.fprintfppf"global_to_regional"|Compose(f0,f1)->letmid=srcdstf0inFmt.fprintfppf"%a ∘ %a"(print_morphdst)f0(print_morphmid)f1letid=Idletlinear_to_unique=function|Linearity.Many->Uniqueness.Aliased|Linearity.Once->Uniqueness.Uniqueletunique_to_linear=function|Uniqueness.Unique->Linearity.Once|Uniqueness.Aliased->Linearity.Manyletportable_to_contended=function|Portability.Portable->Contention.Contended|Portability.Shareable->Contention.Shared|Portability.Nonportable->Contention.Uncontendedletcontended_to_portable=function|Contention.Contended->Portability.Portable|Contention.Shared->Portability.Shareable|Contention.Uncontended->Portability.Nonportableletlocal_to_regional=function|Locality.Global->Regionality.Global|Locality.Local->Regionality.Regionalletregional_to_local=function|Regionality.Local->Locality.Local|Regionality.Regional->Locality.Local|Regionality.Global->Locality.Globalletlocality_as_regionality=function|Locality.Local->Regionality.Local|Locality.Global->Regionality.Globalletregional_to_global=function|Regionality.Local->Locality.Local|Regionality.Regional->Locality.Global|Regionality.Global->Locality.Globalletglobal_to_regional=function|Locality.Local->Regionality.Local|Locality.Global->Regionality.Regionalletstatefulness_to_visibility=function|Statefulness.Stateless->Visibility.Immutable|Statefulness.Observing->Visibility.Read|Statefulness.Stateful->Visibility.Read_writeletvisibility_to_statefulness=function|Visibility.Immutable->Statefulness.Stateless|Visibility.Read->Statefulness.Observing|Visibility.Read_write->Statefulness.Statefulletmin_withdstaxa=Axis.setaxa(mindst)letmax_withdstaxa=Axis.setaxa(maxdst)letmonadic_to_comonadic_min:typea.acomonadic_withobj->Monadic_op.t->acomonadic_with=funobjm->letareality:a=matchobjwith|Comonadic_with_locality->Locality.min|Comonadic_with_regionality->Regionality.mininletlinearity=unique_to_linearm.uniquenessinletportability=contended_to_portablem.contentioninletforkable=Forkable.mininletyielding=Yielding.mininletstatefulness=visibility_to_statefulnessm.visibilityin{areality;linearity;portability;forkable;yielding;statefulness}letcomonadic_to_monadic_min:typea.acomonadic_withobj->acomonadic_with->Monadic_op.t=fun_m->letuniqueness=linear_to_uniquem.linearityinletcontention=portable_to_contendedm.portabilityinletvisibility=statefulness_to_visibilitym.statefulnessinletstaticity=Staticity.minin{uniqueness;contention;visibility;staticity}letcomonadic_to_monadic_max:typea.acomonadic_withobj->acomonadic_with->Monadic_op.t=fun_m->letuniqueness=linear_to_uniquem.linearityinletcontention=portable_to_contendedm.portabilityinletvisibility=statefulness_to_visibilitym.statefulnessinletstaticity=Staticity.maxin{uniqueness;contention;visibility;staticity}letmonadic_to_comonadic_max:typea.acomonadic_withobj->Monadic_op.t->acomonadic_with=funobjm->letareality:a=matchobjwith|Comonadic_with_locality->Locality.max|Comonadic_with_regionality->Regionality.maxinletlinearity=unique_to_linearm.uniquenessinletportability=contended_to_portablem.contentioninletforkable=Forkable.maxinletyielding=Yielding.maxinletstatefulness=visibility_to_statefulnessm.visibilityin{areality;linearity;portability;forkable;yielding;statefulness}letrecapply:typeablr.bobj->(a,b,l*r)morph->a->b=fundstfa->matchfwith|Compose(f,g)->letmid=srcdstfinletg'=applymidginletf'=applydstfinf'(g'a)|Id->a|Proj(_,ax)->Axis.projaxa|Max_withax->max_withdstaxa|Min_withax->min_withdstaxa|Meet_withc->meetdstca|Implyc->implydstca|Monadic_to_comonadic_min->monadic_to_comonadic_mindsta|Comonadic_to_monadic_minsrc->comonadic_to_monadic_minsrca|Comonadic_to_monadic_maxsrc->comonadic_to_monadic_maxsrca|Monadic_to_comonadic_max->monadic_to_comonadic_maxdsta|Local_to_regional->local_to_regionala|Regional_to_local->regional_to_locala|Locality_as_regionality->locality_as_regionalitya|Regional_to_global->regional_to_globala|Global_to_regional->global_to_regionala|Map_comonadicf->letdst0=proj_objArealitydstinleta0=Axis.projArealityainset_areality(applydst0fa0)amoduleFor_hint=struct(** Describes the portion of the input that's responsible for a portion of
the output of a morphism *)type'aresponsible_axis=|NoneResponsible:'aresponsible_axis(** The input is not responsible for the output; instead, the morphism
is solely responsible for the output. *)|SourceIsSingle:'aresponsible_axis(** The input of the morphism is single axis, and is responsible for
the output. *)|Axis:('a,'a_x)Axis.t->'aresponsible_axis(** The specified axis of the input object is responsible for the
output. *)(* CR zqian: the following functions are hard to write, and are redundant since all
the information are already in [apply]. A general and simpler apporach would work
like this: Say we have [b = f a] on RHS, and we want to figure out which axis of
[a] is responsible for a specific axis [ax] of [b] being low. We will iterate
through all axes; for each axis, set that to [max] and get [a'], and calculate [b'
= f a']. If [b'] is not strictly higher than [b] on [ax], then the current axis of
[a] is not responsible for the [ax] of [b] being low. The iteration might end with
no axis of [a] being responsible, in which case the morphism is solely
respoonsible. *)(** Given a morphism either from a single axis to a single axis, or from a
product object to a single axis, return the portion of the input that's
responsible for the output. *)letrecfind_responsible_axis_single:typeablr.(a,b,l*r)morph->aresponsible_axis=function|Proj(_a_obj,ax)->Axisax|Compose(g,f)->(matchfind_responsible_axis_singlegwith|NoneResponsible->NoneResponsible|SourceIsSingle->find_responsible_axis_singlef|Axisc_ax->find_responsible_axis_prodfc_ax)|Id|Meet_with_|Imply_->SourceIsSingle|Max_with_|Min_with_|Map_comonadic_|Monadic_to_comonadic_min|Comonadic_to_monadic_min_|Monadic_to_comonadic_max|Comonadic_to_monadic_max_->assertfalse|Local_to_regional|Regional_to_local|Locality_as_regionality|Regional_to_global|Global_to_regional->SourceIsSingle(** Given a morphism either from a single axis to a product, or from a
product to a product, return the portion of the input that's responsible
for the specified axis of the output. *)andfind_responsible_axis_prod:typeabb_axlr.(a,b,l*r)morph->(b,b_ax)Axis.t->aresponsible_axis=funmax->lethandle_monadic_to_comonadic(typexy)(ax:(xcomonadic_with,y)Axis.t)=(* See [Lattices_mono.monadic_to_comonadic_min] for why these are as they are *)matchaxwith|Areality->NoneResponsible|Linearity->AxisUniqueness|Portability->AxisContention|Forkable->NoneResponsible|Yielding->NoneResponsible|Statefulness->AxisVisibilityinlethandle_comonadic_to_monadic(typey)(ax:(monadic,y)Axis.t)=(* See [Lattices_mono.comonadic_to_monadic_min] for why these are as they are *)matchaxwith|Uniqueness->AxisLinearity|Contention->AxisPortability|Visibility->AxisStatefulness|Staticity->NoneResponsibleinmatchm,axwith|Compose(g,f),ax->((* Operates similarly to the equivalent branch in [find_responsible_axis_single] *)matchfind_responsible_axis_prodgaxwith|NoneResponsible->NoneResponsible|SourceIsSingle->find_responsible_axis_singlef|Axisc_ax->find_responsible_axis_prodfc_ax)|Id,ax->Axisax|Meet_with_,ax->Axisax|Imply_,ax->Axisax|Map_comonadic_,ax->((* The [Map_comonadic] morphism applies a morphsim to the areality axis and
the result is put back into the areality axis. See [Lattices_mono.apply] *)matchaxwith|Areality->AxisAreality|Forkable->AxisForkable|Yielding->AxisYielding|Linearity->AxisLinearity|Statefulness->AxisStatefulness|Portability->AxisPortability)|Max_withm_ax,ax|Min_withm_ax,ax->(matchAxis.eqm_axaxwith|None->NoneResponsible|SomeRefl->SourceIsSingle)|Monadic_to_comonadic_min,ax->handle_monadic_to_comonadicax|Monadic_to_comonadic_max,ax->handle_monadic_to_comonadicax|Comonadic_to_monadic_min_,ax->handle_comonadic_to_monadicax|Comonadic_to_monadic_max_,ax->handle_comonadic_to_monadicax|Proj_,_|Local_to_regional,_|Regional_to_local,_|Locality_as_regionality,_|Regional_to_global,_|Global_to_regional,_->.end(** Compose m0 after m1. Returns [Some f] if the composition can be
represented by [f] instead of [Compose m0 m1]. [None] otherwise. *)letrecmaybe_compose:typeabclr.cobj->(b,c,l*r)morph->(a,b,l*r)morph->(a,c,l*r)morphoption=fundstm0m1->letis_maxc=ledst(maxdst)cinletis_mid_maxc=letmid=srcdstm0inlemid(maxmid)cinmatchm0,m1with|Id,m->Somem|m,Id->Somem|Meet_withc0,Meet_withc1->Some(Meet_with(meetdstc0c1))|Implyc0,Implyc1->Some(Imply(meetdstc0c1))|Implyc0,Meet_withc1whenledstc0c1->Some(Implyc0)|Meet_withc0,m1whenis_maxc0->Somem1|Implyc0,m1whenis_maxc0->Somem1|m1,Meet_withc0whenis_mid_maxc0->Somem1|m1,Implyc0whenis_mid_maxc0->Somem1|Compose(f0,f1),g->(letmid=srcdstf0inmatchmaybe_composemidf1gwith|Somem->Some(composedstf0m)(* the check needed to prevent infinite loop *)|None->None)|f,Compose(g0,g1)->(matchmaybe_composedstfg0with|Somem->Some(composedstmg1)|None->None)|Proj(mid,ax),Meet_withc->Some(composedst(Meet_with(Axis.projaxc))(Proj(mid,ax)))|Proj(_,ax0),Max_withax1->(matchAxis.eqax0ax1withNone->None|SomeRefl->SomeId)|Proj(_,ax0),Min_withax1->(matchAxis.eqax0ax1withNone->None|SomeRefl->SomeId)|Proj(mid,ax),Map_comonadicf->(letsrc'=srcmidm1inmatchaxwith|Areality->Some(composedstf(Proj(src',Areality)))|Linearity->Some(Proj(src',Linearity))|Portability->Some(Proj(src',Portability))|Forkable->Some(Proj(src',Forkable))|Yielding->Some(Proj(src',Yielding))|Statefulness->Some(Proj(src',Statefulness)))|Proj_,Monadic_to_comonadic_min->None|Proj_,Monadic_to_comonadic_max->None|Proj_,Comonadic_to_monadic_min_->None|Proj_,Comonadic_to_monadic_max_->None|Map_comonadicf,Map_comonadicg->letdst0=proj_objArealitydstinSome(Map_comonadic(composedst0fg))|Regional_to_local,Local_to_regional->SomeId|Regional_to_local,Global_to_regional->Some(ImplyLocality.Global)|Regional_to_local,Locality_as_regionality->SomeId|Regional_to_local,Meet_withc->Some(composedst(Meet_with(regional_to_localc))Regional_to_local)|Regional_to_global,Meet_withc->Some(composedst(Meet_with(regional_to_globalc))Regional_to_global)|Local_to_regional,Meet_withc->Some(composedst(Meet_with(local_to_regionalc))Local_to_regional)|Global_to_regional,Meet_withc->Some(composedst(Meet_with(global_to_regionalc))Global_to_regional)|Locality_as_regionality,Meet_withc->Some(composedst(Meet_with(locality_as_regionalityc))Locality_as_regionality)|Map_comonadicf,Meet_withc->letdst0=proj_objArealitydstinletareality=Axis.projArealitycinSome(composedst(Meet_with(set_areality(maxdst0)c))(Map_comonadic(composedst0f(Meet_withareality))))|Map_comonadicf,Implyc->letdst0=proj_objArealitydstinletareality=Axis.projArealitycinSome(composedst(Imply(set_areality(maxdst0)c))(Map_comonadic(composedst0f(Implyareality))))|Regional_to_global,Locality_as_regionality->SomeId|Regional_to_global,Local_to_regional->Some(Meet_withLocality.Global)|Local_to_regional,Regional_to_local->None|Local_to_regional,Regional_to_global->None|Locality_as_regionality,Regional_to_local->None|Locality_as_regionality,Regional_to_global->None|Global_to_regional,Regional_to_local->None|Regional_to_global,Global_to_regional->SomeId|Global_to_regional,Regional_to_global->None|Min_with_,_->None|Max_with_,_->None|_,Meet_with_->None|Meet_with_,_->None|_,Imply_->None|Imply_,_->None|_,Proj_->None|Map_comonadic_,_->None|Monadic_to_comonadic_min,_->None|Monadic_to_comonadic_max,_->None|Comonadic_to_monadic_min_,_->None|Comonadic_to_monadic_max_,_->None|(Proj_,(Local_to_regional|Regional_to_local|Locality_as_regionality|Regional_to_global|Global_to_regional))->.|((Local_to_regional|Regional_to_local|Locality_as_regionality|Regional_to_global|Global_to_regional),Min_with_)->.|((Local_to_regional|Regional_to_local|Locality_as_regionality|Regional_to_global|Global_to_regional),Max_with_)->.andcompose:typeabclr.cobj->(b,c,l*r)morph->(a,b,l*r)morph->(a,c,l*r)morph=fundstfg->matchmaybe_composedstfgwithSomem->m|None->Compose(f,g)letrecleft_adjoint:typeabl.bobj->(a,b,l*allowed)morph->(b,a,allowed*disallowed)morph=fundstf->matchfwith|Id->Id|Proj(_,ax)->Min_withax|Max_withax->Proj(dst,ax)|Compose(f,g)->letmid=srcdstfinletf'=left_adjointdstfinletg'=left_adjointmidginCompose(g',f')|Meet_with_c->(* The downward closure of [Meet_with c]'s image is all [x <= c].
For those, [x <= meet c y] is equivalent to [x <= y]. *)Id|Implyc->Meet_withc|Comonadic_to_monadic_max_->Monadic_to_comonadic_min|Monadic_to_comonadic_max->Comonadic_to_monadic_mindst|Global_to_regional->Regional_to_global|Regional_to_global->Locality_as_regionality|Locality_as_regionality->Regional_to_local|Regional_to_local->Local_to_regional|Map_comonadicf->letdst0=proj_objArealitydstinletf'=left_adjointdst0finMap_comonadicf'andright_adjoint:typeabr.bobj->(a,b,allowed*r)morph->(b,a,disallowed*allowed)morph=fundstf->matchfwith|Id->Id|Proj(_,ax)->Max_withax|Min_withax->Proj(dst,ax)|Compose(f,g)->letmid=srcdstfinletf'=right_adjointdstfinletg'=right_adjointmidginCompose(g',f')|Meet_withc->Implyc|Comonadic_to_monadic_min_->Monadic_to_comonadic_max|Monadic_to_comonadic_min->Comonadic_to_monadic_maxdst|Local_to_regional->Regional_to_local|Regional_to_local->Locality_as_regionality|Locality_as_regionality->Regional_to_global|Regional_to_global->Global_to_regional|Map_comonadicf->letdst0=proj_objArealitydstinletf'=right_adjointdst0finMap_comonadicf'endmoduleC=Lattices_monomoduleSolver=Solver_mono(Hint_for_solver)(C)moduleS=Solverleterase_hints()=S.erase_hints()typemonadic=C.monadic={uniqueness:C.Uniqueness.t;contention:C.Contention.t;visibility:C.Visibility.t;staticity:C.Staticity.t}type'acomonadic_with='aC.comonadic_with={areality:'a;linearity:C.Linearity.t;portability:C.Portability.t;forkable:C.Forkable.t;yielding:C.Yielding.t;statefulness:C.Statefulness.t}moduleAxis=C.Axistypenonrec'asimple_error='asimple_errorletprint_longident=ref(fun__->assertfalse:Fmt.formatter->Longident.t->unit)moduleReport=structopenHint(** Human-readable mode error hints. Compared to [S.error]:
- This doesn't contain branch, and thus forms a chain.
- Each node on the chain talks about a single axis, instead of potentially
on a product lattice. *)type'dhint=|Apply:'dmorph*'bC.obj*('b,'d)ahint->'dhint|Const:'dconst->'dhint|Irrelevant:('l*'r)hint(** The current mode is not responsible for the error (that is, the
surrounding morphism is solely responsible), and should not be
printed. *)constraint'd='l*'r[@@ocaml.warning"-62"]and('a,'d)ahint='a*'dhintconstraint'd='l*'r(** Human-readible mode error report. *)type'at={left:('a,left_only)ahint;right:('a,right_only)ahint}(** Convert Solver error to report. *)moduleOf_solver=struct(** Given a branch of two constant bounds on a single axis, choose the the
one that's responsible for the branch. *)letchoose_branch_axis:typealr.(l*r)Solver_intf.branch->aC.obj->a->a->[`First|`Second]=funba_objxy->(* CR-someday zqian: in the case where [x = y], we currently arbitrarily choose from
[x] and [y], which are unordered anyway. In the future we might want to keep an
order for better error messages. For example, order them by occurrence in the
source code such that the more recent hint is returned. *)matchbwith|Join->ifC.lea_objxythen`SecondelseifC.lea_objyxthen`FirstelseMisc.fatal_error"A single axis should be a total ordering."|Meet->ifC.lea_objxythen`FirstelseifC.lea_objyxthen`SecondelseMisc.fatal_error"A single axis should be a total ordering."(** Given a solver hint on a product lattice, and an axis in that product
that we are interested in, returns a human-readible hint.*)letrechint_apply:typeablr.aC.obj->(l*r)morph->(b,a,l*r)C.morph->(b,l*r)S.ahint->bC.For_hint.responsible_axis->(l*r)hint=funobjmorph_hintmorphahintres->letobj=C.srcobjmorphinmatchreswith|NoneResponsible->Irrelevant|SourceIsSingle->letahint=ahint_axisobjahintinApply(morph_hint,obj,ahint)|Axisax->letahint=ahint_prodobjaxahintinletobj=C.proj_objaxobjinApply(morph_hint,obj,ahint)andhint_prod:typetalr.tC.obj->(t,a)Axis.t->(t,l*r)S.hint->(l*r)hint=funobjax->function|Apply(morph_hint,morph,ahint)->hint_applyobjmorph_hintmorphahint(C.For_hint.find_responsible_axis_prodmorphax)|Constc->Constc|Branch(b,(a0,hint0),(a1,hint1))->letchosen_hint=letproj0=Axis.projaxa0inletproj1=Axis.projaxa1inletobj=C.proj_objaxobjinmatchchoose_branch_axisbobjproj0proj1with|`First->hint0|`Second->hint1inhint_prodobjaxchosen_hintandahint_prod:typetalr.tC.obj->(t,a)Axis.t->(t,l*r)S.ahint->(a,l*r)ahint=funobjax(t,hint)->leta=Axis.projaxtinlethint=hint_prodobjaxhintina,hint(** Given a solver hint on a single axis lattice, returns a human-readible
hint. *)andhint_axis:typealr.aC.obj->(a,l*r)S.hint->(l*r)hint=funobj->function|Apply(morph_hint,morph,ahint)->hint_applyobjmorph_hintmorphahint(C.For_hint.find_responsible_axis_singlemorph)|Constc->Constc|Branch(b,(a0,hint0),(a1,hint1))->letchosen_hint=matchchoose_branch_axisbobja0a1with|`First->hint0|`Second->hint1inhint_axisobjchosen_hintandahint_axis:typealr.aLattices_mono.obj->(a,l*r)S.ahint->(a,l*r)ahint=funobj(a,hint)->a,hint_axisobjhintleterror_prod:typera.rC.obj->(r,a)Axis.t->rS.error->at=funobjaxis{left;right}->letleft=ahint_prodobjaxisleftinletright=ahint_prodobjaxisrightin{left;right}leterror_axis:typea.aC.obj->aS.error->at=funobj{left;right}->letleft=ahint_axisobjleftinletright=ahint_axisobjrightin{left;right}end[@@@warning"-4"]typesound=|Consonant|Vowelletprint_article_noun~definite~capitalizesounds=letarticle=matchdefinite,soundwith|true,_->"the"|false,Consonant->"a"|false,Vowel->"an"inletarticle=ifcapitalizethenString.capitalize_asciiarticleelsearticleinFmt.dprintf"%s %s"articlesletprint_lock_item:lock_item->_=function|Module->print_article_nounConsonant"module"|Class->print_article_nounConsonant"class"|Value->print_article_nounConsonant"value"|Constructor->print_article_nounConsonant"constructor"letprint_structure_item:structure_item->_=fun(category,id)~capitalize->Fmt.dprintf"%t %a"(print_lock_item~definite:true~capitalizecategory)Misc.Style.inline_code(Ident.nameid)letprint_pinpoint_desc:pinpoint_desc->_=function|Unknown->None|Ident{category;lid}->Some(fun~definite~capitalize->Fmt.dprintf"%t %a"(print_lock_item~definite~capitalizecategory)(Misc.Style.as_inline_code!print_longident)lid)|Function->Some(print_article_nounConsonant"function")|Functor->Some(print_article_nounConsonant"functor")|Lazy->Some(print_article_nounConsonant"lazy expression")|Expression->Some(print_article_nounVowel"expression")|Allocation->Some(print_article_nounVowel"allocation")|Class->Some(print_article_nounConsonant"class")|Object->Some(print_article_nounVowel"object")|Loop->Some(print_article_nounConsonant"loop")|Letop->Some(print_article_nounConsonant"letop")|Cases_result->Some(fun~definite~capitalize->Fmt.dprintf"%t of %t"(print_article_noun~definite:true~capitalizeConsonant"result")(print_article_noun~definite~capitalize:falseConsonant"cases"))|Pattern->Some(print_article_nounConsonant"pattern")|Module->Some(print_article_nounConsonant"module")|Structure->Some(print_article_nounConsonant"structure")|Structure_itemx->Some(fun~definite:_~capitalize->Fmt.dprintf"%t in the structure"(print_structure_item~capitalizex))letprint_pinpoint:pinpoint->_=fun(loc,desc)->print_pinpoint_descdesc|>Option.map(funprint_desc~definite~capitalizeppf->matchLocation.is_noneloc,definitewith|true,_->print_desc~definite:false~capitalizeppf|false,true->Fmt.fprintfppf"%t at %a"(print_desc~definite~capitalize)(Location.Doc.loc~capitalize_first:false)loc|false,false->Fmt.fprintfppf"%t (at %a)"(print_desc~definite~capitalize)(Location.Doc.loc~capitalize_first:false)loc)letis_known_pinpoint:pinpoint->bool=function|_,Unknown->false|_->trueletprint_mutable_partppf=function|Record_fields->Fmt.fprintfppf"mutable field %a"Misc.Style.inline_codes|Array_elements->Fmt.fprintfppf"array elements"letprint_always_dynamic=function|Application->Fmt.dprintf"function applications"|Try_with->Fmt.dprintf"try-with clauses"letprint_legacy=function|Toplevel->print_article_nounConsonant"top-level clause"|Compilation_unit->print_article_nounConsonant"compilation unit"|Class->print_article_nounConsonant"class"letprint_region_desc:region_desc->_=function|Borrow->print_article_nounConsonant"borrow region"letprint_region:capitalize:_->region->_=fun~capitalize(loc,desc)->Fmt.dprintf"%t at %a"(print_region_descdesc~definite:true~capitalize)(Location.Doc.loc~capitalize_first:false)loc(** Given a pinpoint and a const, where the pinpoint has been expressed,
prints the const to explain the mode on the pinpoint. *)letprint_const(typelr)((_,pp_desc):pinpoint)ppf:(l*r)const->unit=function|Unknown->Misc.fatal_error"Unknown hint should not be printed"|Lazy_allocated_on_heap->(matchpp_descwith|Lazy->(* if we already said it's a lazy, we don't need to emphasize it again. *)Fmt.pp_print_stringppf"lazy expressions always need"|_->Fmt.pp_print_stringppf"it is a lazy expression and thus needs");Fmt.pp_print_stringppf" to be allocated on the heap"|Legacym->(matchpp_desc,mwith|((Ident{category=Class;_}|Class|Structure_item(Class,_)),Class)->(* if we already said it's a class, we don't need to emphasize it again. *)Fmt.pp_print_stringppf"classes are always"|_->Fmt.fprintfppf"it is %t and thus always"(print_legacym~definite:false~capitalize:false));Fmt.pp_print_stringppf" at the legacy modes"|Tailcall_function->Fmt.pp_print_stringppf"it is the function in a tail call"|Tailcall_argument->Fmt.pp_print_stringppf"it is an argument in a tail call"|Mutable_readm->Fmt.fprintfppf"its %a is being read"print_mutable_partm|Mutable_writem->Fmt.fprintfppf"its %a is being written"print_mutable_partm|Lazy_forced->(matchpp_descwith|Lazy->(* if we already said it's a lazy, we don't need to emphasize it again. *)Fmt.pp_print_stringppf"it is being forced"|_->Fmt.pp_print_stringppf"it is a lazy value being forced")|Function_return->Fmt.fprintfppf"it is a function return value.@ Hint: Use exclave_ to return a local \
value"|Stack_expression->Fmt.fprintfppf"it is %a-allocated"Misc.Style.inline_code"stack_"|Module_allocated_on_heap->(matchpp_descwith|Ident{category=Module;_}|Functor|Module|Structure|Structure_item(Module,_)->(* if we already said it's a module, we don't need to emphasize it again. *)Fmt.pp_print_stringppf"modules always need"|_->Fmt.pp_print_stringppf"it is a module and thus needs");Fmt.pp_print_stringppf" to be allocated on the heap"|Is_used_inpp->letprint_pp=print_pinpointpp|>Option.getinFmt.fprintfppf"it is used in %t"(print_pp~definite:false~capitalize:false)|Always_dynamicx->Fmt.fprintfppf"%t are always dynamic"(print_always_dynamicx)|Branching->Fmt.fprintfppf"it has branches"|Borrowed_->Fmt.fprintfppf"it is borrowed"|Escape_regionreg->Fmt.fprintfppf"it escapes %t"(print_region~capitalize:falsereg)letprint_allocation_l:allocation->Fmt.formatter->unit=fun{txt;loc}->matchtxtwith|Unknown->Fmt.dprintf"is allocated at %a containing data"(Location.Doc.loc~capitalize_first:false)loc|Optional_argument->Fmt.dprintf"is an optional argument wrapper (and thus allocated) of the value at \
%a"(Location.Doc.loc~capitalize_first:false)loc|Function_coercion->Fmt.dprintf"is a partial application of the function at %a on omittable parameters"(Location.Doc.loc~capitalize_first:false)loc|Float_projection->Fmt.dprintf"is projected (at %a) from a float record (and thus allocated)"(Location.Doc.loc~capitalize_first:false)locletprint_allocation_r:allocation->Fmt.formatter->unit=fun{txt;_}->matchtxtwith|Unknown->Fmt.dprintf"is an allocation"|Optional_argument->Fmt.dprintf"is to be put in an optional argument wrapper (and thus an allocation)"|Function_coercion->Fmt.dprintf"is to omit some parameters by partial application (and thus an \
allocation)"|Float_projection->Fmt.dprintf"is a float-record projection (and thus an allocation)"letmodality_if_relevant~fixpointpp=iffixpoint(* if the modality doesn't change the bound, we omit the modality and
print the remaining chain. *)then(fun_ppfModality->()),ppelse(* if the modality change the bound, we signal that. Moreover, since each
axis is total ordering, the modality is solely responsible for the
bound, and we omit the remaining chain. *)(* CR-someday zqian: print the modality on the offending axis. *)((funppfModality->Fmt.fprintfppf" (with some modality)"),(Location.none,Unknown:pinpoint))letprint_contains:fixpoint:bool->contains->((Fmt.formatter->unit)*pinpoint)option=fun~fixpoint{containing;contained}->print_pinpointcontained|>Option.map(funprint_pp->letprint_pp=print_pp~definite:true~capitalize:falseinletmaybe_modality,contained=modality_if_relevant~fixpointcontainedinletpr=matchcontainingwith|Tuple->Fmt.dprintf"is a tuple that contains %t"print_pp|Record(s,moda)->Fmt.dprintf"is a record whose field %a%a is %t"Misc.Style.inline_codesmaybe_modalitymodaprint_pp|Arraymoda->Fmt.dprintf"is an array that contains%a %t"maybe_modalitymodaprint_pp|Constructor(s,moda)->Fmt.dprintf"contains (via constructor %a)%a %t"Misc.Style.inline_codesmaybe_modalitymodaprint_pp|Structure(x,moda)->Fmt.dprintf"contains %t%a defined as %t"(print_structure_item~capitalize:falsex)maybe_modalitymodaprint_ppinpr,contained)letprint_is_contained_by:fixpoint:bool->is_contained_by->(Fmt.formatter->unit)*pinpoint=fun~fixpoint{containing;container}->letmaybe_modality,pp=modality_if_relevant~fixpointcontainerin(* CR-someday zqian: Use the full [container] to improve the printing below.
E.g., insted of printing "the tuple at XXX", we can print "the tuple
pattern at XXX" or "the tuple expression at XXX". *)letcontainer=fstcontainerinletpr=matchcontainingwith|Tuple->Fmt.dprintf"is an element of the tuple at %a"(Location.Doc.loc~capitalize_first:false)container|Record(s,moda)->Fmt.dprintf"is the field %a%a of the record at %a"Misc.Style.inline_codesmaybe_modalitymoda(Location.Doc.loc~capitalize_first:false)container|Arraymoda->Fmt.dprintf"is an element%a of the array at %a"maybe_modalitymoda(Location.Doc.loc~capitalize_first:false)container|Constructor(s,moda)->Fmt.dprintf"is contained (via constructor %a)%a in the value at %a"Misc.Style.inline_codesmaybe_modalitymoda(Location.Doc.loc~capitalize_first:false)container|Structure(x,moda)->Fmt.dprintf"is %t%a in the structure at %a"(print_structure_item~capitalize:falsex)maybe_modalitymoda(Location.Doc.loc~capitalize_first:false)containerinpr,pp(** Given a pinpoint and a morph, where the pinpoint is the destination of the
morph and have been expressed already, print the morph and return the
source pinpoint. The source pinpoint could be [Unknown], in which case the
rest of the chain will not be printed. *)letprint_morph:typelr.fixpoint:bool->pinpoint->(l*r)morph->((Fmt.formatter->unit)*pinpoint)option=fun~fixpointpp->function|Skip->Misc.fatal_error"Skip hint should not be printed"|Unknown->None|Close_over(Comonadic,{closed=pp;_})->print_pinpointpp|>Option.map(funprint_pp->(Fmt.dprintf"closes over %t"(print_pp~definite:true~capitalize:false),pp))|Close_over(Monadic,{closed=pp;_})->print_pinpointpp|>Option.map(funprint_pp->(Fmt.dprintf"contains a usage (of %t)"(print_pp~definite:true~capitalize:false),pp))|Is_closed_by(_,{closure=pp;_})->print_pinpointpp|>Option.map(funprint_pp->(Fmt.dprintf"is used inside %t"(print_pp~definite:true~capitalize:false),pp))|Captured_by_partial_application->Some(Fmt.dprintf"is captured by a partial application",(Location.none,Expression))|Adj_captured_by_partial_application->Some(Fmt.dprintf"has a partial application capturing a value",(Location.none,Expression))|Crossing->Some(Fmt.dprintf"crosses with something",pp)|Allocation_ralloc->Some(print_allocation_ralloc,pp)|Allocation_lalloc->Some(print_allocation_lalloc,pp)|Contains_l(_,contains)->print_contains~fixpointcontains|Contains_r(_,contains)->print_contains~fixpointcontains|Is_contained_by(_,is_contained_by)->Some(print_is_contained_by~fixpointis_contained_by)letprint_mode:typea.[`Actual|`Expected]->aC.obj->Fmt.formatter->a->unit=funsideobjppfx->letmode_printer=Misc.Style.as_inline_code(C.printobj)inmatchside,obj,xwith|`Actual,Regionality,Regional->Fmt.fprintfppf"%a to the parent region"mode_printerC.Regionality.Local(* CR-someday zqian: treat the following cases generally. *)|`Expected,Contention_op,Shared->(* When "shared" is expected, we tell the user that either shared or
uncontended is expected. *)Fmt.fprintfppf"%a or %a"mode_printerC.Contention.Sharedmode_printerC.Contention.Uncontended|`Expected,Visibility_op,Read->Fmt.fprintfppf"%a or %a"mode_printerC.Visibility.Readmode_printerC.Visibility.Read_write|`Expected,Regionality,Regional->Fmt.fprintfppf"%a to the parent region or %a"mode_printerC.Regionality.Localmode_printerC.Regionality.Global|_->mode_printerppfx[@@ocaml.warning"-4"]letadjust_side:typea.aC.obj->[`Left|`Right]->[`Actual|`Expected]=funobjside->matchC.is_oppositeobj,sidewith|true,`Left->`Expected|true,`Right->`Actual|false,`Left->`Actual|false,`Right->`Expectedletprint_mode_with_side:typea.sub:bool->[`Left|`Right]->aC.obj->Fmt.formatter->a->unit=fun~subsideobjppfa->letside=adjust_sideobjsideinifsubthen(Fmt.fprintfppf"@ which ";matchsidewith|`Actual->Fmt.pp_print_stringppf"is "|`Expected->Fmt.pp_print_stringppf"is expected to be ");print_modesideobjppfa(** Some morph hints are said to be "non-rigid", because they should be
printed only when they change modes. *)letis_rigid:typelr.(l*r)morph->bool=function|Unknown->true|Close_over_|Is_closed_by_|Captured_by_partial_application|Contains_l_|Contains_r_|Is_contained_by_|Adj_captured_by_partial_application->true|Allocation_r_|Allocation_l_|Skip|Crossing->falseleteq_mode:typeab.aC.obj->bC.obj->a->b->bool=funa_objb_objab->matchC.eq_obja_objb_objwith|SomeRefl->Misc.Le_result.equal~le:(C.lea_obj)ab|None->falseletrecprint_ahint:typealr.?sub:bool->[`Left|`Right]->pinpoint->aC.obj->Fmt.formatter->(a,l*r)ahint->print_error_resultoption=fun?(sub=false)sidepp(obj:aC.obj)ppf(a,hint)->matchhintwith|Apply(morph_hint,src,ahint)->letfixpoint=eq_modeobjsrca(fstahint)inif(not(is_rigidmorph_hint))&&fixpointthenprint_ahint~subsideppsrcppfahintelse(print_mode_with_side~subsideobjppfa;matchprint_morph~fixpointppmorph_hintwith|None->SomeMode|Some(t,pp)->Fmt.fprintfppf"@ because it %t"t;ifis_known_pinpointppthenignore(print_ahint~sub:truesideppsrcppfahint);SomeMode_with_hint)|ConstUnknown->print_mode_with_side~subsideobjppfa;SomeMode|Irrelevant->ifnotsubthenMisc.fatal_error"the current mode is not responsible for the error, so must be \
inside a responsible morphism";None|Constc->Fmt.fprintfppf"%a@ because %a"(print_mode_with_side~subsideobj)a(print_constpp)c;SomeMode_with_hint[@@ocaml.warning"-4"]type'aahint_sided=|Leftof('a,left_only)ahint|Rightof('a,right_only)ahintletprint_ahint_sided:typea.pinpoint->aC.obj->Fmt.formatter->aahint_sided->print_error_resultoption=funppobjppfahint_sided->matchahint_sidedwith|Leftahint->print_ahint`Leftppobjppfahint|Rightahint->print_ahint`Rightppobjppfahintletprint:typea.pinpoint->aC.obj->at->print_error=funppobj{left;right}->letactual,expected=ifC.is_oppositeobjthenRightright,LeftleftelseLeftleft,Rightrightinletleftppf=Option.get(print_ahint_sidedppobjppfactual)inletrightppf=Option.get(print_ahint_sidedppobjppfexpected)in{left;right}endletprint_pinpoint=Report.print_pinpointtypechanges=S.changesletundo_changes=S.undo_changes(* To be filled in by [types.ml] *)letappend_changes:(changesref->unit)ref=ref(fun_->assertfalse)letset_append_changesf=append_changes:=ftype('a,'d)mode=('a,'d)S.modemoduleError=structtype'at='aS.error_rawtypepacked=|Product:'rC.obj*('r,'a)Axis.t*'rt->packed|Axis:'aC.obj*'at->packedletprint_product:typera.Hint.pinpoint->rC.obj->(r,a)Axis.t->rt->print_error=funppobjaxerr->leterr=S.populate_errorobjerrinleterr=Report.Of_solver.error_prodobjaxerrinletobj=C.proj_objaxobjinReport.printppobjerrletprint_axis:typea.Hint.pinpoint->aC.obj->at->print_error=funppobjerr->leterr=S.populate_errorobjerrinleterr=Report.Of_solver.error_axisobjerrinReport.printppobjerrletprint_packed:Hint.pinpoint->packed->print_error=funpp->function|Product(obj,ax,err)->print_productppobjaxerr|Axis(obj,err)->print_axisppobjerrletprint_packed_simple_context:Hint.pinpoint->packed->Location.error=funpppacked->letopenFormat_docinletloc,desc=ppinletprintppf()=letopen_box=Fmt.dprintf"@[<hov 2>"inletreopen_box=Fmt.dprintf"@]@ %t"open_boxinletprint_desc=Report.print_pinpoint_descdescin(letprint_desc=matchprint_descwith|None->Fmt.dprintf"This"|Someprint_desc->print_desc~definite:true~capitalize:trueinfprintfppf"%t%t is "open_boxprint_desc);let({left;right}:print_error)=print_packedpppackedin(matchleftppfwith|Mode_with_hint->letprint_desc=matchprint_descwith|None->Fmt.dprintf"the highlighted"|Someprint_desc->Fmt.dprintf"%t highlighted"(print_desc~definite:true~capitalize:false)infprintfppf".%tHowever, %t is expected to be "reopen_boxprint_desc|Mode->fprintfppf"%tbut is expected to be "reopen_box);ignore(rightppf);fprintfppf".@]"inLocation.error_of_printer~locprint()endexceptionSubmode_error_simple_contextofHint.pinpoint*Error.packedlet()=Location.register_error_of_exn(function|Submode_error_simple_context(pp,err)->Some(Error.print_packed_simple_contextpperr)|_->None)moduletypeCommon_axis_pos=sigmoduleConst:ConstincludeCommon_axiswithmoduleConst:=Constandtype'dt=(Const.t,'dpos)modeandtype'dhint_const:='dpos_hint_constendmoduletypeCommon_axis_neg=sigmoduleConst:ConstincludeCommon_axiswithmoduleConst:=Constandtype'dt=(Const.t,'dneg)modeandtype'dhint_const:='dneg_hint_constend(** Representing a single object *)moduletypeObj=sigtypeconstvalobj:constC.objendlettry_with_logop=letlog'=refS.empty_changesinletlog=Somelog'inmatchop~logwith|Ok_asx->!append_changeslog';x|Error_asx->S.undo_changes!log';x[@@inline]letwith_logop=letlog'=refS.empty_changesinletlog=Somelog'inletr=op~login!append_changeslog';r[@@inline]letequate_from_submodesubmode_logm0m1~log=matchsubmode_logm0m1~logwith|Errore->Error(Left_le_right,e)|Ok()->(matchsubmode_logm1m0~logwith|Errore->Error(Right_le_left,e)|Ok()->Ok())[@@inline]letequate_from_submode'submodem0m1=matchsubmodem0m1with|Errore->Error(Left_le_right,e)|Ok()->(matchsubmodem1m0with|Errore->Error(Right_le_left,e)|Ok()->Ok())[@@inline]moduleComonadic_gen(Obj:Obj)=structopenObjtype'dt=(const,'l*'r)Solver.modeconstraint'd='l*'rtypel=(allowed*disallowed)ttyper=(disallowed*allowed)ttypelr=(allowed*allowed)ttypenonrecsimple_error=constsimple_errortypenonrecerror=constError.ttypeequate_error=equate_step*errortype(_,_,'d)sided='dtletdisallow_rightm=Solver.disallow_rightmletdisallow_leftm=Solver.disallow_leftmletallow_leftm=Solver.allow_leftmletallow_rightm=Solver.allow_rightmletnewvar()=Solver.newvarobjletmin=Solver.minobjletmax=Solver.maxobjletnewvar_abovem=Solver.newvar_aboveobjmletnewvar_belowm=Solver.newvar_belowobjmletsubmode_log?(pp=(Location.none,Unknown:Hint.pinpoint))ab~log=Solver.submodeppobjab~logletto_simple_error({left;right;_}:error):simple_error={left;right}letsubmode?ppab=try_with_log(submode_log?ppab)letsubmode_errppab=matchsubmode~ppabwith|Ok()->()|Errore->raise(Submode_error_simple_context(pp,Axis(obj,e)))letprint_errorpperr=Error.print_axisppobjerrletjoinl=Solver.joinobjlletmeetl=Solver.meetobjlletsubmode_exn?ppm0m1=submode?ppm0m1|>Result.get_okletequateab=try_with_log(equate_from_submode(submode_log?pp:None)ab)letequate_exnm0m1=equatem0m1|>Result.get_okletprint?verbose()ppfm=Solver.print?verboseobjppfmletzap_to_ceilm=with_log(Solver.zap_to_ceilobjm)letzap_to_floorm=with_log(Solver.zap_to_floorobjm)letof_const:typelr.?hint:(l*r)posHint.const->const->(l*r)t=fun?hinta->Solver.of_const?hintobjaletto_const_exnm=Solver.to_const_exnobjmletunhint=Solver.Unhint.unhintlethint?hint=Solver.Unhint.hintobj?hintletwrap?hint:hfm=m|>unhint|>f|>hint?hint:hletapply_hinthintm=wrap~hintFun.idmletmeet_const_unhintcm=Solver.Unhint.applyobj(Meet_withc)mletmeet_const?hintcm=wrap?hint(meet_const_unhintc)mletimply_unhintcm=Solver.Unhint.applyobj(Implyc)mletimplycm=m|>disallow_left|>wrap(imply_unhintc)moduleGuts=structletget_floorm=Solver.get_floorobjmletget_ceilm=Solver.get_ceilobjmletget_loose_floorm=Solver.get_loose_floorobjmletget_loose_ceilm=Solver.get_loose_ceilobjmendend[@@inline]moduleMonadic_gen(Obj:Obj)=struct(* Monadic lattices are flipped. See "Notes on flipping". *)openObjtype'dt=(const,'r*'l)Solver.modeconstraint'd='l*'rtypel=(allowed*disallowed)ttyper=(disallowed*allowed)ttypelr=(allowed*allowed)ttypenonrecsimple_error=constsimple_errortypenonrecerror=constError.ttypeequate_error=equate_step*errortype(_,_,'d)sided='dtletdisallow_rightm=Solver.disallow_leftmletdisallow_leftm=Solver.disallow_rightmletallow_leftm=Solver.allow_rightmletallow_rightm=Solver.allow_leftmletnewvar()=Solver.newvarobjletmin=Solver.maxobjletmax=Solver.minobjletnewvar_abovem=Solver.newvar_belowobjmletnewvar_belowm=Solver.newvar_aboveobjmletsubmode_log?(pp=(Location.none,Unknown:Hint.pinpoint))ab~log=Solver.submodeppobjba~logletto_simple_error({left;right;_}:error):simple_error={left=right;right=left}letsubmode?ppab=try_with_log(submode_log?ppab)letsubmode_errppab=matchsubmode~ppabwith|Ok()->()|Errore->raise(Submode_error_simple_context(pp,Axis(obj,e)))letprint_errorpperr=Error.print_axisppobjerrletjoinl=Solver.meetobjlletmeetl=Solver.joinobjlletsubmode_exn?ppm0m1=submode?ppm0m1|>Result.get_okletequateab=try_with_log(equate_from_submode(submode_log?pp:None)ab)letequate_exnm0m1=equatem0m1|>Result.get_okletprint?verbose()ppfm=Solver.print?verboseobjppfmletzap_to_ceilm=with_log(Solver.zap_to_floorobjm)letzap_to_floorm=with_log(Solver.zap_to_ceilobjm)letof_const:typelr.?hint:(l*r)negHint.const->const->(l*r)t=fun?hinta->Solver.of_const?hintobjaletto_const_exnm=Solver.to_const_exnobjmletunhint=Solver.Unhint.unhintlethint?hint=Solver.Unhint.hintobj?hintletwrap?hint:hfm=m|>unhint|>f|>hint?hint:hletapply_hinthintm=wrap~hintFun.idmletjoin_const_unhintcm=Solver.Unhint.applyObj.obj(Meet_withc)mletjoin_const?hintcm=wrap?hint(join_const_unhintc)mletsubtract_unhintcm=Solver.Unhint.applyobj(Implyc)mletsubtractcm=m|>disallow_right|>wrap(subtract_unhintc)moduleGuts=structletget_ceilm=Solver.get_floorobjmendend[@@inline]moduleLocality=structmoduleConst=C.LocalitymoduleObj=structtypeconst=Const.tletobj=C.LocalityendincludeComonadic_gen(Obj)letglobal=of_constGloballetlocal=of_constLocalletlegacy=of_constConst.legacyletzap_to_legacy=zap_to_floormoduleGuts=structletcheck_constm=letfloor=Guts.get_floorminletceil=Guts.get_ceilminifConst.leceilfloorthenSomeceilelseNoneletcheck_const_conservativem=letfloor=Guts.get_loose_floorminletceil=Guts.get_loose_ceilminifConst.leceilfloorthenSomeceilelseNoneendendmoduleRegionality=structmoduleConst=C.RegionalitymoduleObj=structtypeconst=Const.tletobj=C.RegionalityendincludeComonadic_gen(Obj)letlocal=of_constConst.Localletregional=of_constConst.Regionalletglobal=of_constConst.Globalletlegacy=of_constConst.legacyletzap_to_legacy=zap_to_floorendmoduleLinearity=structmoduleConst=C.LinearitymoduleObj=structtypeconst=Const.tletobj:_C.obj=C.LinearityendincludeComonadic_gen(Obj)letmany=of_constManyletonce=of_constOnceletlegacy=of_constConst.legacyletzap_to_legacy=zap_to_floorendmoduleStatefulness=structmoduleConst=C.StatefulnessmoduleObj=structtypeconst=Const.tletobj=C.StatefulnessendincludeComonadic_gen(Obj)letstateless=of_constStatelessletobserving=of_constObservingletstateful=of_constStatefulletlegacy=of_constConst.legacyletzap_to_legacy=zap_to_ceilendmoduleVisibility=structmoduleConst=C.VisibilitymoduleObj=structtypeconst=Const.tletobj=C.Visibility_opendincludeMonadic_gen(Obj)letimmutable=of_constImmutableletread=of_constReadletread_write=of_constRead_writeletlegacy=of_constConst.legacyletzap_to_legacy=zap_to_floorendmodulePortability=structmoduleConst=C.PortabilitymoduleObj=structtypeconst=Const.tletobj:_C.obj=C.PortabilityendincludeComonadic_gen(Obj)letlegacy=of_constConst.legacy(* CR dkalinichenko: ideally, [observing] should zap to [sharable]. *)letzap_to_legacy~statefulness=matchstatefulnesswith|Statefulness.Const.Stateful|Statefulness.Const.Observing->zap_to_ceil|Statefulness.Const.Stateless->zap_to_floorendmoduleUniqueness=structmoduleConst=C.UniquenessmoduleObj=structtypeconst=Const.tletobj=C.Uniqueness_opendincludeMonadic_gen(Obj)letaliased=of_constAliasedletunique=of_constUniqueletlegacy=of_constConst.legacyletzap_to_legacy=zap_to_ceilendmoduleContention=structmoduleConst=C.ContentionmoduleObj=structtypeconst=Const.tletobj=C.Contention_opendincludeMonadic_gen(Obj)letlegacy=of_constConst.legacy(* CR dkalinichenko: ideally, [read] should zap to [shared]. *)letzap_to_legacy~visibility=matchvisibilitywith|Visibility.Const.Read_write|Visibility.Const.Read->zap_to_floor|Visibility.Const.Immutable->zap_to_ceilendmoduleForkable=structmoduleConst=C.ForkablemoduleObj=structtypeconst=Const.tletobj=C.ForkableendincludeComonadic_gen(Obj)letunforkable=of_constUnforkableletforkable=of_constForkableletlegacy=of_constConst.legacy(* [forkable] is the default for [global]s and [unforkable] for [local]
or [regional] values, so we vary [zap_to_legacy] accordingly. *)letzap_to_legacy~global=matchglobalwithtrue->zap_to_floor|false->zap_to_ceilendmoduleYielding=structmoduleConst=C.YieldingmoduleObj=structtypeconst=Const.tletobj=C.YieldingendincludeComonadic_gen(Obj)letyielding=of_constYieldingletunyielding=of_constUnyieldingletlegacy=of_constConst.legacy(* [unyielding] is the default for [global]s and [yielding] for [local]
or [regional] values, so we vary [zap_to_legacy] accordingly. *)letzap_to_legacy~global=matchglobalwithtrue->zap_to_floor|false->zap_to_ceilendmoduleStaticity=structmoduleConst=C.Staticitytypeconst=Const.t=|Static|DynamicmoduleObj=structtypeconst=Const.tletobj=C.Staticity_opendincludeMonadic_gen(Obj)letlegacy=of_constConst.legacyletzap_to_legacy=zap_to_ceilendletregional_to_localm=S.applyLocality.Obj.objC.Regional_to_localmletlocality_as_regionalitym=S.applyRegionality.Obj.objC.Locality_as_regionalitymletregional_to_globalm=S.applyLocality.Obj.objC.Regional_to_globalmmoduletypeAreality=sigmoduleConst:C.ArealitymoduleObj:Objwithtypeconst=Const.tvalzap_to_legacy:(Const.t,allowed*'r)Solver.mode->Const.tendmoduleLattice_Product(L:Lattice)=structopenLletmin_withaxc=Axis.setaxcminletmax_withaxc=Axis.setaxcmaxendmoduleComonadic_with(Areality:Areality)=structmoduleObj=structtypeconst=Areality.Const.tC.comonadic_withletobj=C.comonadic_with_objAreality.Obj.objendincludeComonadic_gen(Obj)moduleAxis=structtype'at=(Obj.const,'a)Axis.ttypepacked=P:'at->packedletprint=Axis.printletcompare=Axis.compareletproj=Axis.projletall=[PAreality;PLinearity;PPortability;PForkable;PYielding;PStatefulness]|>List.sort(fun(Pax0)(Pax1)->compareax0ax1)endletproj_objax=(C.proj_obj[@inlinedhint])axObj.objmoduleConst=structincludeC.Comonadic_with(Areality.Const)includeLattice_Product(C.Comonadic_with(Areality.Const))letproj=Axis.projmodulePer_axis=structletprintaxppfa=letobj=proj_objaxinC.printobjppfaletleaxab=letobj=(proj_obj[@inlinedhint])axin(C.le[@inlinedhint])objabletjoinaxab=letobj=(proj_obj[@inlinedhint])axin(C.join[@inlinedhint])objabletmeetaxab=letobj=(proj_obj[@inlinedhint])axin(C.meet[@inlinedhint])objabletmaxax=letobj=(proj_obj[@inlinedhint])axin(C.max[@inlinedhint])objletminax=letobj=(proj_obj[@inlinedhint])axin(C.min[@inlinedhint])objleteq_objax0ax1=letobj0=proj_objax0inletobj1=proj_objax1inC.eq_objobj0obj1letprint_objppfax=letobj=proj_objaxinC.print_objppfobjendendletprojaxm=Solver.apply~hint:Skip(proj_objax)(Proj(Obj.obj,ax))mmodulePer_axis=structletzap_to_flooraxm=letobj=proj_objaxinwith_log(Solver.zap_to_floorobjm)letzap_to_ceilaxm=letobj=proj_objaxinwith_log(Solver.zap_to_ceilobjm)endletmin_withaxm=Solver.apply~hint:SkipObj.obj(Min_withax)(Solver.disallow_rightm)letmax_withaxm=Solver.apply~hint:SkipObj.obj(Max_withax)(Solver.disallow_leftm)letmeet_withaxcm=meet_const(Const.max_withaxc)mletzap_to_legacym:Const.t=letareality=projArealitym|>Areality.zap_to_legacyinletlinearity=projLinearitym|>Linearity.zap_to_legacyinletstatefulness=projStatefulnessm|>Statefulness.zap_to_legacyinletportability=projPortabilitym|>Portability.zap_to_legacy~statefulnessinletglobal=Areality.Const.(equalarealitylegacy)inletforkable=projForkablem|>Forkable.zap_to_legacy~globalinletyielding=projYieldingm|>Yielding.zap_to_legacy~globalin{areality;linearity;portability;forkable;yielding;statefulness}letlegacy=of_constConst.legacytypesimple_error=|Error:'aAxis.t*'aMode_intf.simple_error->simple_errorletaxis_of_error(actual:Obj.const)(expected:Obj.const):simple_error=List.find_map(fun(Axis.Pax)->letleft=Const.projaxactualinletright=Const.projaxexpectedinifConst.Per_axis.leaxleftrightthenNoneelseSome(Error(ax,{left;right})))Axis.all|>Option.get(* overriding to report the offending axis *)letto_simple_error({left;right;_}:error)=axis_of_errorleftrightletsubmode_errppab=matchsubmode~ppabwith|Ok()->()|Errore->let(Error(ax,_))=to_simple_erroreinraise(Submode_error_simple_context(pp,Product(Obj.obj,ax,e)))letprint_errorpperr=let(Error(ax,_))=to_simple_errorerrinError.print_productppObj.objaxerrend[@@inline]moduleMonadic=struct(* Monadic lattices are flipped. See "Notes on flipping". *)moduleObj=structtypeconst=C.Monadic_op.tletobj=C.Monadic_opendincludeMonadic_gen(Obj)moduleAxis=structtype'at=(Obj.const,'a)C.Axis.ttypepacked=P:'at->packedletcompare=Axis.compareletprint=Axis.printletproj=Axis.projletall=[PUniqueness;PContention;PVisibility;PStaticity]|>List.sort(fun(Pax0)(Pax1)->compareax0ax1)endletproj_objax=(C.proj_obj[@inlinedhint])axObj.objmoduleConst=structincludeC.MonadicincludeLattice_Product(C.Monadic)letproj=Axis.projmodulePer_axis=structletprintaxppfa=letobj=proj_objaxinC.printobjppfa(* See "Notes on flipping" *)letleaxab=letobj=(proj_obj[@inlinedhint])axin(C.le[@inlinedhint])objbaletjoinaxab=letobj=(proj_obj[@inlinedhint])axin(C.meet[@inlinedhint])objabletmeetaxab=letobj=(proj_obj[@inlinedhint])axin(C.join[@inlinedhint])objabletmaxax=letobj=(proj_obj[@inlinedhint])axin(C.min[@inlinedhint])objletminax=letobj=(proj_obj[@inlinedhint])axin(C.max[@inlinedhint])objleteq_objax0ax1=letobj0=proj_objax0inletobj1=proj_objax1inC.eq_objobj0obj1letprint_objppfax=letobj=proj_objaxinC.print_objppfobjendendletprojaxm=Solver.apply~hint:Skip(proj_objax)(Proj(Obj.obj,ax))mmodulePer_axis=structletzap_to_flooraxm=letobj=proj_objaxinwith_log(Solver.zap_to_ceilobjm)letzap_to_ceilaxm=letobj=proj_objaxinwith_log(Solver.zap_to_floorobjm)end(* The monadic fragment is inverted. *)letjoin_withaxcm=join_const(Const.min_withaxc)mletmin_withaxm=Solver.apply~hint:SkipObj.obj(Max_withax)(Solver.disallow_leftm)letzap_to_legacym:Const.t=letuniqueness=projUniquenessm|>Uniqueness.zap_to_legacyinletvisibility=projVisibilitym|>Visibility.zap_to_legacyinletcontention=projContentionm|>Contention.zap_to_legacy~visibilityinletstaticity=projStaticitym|>Staticity.zap_to_legacyin{uniqueness;contention;visibility;staticity}letlegacy=of_constConst.legacytypesimple_error=|Error:'aAxis.t*'aMode_intf.simple_error->simple_errorletaxis_of_error(actual:Obj.const)(expected:Obj.const):simple_error=List.find_map(fun(Axis.Pax)->letleft=Const.projaxactualinletright=Const.projaxexpectedinifConst.Per_axis.leaxleftrightthenNoneelseSome(Error(ax,{left;right})))Axis.all|>Option.getletto_simple_error({left;right;_}:error)=(* monadic fragment is flipped *)axis_of_errorrightleftletsubmode_errppab=matchsubmode~ppabwith|Ok()->()|Errore->let(Error(ax,_))=to_simple_erroreinraise(Submode_error_simple_context(pp,Product(Obj.obj,ax,e)))letprint_errorpperr=let(Error(ax,_))=to_simple_errorerrinError.print_productppObj.objaxerrendtype('mo,'como)monadic_comonadic={monadic:'mo;comonadic:'como}moduleValue_with(Areality:Areality)=structmoduleComonadic=Comonadic_with(Areality)moduleMonadic=Monadictype'dt=('dMonadic.t,'dComonadic.t)monadic_comonadictypel=(allowed*disallowed)ttyper=(disallowed*allowed)ttypelr=(allowed*allowed)tmoduleAxis=structtype'at=|Monadic:'aMonadic.Axis.t->'at|Comonadic:'aComonadic.Axis.t->'atletcompare:typeab.at->bt->int=funt0t1->matcht0,t1with|Monadict0,Monadict1->Axis.comparet0t1|Monadict0,Comonadict1->Axis.comparet0t1|Comonadict0,Monadict1->Axis.comparet0t1|Comonadict0,Comonadict1->Axis.comparet0t1typepacked=P:'at->packedletprint(typea)ppf(t:at)=matchtwith|Monadicax->Axis.printppfax|Comonadicax->Axis.printppfaxletall=List.map(fun(Monadic.Axis.Pax)->P(Monadicax))Monadic.Axis.all@List.map(fun(Comonadic.Axis.Pax)->P(Comonadicax))Comonadic.Axis.all|>List.sort(fun(Pax0)(Pax1)->compareax0ax1)endletproj_obj:typea.aAxis.t->aC.obj=function|Monadicax->Monadic.proj_objax|Comonadicax->Comonadic.proj_objax(* CR-soon zqian: make a functor [Mode.Value.Const.Make] to generalize over any type
operator applied on each mode constants. *)type('a,'b,'c,'d,'e,'f,'g,'h,'i,'j)modes={areality:'a;linearity:'b;uniqueness:'c;portability:'d;contention:'e;forkable:'f;yielding:'g;statefulness:'h;visibility:'i;staticity:'j}letsplit{areality;linearity;portability;forkable;yielding;statefulness;uniqueness;contention;visibility;staticity}=letmonadic:Monadic.Const.t={uniqueness;contention;visibility;staticity}inletcomonadic:Comonadic.Const.t={areality;linearity;portability;forkable;yielding;statefulness}in{comonadic;monadic}letmerge{comonadic;monadic}=let({areality;linearity;portability;forkable;yielding;statefulness}:Comonadic.Const.t)=comonadicinlet({uniqueness;contention;visibility;staticity}:Monadic.Const.t)=monadicin{areality;linearity;portability;forkable;yielding;statefulness;uniqueness;contention;visibility;staticity}letprint?verbose()ppf{monadic;comonadic}=Fmt.fprintfppf"%a;%a"(Comonadic.print?verbose())comonadic(Monadic.print?verbose())monadicletof_const?hint_monadic?hint_comonadicc=let{monadic;comonadic}=splitcinletcomonadic=Comonadic.of_const?hint:hint_comonadiccomonadicinletmonadic=Monadic.of_const?hint:hint_monadicmonadicin{comonadic;monadic}letto_const_exnm=let{comonadic;monadic}=minletcomonadic=Comonadic.to_const_exncomonadicinletmonadic=Monadic.to_const_exnmonadicin{comonadic;monadic}|>mergeletunhint{monadic;comonadic}=letcomonadic=Comonadic.unhintcomonadicinletmonadic=Monadic.unhintmonadicin{monadic;comonadic}lethint?monadic?comonadict=letcomonadic=Comonadic.hint?hint:comonadict.comonadicinletmonadic=Monadic.hint?hint:monadict.monadicin{monadic;comonadic}letwrap?monadic?comonadicft=t|>unhint|>f|>hint?monadic?comonadicmoduleConst=structletcomonadic_to_monadic_min=C.comonadic_to_monadic_minComonadic.Obj.objmoduleMonadic=Monadic.ConstmoduleComonadic=Comonadic.Const(* CR-soon zqian: make a functor [Mode.Value.Const.Make] to generalize over any type
operator applied on each mode constants. *)typet=(Areality.Const.t,Linearity.Const.t,Uniqueness.Const.t,Portability.Const.t,Contention.Const.t,Forkable.Const.t,Yielding.Const.t,Statefulness.Const.t,Visibility.Const.t,Staticity.Const.t)modesletmin=merge{comonadic=Comonadic.min;monadic=Monadic.min}letmax=merge{comonadic=Comonadic.max;monadic=Monadic.max}letlem0m1=letm0=splitm0inletm1=splitm1inComonadic.lem0.comonadicm1.comonadic&&Monadic.lem0.monadicm1.monadicletequalm0m1=letm0=splitm0inletm1=splitm1inComonadic.equalm0.comonadicm1.comonadic&&Monadic.equalm0.monadicm1.monadicletprintppfm=let{monadic;comonadic}=splitminFmt.fprintfppf"%a,%a"Comonadic.printcomonadicMonadic.printmonadicletlegacy=merge{comonadic=Comonadic.legacy;monadic=Monadic.legacy}letmeetm0m1=letm0=splitm0inletm1=splitm1inletmonadic=Monadic.meetm0.monadicm1.monadicinletcomonadic=Comonadic.meetm0.comonadicm1.comonadicinmerge{monadic;comonadic}letjoinm0m1=letm0=splitm0inletm1=splitm1inletmonadic=Monadic.joinm0.monadicm1.monadicinletcomonadic=Comonadic.joinm0.comonadicm1.comonadicinmerge{monadic;comonadic}moduleOption=structtypesome=ttypet=(Areality.Const.toption,Linearity.Const.toption,Uniqueness.Const.toption,Portability.Const.toption,Contention.Const.toption,Forkable.Const.toption,Yielding.Const.toption,Statefulness.Const.toption,Visibility.Const.toption,Staticity.Const.toption)modesletnone={areality=None;uniqueness=None;linearity=None;portability=None;contention=None;forkable=None;yielding=None;statefulness=None;visibility=None;staticity=None}letvalueopt~default=letareality=Option.valueopt.areality~default:default.arealityinletuniqueness=Option.valueopt.uniqueness~default:default.uniquenessinletlinearity=Option.valueopt.linearity~default:default.linearityinletportability=Option.valueopt.portability~default:default.portabilityinletcontention=Option.valueopt.contention~default:default.contentioninletyielding=Option.valueopt.yielding~default:default.yieldinginletforkable=Option.valueopt.forkable~default:default.forkableinletstatefulness=Option.valueopt.statefulness~default:default.statefulnessinletvisibility=Option.valueopt.visibility~default:default.visibilityinletstaticity=Option.valueopt.staticity~default:default.staticityin{areality;uniqueness;linearity;portability;contention;forkable;yielding;statefulness;visibility;staticity}letproj(typea)(ax:aAxis.t)(t:t):aoption=matchaxwith|Monadicax->(matchaxwith|Uniqueness->t.uniqueness|Contention->t.contention|Visibility->t.visibility|Staticity->t.staticity)|Comonadicax->(matchaxwith|Areality->t.areality|Linearity->t.linearity|Portability->t.portability|Forkable->t.forkable|Yielding->t.yielding|Statefulness->t.statefulness)letset(typea)(ax:aAxis.t)(a:aoption)(t:t):t=matchaxwith|Monadicax->(matchaxwith|Uniqueness->{twithuniqueness=a}|Contention->{twithcontention=a}|Visibility->{twithvisibility=a}|Staticity->{twithstaticity=a})|Comonadicax->(matchaxwith|Areality->{twithareality=a}|Linearity->{twithlinearity=a}|Portability->{twithportability=a}|Yielding->{twithyielding=a}|Forkable->{twithforkable=a}|Statefulness->{twithstatefulness=a})letprintppf{areality;uniqueness;linearity;portability;contention;forkable;yielding;statefulness;visibility;staticity}=letoption_printprintppf=function|None->Fmt.fprintfppf"None"|Somea->Fmt.fprintfppf"Some %a"printainFmt.fprintfppf"%a,%a,%a,%a,%a,%a,%a,%a,%a,%a"(option_printAreality.Const.print)areality(option_printLinearity.Const.print)linearity(option_printUniqueness.Const.print)uniqueness(option_printPortability.Const.print)portability(option_printContention.Const.print)contention(option_printForkable.Const.print)forkable(option_printYielding.Const.print)yielding(option_printStatefulness.Const.print)statefulness(option_printVisibility.Const.print)visibility(option_printStaticity.Const.print)staticityendletdiffm0m1=letdifflea0a1=iflea0a1&&lea1a0thenNoneelseSomea0inletareality=diffAreality.Const.lem0.arealitym1.arealityinletlinearity=diffLinearity.Const.lem0.linearitym1.linearityinletuniqueness=diffUniqueness.Const.lem0.uniquenessm1.uniquenessinletportability=diffPortability.Const.lem0.portabilitym1.portabilityinletcontention=diffContention.Const.lem0.contentionm1.contentioninletforkable=diffForkable.Const.lem0.forkablem1.forkableinletyielding=diffYielding.Const.lem0.yieldingm1.yieldinginletstatefulness=diffStatefulness.Const.lem0.statefulnessm1.statefulnessinletvisibility=diffVisibility.Const.lem0.visibilitym1.visibilityinletstaticity=diffStaticity.Const.lem0.staticitym1.staticityin{areality;linearity;uniqueness;portability;contention;forkable;yielding;statefulness;visibility;staticity}(** See [Alloc.close_over] for explanation. *)letclose_overm=let{monadic;comonadic}=splitminComonadic.joincomonadic(C.monadic_to_comonadic_min(C.comonadic_with_objAreality.Obj.obj)monadic)(** See [Alloc.partial_apply] for explanation. *)letpartial_applym=let{comonadic;_}=splitmincomonadicletprint_axis:typea.aAxis.t->Fmt.formatter->a->unit=funaxppfa->letobj=proj_objaxinC.printobjppfaletle_axis:typea.aAxis.t->a->a->bool=funaxm0m1->matchaxwith|Comonadicax->Comonadic.Per_axis.leaxm0m1|Monadicax->Monadic.Per_axis.leaxm0m1letmin_axis:typea.aAxis.t->a=function|Comonadicax->Comonadic.Per_axis.minax|Monadicax->Monadic.Per_axis.minaxletmax_axis:typea.aAxis.t->a=function|Comonadicax->Comonadic.Per_axis.maxax|Monadicax->Monadic.Per_axis.maxaxletis_max:typea.aAxis.t->a->bool=funaxm->le_axisax(max_axisax)mletis_min:typea.aAxis.t->a->bool=funaxm->le_axisaxm(min_axisax)letsplit=splitletmerge=mergeendletmin={comonadic=Comonadic.min;monadic=Monadic.min}letmax={comonadic=Comonadic.max;monadic=Monadic.max}includeMagic_allow_disallow(structtype(_,_,'d)sided='dtconstraint'd='l*'rletallow_left{monadic;comonadic}=letmonadic=Monadic.allow_leftmonadicinletcomonadic=Comonadic.allow_leftcomonadicin{monadic;comonadic}letallow_right{monadic;comonadic}=letmonadic=Monadic.allow_rightmonadicinletcomonadic=Comonadic.allow_rightcomonadicin{monadic;comonadic}letdisallow_left{monadic;comonadic}=letmonadic=Monadic.disallow_leftmonadicinletcomonadic=Comonadic.disallow_leftcomonadicin{monadic;comonadic}letdisallow_right{monadic;comonadic}=letmonadic=Monadic.disallow_rightmonadicinletcomonadic=Comonadic.disallow_rightcomonadicin{monadic;comonadic}end)letnewvar()=letcomonadic=Comonadic.newvar()inletmonadic=Monadic.newvar()in{comonadic;monadic}letnewvar_above{comonadic;monadic}=letcomonadic,b0=Comonadic.newvar_abovecomonadicinletmonadic,b1=Monadic.newvar_abovemonadicin{monadic;comonadic},b0||b1letnewvar_below{comonadic;monadic}=letcomonadic,b0=Comonadic.newvar_belowcomonadicinletmonadic,b1=Monadic.newvar_belowmonadicin{monadic;comonadic},b0||b1typeatom=Atom:'aAxis.t*'a->atomtypeerror=|MonadicofMonadic.error|ComonadicofComonadic.errortypeequate_error=equate_step*errortypesimple_error=|Error:'aAxis.t*'aMode_intf.simple_error->simple_errorletto_simple_error=function|Monadice->let(Error(ax,e))=Monadic.to_simple_erroreinError(Monadicax,e)|Comonadice->let(Error(ax,e))=Comonadic.to_simple_erroreinError(Comonadicax,e)letprint_errorpp=function|Monadice->Monadic.print_errorppe|Comonadice->Comonadic.print_errorppeletsubmode_log?pp{monadic=monadic0;comonadic=comonadic0}{monadic=monadic1;comonadic=comonadic1}~log:(_,error)result=(* comonadic before monadic, so that locality errors dominate
(error message backward compatibility) *)matchComonadic.submode_log?ppcomonadic0comonadic1~logwith|Errore->Error(Comonadice)|Ok()->(matchMonadic.submode_log?ppmonadic0monadic1~logwith|Errore->Error(Monadice)|Ok()->Ok())letsubmode?ppab=try_with_log(submode_log?ppab)letsubmode_errppab=Comonadic.submode_errppa.comonadicb.comonadic;Monadic.submode_errppa.monadicb.monadicletequateab=try_with_log(equate_from_submode(submode_log?pp:None)ab)letsubmode_exn?ppm0m1=matchsubmode?ppm0m1with|Ok()->()|Error_->invalid_arg"submode_exn"letequate_exnm0m1=matchequatem0m1withOk()->()|Error_->invalid_arg"equate_exn"letlegacy=letcomonadic=Comonadic.legacyinletmonadic=Monadic.legacyin{comonadic;monadic}letproj_monadicax{monadic;_}=Monadic.projaxmonadicletproj_comonadicax{comonadic;_}=Comonadic.projaxcomonadicletmax_with_comonadicaxm=letcomonadic=Comonadic.max_withaxminletmonadic=Monadic.max|>Monadic.disallow_left|>Monadic.allow_rightin{comonadic;monadic}letmin_with_comonadicaxm=letcomonadic=Comonadic.min_withaxminletmonadic=Monadic.min|>Monadic.disallow_right|>Monadic.allow_leftin{comonadic;monadic}letmin_with_monadicaxm=letmonadic=Monadic.min_withaxminletcomonadic=Comonadic.min|>Comonadic.disallow_right|>Comonadic.allow_leftin{comonadic;monadic}letjoin_withaxc{monadic;comonadic}=letmonadic=Monadic.join_withaxcmonadicin{monadic;comonadic}letmeet_withaxc{monadic;comonadic}=letcomonadic=Comonadic.meet_withaxccomonadicin{comonadic;monadic}letjoinl=letcomo,mo=List.fold_left(fun(como,mo){comonadic;monadic}->comonadic::como,monadic::mo)([],[])linletcomonadic=Comonadic.joincomoinletmonadic=Monadic.joinmoin{comonadic;monadic}letmeetl=letcomo,mo=List.fold_left(fun(como,mo){comonadic;monadic}->comonadic::como,monadic::mo)([],[])linletcomonadic=Comonadic.meetcomoinletmonadic=Monadic.meetmoin{comonadic;monadic}letcomonadic_to_monadic_min?hintm=S.apply?hintMonadic.Obj.obj(Comonadic_to_monadic_maxComonadic.Obj.obj)(Comonadic.disallow_leftm)letmonadic_to_comonadic_minm=S.applyComonadic.Obj.objMonadic_to_comonadic_min(Monadic.disallow_leftm)letmonadic_to_comonadic_maxm=S.applyComonadic.Obj.objMonadic_to_comonadic_max(Monadic.disallow_rightm)letmeet_constc{comonadic;monadic}=letcomonadic=Comonadic.meet_constccomonadicin{monadic;comonadic}letjoin_constc{comonadic;monadic}=letmonadic=Monadic.join_constcmonadicin{monadic;comonadic}letzap_to_ceil{comonadic;monadic}=letmonadic=Monadic.zap_to_ceilmonadicinletcomonadic=Comonadic.zap_to_ceilcomonadicinmerge{monadic;comonadic}letzap_to_floor{comonadic;monadic}=letmonadic=Monadic.zap_to_floormonadicinletcomonadic=Comonadic.zap_to_floorcomonadicinmerge{monadic;comonadic}letzap_to_legacy{comonadic;monadic}=letmonadic=Monadic.zap_to_legacymonadicinletcomonadic=Comonadic.zap_to_legacycomonadicinmerge{monadic;comonadic}(** This is about partially applying [A -> B -> C] to [A] and getting
[B -> C]. [comonadic] and [monadic] constutute the mode of [A], and we
need to give the lower bound mode of [B -> C]. *)letclose_over{comonadic;monadic}=letcomonadic=Comonadic.disallow_rightcomonadicin(* The comonadic of the returned function is constrained by the monadic of the closed argument via the dualizing morphism. *)letcomonadic1=monadic_to_comonadic_minmonadicin(* It's also constrained by the comonadic of the closed argument. *)letcomonadic=Comonadic.join[comonadic;comonadic1]in(* The closure will access [A] at the specified monadic modes, and thus the
monadic mode of the closure itself is not constrained by it. *)letmonadic=Monadic.disallow_rightMonadic.minin{comonadic;monadic}(** Similar to above, but we are given the mode of [A -> B -> C], and need to
give the lower bound mode of [B -> C]. *)letpartial_apply{comonadic;_}=(* The closure will invoke the original function at the specified monadic
modes, and thus the monadic mode of the closure itself is not constrained by
it. *)letmonadic=Monadic.disallow_rightMonadic.mininletcomonadic=Comonadic.disallow_rightcomonadicin{comonadic;monadic}moduleList=structtypenonrec'dt='dtlistincludeMagic_allow_disallow(structtype(_,_,'d)sided='dtconstraint'd='l*'rletallow_leftl=List.mapallow_leftlletallow_rightl=List.mapallow_rightlletdisallow_leftl=List.mapdisallow_leftlletdisallow_rightl=List.mapdisallow_rightlend)endend[@@inline]moduleValue=Value_with(Regionality)moduleAlloc=Value_with(Locality)moduleConst=structletalloc_as_value({areality;linearity;portability;uniqueness;contention;forkable;yielding;statefulness;visibility;staticity}:Alloc.Const.t):Value.Const.t=letareality=C.locality_as_regionalityarealityin{areality;linearity;portability;uniqueness;contention;forkable;yielding;statefulness;visibility;staticity}moduleAxis=structletis_areality(typea):aAlloc.Axis.t->((a,Locality.Const.t)Misc.eq,aValue.Axis.t)Either.t=function|ComonadicAreality->LeftRefl|ComonadicLinearity->Right(ComonadicLinearity)|ComonadicPortability->Right(ComonadicPortability)|ComonadicForkable->Right(ComonadicForkable)|ComonadicYielding->Right(ComonadicYielding)|ComonadicStatefulness->Right(ComonadicStatefulness)|MonadicUniqueness->Right(MonadicUniqueness)|MonadicContention->Right(MonadicContention)|MonadicVisibility->Right(MonadicVisibility)|MonadicStaticity->Right(MonadicStaticity)letalloc_as_value:Alloc.Axis.packed->Value.Axis.packed=fun(Pax)->matchis_arealityaxwith|LeftRefl->P(ComonadicAreality)|Rightax->Paxendletlocality_as_regionality=C.locality_as_regionalityend(* CR-someday zqian: all the function that converts between [Alloc] and [Value] should
operate on [Unhint] so they can be composed and assigned hint as a whole. *)letcomonadic_locality_as_regionalitycomonadic=S.Unhint.applyValue.Comonadic.Obj.obj(Map_comonadicLocality_as_regionality)comonadicletcomonadic_regional_to_localcomonadic=S.Unhint.applyAlloc.Comonadic.Obj.obj(Map_comonadicRegional_to_local)comonadicletalloc_as_value_unhintm=let{comonadic;monadic}=minletcomonadic=comonadic_locality_as_regionalitycomonadicin{comonadic;monadic}letalloc_as_valuem=m|>Alloc.unhint|>alloc_as_value_unhint|>Value.hint~monadic:Skipletalloc_to_value_l2r_unhintm=let{comonadic;monadic}=minletcomonadic=S.Unhint.applyValue.Comonadic.Obj.obj(Map_comonadicLocal_to_regional)comonadicin{comonadic;monadic}letalloc_to_value_l2rm=m|>Alloc.disallow_right|>Alloc.unhint|>alloc_to_value_l2r_unhint|>Value.hint~monadic:Skipletvalue_to_alloc_r2g_unhintm=let{comonadic;monadic}=minletcomonadic=S.Unhint.applyAlloc.Comonadic.Obj.obj(Map_comonadicRegional_to_global)comonadicin{comonadic;monadic}letvalue_to_alloc_r2gm=m|>Value.unhint|>value_to_alloc_r2g_unhint|>Alloc.hint~monadic:Skipletvalue_r2g?hintm=Value.wrap~monadic:Skip?comonadic:hint(funm->m|>value_to_alloc_r2g_unhint|>alloc_as_value_unhint)mletvalue_to_alloc_r2l_unhintm=let{comonadic;monadic}=minletcomonadic=comonadic_regional_to_localcomonadicin{comonadic;monadic}letvalue_to_alloc_r2lm=m|>Value.unhint|>value_to_alloc_r2l_unhint|>Alloc.hint~monadic:SkipmoduleModality=struct(* Inferred modalities
Similar to constant modalities, an inferred modality maps the mode of a
record/structure to the mode of a value therein. An inferred modality [f]
is inferred from the structure/record mode [mm] and the value mode [m]. It
will only be applied on some [x >= mm]: That is, it will only be applied
on the original module.
It should satisfy the following conditions:
Zapping: [f] should be of the form [join_c] for monadic axes, or [meet_c]
for comonadic axes.
Soundness: You should not get a value from a record/structure at a mode
strictly stronger than how it was put in. That is, for any [x >= mm], [f x
>= m].
Completeness: Ideally we also want [f mm <= m].
Monadic axes
Soundness condition says [join_c x >= m] for any [x >= mm]. Equivalently,
[join_c mm >= m]. By adjunction, [c >= subtract_mm m]. We take the lower
bound [c := subtract_mm m]. Note that this is equivalent to taking [c := m
>= subtract_mm m]. Proof:
- [join_m x >= join_(subtract_mm m) x] is trivial since [m >= subtract_mm
m].
- [join_m x <= join_(subtract_mm m) x], or equivalently [m <=
join_(subtract_mm m) x], or equivalently [subtract_x m <= subtract_mm m],
which is trivial since [x >= mm].
Taking [c := subtract_mm m] is better for zapping since it's lower and
thus closer to identity modality. Taking [c := m] is easier for [apply]
and [sub].
Comonadic axes
Soundness condition says [meet_c x >= m] for any [x >= mm]. Equivalently,
[meet_c mm >= m]. By def. of [meet], we have both [c >= m] and [mm >= m].
The latter is guaranteed by the user of [infer]. We guarantee the former
by taking [c := imply_mm m >= m]. One might worry that this is too relaxed
and will be "less complete" than taking [c := m]; however, note that
[imply_mm m <= imply_mm m] and thus by adjunction [meet_(imply_mm m) mm <=
m], which means the chosen [c] is complete.
Taking [c := m] is easier for [apply] and [sub]. Taking [c := imply_mm m]
is better for zapping since it's higher and thus closer to identity
modality. However, note that we DON'T have [meet_m x = meet_(imply_mm m)
x], which means [apply/sub] and [zap] might behave in a confusing (albeit
sound) manner.
CR zqian: once we support binary mode solver, [c := imply_mm m] will be
used uniformly by [apply] [sub] and [zap].
*)moduleMonadic=structmoduleMode=Value.Monadictype'aaxis='aMode.Axis.tmoduleAtom=structtype'at=Join_withof'a[@@unboxed]letis_idax(Join_withc)=Mode.Const.Per_axis.(leaxc(minax))letis_constantax(Join_withc)=Mode.Const.Per_axis.(leax(maxax)c)endtypeerror=Error:'aaxis*'aAtom.tsimple_error->errormoduleConst=structtypet=Join_constofMode.Const.t[@@unboxed]letid=Join_constMode.Const.minletis_idt=t=idletmax=Join_constMode.Const.maxletsubleftright:(_,error)Result.t=matchleft,rightwith|Join_constc0,Join_constc1->ifMode.Const.lec0c1thenOk()elselet(Error(ax,{left;right}))=Mode.axis_of_errorc0c1inError(Error(ax,{left=Join_withleft;right=Join_withright}))letconcat~then_t=matchthen_,twith|Join_constc0,Join_constc1->Join_const(Mode.Const.joinc0c1)letapply:typelr.?hint:(l*r)negHint.morph->t->(l*r)Mode.t->(l*r)Mode.t=fun?(hint=Hint.Unknown)tx->matchtwithJoin_constc->Mode.join_const~hintcxletprojax(Join_constc):_Atom.t=Join_with(Axis.projaxc)letsetax(Join_witha:_Atom.t)(Join_constc)=Join_const(Axis.setaxac)letprintppf=function|Join_constc->Fmt.fprintfppf"join_const(%a)"Mode.Const.printcendtypet=|ConstofConst.t|DiffofMode.lr*Mode.lr(** See "Inferred modalities" comments *)|Undefinedletsub_logleftright~log:(unit,error)Result.t=matchleft,rightwith|Constc0,Constc1->Const.subc0c1|Diff(mm,m),Const(Join_constc)->((* Check that for any x >= mm, join(x, m) <= join(x, c), which (by
definition of join) is equivalent to m <= join(x, c). This has to
hold for all x >= mm, so we check m <= join(mm, c). *)matchMode.submode_logm(Mode.join_constcmm)~logwith|Ok()->Ok()|Errorerr->let(Error(ax,{left;_}))=Mode.to_simple_errorerrinError(Error(ax,{left=Join_withleft;right=Join_with(Axis.projaxc)})))|Diff(_,_m0),Diff(_,_m1)->(* [m1] is a left mode so it cannot appear on the right. So we can't do
a proper check. However, this branch is only hit by
[wrap_constraint_with_shape], in which case LHS and RHS should be
physically equal. *)assert(left==right);Ok()|Const_,Diff_->Misc.fatal_error"inferred modality Diff should not be on the RHS of sub."|Undefined,_|_,Undefined->Misc.fatal_error"modality Undefined should not be in sub."letapply:typer.?hint:(allowed*r)negHint.morph->t->(allowed*r)Mode.t->Mode.l=fun?hinttx->matchtwith|Constc->Const.apply?hintcx|>Mode.disallow_right|Undefined->Misc.fatal_error"modality Undefined should not be applied."|Diff(_,m)->Mode.join[Mode.allow_rightm;x]letprintppf=function|Constc->Const.printppfc|Undefined->Fmt.fprintfppf"undefined"|Diff_->Fmt.fprintfppf"diff"(* All zapping functions mutate [mm] and [m] to the degree that's sufficient
to fix [subtract_mm m], and return it. [subtract] is antitone for [mm]
and monotone for [m]. *)letzap_to_floor=function|Constc->c|Undefined->Misc.fatal_error"modality Undefined should not be zapped."|Diff(mm,m)->(* Ideally we will take [c = subtract_mm m] and zap it to floor.
However, [subtract] requires [mm] to be constant. We get the ceil of
[mm] to construct the floor of [c]. *)letcc=Mode.Guts.get_ceilmminletc=Mode.subtractccminletc=Mode.zap_to_floorcin(* Note that we did not mutate [mm] but simply took its ceil, which
might be mutated later. To satisfy the coherence condition (see the
comment in the mli), we want to:
- make it impossible that [subtract_mm m < c], which is trivial since
[mm <= cc] and thus [subtract_mm m >= subtract_cc m = c].
- make it impossible that [subtract_mm m > c], which is to ensure
[subtract_mm m <= c], equivalently [m <= join_mm c], which is
achieved by the following [submode].
*)Mode.submode_exnm(Mode.join_constcmm);Const.Join_constcletzap_to_id=zap_to_floorletto_const_opt=function|Constc->Somec|Undefined->Misc.fatal_error"modality Undefined should not be looked at"|Diff_->Noneletof_constc=Constcletinfer~md_mode~mode=Diff(md_mode,mode)letmax=ConstConst.maxendmoduleComonadic=structmoduleMode=Value.Comonadictype'aaxis='aMode.Axis.tmoduleAtom=structtype'at=Meet_withof'a[@@unboxed]letis_idax(Meet_withc)=Mode.Const.Per_axis.(leax(maxax)c)letis_constantax(Meet_withc)=Mode.Const.Per_axis.(leaxc(minax))endtypeerror=Error:'aaxis*'aAtom.tsimple_error->errormoduleConst=structtypet=Meet_constofMode.Const.t[@@unboxed]letid=Meet_constMode.Const.maxletis_idt=t=idletmax=Meet_constMode.Const.maxletsubleftright:(_,error)Result.t=matchleft,rightwith|Meet_constc0,Meet_constc1->ifMode.Const.lec0c1thenOk()elselet(Error(ax,{left;right}))=Mode.axis_of_errorc0c1inError(Error(ax,{left=Meet_withleft;right=Meet_withright}))letconcat~then_t=matchthen_,twith|Meet_constc0,Meet_constc1->Meet_const(Mode.Const.meetc0c1)letapply:typelr.?hint:(l*r)posHint.morph->t->(l*r)Mode.t->(l*r)Mode.t=fun?(hint=Hint.Unknown)tx->matchtwithMeet_constc->Mode.meet_const~hintcxletprojax(Meet_constc):_Atom.t=Meet_with(Axis.projaxc)letsetax(Meet_witha:_Atom.t)(Meet_constc)=Meet_const(Axis.setaxac)letprintppf=function|Meet_constc->Fmt.fprintfppf"meet_const(%a)"Mode.Const.printcendtypet=|ConstofConst.t|Undefined|ExactlyofMode.lr*Mode.lr(** See "Inferred modalities" comments *)letsub_logleftright~log:(unit,error)Result.t=matchleft,rightwith|Constc0,Constc1->Const.subc0c1|Exactly(_mm,m),Const(Meet_constc)->((* Check for all [x >= mm], [meet_(imply_mm m) x <= meet_c x], or
equivalently [meet_(imply_mm m) x <= c], or equivalently [meet_(imply_mm
m) max <= c], or equivalently [imply_mm m <= c]. We can't check this
without binary mode solver.
So instead we check [meet_m x <= meet_c x] (See "Inferred modalities"
comments), which amounts to [m <= c]. *)matchMode.submode_logm(Mode.of_constc)~logwith|Ok()->Ok()|Errorerr->let(Error(ax,{left;_}))=Mode.to_simple_errorerrinError(Error(ax,{left=Meet_withleft;right=Meet_with(Axis.projaxc)})))|Exactly(_,_m0),Exactly(_,_m1)->(* [m1] is a left mode, so there is no good way to check.
However, this branch only hit by [wrap_constraint_with_shape],
in which case LHS and RHS should be physically equal. *)assert(left==right);Ok()|Const_,Exactly_->Misc.fatal_error"inferred modaltiy Exactly should not be on the RHS of sub."|Undefined,_|_,Undefined->Misc.fatal_error"modality Undefined should not be in sub."letapply:typer.?hint:(allowed*r)posHint.morph->t->(allowed*r)Mode.t->Mode.l=fun?hinttx->matchtwith|Constc->Const.apply?hintcx|>Mode.disallow_right|Undefined->Misc.fatal_error"modality Undefined should not be applied."|Exactly(_mm,m)->(* Ideally want to return [meet_(imply_mm m) x], which we can't do
without binary mode solver, so instead we return [meet_m x] (See
"Inferred modalities" comments), which because of [x >= mm >= m] is
equal to [m]. *)Mode.disallow_rightmletprintppf=function|Constc->Const.printppfc|Undefined->Fmt.fprintfppf"undefined"|Exactly_->Fmt.fprintfppf"exactly"letinfer~md_mode~mode=Exactly(md_mode,mode)letmax=ConstConst.max(* All zapping functions mutate [mm] and [m] to the degree that's sufficient
to fix [imply_mm m], and return it. [imply] is antitone for [mm] and
monotone for [m]. *)letzap_to_ceil=function|Constc->c|Undefined->Misc.fatal_error"modality Undefined should not be zapped."|Exactly(mm,m)->(* Ideally we will take [c = imply_mm m] and zap it to ceil. However,
[imply] requires [mm] to be constant. We get the floor of [mm] to
construct the ceil of [c]. *)letcc=Mode.Guts.get_floormminletc=Mode.implyccminletc=Mode.zap_to_ceilcin(* Note that we did not mutate [mm] but simply took its floor, which
might be mutated later. To satisfy the coherence condition (see the
comment in the mli), we want to:
- make it impossible that [imply_mm m > c], which is trivial since
[mm >= cc] and thus [imply_mm m <= imply_cc m = c].
- make it impossible that [imply_mm m < c], which is to ensure
[imply_mm m >= c], equivalently [m >= meet_mm c], which is achieved
by the following [submode].
*)Mode.submode_exn(Mode.meet_constcmm)m;Const.Meet_constcletzap_to_id=zap_to_ceilletzap_to_floor=function|Constc->c|Undefined->Misc.fatal_error"modality Undefined should not be zapped."|Exactly(mm,m)->(* The following zaps [mm] to ceil, which might conflict with future
mode constraints on [mm]. We find constraining [mm] to [legacy] a
good workaround. *)(* CR zqian: Find a better solution *)Mode.submodemmMode.legacy|>ignore;letm=Mode.zap_to_floorminletmm=Mode.zap_to_ceilmminletc=Mode.Const.implymmminConst.Meet_constcletto_const_opt=function|Constc->Somec|Undefined->Misc.fatal_error"modality Undefined should not be looked at"|Exactly_->Noneletof_constc=ConstcendmoduleAxis=structtype'at=|Monadic:'aMonadic.axis->'aMonadic.Atom.tt|Comonadic:'aComonadic.axis->'aComonadic.Atom.tttypepacked=P:'at->packedletof_value:Value.Axis.packed->packed=function|P(Monadicax)->P(Monadicax)|P(Comonadicax)->P(Comonadicax)letto_value:packed->Value.Axis.packed=function|P(Monadicax)->P(Monadicax)|P(Comonadicax)->P(Comonadicax)endtypeatom=Atom:'aAxis.t*'a->atommodulePer_axis=structopenstructmoduleMonadic=Monadic.AtommoduleComonadic=Comonadic.Atomendletis_id:typea.aAxis.t->a->bool=function|Monadicax->Monadic.is_idax|Comonadicax->Comonadic.is_idaxletis_constant:typea.aAxis.t->a->bool=function|Monadicax->Monadic.is_constantax|Comonadicax->Comonadic.is_constantaxletprint(typea)(ax:aAxis.t)ppf(t:a)=matchax,twith|Comonadicax,Meet_witht->Value.Comonadic.Const.Per_axis.printaxppft|Monadicax,Join_witht->Value.Monadic.Const.Per_axis.printaxppftendtypeerror=Error:'aAxis.t*'asimple_error->errortypeequate_error=equate_step*errormoduleConst=structmoduleMonadic=Monadic.ConstmoduleComonadic=Comonadic.Consttypet=(Monadic.t,Comonadic.t)monadic_comonadicletid={monadic=Monadic.id;comonadic=Comonadic.id}letis_id{monadic;comonadic}=Monadic.is_idmonadic&&Comonadic.is_idcomonadicletsubt0t1:(unit,error)Result.t=matchMonadic.subt0.monadict1.monadicwith|Error(Error(ax,e))->Error(Error(Monadicax,e))|Ok()->(matchComonadic.subt0.comonadict1.comonadicwith|Ok()->Ok()|Error(Error(ax,e))->Error(Error(Comonadicax,e)))letequate=equate_from_submode'subletapply?hintt{monadic;comonadic}=letmonadic=Monadic.apply?hint:(Option.map(fun{monadic;_}->monadic)hint)t.monadicmonadicinletcomonadic=Comonadic.apply?hint:(Option.map(fun{comonadic;_}->comonadic)hint)t.comonadiccomonadicin{monadic;comonadic}letconcat~then_t=letmonadic=Monadic.concat~then_:then_.monadict.monadicinletcomonadic=Comonadic.concat~then_:then_.comonadict.comonadicin{monadic;comonadic}letproj(typea)(ax:aAxis.t){monadic;comonadic}:a=matchaxwith|Monadicax->Monadic.projaxmonadic|Comonadicax->Comonadic.projaxcomonadicletset(typea)(ax:aAxis.t)(a:a){monadic;comonadic}:t=matchaxwith|Monadicax->{monadic=Monadic.setaxamonadic;comonadic}|Comonadicax->{monadic;comonadic=Comonadic.setaxacomonadic}letdifft0t1=List.filter_map(funax:atomoption->let(Pax)=Axis.of_valueaxinleta0=projaxt0inleta1=projaxt1inifa0=a1thenNoneelseSome(Atom(ax,a1)))Value.Axis.allletprintppf{monadic;comonadic}=Fmt.fprintfppf"%a;%a"Monadic.printmonadicComonadic.printcomonadicendtypet=(Monadic.t,Comonadic.t)monadic_comonadicletundefined:t={monadic=Undefined;comonadic=Undefined}letis_undefined:t->bool=function|{monadic=Undefined;comonadic=Undefined}->true|_->false[@@ocaml.warning"-4"]letapply?hintt{monadic;comonadic}=letmonadic=Monadic.apply?hint:(Option.map(fun{monadic;_}->monadic)hint)t.monadicmonadicinletcomonadic=Comonadic.apply?hint:(Option.map(fun{comonadic;_}->comonadic)hint)t.comonadiccomonadicin{monadic;comonadic}letsub_logt0t1~log:(unit,error)Result.t=matchMonadic.sub_logt0.monadict1.monadic~logwith|Error(Error(ax,e))->Error(Error(Monadicax,e))|Ok()->(matchComonadic.sub_logt0.comonadict1.comonadic~logwith|Ok()->Ok()|Error(Error(ax,e))->Error(Error(Comonadicax,e)))letsublr=try_with_log(sub_loglr)letequatem0m1=try_with_log(equate_from_submodesub_logm0m1)letprintppf({monadic;comonadic}:t)=Fmt.fprintfppf"%a;%a"Monadic.printmonadicComonadic.printcomonadicletinfer~md_mode~mode:t=letcomonadic=Comonadic.infer~md_mode:md_mode.comonadic~mode:mode.comonadicinletmonadic=Monadic.infer~md_mode:md_mode.monadic~mode:mode.monadicin{monadic;comonadic}letzap_to_idt=let{monadic;comonadic}=tinletcomonadic=Comonadic.zap_to_idcomonadicinletmonadic=Monadic.zap_to_idmonadicin{monadic;comonadic}letzap_to_floort=let{monadic;comonadic}=tinletcomonadic=Comonadic.zap_to_floorcomonadicinletmonadic=Monadic.zap_to_floormonadicin{monadic;comonadic}letto_const_optt=let{monadic;comonadic}=tinOption.bind(Comonadic.to_const_optcomonadic)(funcomonadic->Option.bind(Monadic.to_const_optmonadic)(funmonadic->Some{monadic;comonadic}))letto_const_exnt=t|>to_const_opt|>Option.getletof_const{monadic;comonadic}=letcomonadic=Comonadic.of_constcomonadicinletmonadic=Monadic.of_constmonadicin{monadic;comonadic}letmax=letmonadic=Monadic.maxinletcomonadic=Comonadic.maxin{monadic;comonadic}endmoduleCrossing=struct(* The mode crossing capability of a type [t] is characterized by a monotone
function [f] from modes to some lattice [L], in the following way:
To check [e : t @ m0 <= m1], we should instead check [f m0 <= f m1] to
allow more programs.
For example, if [f] is the identity function, then [t] does not cross modes
at all. If [f] maps to the unit lattice (containing only one element), [f
m0 <= f m1] always succeeds, which means [t] crosses modes fully.
In practice, during mode checking we usually have either [m0] or [m1], but
not both. In order to perform mode crossing one-sided, we require [f] to
have left adjoint [fl] and right adjoint [fr], which gives:
[f m0 <= f m1] is equivalent to [fl (f m0) <= m1] is equivalent to [m0 <=
fr (f m1)]
Therefore, we can perform any of the following for mode crossing:
- Apply [f] on both [m0] and [m1]
- Apply [fl ∘ f] on [m0]
- Apply [fr ∘ f] on [m1]
Mode crossing forms a lattice: [f0 <= f1] iff [f0] allows more mode
crossing than [f1]. Concretely:
[f0 <= f1] iff, for any [m0, m1], if [f1 m0 <= f1 m1],
then [f0 m0 <= f0 m1].
*)moduleMonadic=structmoduleModality=Modality.MonadicmoduleMode=Value.MonadicmoduleAtom=structtype'at=Modalityof'aModality.Atom.t[@@unboxed](* By the ordering of crossings (see comments above) [join_c0 <= join_c1]
iff the following holds:
For all [a,b], if [join_c1 a <= join_c1 b](E0), then [join_c0 a <=
join_c0 b](E1)
Case analysis by the relation between [c0] and [c1]:
- If [c0 >= c1], then [c0] can be written as [join c1 k] for some [k].
Then apply [join k] to E0 and we get E1 (by monotonicity of join).
- If [c0 <= c1], take [a := c1] and [b := c0]. E0 holds but E1 doesn't.
- If neither, then we take [a := c1] and [b := meet a c0]. E0 is
satisfied:
[join_c1 a = c1 <= c1 = join_c1 (meet a c0) = join_c1 b]. But E1 is
not satisfied:
[join_c0 a = join c0 c1 </= c0 = join_c0 (meet c0 c1) = join_c0 b]
Therefore, [join_c0 <= join_c1] iff [c0 >= c1]. *)letminax=Modality(Join_with((Mode.Const.Per_axis.max[@inlinedhint])ax))letmaxax=Modality(Join_with((Mode.Const.Per_axis.min[@inlinedhint])ax))letleax(Modality(Join_withc0))(Modality(Join_withc1))=(Mode.Const.Per_axis.le[@inlinedhint])axc1c0letjoinax(Modality(Join_withc0))(Modality(Join_withc1))=Modality(Join_with((Mode.Const.Per_axis.meet[@inlinedhint])axc0c1))letmeetax(Modality(Join_withc0))(Modality(Join_withc1))=Modality(Join_with(Mode.Const.Per_axis.joinaxc0c1))letprintaxppf(Modality(Join_withc))=Mode.Const.Per_axis.printaxppfcendtypet=ModalityofModality.Const.t[@@unboxed]letcreate~uniqueness:(Atom.Modality(Join_withuniqueness))~contention:(Atom.Modality(Join_withcontention))~visibility:(Atom.Modality(Join_withvisibility))~staticity:(Atom.Modality(Join_withstaticity))=Modality(Join_const{uniqueness;contention;visibility;staticity})letmodalitym(Modalityt)=Modality(Modality.Const.concat~then_:tm)letapply_left(Modality(Join_constc))m=Mode.subtract_unhintc(Mode.join_const_unhintcm)letapply_right(Modality(Join_constc))m=(* The right adjoint of join is a restriction of identity *)Mode.join_const_unhintcmletproj(typea)(ax:aMode.Axis.t)(Modality(Join_constc)):aAtom.t=Modality(Join_with((Axis.proj[@inlinedhint])axc))letset(typea)(ax:aMode.Axis.t)(Modality(Join_witha):aAtom.t)(Modality(Join_constc))=Modality(Join_const((Axis.set[@inlinedhint])axac))letle(Modality(Join_constc0))(Modality(Join_constc1))=Mode.Const.lec1c0letequal(Modality(Join_constc0))(Modality(Join_constc1))=Mode.Const.equalc0c1letmax=Modality(Join_constMode.Const.min)letmin=Modality(Join_constMode.Const.max)letjoin(Modality(Join_constc0))(Modality(Join_constc1))=Modality(Join_const(Mode.Const.meetc0c1))letmeet(Modality(Join_constc0))(Modality(Join_constc1))=Modality(Join_const(Mode.Const.joinc0c1))letprintppf(Modalitym)=Fmt.fprintfppf"Modality %a"Modality.Const.printmendmoduleComonadic=structmoduleModality=Modality.ComonadicmoduleMode=Value.ComonadicmoduleAtom=structtype'at=Modalityof'aModality.Atom.t[@@unboxed](* The ordering of crossing here is derived similarly to the monadic
fragment. See comments there. *)letminax=Modality(Meet_with((Mode.Const.Per_axis.min[@inlinedhint])ax))letmaxax=Modality(Meet_with((Mode.Const.Per_axis.max[@inlinedhint])ax))letleax(Modality(Meet_withc0))(Modality(Meet_withc1))=(Mode.Const.Per_axis.le[@inlinedhint])axc0c1letjoinax(Modality(Meet_withc0))(Modality(Meet_withc1))=Modality(Meet_with((Mode.Const.Per_axis.join[@inlinedhint])axc0c1))letmeetax(Modality(Meet_withc0))(Modality(Meet_withc1))=Modality(Meet_with(Mode.Const.Per_axis.meetaxc0c1))letprintaxppf(Modality(Meet_withc))=Mode.Const.Per_axis.printaxppfcendtypet=ModalityofModality.Const.t[@@unboxed]letcreate~regionality:(Atom.Modality(Meet_withareality))~linearity:(Atom.Modality(Meet_withlinearity))~portability:(Atom.Modality(Meet_withportability))~forkable:(Atom.Modality(Meet_withforkable))~yielding:(Atom.Modality(Meet_withyielding))~statefulness:(Atom.Modality(Meet_withstatefulness))=Modality(Meet_const{areality;linearity;portability;statefulness;forkable;yielding})letalways_constructed_atc=Modality(Meet_constc)letproj(typea)(ax:aMode.Axis.t)(Modality(Meet_constc)):aAtom.t=Modality(Meet_with((Axis.proj[@inlinedhint])axc))letset(typea)(ax:aMode.Axis.t)(Modality(Meet_witha):aAtom.t)(Modality(Meet_constc))=Modality(Meet_const((Axis.set[@inlinedhint])axac))letmodalitym(Modalityt)=Modality(Modality.Const.concat~then_:tm)letapply_left(Modality(Meet_constc))m=(* The left adjoint of meet is a restriction of identity *)Mode.meet_const_unhintcmletapply_right(Modality(Meet_constc))m=Mode.imply_unhintc(Mode.meet_const_unhintcm)letle(Modality(Meet_constc0))(Modality(Meet_constc1))=Mode.Const.lec0c1letequal(Modality(Meet_constc0))(Modality(Meet_constc1))=Mode.Const.equalc0c1letmax=Modality(Meet_constMode.Const.max)letmin=Modality(Meet_constMode.Const.min)letjoin(Modality(Meet_constc0))(Modality(Meet_constc1))=Modality(Meet_const(Mode.Const.joinc0c1))letmeet(Modality(Meet_constc0))(Modality(Meet_constc1))=Modality(Meet_const(Mode.Const.meetc0c1))letprintppf(Modalitym)=Fmt.fprintfppf"Modality %a"Modality.Const.printmendmoduleAxis=structtype'at=|Monadic:'aValue.Monadic.Axis.t->'aMonadic.Atom.tt|Comonadic:'aValue.Comonadic.Axis.t->'aComonadic.Atom.tttypepacked=P:'at->packedletof_modality:Modality.Axis.packed->packed=function|P(Monadicax)->P(Monadicax)|P(Comonadicax)->P(Comonadicax)letto_modality:packed->Modality.Axis.packed=function|P(Monadicax)->P(Monadicax)|P(Comonadicax)->P(Comonadicax)leteq:typeab.at->bt->(a,b)Misc.eqoption=funax0ax1->matchax0,ax1with|Monadicax0,Monadicax1->(matchAxis.eqax0ax1withSomeRefl->SomeRefl|None->None)|Comonadicax0,Comonadicax1->(matchAxis.eqax0ax1withSomeRefl->SomeRefl|None->None)|Monadic_,Comonadic_->None|Comonadic_,Monadic_->Noneletprint:typea.Fmt.formatter->at->unit=funppf->function|Monadicax->Axis.printppfax|Comonadicax->Axis.printppfaxendmodulePer_axis=structopenAxisletle:typea.at->a->a->bool=fun[@inlineavailable]axab->matchaxwith|Monadicax->(Monadic.Atom.le[@inlinedhint])axab|Comonadicax->(Comonadic.Atom.le[@inlinedhint])axabletmin:typea.at->a=function[@inlineavailable]|Monadicax->(Monadic.Atom.min[@inlinedhint])ax|Comonadicax->(Comonadic.Atom.min[@inlinedhint])axletmax:typea.at->a=function[@inlineavailable]|Monadicax->(Monadic.Atom.max[@inlinedhint])ax|Comonadicax->(Comonadic.Atom.max[@inlinedhint])axletmeet:typea.at->a->a->a=fun[@inlineavailable]axab->matchaxwith|Monadicax->(Monadic.Atom.meet[@inlinedhint])axab|Comonadicax->(Comonadic.Atom.meet[@inlinedhint])axabletjoin:typea.at->a->a->a=fun[@inlineavailable]axab->matchaxwith|Monadicax->(Monadic.Atom.join[@inlinedhint])axab|Comonadicax->(Comonadic.Atom.join[@inlinedhint])axabletprint:typea.at->Fmt.formatter->a->unit=function|Monadicax->Monadic.Atom.printax|Comonadicax->Comonadic.Atom.printaxletprint_obj=Axis.printleteq_obj=Axis.eqendtypet=(Monadic.t,Comonadic.t)monadic_comonadicletmodalitym{monadic;comonadic}=letmonadic=Monadic.modalitym.monadicmonadicinletcomonadic=Comonadic.modalitym.comonadiccomonadicin{monadic;comonadic}letapply_left_unhintt{monadic;comonadic}=letmonadic=Monadic.apply_leftt.monadicmonadicinletcomonadic=Comonadic.apply_leftt.comonadiccomonadicin{monadic;comonadic}letapply_lefttm=m|>Value.disallow_right|>Value.unhint|>apply_left_unhintt|>Value.hint~monadic:Crossing~comonadic:Crossingletapply_right_unhintt{monadic;comonadic}=letmonadic=Monadic.apply_rightt.monadicmonadicinletcomonadic=Comonadic.apply_rightt.comonadiccomonadicin{monadic;comonadic}letapply_righttm=m|>Value.disallow_left|>Value.unhint|>apply_right_unhintt|>Value.hint~monadic:Crossing~comonadic:Crossing(* Our mode crossing is for [Value] modes, but can be extended to [Alloc]
modes via [alloc_as_value], defined as follows:
Given a mode crossing [f] for [Value], and we are to check [Alloc] submoding
[m0 <= m1], we will instead check
[f (alloc_as_value m0) <= f (alloc_as_value m1)].
By adjunction tricks, this is equivalent to
- [ m0 <= regional_to_global ∘ fr ∘ f ∘ alloc_as_value m1 ]
- [ regional_to_local ∘ fl ∘ f ∘ alloc_as_value m0 <= m1 ]
where [regional_to_global] is the right adjoint of [alloc_as_value], and
[regional_to_local] the left adjoint. *)letapply_left_alloctm=m|>Alloc.unhint|>alloc_as_value_unhint|>apply_left_unhintt|>value_to_alloc_r2l_unhint|>Alloc.hint~comonadic:Crossing~monadic:Crossingletapply_right_alloctm=m|>Alloc.unhint|>alloc_as_value_unhint|>apply_right_unhintt|>value_to_alloc_r2g_unhint|>Alloc.hint~comonadic:Crossing~monadic:Crossingletapply_left_right_alloctm=let{monadic;comonadic}=Alloc.unhintminletmonadic=Monadic.apply_rightt.monadicmonadicinletcomonadic=comonadic|>comonadic_locality_as_regionality|>Comonadic.apply_leftt.comonadic|>comonadic_regional_to_local(* the left adjoint of [locality_as_regionality]*)inAlloc.hint~monadic:Crossing~comonadic:Crossing{monadic;comonadic}letlet0t1=Monadic.let0.monadict1.monadic&&Comonadic.let0.comonadict1.comonadicletmax={monadic=Monadic.max;comonadic=Comonadic.max}letmin={monadic=Monadic.min;comonadic=Comonadic.min}letjoint0t1={monadic=Monadic.joint0.monadict1.monadic;comonadic=Comonadic.joint0.comonadict1.comonadic}letmeett0t1={monadic=Monadic.meett0.monadict1.monadic;comonadic=Comonadic.meett0.comonadict1.comonadic}letequalt0t1=let0t1&&let1t0let[@inlineavailable]proj(typea)(ax:aAxis.t){monadic;comonadic}:a=matchaxwith|Monadicax->(Monadic.proj[@inlinedhint])axmonadic|Comonadicax->(Comonadic.proj[@inlinedhint])axcomonadiclet[@inlineavailable]set(typea)(ax:aAxis.t)(a:a){monadic;comonadic}:t=matchaxwith|Monadicax->{monadic=(Monadic.set[@inlinedhint])axamonadic;comonadic}|Comonadicax->{monadic;comonadic=(Comonadic.set[@inlinedhint])axacomonadic}letcreate~regionality~linearity~uniqueness~portability~contention~forkable~yielding~statefulness~visibility~staticity=letcomonadicbax=ifbthenPer_axis.min(Comonadicax)elsePer_axis.max(Comonadicax)inletmonadicbax=ifbthenPer_axis.min(Monadicax)elsePer_axis.max(Monadicax)inletregionality=comonadicregionalityArealityinletlinearity=comonadiclinearityLinearityinletuniqueness=monadicuniquenessUniquenessinletportability=comonadicportabilityPortabilityinletcontention=monadiccontentionContentioninletforkable=comonadicforkableForkableinletyielding=comonadicyieldingYieldinginletstatefulness=comonadicstatefulnessStatefulnessinletvisibility=monadicvisibilityVisibilityinletstaticity=monadicstaticityStaticityinletmonadic=Monadic.create~uniqueness~contention~visibility~staticityinletcomonadic=Comonadic.create~regionality~linearity~portability~yielding~forkable~statefulnessin{monadic;comonadic}letprintppft=letl=List.filter_map(funax->let(Pax)=ax|>Modality.Axis.of_value|>Axis.of_modalityinleta=projaxtinifPer_axis.(leax(maxax)a)thenNoneelseSome(Fmt.asprintf"%a"(Per_axis.printax)a))Value.Axis.allinFmt.(pp_print_list~pp_sep:pp_print_spacepp_print_stringppfl)letto_modality{monadic=Monadic.Modalitymonadic;comonadic=Comonadic.Modalitycomonadic}={monadic;comonadic}end