12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182(******************************************************************************)(* *)(* Fix *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright Inria. All rights reserved. This file is distributed under the *)(* terms of the GNU Library General Public License version 2, with a *)(* special exception on linking, as described in the file LICENSE. *)(* *)(******************************************************************************)openSigsmoduleMake(M:IMPERATIVE_MAPS)(G:GRAPHwithtypet=M.key)=structtypet=G.tletpushfrontierx=Stack.pushxfrontierletrecvisitgensymtablefrontier=matchStack.popfrontierwith|exceptionStack.Empty->(* The stack is empty: we are done. *)()|x->matchM.findxtablewith|_->(* [x] is known already: ignore it. *)visitgensymtablefrontier|exceptionNot_found->(* Assign the number [i] to [x]. *)leti=gensym()inM.addxitable;G.foreach_successorx(pushfrontier);visitgensymtablefrontierletn,encode,decode=(* Perform a depth-first traversal of the graph. Assign a unique number [i]
to every newly-discovered vertex [x]. *)letgensym=Gensym.make()inlettable=M.create()inletfrontier=Stack.create()inG.foreach_root(pushfrontier);visitgensymtablefrontier;letn=gensym()in(* We have discovered [n] graph vertices. [table] now contains a mapping
of these vertices to integers in the range [0..n). We now build the
reverse mapping in an array. This may seem a little clumsy (an array of
options is allocated in an intermediate step), but requires only linear
time. *)letvertex:G.toptionarray=Array.makenNoneinM.iter(funxi->vertex.(i)<-Somex)table;letforce=functionSomex->x|None->assertfalseinletvertex:G.tarray=Array.mapforcevertexin(* Return two conversions functions. *)letencodex=tryM.findxtablewithNot_found->letmsg=Printf.sprintf"\n Fix.Number says: \
please check the argument passed to \"encode\".\n %s\n"__LOC__inraise(Invalid_argumentmsg)anddecodei=vertex.(i)inn,encode,decodeendmoduleForOrderedType(T:OrderedType)=Make(Glue.PersistentMapsToImperativeMaps(Map.Make(T)))moduleForHashedType(T:HashedType)=Make(Glue.HashTablesAsImperativeMaps(T))moduleForType(T:TYPE)=ForHashedType(Glue.TrivialHashedType(T))