123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591(*
* Stream - streams and stream parsers
* Copyright (C) 1997 Daniel de Rauglaudre
* 2007 Zheng Li
* 2008 David Teller
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version,
* with the special exception on linking described in file LICENSE.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)includeStreamtype'aenumerable='attype'amappable='atexceptionEnd_of_flow=Failurelet(|>)xf=fxlet(|-)fgx=g(fx)let(//)fg(x,y)=((fx),(gy))letcurryfxy=f(x,y)letuncurryf(x,y)=fxyletidx=xletrecof_funf=Stream.slazy(fun_->tryleth=f()inStream.iconsh(Stream.slazy(fun_->of_funf))with|End_of_flow->Stream.sempty)letto_funfl()=nextflletto_listfl=letbuf=ref[]initer(funx->buf:=x::!buf)fl;List.rev!bufletto_stringfl=letbuf=Buffer.create16initer(Buffer.add_charbuf)fl;Buffer.contentsbufletto_string_fmtfmtfl=letbuf=Buffer.create16inStream.iter(funit->Buffer.add_stringbuf(Printf.sprintffmtit))fl;Buffer.contentsbufletto_string_funfnfl=letbuf=Buffer.create16inStream.iter(funit->Buffer.add_stringbuf(fnit))fl;Buffer.contentsbuf(*UNUSED let on_channel ch = iter (output_char ch) *)leton_outputo=iter(BatIO.writeo)letrecof_inputi=Stream.slazy(fun_->tryleth=BatIO.readiinStream.iconsh(Stream.slazy(fun_->of_inputi))with|BatIO.No_more_input->Stream.sempty)letreccycletimesx=matchtimeswith|None->Stream.iappx(Stream.slazy(fun_->cycleNonex))|Some1->x|(* in case of destriction *)Somenwhenn<=0->Stream.sempty|Somen->Stream.iappx(Stream.slazy(fun_->cycle(Some(n-1))x))letrepeattimesx=cycletimes(Stream.isingx)letrecseqinitstepcont=ifcontinitthenStream.iconsinit(Stream.slazy(fun_->seq(stepinit)stepcont))elseStream.semptyletrangenuntil=letstepx=(x+1)landmax_intinletcont=matchuntilwith|None->(fun_->true)|Somex->(>=)xinseqnstepcontlet(--)pq=rangep(Someq)letnext(__strm:_Stream.t)=matchStream.peek__strmwith|Someh->(Stream.junk__strm;h)|_->raiseEnd_of_flowletrecfoldlfinits=matchpeekswith|Someh->(matchfinithwith|(accu,None)->(junks;foldlfaccus)|(accu,Sometrue)->(junks;accu)|(_,Somefalse)->init)|None->initletrecfoldrfinits=let(__strm:_Stream.t)=sinmatchStream.peek__strmwith|Someh->(Stream.junk__strm;fh(lazy(foldrfinits)))|_->initletfoldfs=let(__strm:_Stream.t)=sinmatchStream.peek__strmwith|Someh->(Stream.junk__strm;foldlfhs)|_->raiseEnd_of_flowletconsxs=Stream.iconsxsletapnds1s2=Stream.iapps1s2letis_emptys=matchpeekswith|None->true|_->falseletrecconcatss=Stream.slazy(fun_->let(__strm:_Stream.t)=ssinmatchStream.peek__strmwith|Somep->(Stream.junk__strm;Stream.iappp(Stream.slazy(fun_->concatss)))|_->Stream.sempty)letrecconcat_mapfl=Stream.slazy(fun()->matchStream.peeklwith|Somep->letp'=fpinStream.junkl;Stream.iappp'(Stream.slazy(fun()->concat_mapfl))|None->Stream.sempty)letrecfilterfs=Stream.slazy(fun_->let(__strm:_Stream.t)=sinmatchStream.peek__strmwith|Someh->(Stream.junk__strm;iffhthenStream.iconsh(Stream.slazy(fun_->filterfs))elseStream.slazy(fun_->filterfs))|_->Stream.sempty)lettakenfl=leti=refninof_fun(fun()->(if!i<=0thenraiseEnd_of_flowelsedecri;nextfl))letdropnfl=leti=refninletrecf()=if!i<=0thennextflelse(ignore(nextfl);decri;f())inof_funfletrectake_whilefs=Stream.slazy(fun_->matchpeekswith|Someh->iffhthen(junks;Stream.iconsh(Stream.slazy(fun_->take_whilefs)))elseStream.sempty|None->Stream.sempty)letrecdrop_whilefs=Stream.slazy(fun_->let(__strm:_Stream.t)=sinmatchStream.peek__strmwith|Someh->(Stream.junk__strm;iffhthenStream.slazy(fun_->drop_whilefs)elseStream.iconshs)|_->Stream.sempty)letspanps=letq=Queue.create()andsr=refNoneinletrecget_head()=Stream.slazy(fun_->ifnot(Queue.is_emptyq)thenStream.lcons(fun_->Queue.takeq)(Stream.slazyget_head)else(let(__strm:_Stream.t)=sinmatchStream.peek__strmwith|Someh->(Stream.junk__strm;ifphthenStream.iconsh(Stream.slazyget_head)else(sr:=Someh;Stream.sempty))|_->Stream.sempty))inletrecget_tail()=match!srwith|Somev->Stream.iconsvs|None->Stream.slazy(fun_->let(__strm:_Stream.t)=sinmatchStream.peek__strmwith|Someh->(Stream.junk__strm;ifphthenQueue.addhqelsesr:=Someh;get_tail())|_->Stream.sempty)in((get_head()),(Stream.slazyget_tail))letbreakps=span(p|-not)sletrecgroupps=Stream.slazy(fun_->matchpeekswith|None->Stream.sempty|Somev->ifpvthengroup_auxpselsegroup_aux(p|-not)s)andgroup_auxps=matchpeekswith|None->Stream.sempty|Some_->leth=nextsinlet(s1,s2)=spanpsinStream.lcons(fun_->Stream.iconshs1)(Stream.slazy(fun_->group_aux(p|-not)s2))letrecmapfs=Stream.slazy(fun_->let(__strm:_Stream.t)=sinmatchStream.peek__strmwith|Someh->(Stream.junk__strm;Stream.lcons(fun_->fh)(Stream.slazy(fun_->mapfs)))|_->Stream.sempty)letdup(_s:'aStream.t)=failwith"Correct implementation needed"(* let rec gen q_in q_out =
Printf.printf "0%!";
Stream.slazy (fun () ->
Printf.printf "a%!";
if Queue.is_empty q_in
then (* take from stream, put onto other queue *)
match Stream.peek s with
| Some h ->
Printf.printf "b%!";
Stream.junk s;
Queue.add h q_out;
Stream.icons h (Stream.slazy (fun () -> gen q_in q_out))
| _ -> Stream.sempty
else ( (* take from queue *)
Printf.printf "c%!";
Stream.lcons (fun () -> Queue.take q_in)
(Stream.slazy (fun () -> gen q_in q_out))))
in
let q1 = Queue.create () in
let q2 = Queue.create () in
Printf.printf "!!%!";
gen q1 q2, gen q2 q1
*)(* dup
let block_stream =
let x = ref 10 in
BatStream.of_fun (fun pos -> decr x; if !x < 0 then None else Some !x) in
let rec show count stream =
match BatStream.next block_stream with
| Some x -> show (succ count) stream
| None -> count
in
let q1, q2 = BatStream.dup block_stream in
Printf.printf "x%!";
assert_equal ~msg:"Second stream from dup length wrong" ~printer:(IO.to_string Int.print) 10 (show 0 q2);
Printf.printf "x%!";
assert_equal ~msg:"First stream from dup length wrong" ~printer:(IO.to_string Int.print) 10 (show 0 q1);
Printf.printf "x%!";
()
**)(*NOT EXPORTED
let rec combn sa =
Stream.slazy
(fun _ ->
if Array.fold_left (fun b s -> b || (is_empty s)) false sa
then Stream.sempty
else
Stream.lcons (fun _ -> Array.map next sa)
(Stream.slazy (fun _ -> combn sa)))
*)letreccomb(s1,s2)=Stream.slazy(fun_->matchpeeks1with|Someh1->(matchpeeks2with|Someh2->(junks1;junks2;Stream.lcons(fun_->(h1,h2))(Stream.slazy(fun_->comb(s1,s2))))|None->Stream.sempty)|None->Stream.sempty)(*NOT EXPORTED
let dupn n s =
let qa = Array.init n (fun _ -> Queue.create ()) in
let rec gen i =
Stream.slazy
(fun _ ->
if not (Queue.is_empty qa.(i))
then
Stream.lcons (fun _ -> Queue.take qa.(i))
(Stream.slazy (fun _ -> gen i))
else
(let (__strm : _ Stream.t) = s
in
match Stream.peek __strm with
| Some h ->
(Stream.junk __strm;
for i = 0 to n - 1 do Queue.add h qa.(i) done;
gen i)
| _ -> Stream.sempty))
in Array.init n gen
let splitn n s =
let qa = Array.init n (fun _ -> Queue.create ()) in
let rec gen i =
Stream.slazy
(fun _ ->
if not (Queue.is_empty qa.(i))
then
Stream.lcons (fun _ -> Queue.take qa.(i))
(Stream.slazy (fun _ -> gen i))
else
(let (__strm : _ Stream.t) = s
in
match Stream.peek __strm with
| Some h ->
(Stream.junk __strm;
for i = 0 to n - 1 do Queue.add h.(i) qa.(i) done;
gen i)
| _ -> Stream.sempty))
in Array.init n gen
*)letsplits=(|-)dup((mapfst)//(mapsnd))sletmergenfsa=letn=Array.lengthsainletpt=Array.initnidinletrecaltxi=(i<n)&&(ifpt.((x+i)modn)=pt.(x)thenaltx(i+1)else(forj=0toi-1dopt.((x+j)modn)<-pt.((x+i)modn)done;true))inletrecauxi=Stream.slazy(fun_->let(__strm:_Stream.t)=sa.(pt.(i))inmatchStream.peek__strmwith|Someh->(Stream.junk__strm;leti'=pt.(i)inStream.iconsh(Stream.slazy(fun_->auxpt.((fi'h)modn))))|_->ifalti1thenauxielseStream.sempty)inaux0letmergef(s1,s2)=leti2b=function|0->true|1->false|_->assertfalseandb2i=function|true->0|false->1inmergen(funix->b2i(f(i2bi)x))[|s1;s2|]letswitchnnfs=letqa=Array.initn(fun_->Queue.create())inletrecgeni=Stream.slazy(fun_->ifnot(Queue.is_emptyqa.(i))thenStream.lcons(fun_->Queue.takeqa.(i))(Stream.slazy(fun_->geni))else(let(__strm:_Stream.t)=sinmatchStream.peek__strmwith|Someh->(Stream.junk__strm;leti'=(fh)modninifi'=ithenStream.iconsh(Stream.slazy(fun_->geni))else(Queue.addhqa.(i');Stream.slazy(fun_->geni)))|_->Stream.sempty))inArray.initngenletswitchfs=letsa=switchn2(funx->iffxthen0else1)sin((sa.(0)),(sa.(1)))letrecscanlfinits=Stream.slazy(fun_->let(__strm:_Stream.t)=sinmatchStream.peek__strmwith|Someh->(Stream.junk__strm;Stream.iconsinit(Stream.slazy(fun_->scanlf(finith)s)))|_->Stream.isinginit)letscanfs=Stream.slazy(fun_->let(__strm:_Stream.t)=sinmatchStream.peek__strmwith|Someh->(Stream.junk__strm;Stream.slazy(fun_->scanlfhs))|_->Stream.sempty)letmap2f=(comb|-(map(uncurryf)))|>curry(*NOT EXPORTED
let rec map_fold f s =
Stream.slazy
(fun _ ->
match peek s with
| None -> Stream.sempty
| Some _ ->
Stream.lcons (fun _ -> fold f s)
(Stream.slazy (fun _ -> map_fold f s)))
*)letfeedstfvfdelayexp=lets_in'=refStream.semptyinletout=exp(Stream.iappdelay(Stream.slazy(fun_->!s_in')))inlets_in=stfoutands_out=vfoutin(s_in':=s_in;s_out)letfeedldelayexp=feedfstsnddelayexp(* NOT EXPORTED let feedr delay exp = feed snd fst delay exp *)(* NOT EXPORTED let circ delay exp = feedl delay (exp |- dup) *)letwhile_dosizetestexp=letsize=matchsizewith|Somenwhenn>=1->n|_->1inletinside=ref0inletjudgex=iftestxthen(incrinside;true)elsefalseinletchooseb_=(ifnotbthendecrinsideelse();!inside<size)in((((mergechoose)|-(switchjudge))|-(exp//id))|>curry)|-(feedlStream.sempty)letdo_whilesizetestexp=letsize=matchsizewith|Somenwhenn>=1->n|_->1inletinside=ref0inletjudgex=iftestxthen(incrinside;true)elsefalseinletchooseb_=(ifnotbthendecrinsideelse();!inside<size)in((((mergechoose)|-exp)|-(switchjudge))|>curry)|-(feedlStream.sempty)letfarmparsizepathexp_gens=letpar=matchparwith|None->1|Somep->pinletsize=matchsizewith|None->(fun_->1)|Somef->finletpath=matchpathwith|None->ignore|-(to_fun(cycleNone(0--(par-1))))|Somef->finletpar=ifpar<1then1elseparinletcount=Array.makepar0inletsizex=lets=sizexinifs<1then1elsesinletpathx=leti=pathxin(count.(i)<-succcount.(i);i)inletchoose=letrecfind_nextcondlasti=ifi<parthen(letj=(last+i)modparinifcondjthenSomejelsefind_nextcondlast(i+1))elseNoneinfunlast_->(count.(last)<-count.(last)-1;letnth=matchfind_next(funi->count.(i)>=(sizei))last1with|Somej->j|None->(matchfind_next(funi->count.(i)>0)last1with|Somej->j|None->last+(1modpar))innth)inletsa_in=switchnparpathsinletsa_out=Array.mapiexp_gensa_ininmergenchoosesa_out(* let ( ||| ) exp1 exp2 = exp1 |- exp2 *)letenumx=BatEnum.from(fun()->trynextxwith|End_of_flow->raiseBatEnum.No_more_elements)letrecof_enume=Stream.slazy(fun_->matchBatEnum.getewith|Someh->Stream.iconsh(Stream.slazy(fun_->of_enume))|None->Stream.sempty)##V<4.2##letof_bytes=of_stringmoduleStreamLabels=structletiter~fx=iterfxletswitch~fx=switchfxletto_string_fmt~fmt=to_string_fmtfmtletto_string_fun~fn=to_string_funfnletfoldl~f~init=foldlfinitletfoldr~f~init=foldrfinitletfold~f~init=foldfinitletfilter~f=filterfletmap~f=mapfletmap2~f=map2fletscanl~f=scanlfletscan~f=scanfletwhile_do?size~f=while_dosizefletdo_while?size~f=do_whilesizefletrange?untilp=rangepuntilletrepeat?times=repeattimesletcycle?times=cycletimeslettake_while~f=take_whilefletdrop_while~f=drop_whilefletspan~f=spanfletbreak~f=breakfletgroup~f=groupfletmerge~f=mergefletmergen~f=mergenfletswitchnx~f=switchnxfletfarm?par?size?path=farmparsizepathend