Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file univ_map.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338open!ImportopenStd_internalincludeUniv_map_intfmoduleUid=Type_equal.Id.UidmoduleMake1(Key:Key)(Data:sigtype('s,'a)t[@@derivingsexp_of]end)=struct(* A wrapper for the [Key] module that adds a dynamic check to [Key.type_id].
It's a bug if the user-provided [Key.type_id] gives different type ids on different
calls. Because this check should be fairly cheap, we do it dynamically to avoid
subtler problems later.
Of course, we're not checking truly pathological things like the provided
[Key.type_id] only changes the value it returns on every third call... *)moduleKey=structtype'at='aKey.t[@@derivingsexp_of](* test-friendly sexp conversion *)letsexp_of_type_idtype_id=[%sexp{name=(Type_equal.Id.nametype_id:string);uid=((ifam_running_inline_testthenSexp.Atom"<uid>"elseType_equal.Id.Uid.sexp_of_t(Type_equal.Id.uidtype_id)):Sexp.t)}];;lettype_idkey=lettype_id1=Key.type_idkeyinlettype_id2=Key.type_idkeyinifType_equal.Id.sametype_id1type_id2thentype_id1elseraise_s[%message"[Key.type_id] must not provide different type ids when called on the same \
input"(key:_Key.t)(type_id1:type_id)(type_id2:type_id)];;endtype('s,'a)data=('s,'a)Data.tletname_of_keykey=Type_equal.Id.name(Key.type_idkey)letuid_of_keykey=Type_equal.Id.uid(Key.type_idkey)modulePacked=structtype'st=T:'aKey.t*('s,'a)Data.t->'stletsexp_of_tsexp_of_a(T(key,data))=Data.sexp_of_tsexp_of_a(Type_equal.Id.to_sexp(Key.type_idkey))data;;lettype_id_name(T(key,_))=name_of_keykeylettype_id_uid(T(key,_))=uid_of_keykeyletcomparet1t2=letc=String.compare(type_id_namet1)(type_id_namet2)inifc<>0thencelseUid.compare(type_id_uidt1)(type_id_uidt2);;endtype'st='sPacked.tUid.Map.tletto_alistt=Map.datat|>List.sort~compare:Packed.compareletsexp_of_tsexp_of_at=to_alistt|>List.map~f:(funpacked->Packed.type_id_namepacked,packed)|>[%sexp_of:(string*aPacked.t)list];;letinvariant(t:_t)=Invariant.invariant[%here]t[%sexp_of:_t](fun()->Map.iterit~f:(fun~key~data->assert(Uid.equalkey(Packed.type_id_uiddata))));;letsett~key~data=Map.sett~key:(uid_of_keykey)~data:(Packed.T(key,data))letmem_by_idtid=Map.memtidletmemtkey=mem_by_idt(uid_of_keykey)letremove_by_idtid=Map.removetidletremovetkey=remove_by_idt(uid_of_keykey)letempty=Uid.Map.emptyletsingletonkeydata=Uid.Map.singleton(uid_of_keykey)(Packed.T(key,data))letis_empty=Map.is_emptyletfind(typeb)t(key:bKey.t)=matchMap.findt(uid_of_keykey)with|None->None|Some(Packed.T(key',value))->(* cannot raise -- see [invariant] *)letType_equal.T=Type_equal.Id.same_witness_exn(Key.type_idkey)(Key.type_idkey')inSome(value:(_,b)Data.t);;letfind_exntkey=matchfindtkeywith|Somedata->data|None->failwithf"Univ_map.find_exn on unknown key %s"(name_of_keykey)();;letaddt~key~data=ifmemtkeythen`Duplicateelse`Ok(sett~key~data)letadd_exnt~key~data=matchaddt~key~datawith|`Okt->t|`Duplicate->failwithf"Univ_map.add_exn on existing key %s"(name_of_keykey)();;letchange_exntkey~f:update=matchfindtkeywith|Somedata->sett~key~data:(updatedata)|None->failwithf"Univ_map.change_exn on unknown key %s"(name_of_keykey)();;letchangetkey~f:update=letorig=findtkeyinletnext=updateoriginmatchnextwith|Somedata->sett~key~data|None->ifOption.is_noneorigthentelseremovetkey;;letupdatetkey~f=changetkey~f:(fundata->Some(fdata))letof_alist_exnt=Uid.Map.of_alist_exn(List.mapt~f:(funp->Packed.type_id_uidp,p));;endmoduleMake(Key:Key)(Data:sigtype'at[@@derivingsexp_of]end)=structmoduleM=Make1(Key)(structtype(_,'a)t='aData.t[@@derivingsexp_of]end)typet=unitM.t[@@derivingsexp_of]moduleKey=Keytype'adata='aData.tletinvariant=M.invariantletempty=M.emptyletsingleton=M.singletonletis_empty=M.is_emptyletset=M.setletmem=M.memletmem_by_id=M.mem_by_idletfind=M.findletfind_exn=M.find_exnletadd=M.addletadd_exn=M.add_exnletchange=M.changeletchange_exn=M.change_exnletupdate=M.updateletremove=M.removeletremove_by_id=M.remove_by_idmodulePacked=structtypet=T:'aKey.t*'aData.t->tendletto_alistt=List.map(M.to_alistt)~f:(functionM.Packed.T(key,data)->Packed.T(key,data));;letof_alist_exnt=M.of_alist_exn(List.mapt~f:(functionPacked.T(key,data)->M.Packed.T(key,data)));;endmoduleMerge(Key:Key)(Input1_data:Data)(Input2_data:Data)(Output_data:Data)=structtypef={f:'a.key:'aKey.t->[`Leftof'aInput1_data.t|`Rightof'aInput2_data.t|`Bothof'aInput1_data.t*'aInput2_data.t]->'aOutput_data.toption}moduleOutput=Make(Key)(Output_data)letmerge(t1:Make(Key)(Input1_data).t)(t2:Make(Key)(Input2_data).t)~f:{f}:Make(Key)(Output_data).t=letf~keymerge_result=Option.map(f~keymerge_result)~f:(fundata->Output.M.Packed.T(key,data))inMap.merget1t2~f:(fun~key:_->function|`Left(T(key,data))->f~key(`Leftdata)|`Right(T(key,data))->f~key(`Rightdata)|`Both(T(left_key,left_data),T(right_key,right_data))->(* Can't raise due to the invariant *)letType_equal.T=Type_equal.Id.same_witness_exn(Key.type_idleft_key)(Key.type_idright_key)inf~key:left_key(`Both(left_data,right_data)));;endmoduleMerge1(Key:Key)(Input1_data:Data1)(Input2_data:Data1)(Output_data:Data1)=structtype('s1,'s2,'s3)f={f:'a.key:'aKey.t->[`Leftof('s1,'a)Input1_data.t|`Rightof('s2,'a)Input2_data.t|`Bothof('s1,'a)Input1_data.t*('s2,'a)Input2_data.t]->('s3,'a)Output_data.toption}moduleOutput=Make1(Key)(Output_data)letmerge(types1s2)(t1:s1Make1(Key)(Input1_data).t)(t2:s2Make1(Key)(Input2_data).t)~f:{f}=letf~keymerge_result=Option.map(f~keymerge_result)~f:(fundata->Output.Packed.T(key,data))inMap.merget1t2~f:(fun~key:_->function|`Left(T(key,data))->f~key(`Leftdata)|`Right(T(key,data))->f~key(`Rightdata)|`Both(T(left_key,left_data),T(right_key,right_data))->(* Can't raise due to the invariant *)letType_equal.T=Type_equal.Id.same_witness_exn(Key.type_idleft_key)(Key.type_idright_key)inf~key:left_key(`Both(left_data,right_data)));;endmoduleType_id_key=structtype'at='aType_equal.Id.t[@@derivingsexp_of]lettype_id=Fn.idendinclude(Make(Type_id_key)(structtype'at='a[@@derivingsexp_of]end):Swithtype'adata='aandmoduleKey:=Type_id_key)moduleKey=Type_equal.IdmoduleWith_default=structmoduleKey=structtype'at={key:'aType_equal.Id.t;default:'a}letcreate~default~namesexp_of={default;key=Type_equal.Id.create~namesexp_of};;letidt=t.keyendletfindt{Key.key;default}=Option.value~default(findtkey)letsett~key:{Key.key;default=_}~data=sett~key~dataletchangetkey~f:update=sett~key~data:(update(findtkey))endmoduleWith_fold=structmoduleKey=structtype('a,'b)t={key:'bWith_default.Key.t;f:'b->'a->'b}letcreate~init~f~namesexp_of={f;key=With_default.Key.create~default:init~namesexp_of};;letidt=With_default.Key.idt.keyendletfindt{Key.key;f=_}=With_default.findtkeyletsett~key:{Key.key;f=_}~data=With_default.sett~key~dataletchanget{Key.key;f=_}~f:update=With_default.changetkey~f:updateletaddt~key:{Key.key;f}~data=With_default.changetkey~f:(funacc->faccdata);;endmoduleMulti=structopenWith_foldmoduleKey=structtype'at=('a,'alist)Key.tletcreate~namesexp_of=Key.create~init:[]~f:(funxsx->x::xs)~name(List.sexp_of_tsexp_of);;letid=With_fold.Key.idendletset=setletfind=findletadd=addletchange=changeend