12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788(*
* 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.
*)openMiscopenCompattypet=[`Outputofstring|`Ellipsis]letdumpppf=function|`Outputs->Fmt.pfppf"`Output %S"s|`Ellipsis->Fmt.pfppf"`Ellipsis"letpp?(pad=0)ppf=function|`Outputs->Fmt.pfppf"%a%s\n"pp_padpads|`Ellipsis->Fmt.pfppf"%a...\n"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|`Outputv::xswhennot(String.equalvx)->loopxs|xs->xsinloopxsletmerge(a:[`Outputofstring]list)(b:tlist)=letrecaux(acc:tlist)in_sync=function|a,[]->List.rev_appendacc(a:[`Outputofstring]list:>[>`Outputofstring]list)|a,([`Ellipsis]asb)->List.rev_appendacc((a:[`Outputofstring]list:>[>`Outputofstring]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)elseauxaccin_sync(xs,ys)inaux[]true(a,b)