Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file utils.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302(*
======================================================================
Copyright Christophe Raffalli & Rodolphe Lepigre
LAMA, UMR 5127 CNRS, Université Savoie Mont Blanc
christophe.raffalli@univ-savoie.fr
rodolphe.lepigre@univ-savoie.fr
This software contains a parser combinator library for the OCaml lang-
uage. It is intended to be used in conjunction with pa_ocaml (an OCaml
parser and syntax extention mechanism) to provide a fully-integrated
way of building parsers using an extention of OCaml's syntax.
This software is governed by the CeCILL-B license under French law and
abiding by the rules of distribution of free software. You can use,
modify and/or redistribute the software under the terms of the CeCILL-
B license as circulated by CEA, CNRS and INRIA at the following URL.
http://www.cecill.info
As a counterpart to the access to the source code and rights to copy,
modify and redistribute granted by the license, users are provided
only with a limited warranty and the software's author, the holder of
the economic rights, and the successive licensors have only limited
liability.
In this respect, the user's attention is drawn to the risks associated
with loading, using, modifying and/or developing or reproducing the
software by the user in light of its specific status of free software,
that may mean that it is complicated to manipulate, and that also
therefore means that it is reserved for developers and experienced
professionals having in-depth computer knowledge. Users are therefore
encouraged to load and test the software's suitability as regards
their requirements in conditions enabling the security of their sys-
tems and/or data to be ensured and, more generally, to use and operate
it in the same conditions as regards security.
The fact that you are presently reading this means that you have had
knowledge of the CeCILL-B license and that you accept its terms.
======================================================================
*)(* Comparison function accepting to compare everything. *)leteq_closure:typea.a->a->bool=funfg->letopenObjin(* repr f == repr g
|| (Marshal.to_string f [Closures] = Marshal.to_string g [Closures]) *)letadone=ref[]inletrecfnfg=f==g||matchis_intf,is_intgwith|true,true->f==g|false,true|true,false->false|false,false->letft=tagfandgt=tagginifft=forward_tagthen(fn(fieldf0)g)elseifgt=forward_tagthen(fnf(fieldg0))elseifft<>gtthenfalseelseifft=string_tag||ft=double_tag||ft=double_array_tagthenf=gelseifft=abstract_tag||ft=out_of_heap_tag||ft=no_scan_tag||ft=custom_tag||ft=infix_tag(* FIXME: we could certainly do better with infix_tag
i.e. mutually recursive functions *)thenf==gelsesizef==sizeg&&letrecgni=ifi<0thentrueelsefn(fieldfi)(fieldgi)&&gn(i-1)inList.exists(fun(f',g')->f==f'&&g==g')!adone||(List.for_all(fun(f',g')->f!=f'&&g!=g')!adone&&(adone:=(f,g)::!adone;gn(sizef-1)))infn(reprf)(reprg)(* Custom hash table module. [Hashtbl] won't do because it does not
accept keys that contain closures. Here a custom comparing function
can be provided at the creation of the hash table. *)moduleEqHashtbl:sigtype('a,'b)tvalcreate:int->('a,'b)tvaladd:('a,'b)t->'a->'b->unitvalfind:('a,'b)t->'a->'bvaliter:('a->'b->unit)->('a,'b)t->unitend=structtype('a,'b)t={mutablenb_buckets:int;mutablebuckets:('a*'b)listarray;mutablemax_size:int;mutablesize_limit:int}letreclog2n=ifn<=0then0else1+log2(nlsr1)letcreate:int->('a,'b)t=funnb_buckets->letnb_buckets=maxnb_buckets8inletbuckets=Array.makenb_buckets[]inletsize_limit=log2nb_buckets+7in{nb_buckets;buckets;max_size=0;size_limit}letiter:('a->'b->unit)->('a,'b)t->unit=funfnh->Array.iter(List.iter(fun(k,v)->fnkv))h.bucketslethash=Hashtbl.hashletfind_bucket:('a,'b)t->'a->int=funhk->hashkmodh.nb_bucketsexceptionSize_isofintletrecadd:('a,'b)t->'a->'b->unit=funhkv->leti=find_buckethkinletrecremovesz=function|[]->raise(Size_issz)|(kv,_)::lswheneq_closurekkv->ls|e::ls->e::remove(sz+1)lsintryh.buckets.(i)<-(k,v)::remove0h.buckets.(i)withSize_is(sz)->h.buckets.(i)<-(k,v)::h.buckets.(i);h.max_size<-maxh.max_sizesz;ifh.max_size>h.size_limitthengrowhandgrow:('a,'b)t->unit=funh->letold_tbl=h.bucketsinh.nb_buckets<-h.nb_buckets*2;h.buckets<-Array.makeh.nb_buckets[];h.size_limit<-h.size_limit+1;h.max_size<-0;Array.iter(List.iter(fun(k,v)->addhkv))old_tblletfind:('a,'b)t->'a->'b=funhk->leti=find_buckethkinletrecfind=function|[]->raiseNot_found|(kv,v)::xs->ifeq_closurekkvthenvelsefindxsinfindh.buckets.(i)end(** This modules implements a computation of a fixpoints for valus
that depends upon other values. Cycles are handled through update of
references. If the fixpoint is not reached, this might loop.
This modules ressemble a little the Lazy module.
*)moduleFixpoint:sigtype'at(** Standard way to construct a value of type ['a t] *)valfrom_val:'a->'atvalfrom_fun:'at->('a->'b)->'btvalfrom_fun2:'at->'bt->('a->'b->'c)->'ctvalfrom_funl:'atlist->'b->('b->'a->'b)->'bt(** value obtained by reading 'b which is mutable *)valfrom_ref:'b->('b->'at)->'at(** Must be called when updating a mutable field used in [from_ref] *)valupdate:'at->unit(** Reading the value *)valforce:'at->'aend=structmodulerecH:sigtype'afix={mutablevalue:'a;compute:unit->unit;mutabledeps:W.toption;mutableis_ref:('afix*(unit->'afix))option;ident:int}includeHashtbl.HashedTypewithtypet=Obj.tfixend=structtype'afix={mutablevalue:'a;compute:unit->unit;mutabledeps:W.toption;mutableis_ref:('afix*(unit->'afix))option;ident:int}typet=Obj.tfixletequalab=a.ident=b.identlethasha=a.identendandW:Weak.Swithtypedata=H.t=Weak.Make(H)openHtype'at='afixletforce:'at->'a=funb->b.valueletnew_id=letr=ref0in(fun()->letx=!rinr:=x+1;x)letadd_depsr{deps;_}=matchdepswith|None->true|Sometbl->letr=Obj.magicrinifnot(W.memtblr)thenW.addtblr;falseletiter_depsfn{deps;_}=matchdepswith|None->()|Sometbl->W.iter(funv->fn(Obj.magicv))tblletfrom_valvalue={value;compute=ignore;deps=None;is_ref=None;ident=new_id()}letfrom_funlfn=letrecres={value=fnl.value;compute=(fun()->res.value<-fnl.value);deps=Some(W.create7);is_ref=None;ident=new_id()}inifadd_depsreslthenres.deps<-None;resletfrom_fun2l1l2fn=letrecres={value=fnl1.valuel2.value;compute=(fun()->res.value<-fnl1.valuel2.value);deps=Some(W.create7);is_ref=None;ident=new_id()}inletb1=add_depsresl1inletb2=add_depsresl2inifb1&&b2thenres.deps<-None;resletrecfoldlaf=matchlwith|[]->a|x::l->foldl(fax.value)fletfrom_funllafn=letrecres={value=foldlafn;compute=(fun()->res.value<-foldlafn);deps=Some(W.create7);is_ref=None;ident=new_id()}inletfnaccx=add_depsresx&&accinifList.fold_leftfntruelthenres.deps<-None;resletfrom_reflfn=leta=fnlinletrecres={value=a.value;compute=(fun()->res.value<-(fnl).value);deps=Some(W.create7);is_ref=Some(a,fun()->fnl);ident=new_id()}inignore(add_depsresa);resletupdateb=beginmatchb.is_refwith|None->invalid_arg"Fixpoint.update";|Some(_,f)->leta'=f()inignore(add_depsba');b.is_ref<-Some(a',f)end;letrecfnx=letold=x.valueinx.compute();ifold<>x.valuetheniter_depsfnxinfnbend