123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160(******************************************************************************)(* *)(* Sek *)(* *)(* Arthur Charguéraud, Émilie Guermeur and François Pottier *)(* *)(* Copyright Inria. All rights reserved. This file is distributed under the *)(* terms of the GNU Lesser General Public License as published by the Free *)(* Software Foundation, either version 3 of the License, or (at your *)(* option) any later version, as described in the file LICENSE. *)(* *)(******************************************************************************)openPrivateSignaturesmodule[@inline]Make(SSeq:SSEQ)=struct(* A persistent sequence is represented as a shareable sequence. *)(* Every operation on the shareable sequence [s] uses the unit measure (so
that every element has weight 1) and owner [none]. *)type'aschunk='aSSeq.schunktype'at='aSSeq.t=|Zeroof{default:'a;}|Oneof{default:'a;x:'a}|Shortof{default:'a;a:'aarray}|Levelof{weight:weight;front:'aschunk;middle:'aschunkt;back:'aschunk;}letdepth0=0letunit_weight=SSeq.MUnitletcreate=SSeq.createlet[@inline]makedefaultsizev=SSeq.makedefaultsizevOwner.nonelet[@inline]initdefaultsizef=SSeq.initdefaultsizefOwner.noneletdefault=SSeq.defaultletlength=SSeq.weightletis_empty=SSeq.is_emptylet[@inline]pushpovsx=SSeq.pushpovsxunit_weightOwner.nonedepth0let[@inline]poppovs=SSeq.poppovsunit_weightOwner.noneletpeek=SSeq.peeklet[@inline]getsi=let_,x=SSeq.getsiunit_weightinxlet[@inline]setsix=SSeq.setsiunit_weightOwner.nonexletconcats1s2=SSeq.concats1s2Owner.nonedepth0letsplitsi=assert(0<=i&&i<=lengths);(* Fast paths. *)ifi=0thenletdefault=defaultsinZero{default},selseifi=lengthsthenletdefault=defaultsins,Zero{default}elsebegin(* We implement a binary split in terms of [three_way_split]. *)assert(i<lengths);lets1,x,s2=SSeq.three_way_splitsiunit_weightOwner.noneinassert(SSeq.weights1=i);lets2=SSeq.pushFronts2xunit_weightOwner.nonedepth0ins1,s2endlettakesi=assert(0<=i&&i<=lengths);(* Fast paths. *)ifi=0thenletdefault=defaultsinZero{default}elseifi=lengthsthenselsebegin(* We implement a binary split in terms of [take]. *)lets1,_=SSeq.takesiunit_weightOwner.noneinassert(SSeq.weights1=i);s1endletdropsi=assert(0<=i&&i<=lengths);(* Fast paths. *)ifi=0thenselseifi=lengthsthenletdefault=defaultsinZero{default}elsebegin(* We implement a binary split in terms of [drop]. *)assert(0<i);(* A slight twist: we split at [i-1], not [i], so as to avoid
the need to push [x] into [s2]. *)let_,s2=SSeq.drops(i-1)unit_weightOwner.noneinassert(SSeq.weights2=lengths-i);s2endletsubsheadsize=(* The cost of [take] is about the same as the cost of [reach].
Thus, if [size] is small, then creating an iterator, moving
it to the appropriate place, and using it to copy the data
could be up to twice faster than the code below. However,
this code still offers the advantage that the data is shared. *)take(dropshead)sizeletiter_segments=SSeq.iter_segmentsletto_array=SSeq.to_arraylet[@inline]of_array_segmentdefaultaheadsize=SSeq.of_array_segmentdefaultaheadsizeOwner.nonelet[@inline]of_arraydefaulta=of_array_segmentdefaulta0(Array.lengtha)letprintelements=SSeq.printSSeq.MUnitelementsletchecks=(* Check that [s] is well-formed, with owner [Owner.none], which
means that the sequence is considered shared. *)SSeq.checksunit_weightOwner.nonedepth0;end(* Make *)