12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788openCoretypet=|SameofSexp.t|AddofSexp.t|DeleteofSexp.t|ReplaceofSexp.t*Sexp.t|Encloseoftlist[@@derivingsexp,hash,compare]letprint_for_testt=print_s(sexp_of_tt)letrecinvert=function|Samex->Samex|Addx->Deletex|Deletex->Addx|Replace(a,b)->Replace(b,a)|Enclosexs->Enclose(List.mapxs~f:invert);;letrequire_equal~expected~found=ifnot(Sexp.equalexpectedfound)thenOr_error.error_s[%message"Can't apply the diff because the sexp is not equal to the original"(expected:Sexp.t)(found:Sexp.t)]elseOk();;letfound_nothing~expected=Or_error.error_s[%message"Can't apply the diff because the sexp ended unexpectedly"(expected:Sexp.t)];;letexpected_nothing~found=Or_error.error_s[%message"Can't apply the diff: expected nothing"(found:Sexp.tlist)];;letunexpected_atom~atom=Or_error.error_s[%message"Can't apply the diff: expected a list, found an atom"(atom:string)];;letrecapply_list~(diffs:tlist)~(sexps:Sexp.tlist):Sexp.tlistOr_error.t=letopenOr_error.Let_syntaxinmatchdiffs,sexpswith|Sameexpected::_,[]|Deleteexpected::_,[]|Replace(expected,_)::_,[]->found_nothing~expected|Enclose_::_,[]->Or_error.error_string"Can't apply the diff: expected a list, found nothing"|Sameexpected::diffs,found::sexps->let%bind()=require_equal~expected~foundinlet%maprest=apply_list~diffs~sexpsinexpected::rest|Addx::diffs,sexps->let%maprest=apply_list~diffs~sexpsinx::rest|Deleteexpected::diffs,found::sexps->let%bind()=require_equal~expected~foundinapply_list~diffs~sexps|Replace(expected,new_sexp)::diffs,found::sexps->let%bind()=require_equal~expected~foundinlet%maprest=apply_list~diffs~sexpsinnew_sexp::rest|Enclose_::_,Sexp.Atomatom::_->unexpected_atom~atom|Enclosexs::diffs,Sexp.Listys::sexps->let%bindfirst=apply_list~diffs:xs~sexps:ysinlet%maprest=apply_list~diffs~sexpsinSexp.Listfirst::rest|[],[]->Ok[]|[],found->expected_nothing~found;;letapplydiffsexp=letresult=apply_list~diffs:[diff]~sexps:[sexp]inOr_error.mapresult~f:(function|[x]->x|_->raise_s[%message"internal error in [Sexp_diff] while applying diff"(diff:t)(sexp:Sexp.t)]);;letapply_exndiffsexp=applydiffsexp|>Or_error.ok_exn