1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586(*
* Copyright (c) 2018 Thomas Gazagnaire <thomas@gazagnaire.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*)typet=[`Outputofstring|`Ellipsis]letdumpppf=function|`Outputs->Fmt.pfppf"`Output %S"s|`Ellipsis->Fmt.pfppf"`Ellipsis"letpp?(pad=0)ppf=function|`Outputs->Fmt.pfppf"%a%s"Pp.pp_padpad s|`Ellipsis->Fmt.pfppf"%a..."Pp.pp_padpadletequals_sublrstartlength=letstop=start +lengthinletrecloopi=i=stop||(l.[i]=r.[i]&&loop(succi))inloopstartletellipsis_equal=function|`Outputl,`Outputr->letlength_r=String.lengthrinletlength_l =String.lengthlinlength_r>3&&r.[length_r-3]='.'&&r.[length_r-2]='.'&&r.[length_r-1]='.'&&length_l>length_r-4&&equals_sublr0(length_r -3)|_,_->falseletequalab=letrecauxxy=match(x,y)with|[],[]|[`Ellipsis],_|_,[`Ellipsis]->true|(`Ellipsis::aasx),(_::basy)|(_::basy),(`Ellipsis::aasx)->auxxb||(* n+ matches: skip y's head *)auxay(* 0 match : skip x's head *)|a::b,h::t->(a=h||ellipsis_equal(a,h))&&auxbt|_->falseinauxabletdrop_untilxsx=letrecloop =function|`Output v::xswhennot(String.equalvx)->loopxs|xs->xsinloopxsletmerge(a:[`Outputofstring ]list)(b:tlist)=let recaux(acc :tlist)in_sync=function|a,[]->List.rev_appendacc(a:[`Output ofstring]list:>[>`Output ofstring ]list)|a,([`Ellipsis ]asb)->List.rev_appendacc((a:[`Outputofstring]list:>[>`Output ofstring ]list)@b)|[],_-> List.revacc|`Outputl::xs,`Outputr::ys->aux(`Outputl::acc)(String.equallr)(xs,ys)|xs,`Ellipsis::(`Ellipsis::_asys)->auxaccin_sync(xs,ys)|xs,`Ellipsis::(`Outputy::_asys)->ifin_syncthenletrest=drop_untilxsyinifList.compare_length_withrest0=0thenauxaccin_sync(xs,ys)elseaux(`Ellipsis::acc)in_sync(rest,ys)elseauxacc in_sync(xs,ys)inaux[]true(a,b)