123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102(* A cell, recording a single change of the changelog.
It needs to be a GADT to hide the parameters of the Hashtbl. *)typecell=Cell:{stamp:int;table:('a,'b)Hashtbl.t;key:'a;}->celltypechangelog={mutablerecent:celllist;(* The [recent] list contains the changes that happened since the last
call to backtrack, in reverse order (the most recent change is first
in the list). *)mutablesorted:celllist;(* Cells in the [sorted] list are sorted by decreasing stamp, such that
listing all cells greater than a threshold is a simple, in order,
traversal. *)}letcreate_changelog()={recent=[];sorted=[];}(* Wrappers around [Hashtbl] *)type('a,'b)t={table:('a,'b)Hashtbl.t;changelog:changelog;}letcreatechangelogn={table=Hashtbl.createn;changelog;}letadd{table;changelog}?stampkeyvalue=Hashtbl.addtablekeyvalue;matchstampwith|None->()|Somestamp->changelog.recent<-Cell{stamp;key;table}::changelog.recentletreplacetkv=Hashtbl.replacet.tablekvletmemta=Hashtbl.memt.tablealetfindta=Hashtbl.findt.tablealetfoldftacc=Hashtbl.foldft.tableaccletcleart=Hashtbl.cleart.table;t.changelog.recent<-[];t.changelog.sorted<-[](* Implementation of backtracking *)(* Helper to sort by decreasing stamps *)letorder(Cellc1)(Cellc2)=Int.comparec2.stampc1.stamp(* Drop the prefix not satisfying a certain predicate *)letrecfilter_prefixpred=function|x::xswhennot(predx)->filter_prefixpredxs|xs->xsletbacktrackcs~stamp=(* Check if a cell is still valid (older than [stamp]).
If not, remove it from its table. *)letprocess(Cellc)=ifc.stamp>stampthen(Hashtbl.removec.tablec.key;false)elsetruein(* Process recent list:
- remove items newer than [stamp]
- sort the remainder *)letrecent=cs.recent|>List.filterprocess|>List.fast_sortorderincs.recent<-[];(* Process sorted list:
- remove prefix items newer than [stamp]
- merge remaining items with the recent ones
*)letsorted=cs.sorted|>filter_prefixprocess|>List.mergeorderrecentincs.sorted<-sorted