123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187(************************************************************************)(* * The Coq Proof Assistant / The Coq Development Team *)(* v * Copyright INRIA, CNRS and contributors *)(* <O___,, * (see version control and CREDITS file for authors & dates) *)(* \VV/ **************************************************************)(* // * This file is distributed under the terms of the *)(* * GNU Lesser General Public License Version 2.1 *)(* * (see LICENSE file for the text of the license) *)(************************************************************************)moduletypeValueS=sigtype'atendmoduletypeMapS=sigtypettype'akeytype'avaluevalempty:tvaladd:'akey->'avalue->t->tvalremove:'akey->t->tvalfind:'akey->t->'avaluevalmem:'akey->t->boolvalmodify:'akey->('avalue->'avalue)->t->ttypemap={map:'a.'akey->'avalue->'avalue}valmap:map->t->ttypeany=Any:'akey*'avalue->anyvaliter:(any->unit)->t->unitvalfold:(any->'r->'r)->t->'r->'rtypefilter={filter:'a.'akey->'avalue->bool}valfilter:filter->t->tendmoduletypePreS=sigtype'atagtypet=Dyn:'atag*'a->tvalcreate:string->'atagvaleq:'atag->'btag->('a,'b)CSig.eqoptionvalrepr:'atag->stringvaldump:unit->(int*string)listtypeany=Any:'atag->anyvalname:string->anyoptionmoduleMap(Value:ValueS):MapSwithtype'akey='atagandtype'avalue='aValue.tmoduleHMap(V1:ValueS)(V2:ValueS):sigtypemap={map:'a.'atag->'aV1.t->'aV2.t}valmap:map->Map(V1).t->Map(V2).ttypefilter={filter:'a.'atag->'aV1.t->bool}valfilter:filter->Map(V1).t->Map(V1).tendendmoduletypeS=sigincludePreSmoduleEasy:sigvalmake_dyn_tag:string->('a->t)*(t->'a)*'atagvalmake_dyn:string->('a->t)*(t->'a)valinj:'a->'atag->tvalprj:t->'atag->'aoptionendendmoduleMake()=structmoduleSelf:PreS=struct(* Dynamics, programmed with DANGER !!! *)type'atag=inttypet=Dyn:'atag*'a->ttypeany=Any:'atag->anyletdyntab=ref(Int.Map.empty:stringInt.Map.t)(** Instead of working with tags as strings, which are costly, we use their
hash. We ensure unicity of the hash in the [create] function. If ever a
collision occurs, which is unlikely, it is sufficient to tweak the offending
dynamic tag. *)letcreate(s:string)=lethash=Hashtbl.hashsinifInt.Map.memhash!dyntabthenbeginletold=Int.Map.findhash!dyntabinPrintf.eprintf"Dynamic tag collision: %s vs. %s\n%!"sold;assertfalseend;dyntab:=Int.Map.addhashs!dyntab;hashleteq:'a'b.'atag->'btag->('a,'b)CSig.eqoption=funh1h2->ifInt.equalh1h2thenSome(Obj.magicCSig.Refl)elseNoneletreprs=tryInt.Map.finds!dyntabwithNot_found->let()=Printf.eprintf"Unknown dynamic tag %i\n%!"sinassertfalseletnames=lethash=Hashtbl.hashsinifInt.Map.memhash!dyntabthenSome(Anyhash)elseNoneletdump()=Int.Map.bindings!dyntabmoduleMap(Value:ValueS)=structtypet=Obj.tValue.tInt.Map.ttype'akey='atagtype'avalue='aValue.tletcast:'avalue->'bvalue=Obj.magicletempty=Int.Map.emptyletaddtagvm=Int.Map.addtag(castv)mletremovetagm=Int.Map.removetagmletfindtagm=cast(Int.Map.findtagm)letmem=Int.Map.memletmodifytagfm=Int.Map.modifytag(fun_v->cast(f(castv)))mtypemap={map:'a.'atag->'avalue->'avalue}letmapfm=Int.Map.mapif.mapmtypeany=Any:'atag*'avalue->anyletiterfm=Int.Map.iter(funkv->f(Any(k,v)))mletfoldfmaccu=Int.Map.fold(funkvaccu->f(Any(k,v))accu)maccutypefilter={filter:'a.'atag->'avalue->bool}letfilterfm=Int.Map.filterf.filtermendmoduleHMap(V1:ValueS)(V2:ValueS)=structtypemap={map:'a.'atag->'aV1.t->'aV2.t}letmap(f:map)(m:Map(V1).t):Map(V2).t=Int.Map.mapif.mapmtypefilter={filter:'a.'atag->'aV1.t->bool}letfilter(f:filter)(m:Map(V1).t):Map(V1).t=Int.Map.filterf.filtermendendincludeSelfmoduleEasy=struct(* now tags are opaque, we can do the trick *)letmake_dyn_tag(s:string)=(fun(typea)(tag:atag)->letinfun:(a->t)=funx->Dyn(tag,x)inletoutfun:(t->a)=fun(Dyn(t,x))->matcheqtagtwith|None->assertfalse|SomeCSig.Refl->xininfun,outfun,tag)(creates)letmake_dyn(s:string)=letinf,outf,_=make_dyn_tagsininf,outfletinjxtag=Dyn(tag,x)letprj:typea.t->atag->aoption=fun(Dyn(tag',x))tag->matcheqtagtag'with|None->None|SomeCSig.Refl->Somexendend