123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934open!Stdppxopen!ImportincludeLanguage_intf.DefinitionsopenResult.Let_syntaxmoduleType=structincludeTypeletequal_witness_non_tuple:typeab.anon_tuple->bnon_tuple->(a,b)Stdlib.Type.eqoption=funt1t2->matcht1,t2with|Kind,Kind->SomeEqual|Mode,Mode->SomeEqual|Modality,Modality->SomeEqual|Alloc,Alloc->SomeEqual|Synchro,Synchro->SomeEqual|(Kind|Mode|Modality|Alloc|Synchro),_->None;;letsexp_of_non_tuple:typea.anon_tuple->Sexp.t=function|Kind->Atom"Kind"|Mode->Atom"Mode"|Modality->Atom"Modality"|Alloc->Atom"Alloc"|Synchro->Atom"Synchro";;letrecequal_witness:typeab.at->bt->(a,b)Stdlib.Type.eqoption=funt1t2->matcht1,t2with|Non_tupleb1,Non_tupleb2->(matchequal_witness_non_tupleb1b2with|SomeEqual->SomeEqual|None->None)|Tupletp1,Tupletp2->(matchequal_tuple_witnesstp1tp2with|None->None|SomeEqual->SomeEqual)|(Non_tuple_|Tuple_),_->Noneandequal_tuple_witness:typeab.atuple->btuple->(a,b)Stdlib.Type.eqoption=funtp1tp2->matchtp1,tp2with|[],[]->SomeEqual|hd1::tl1,hd2::tl2->(matchequal_witnesshd1hd2with|None->None|SomeEqual->(matchequal_tuple_witnesstl1tl2with|None->None|SomeEqual->SomeEqual))|[],_::_|_::_,[]->None;;letrecsexp_of_t:typea.at->Sexp.t=function|Non_tuplenon_tuple->sexp_of_non_tuplenon_tuple|Tuple[(Non_tupleAllocast1);(Non_tupleModeast2)]->List[sexp_of_tt1;Atom"@";sexp_of_tt2]|Tuple[(Non_tupleSynchroast1);(Non_tupleModeast2)]->List[sexp_of_tt1;Atom"@";sexp_of_tt2]|Tupletp->List(Atom"Tuple"::sexp_of_tupletp)andsexp_of_tuple:typea.atuple->Sexp.tlist=function|[]->[]|hd::tl->sexp_of_thd::sexp_of_tupletl;;letcompare_packed:packed->packed->int=Poly.compareletsexp_of_packed(Pt)=sexp_of_ttletkind=Non_tupleKindletmode=Non_tupleModeletmodality=Non_tupleModalityletalloc=Non_tupleAllocletsynchro=Non_tupleSynchrolettuple2t1t2=Tuple[t1;t2]endmoduleUntyped=structincludeUntypedmoduleAxis=structincludeAxisletcompare:t->t->int=Poly.comparemoduleMap=Map.Make(structtypenonrect=tletcompare=compareend)endmoduleIdentifier=structincludeIdentifierletcomparet1t2=String.comparet1.identt2.identletsexp_of_tt=Atomt.identendmoduleValue=structincludeValueletreccompare:t->t->int=funt1t2->matcht1,t2with|Identifierident1,Identifierident2->Identifier.compareident1ident2|Kind_productkinds1,Kind_productkinds2->Nonempty_list.comparekinds1kinds2~cmp:compare|Kind_mod(kind1,mods1),Kind_mod(kind2,mods2)->(matchcomparekind1kind2with|0->letmods1=Nonempty_list.sort_uniq~cmp:comparemods1inletmods2=Nonempty_list.sort_uniq~cmp:comparemods2inNonempty_list.compare~cmp:comparemods1mods2|n->n)|Tuplets1,Tuplets2->Nonempty_list.compare~cmp:comparets1ts2|Identifier_,_->-1|_,Identifier_->1|Kind_product_,_->-1|_,Kind_product_->1|Kind_mod_,_->-1|_,Kind_mod_->1|Tuple_,_->.|_,Tuple_->.;;letrecsexp_of_t:t->Sexp.t=function|Identifierident->Identifier.sexp_of_tident|Kind_productkinds->List[Atom"Product";kinds|>Nonempty_list.sexp_of_tsexp_of_t]|Kind_mod(kind,mods)->List[Atom"Mod";sexp_of_tkind;mods|>Nonempty_list.sort_uniq~cmp:compare|>Nonempty_list.sexp_of_tsexp_of_t]|Tuplets->List(Atom"Tuple"::(ts|>Nonempty_list.to_list|>List.map~f:sexp_of_t));;endmodulePattern=structincludePatternletreccompare:t->t->int=funt1t2->matcht1,t2with|Wildcard,Wildcard->0|Identifierident1,Identifierident2->Identifier.compareident1ident2|Tuplets1,Tuplets2->Nonempty_list.compare~cmp:comparets1ts2|Wildcard,_->-1|_,Wildcard->1|Identifier_,_->-1|_,Identifier_->1|Tuple_,_->.|_,Tuple_->.;;letrecsexp_of_t:t->Sexp.t=function|Wildcard->Atom"Wildcard"|Identifier ident->Identifier.sexp_of_tident|Tuplets->List(Atom"Tuple"::(ts|>Nonempty_list.to_list|>List.map~f:sexp_of_t));;endmoduleExpression=structincludeExpressionletreccompare:t->t->int=funt1t2->matcht1,t2with|Identifier ident1,Identifierident2->Identifier.compareident1ident2|Kind_productkinds1,Kind_productkinds2->Nonempty_list.comparekinds1kinds2~cmp:compare|Kind_mod(kind1,mods1),Kind_mod(kind2,mods2)->(matchcomparekind1 kind2with|0->letmods1=Nonempty_list.sort_uniq~cmp:comparemods1inletmods2=Nonempty_list.sort_uniq~cmp:compare mods2inNonempty_list.compare~cmp:comparemods1mods2|n->n)|Kind_coercion (kind1,coerce_to1),Kind_coercion(kind2,coerce_to2)->(matchcomparekind1kind2with|0->comparecoerce_to1coerce_to2|n->n)|Comma_separatedts1,Comma_separatedts2->Nonempty_list.compare~cmp:comparets1ts2|Typed(t1,typ1),Typed(t2,typ2)->(matchcomparet1t2with|0->Type.compare_packed typ1typ2|n->n)|Identifier_,_->-1|_,Identifier_->1|Kind_product_,_->-1|_,Kind_product _->1|Kind_mod_,_->-1|_,Kind_mod_->1|Kind_coercion_,_->-1|_,Kind_coercion_->1|Comma_separated_,_->-1|_,Comma_separated _->1|Typed_,_->.|_,Typed_->.;;letrecsexp_of_t:t->Sexp.t=function|Identifierident->Identifier.sexp_of_tident|Kind_productkinds->List(Atom"Product"::(kinds|>Nonempty_list.to_list|>List.map~f:sexp_of_t))|Kind_mod(kind,mods)->List[Atom"Mod";sexp_of_tkind;mods|>Nonempty_list.sort_uniq~cmp:compare|>Nonempty_list.sexp_of_tsexp_of_t]|Kind_coercion(kind,coerce_to)->List[Atom"Kind_coercion";sexp_of_tkind;sexp_of_tcoerce_to]|Comma_separatedts->List(Atom"Comma_separated"::(ts|>Nonempty_list.to_list|>List.map~f:sexp_of_t))|Typed(t,typ)->List[sexp_of_tt;Atom":";Type.sexp_of_packedtyp];;endendmoduleTyped=structincludeTypedmoduleVec=struct(* Used in some logic below to make error handling easier. *)type('item,'length)t=|[]:(_,unit)t|(::):'item*('item,'length)t->('item,_*'length)ttypewrong_length=Wrong_lengthletrecof_list_with_length:typeitem length.itemlist->lengthType.tuple->((item,length)t,wrong_length)result=funitemslength->matchitems,lengthwith|[],[]->Ok[]|hd_items::tl_items,_::tl_length->let*tl=of_list_with_lengthtl_itemstl_lengthinOk(hd_items::tl)|_::_,[]|[],_::_->ErrorWrong_length;;endmoduleAxis=structincludeAxisletcompare_packed:packed->packed->int=Poly.compareletof_type:typea.aType.non_tupleType.t->aType.non_tuplet=function|Non_tupleKind->SingletonKind|Non_tupleMode->SingletonMode|Non_tupleModality->SingletonModality|Non_tupleAlloc->SingletonAlloc|Non_tupleSynchro->SingletonSynchro;;letis_set:typea.at->bool=function|Set_->true|Singleton_->false;;moduleMap=Map.Make(structtypet=packedletcompare=compare_packedend)moduleSub_axis=structincludeSub_axismoduleModal=structincludeModalletof_mode_identifier:string->tOr_unrecognized.t=function|"global"|"local"->KnownLocality|"nonportable"|"shareable"|"corruptible"|"portable"->KnownPortability|"uncontended"|"contended"|"corrupted"|"shared"->KnownContention|"stateful"|"reading"|"writing"|"stateless"->KnownStatefulness|"read_write"|"read"|"write"|"immutable"->Known Visibility|"many"|"once"->KnownLinearity|"aliased"|"unique"->KnownUniqueness|"unyielding"|"yielding"->KnownYielding|"forkable"|"unforkable"->KnownForkable|_->Unrecognized;;letsexp_of_t=function|Locality->Atom"Locality"|Portability->Atom"Portability"|Contention->Atom"Contention"|Statefulness->Atom"Statefulness"|Visibility->Atom"Visibility"|Linearity->Atom"Linearity"|Uniqueness->Atom"Uniqueness"|Yielding->Atom"Yielding"|Forkable->Atom"Forkable";;endmoduleMode=structincludeModeletdefault(Modem)=matchmwith|Locality->"global"|Portability->"nonportable"|Contention->"uncontended"|Statefulness->"stateful"|Visibility->"read_write"|Linearity->"many"|Uniqueness->"aliased"|Yielding->"unyielding"|Forkable->(* Above comment also applies to [forkable]. *)"forkable";;letof_mode_identifierstr:_Or_unrecognized.t=matchModal.of_mode_identifierstrwith|Knownm->Known(Modem)|Unrecognized->Unrecognized;;letsexp_of_t(Modem)=Modal.sexp_of_tmendmoduleModality=structincludeModalityletdefault(Modalitym)=matchmwith|Locality->"local"|Portability->"nonportable"|Contention->"uncontended"|Statefulness->"stateful"|Visibility->"read_write"|Linearity->"once"|Uniqueness->"unique"|Yielding ->"yielding"|Forkable->"unforkable";;letof_mode_identifierstr:_Or_unrecognized.t=matchModal.of_mode_identifierstrwith|Known m->Known(Modalitym)|Unrecognized->Unrecognized;;letsexp_of_t(Modalitym)=Modal.sexp_of_tmendmoduleOr_unrecognized=structincludeOr_unrecognizedletsexp_of_tsexp_of_a=function|Knowna->sexp_of_aa|Unrecognized->Atom"unrecognized";;endletcompare_packed:packed->packed->int=Poly.comparemoduleMap=Stdlib.Map.Make(structtypet=packedletcompare=compare_packedend)letof_identifier:typea.aType.non_tupleIdentifier.t->aType.non_tuplet=fun{ident;type_=Non_tupletype_}->matchtype_with|Kind->Kind|Mode->Mode(Mode.of_mode_identifierident)|Modality->Modality(Modality.of_mode_identifierident)|Alloc->Alloc|Synchro->Synchro;;letof_value:typea.aType.non_tupleValue.t->aType.non_tuplet=function|Identifierident->of_identifierident|Kind_product_->Kind|Kind_mod_->Kind;;letdefault:typea.aType.non_tuplet->stringOr_unrecognized.t=function|Kind->Known"value"|Mode(Knownmode)->Known(Mode.defaultmode)|Modality(Knownmodality)->Known(Modality.defaultmodality)|ModeUnrecognized|ModalityUnrecognized->Unrecognized|Alloc->Known"heap"|Synchro->Known"unsync";;letsexp_of_t:typea.at->Sexp.t=function|Kind->Atom"Kind"|Modem->List[Atom"Mode";Or_unrecognized.sexp_of_tMode.sexp_of_tm]|Modalitym->List[Atom"Modality";Or_unrecognized.sexp_of_tModality.sexp_of_tm]|Alloc->Atom"Alloc"|Synchro->Atom"Synchro";;endmoduleNamespace=structincludeNamespaceletrecof_value:typea.is_set:bool->aValue.t->at=fun~is_setval_->letto_namespacesub_axis=ifis_setthenSetsub_axiselseSingletonsub_axisinmatchval_with|Identifier_->to_namespace(Sub_axis.of_valueval_)|Kind_product_->to_namespace(Sub_axis.of_valueval_)|Kind_mod_->to_namespace(Sub_axis.of_valueval_)|Tupletp->Tuple(of_value_tuple~is_settp)andof_value_tuple:typea.is_set:bool->aValue.tuple->atuple=fun~is_settp->matchtpwith|[]->[]|hd::tl->of_value~is_sethd::of_value_tuple~is_settl;;(* equality modulo mode/modality conflation *)letrecsame_namespace:typeab.at->bt->bool=funtp1tp2->matchtp1,tp2with|Singletontp1,Singletontp2|Settp1,Settp2->(* We conflate modalities and modes *)(matchtp1,tp2with|Mode(Known(Modem1)),Modality(Known(Modalitym2))->m1=m2|Modality(Known(Modalitym1)),Mode(Known(Modem2))->m1=m2|ModeUnrecognized,ModalityUnrecognized|ModalityUnrecognized,ModeUnrecognized->true|_,_->Sub_axis.compare_packed(Ptp1)(Ptp2)=0)|Tupletp1,Tupletp2->same_namespace_tupletp1tp2|(Singleton_|Set_),Tuple_|Tuple_,(Singleton_|Set_)|Singleton_,Set_|Set_,Singleton_->falseandsame_namespace_tuple:typeab.atuple->btuple->bool=funtp1tp2->matchtp1,tp2with|[],[]->true|hd1::tl1,hd2::tl2->same_namespacehd1hd2&&same_namespace_tupletl1tl2|[],_::_|_::_,[]->false;;letrecsexp_of_t:typea.at->Sexp.t=function|Singletont->Sub_axis.sexp_of_tt|Sett->List[Atom"Set";Sub_axis.sexp_of_tt]|Tupletp->List(Atom"Tuple"::sexp_of_tupletp)andsexp_of_tuple:typea.atuple->Sexp.tlist=function|[]->[]|hd::tl->sexp_of_thd::sexp_of_tupletl;;endendmoduleIdentifier=structincludeIdentifierletequal_witness{type_;ident}t=matchType.equal_witnesstype_t.type_with|Some_aseqwhenString.equalidentt.ident->eq|_->None;;endmoduleValue=structincludeValueletrecuntype:typea.at->Untyped.Value.t=function|Identifier{ident;type_=_}->Identifier{ident}|Kind_productkinds->Kind_product(Nonempty_list.mapkinds~f:untype)|Kind_mod(kind,mods)->Kind_mod(untypekind,Nonempty_list.mapmods~f:untype)|Tupletp->Tuple(untype_tupletp)anduntype_tuple:typeab.(a*b)tuple->Untyped.Value.tNonempty_list.t=function|[hd]->Nonempty_list.singleton(untypehd)|hd::(_::_astl)->Nonempty_list.cons(untypehd)(untype_tupletl);;letcomparet1t2=Untyped.Value.compare(untypet1)(untypet2)letsexp_of_tt=Untyped.Value.sexp_of_t(untypet)(* Translate a value back into the expression that most directly corresponds to it.
More exactly, [eval (as_expression t) === t] when evaluating in an empty
environment. *)letrecas_expression:typea.at->(a,Expression.singleton)Expression.t=function|Identifierident->Identifierident|Kind_mod(kind,mods)->Kind_mod(as_expressionkind,Nonempty_list.mapmods~f:as_expression)|Kind_productkinds->Kind_product(Nonempty_list.mapkinds~f:as_expression)|Tupletp->Tuple(uneval_tupletp)anduneval_tuple:typea.atuple->aExpression.tuple=function|[]->[]|hd::tl->as_expressionhd::uneval_tupletl;;letis_actual_default:typea.aType.non_tuplet->bool=function|Identifierident->(matchAxis.Sub_axis.default(Axis.Sub_axis.of_identifierident)with|Knowndefault->String.equalident.identdefault|Unrecognized->false)|Kind_product_|Kind_mod_->false;;letis_default_for_standard_mangling:typea.aType.non_tuplet->bool=function|Identifier{type_=Non_tupleKind;ident="value_or_null"}->true|_->false;;letdefaultness:typea.aType.non_tuplet->Defaultness.t=funvalue->ifis_actual_defaultvaluethenActual_defaultelseifis_default_for_standard_manglingvaluethenDefault_for_standard_manglingelseNot_a_default;;letrecto_node:typea.aType.non_tuplet->loc:location->aType.non_tupleNode.t=funt~loc->matchtwith|Identifier{ident;type_}->(matchtype_with|Non_tupleMode->Mode{txt=Modeident;loc}|Non_tupleModality->Modality{txt=Modalityident;loc}|Non_tupleKind->Jkind_annotation{pjka_desc=Pjk_abbreviation({txt=Lidentident;loc},[]);pjka_loc=loc}|Non_tupleAlloc->Alloc|Non_tupleSynchro->Synchro)|Kind_productkinds->letghost_loc={locwithloc_ghost=true}inletkinds=kinds|>Nonempty_list.to_list|>List.map~f:(funkind->let(Jkind_annotationkind)=to_node~loc:ghost_lockindinkind)inJkind_annotation{pjka_desc=Pjk_productkinds;pjka_loc=loc}|Kind_mod(kind,mods)->letghost_loc={locwithloc_ghost=true}inlet(Jkind_annotationkind)=to_node~loc:ghost_lockindinletmods=mods|>Nonempty_list.to_list|>List.sort_uniq~cmp:compare|>List.map~f:(fun(Identifier{ident;type_=Non_tupleModality})->{txt=Modeident;loc=ghost_loc})inJkind_annotation{pjka_desc=Pjk_mod(kind,mods);pjka_loc=loc};;endmodulePattern=structincludePatternletrecuntype:typea.at->Untyped.Pattern.t=function|Wildcard->Wildcard|Identifier{ident;type_=_}->Identifier{ident}|Tupletp->Tuple(untype_tupletp)anduntype_tuple:typeab.(a*b)tuple->Untyped.Pattern.tNonempty_list.t=function|[hd]->Nonempty_list.singleton(untypehd)|hd::(_::_astl)->Nonempty_list.cons(untypehd)(untype_tupletl);;letrectype_check:typea.Untyped.Pattern.t->expected:aType.t->(at,Type_error.t)result=fununtyped~expected->matchuntyped,expectedwith|Wildcard,_->OkWildcard|Identifier{ident},type_->Ok(Identifier{ident;type_})|Tupleuntyped_tp,Tupletype_tp->let*vec=matchVec.of_list_with_length(Nonempty_list.to_listuntyped_tp)type_tpwith|Okvec->Okvec|ErrorWrong_length->Error(Type_error.Tuple_length_mismatch{kind="pattern";sexp_of_kind=Untyped.Pattern.sexp_of_t;value=Tupleuntyped_tp;expected_type=Tupletype_tp})inlet+tuple=type_check_tuplevec~expected:type_tpinTupletuple|(Tuple_asnode),(Non_tuple_astype_)->Error(Type_mismatch{kind="pattern";sexp_of_kind=Untyped.Pattern.sexp_of_t;value=node;expected_type=type_;expected_sets=None;hint=None})andtype_check_tuple:typea.(Untyped.Pattern.t,a)Vec.t->expected:aType.tuple->(atuple,Type_error.t)result=fununtyped~expected->matchuntyped,expectedwith|[],[]->Ok[]|untyped_hd::untyped_tl,type_hd::type_tl->let*hd=type_checkuntyped_hd~expected:type_hdinlet+tl=type_check_tupleuntyped_tl~expected:type_tlinhd::tl;;endmoduleExpression=structincludeExpressionletrecof_parsetree_jkind:jkind_annotation->((Type.kind,_)Expression.t,stringloc)result=function|{pjka_desc=Pjk_abbreviation({txt=Lidentident;_},[]);_}->Ok(Identifier{ident;type_=Non_tupleKind})|{pjka_desc=Pjk_abbreviation(_,_::_);pjka_loc}->Error{loc=pjka_loc;txt="no kind modifiers"}|{pjka_desc=Pjk_mod(jkind,mode::modes);_}->letmodes=Nonempty_list.map(mode::modes)~f:(fun{txt=Modeident;_}->Expression.Identifier{ident;type_=Non_tupleModality})inlet+jkind=of_parsetree_jkindjkindinKind_mod(jkind,modes)|{pjka_desc=Pjk_product(jkind::jkinds);_}->let+kinds=Nonempty_list.Or_first_error.map(jkind::jkinds)~f:of_parsetree_jkindinKind_productkinds|{pjka_desc=_;pjka_loc}->Error{loc=pjka_loc;txt="unrecognized kind shape: only kind abbreviation, mod, or product"};;letsexp_of_sets:types.(string,s)allow_set->Sexp.t=function|Singleton_only_hint->Atom"singleton"|Set_or_singleton->Atom"set with unions";;letrectype_:typeais_set.(a,is_set)t->aType.t=function|Identifier{type_;_}->type_|Kind_mod_->Type.kind|Kind_product_->Type.kind|Kind_coercion_->Type.kind|Tupletp->Tuple(type_tupletp)|Union(hd::_)->type_hdandtype_tuple:typeab.(a*b)tuple->(a*b)Type.tuple=function|[hd]->[type_hd]|hd::(_::_astl)->type_hd::type_tupletl;;letrecuntype:typeais_set.(a,is_set)t->Untyped.Expression.t=function|Identifier{ident;type_=_}->Identifier{ident}|Kind_mod(kind,mods)->Kind_mod(untypekind,Nonempty_list.mapmods~f:untype)|Kind_productkinds->Kind_product(Nonempty_list.mapkinds~f:untype)|Kind_coercion(kind,coerce_to)->Kind_coercion(untypekind,untypecoerce_to)|Tupletp->Comma_separated(untype_tupletp)|Unionts->Comma_separated(Nonempty_list.mapts~f:untype)anduntype_tuple:typeab.(a*b)tuple->Untyped.Expression.tNonempty_list.t=function|[hd]->[untypehd]|hd::(_::_astl)->untypehd::Nonempty_list.to_list(untype_tupletl);;letrecto_set:typeais_set.(a,is_set)t->(a,set)t=function|Identifierident->Identifierident|Kind_mod(kind,mods)->Kind_mod(to_setkind,mods)|Kind_productkinds->Kind_product(Nonempty_list.mapkinds~f:to_set)|Kind_coercion(kind,coerce_to)->Kind_coercion(to_setkind,coerce_to)|Tupletp->Tupletp|Unionts->Union(Nonempty_list.mapts~f:to_set);;lettype_mismatch(types)?hint~value~expected~(allow_set:(string,s)Expression.allow_set)()=Error(Type_error.Type_mismatch{kind="expression";sexp_of_kind=Untyped.Expression.sexp_of_t;value;expected_type=expected;expected_sets=Someallow_set;hint});;letrectype_check:typeas.Untyped.Expression.t->expected:aType.t->allow_set:(string,s)allow_set->((a,s)t,Type_error.t)result=fununtyped~expected~allow_set->matchuntyped,expectedwith|Identifier{ident},type_->Ok(Identifier{ident;type_})|Kind_productkinds,Non_tupleKind->let+kinds=Nonempty_list.Or_first_error.mapkinds~f:(type_check~expected:(Non_tupleKind)~allow_set)inKind_productkinds|(Kind_product_asvalue),expected->type_mismatch~value~expected~allow_set()|Kind_mod(kind,mods),Non_tupleKind->let*kind=type_checkkind~expected:(Non_tupleKind)~allow_setinlet+mods=Nonempty_list.Or_first_error.mapmods~f:(type_check~expected:(Non_tupleModality)~allow_set:(Singleton_only{why_no_set="sets not allowed inside [kind mod] modalities"}))inKind_mod(kind,mods)|Kind_coercion(kind,coerce_to),Non_tupleKind->let*kind=type_checkkind~expected~allow_setinlet+coerce_to=type_checkcoerce_to~expected~allow_set:Set_or_singletoninKind_coercion(kind,coerce_to)|(Kind_coercion_asvalue),expected->type_mismatch~value~expected~allow_set()|(Kind_mod_asvalue),expected->type_mismatch~value~expected~allow_set()|Comma_separateduntyped_tp,Tupletype_tp->let*vec=matchVec.of_list_with_length(Nonempty_list.to_listuntyped_tp)type_tpwith|Okvec->Okvec|ErrorWrong_length->Error(Type_error.Tuple_length_mismatch{kind="expression";sexp_of_kind=Untyped.Expression.sexp_of_t;value=untyped;expected_type=expected})inlet+tuple=type_check_tuplevec~expected:type_tpinTupletuple|Comma_separateduntyped_union,Non_tuple_->(matchallow_setwith|Singleton_only{why_no_set=hint}->type_mismatch~hint~value:untyped~expected~allow_set()|Set_or_singleton->let+subsets=Nonempty_list.Or_first_error.mapuntyped_union~f:(type_check~expected~allow_set:Set_or_singleton)inUnion(subsets:>(_,set)tNonempty_list.t))|(Typed(untyped,Ptyp)asvalue),expected->(matchType.equal_witnesstypexpectedwith|None->type_mismatch~value~expected~allow_set()|SomeEqual->type_checkuntyped~expected~allow_set)andtype_check_tuple:typea.(Untyped.Expression.t,a)Vec.t->expected:aType.tuple->(atuple,Type_error.t)result=fununtyped~expected->matchuntyped,expectedwith|[],[]->Ok[]|untyped_hd::untyped_tl,type_hd::type_tl->let*hd=type_checkuntyped_hd~expected:type_hd~allow_set:(Singleton_only{why_no_set="sets not allowed inside tuples"})inlet+tl=type_check_tupleuntyped_tl~expected:type_tlinhd::tl;;endendmoduleType_error=structincludeType_errorletsexp_of_t:t->Sexp.t=function|Type_mismatch{kind;sexp_of_kind;value;expected_type=type_;expected_sets=is_set;hint}->Sexplib0.Sexp.message"Type mismatch"(["kind",Atomkind;"value",sexp_of_kindvalue;"expected type",Type.sexp_of_ttype_]@(matchis_setwith|Someis_set->["expected sets",Typed.Expression.sexp_of_setsis_set]|None->[])@matchhintwith|Somehint->["hint",Atomhint]|None->[])|Tuple_length_mismatch{kind;sexp_of_kind;value;expected_type=type_}->Sexplib0.Sexp.message"Tuple length mismatch"["kind",Atomkind;"value",sexp_of_kindvalue;"expected type",Type.sexp_of_ttype_];;letto_error~loct=Syntax_error.createf~loc"%s"(Sexp.to_string_hum(List[Atom"[%template]";sexp_of_tt]));;letlift_to_error_result~loc=function|Ok_asok->ok|Errortype_error->Error(to_error~loctype_error);;end(* Note about conflating axes (e.g. in [Env.bind]):
We always conflate modes and modalities for the portability and contention axes. These
axes have the property that the legacy mode coincides with the top mode for comonadic
axes and bottom mode for monadic axes[^0]. When this holds, ['a @ m -> 'b @ n] is
equivalent to ['a @@ m -> 'b @@ n].
More thoroughly: let [t @@ m] be a type whenever [t] is a type and [m] is a modality,
such that [t @@ m] behaves like
{[
type t_atat_m = { inner : t @@ m } [@@unboxed]
]}
i.e. is a zero-cost modality box around the type. Note that we define [t @@ m] even
when [m] is a modality that does nothing; for example, [t @@ local] behaves just as [t]
(since the [local] modality does nothing[^1]).
Then, for all modes/modalities [m] and [n] on comonadic (resp. monadic) axes, if we let
[ext_m] and [ext_n] be the top (resp. bottom) mode of the corresponding axes ([ext] as
in "extremum"), then ['a @ m -> 'b @ n] is equivalent to
['a @@ m @ ext_m -> 'b @@ n @ ext_n]. For example, ['a @ local -> 'b @ global] is
equivalent to ['a @@ local @ local -> 'b @@ global @ local], and (since ['a @@ local]
is just ['a]) also ['a @ local -> 'b @@ global @ local].
To make conflating a mode with its corresponding modality act in unsurprising ways, we
want ['a @ m -> 'b @ n] to be equivalent to ['a @@ m -> 'b @@ n], which is implicitly
['a @@ m @ legacy_m -> 'b @@ n @ legacy_n]. This holds exactly when [ext_m = legacy_m]
and [ext_n = legacy_n].
Going through all of the currently supported axes:
{v
+-------------+-------------+-------------+-------------+
| axis | direction | [ext_m] | legacy |
+-------------+-------------+-------------+-------------+
| locality | comonadic | local | global |
+-------------+-------------+-------------+-------------+
| portability | comonadic | nonportable | nonportable |
+-------------+-------------+-------------+-------------+
| contention | monadic | uncontended | uncontended |
+-------------+-------------+-------------+-------------+
| visibility | comonadic | stateful | stateful |
+-------------+-------------+-------------+-------------+
| access | monadic | read_write | read_write |
+-------------+-------------+-------------+-------------+
| affinity | comonadic | once | many |
+-------------+-------------+-------------+-------------+
| uniqueness | monadic | unique | aliased |
+-------------+-------------+-------------+-------------+
| yielding | comonadic | yielding | unyielding |
+-------------+-------------+-------------+-------------+
| forkable | comonadic | unforkable | forkable |
+-------------+-------------+-------------+-------------+
v}
The only axes for which the right two columns align are portability and contention. For
this reason, we always conflate modes and modalities on these two axes, and never on
the other axes.
[^0] The "top" (resp. "bottom") mode of an axis is the mode which is a super-mode
(resp. sub-mode) of all other modes on the axis.
[^1] Each modality acts as meet (min) for comonadic axes and join (max) for monadic
axes; e.g. the [global] modality acts as [fun m -> meet global m]. This means the
[local] modality acts as [fun m -> meet local m], but since [local] is top for the
locality axis, [meet local m = m], so [local] just acts as [fun m -> m], i.e. does
nothing.
*)