12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394(* This file is free software, part of gen. See file "license" for more details. *)(** {1 Clonable Generators} *)type'agen=unit->'aoptionclassvirtual['a]t=objectmethodvirtualgen:'agen(** Generator of values tied to this copy *)methodvirtualclone:'at(** Clone the internal state *)end(** A generator that can be cloned as many times as required. *)type'aclonable='at(** Alias to {!'a t} *)(** {2 Prepend method} *)type'aprependable=<gen:'agen;clone:'aprependable;prepend:'a->unit(** Add value at front position *)>(* helper function for {!to_prependable} *)letrecto_prependablec=letg=c#geninletst=ref`Fwdin(* state: forward *)letnext()=match!stwith|`Fwd->g()|`Yield[]->assertfalse|`Yield[x]->st:=`Fwd;Somex|`Yield(x::l)->st:=`Yieldl;Somexinobjectmethodgen=nextmethodclone=to_prependable(c#clone)methodprependx=st:=match!stwith|`Fwd->`Yield[x]|`Yieldl->`Yield(x::l)end(** {2 Misc} *)letrecmapfc=letg=c#geninletnext()=matchg()with|None->None|Somex->Some(fx)inobjectmethodgen=nextmethodclone=mapfc#cloneend(** {2 Basic IO} *)moduleIO=structletwith_in?(mode=0o644)?(flags=[])filenamef=letic=open_in_genflagsmodefilenameinlettimestamp=ref0in(* make a generator at offset [i] *)letrecmakei:_clonable=letstate=ref`Not_startedinletrecnext()=match!statewith|`Not_started->(* initialize by restoring state *)seek_inici;incrtimestamp;state:=`Started!timestamp;next()|`Startedt->(* check whether another iterator was used more recently *)ift<!timestampthenfailwith"invalidated iterator";trySome(input_charic)withEnd_of_file->Noneinobjectmethodclone=leti=pos_inicinmakeimethodgen=nextendintryletx=f(make0)inclose_in_noerric;xwithe->close_in_noerric;raiseeend