123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136(* This file is free software, part of Archsat. See file "LICENSE" for more details. *)(* Arbitrary tags for expressions.
Uses a mixed map (see containers.data.CCMixmap) *)(* Mixmap Implementation (from containers) *)(* ************************************************************************ *)(* Implementation taken from containers. *)type'binjection={get:(unit->unit)->'boption;set:'b->(unit->unit);}letcreate_inj()=letr=refNoneinletgetf=r:=None;f();!randsetv=(fun()->r:=Somev)in{get;set}moduletypeS=sigtypekeytypet(** A map containing values of different types, indexed by {!key}. *)valempty:t(** Empty map *)valget:inj:'ainjection->key->t->'aoption(** Get the value corresponding to this key, if it exists and
belongs to the same key *)valadd:inj:'ainjection->key->'a->t->t(** Bind the key to the value, using [inj] *)valremove:inj:'ainjection->key->t->t(** Remove the binding to the key. *)endmoduletypeORD=sigtypetvalcompare:t->t->intendmoduleMake(X:ORD):Swithtypekey=X.t=structmoduleM=Map.Make(X)typekey=X.ttypet=(unit->unit)M.tletempty=M.emptyletget~injxmap=tryinj.get(M.findxmap)withNot_found->Noneletadd~injxymap=M.addx(inj.sety)mapletremove~inj:_xmap=M.removexmapend(* Functor instantiation *)(* ************************************************************************ *)moduleM=Make(structtypet=intletcompare(a:int)(b:int)=compareabend)typemap=M.ttype'at={id:int;inj:'ainjection;}letequalkk'=k.id=k'.idletmk_keyid={id;inj=create_inj();}letmax_id=ref0letcreate()=incrmax_id;mk_key!max_idletempty=M.emptyletgetmk=M.get~inj:k.injk.idmletget_listmk=matchgetmkwith|None->[]|Somel->lletget_lastmk=matchgetmkwith|None->None|Some[]->None|Some(x::_)->Somexletunsetmk=M.remove~inj:k.injk.idmletsetmkl=M.add~inj:k.injk.idlmletset_optmk=function|None->m|Somev->setmkvletaddmkv=setmk(v::get_listmk)letadd_optmk=function|None->m|Somev->addmkvletadd_listmk=function|[]->m|l->setmk(List.rev_appendl(get_listmk))