Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
diff.ml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88open Core type t = | Same of Sexp.t | Add of Sexp.t | Delete of Sexp.t | Replace of Sexp.t * Sexp.t | Enclose of t list [@@deriving sexp, hash, compare] let print_for_test t = print_s (sexp_of_t t) let rec invert = function | Same x -> Same x | Add x -> Delete x | Delete x -> Add x | Replace (a, b) -> Replace (b, a) | Enclose xs -> Enclose (List.map xs ~f:invert) ;; let require_equal ~expected ~found = if not (Sexp.equal expected found) then Or_error.error_s [%message "Can't apply the diff because the sexp is not equal to the original" (expected : Sexp.t) (found : Sexp.t)] else Ok () ;; let found_nothing ~expected = Or_error.error_s [%message "Can't apply the diff because the sexp ended unexpectedly" (expected : Sexp.t)] ;; let expected_nothing ~found = Or_error.error_s [%message "Can't apply the diff: expected nothing" (found : Sexp.t list)] ;; let unexpected_atom ~atom = Or_error.error_s [%message "Can't apply the diff: expected a list, found an atom" (atom : string)] ;; let rec apply_list ~(diffs : t list) ~(sexps : Sexp.t list) : Sexp.t list Or_error.t = let open Or_error.Let_syntax in match diffs, sexps with | Same expected :: _, [] | Delete expected :: _, [] | Replace (expected, _) :: _, [] -> found_nothing ~expected | Enclose _ :: _, [] -> Or_error.error_string "Can't apply the diff: expected a list, found nothing" | Same expected :: diffs, found :: sexps -> let%bind () = require_equal ~expected ~found in let%map rest = apply_list ~diffs ~sexps in expected :: rest | Add x :: diffs, sexps -> let%map rest = apply_list ~diffs ~sexps in x :: rest | Delete expected :: diffs, found :: sexps -> let%bind () = require_equal ~expected ~found in apply_list ~diffs ~sexps | Replace (expected, new_sexp) :: diffs, found :: sexps -> let%bind () = require_equal ~expected ~found in let%map rest = apply_list ~diffs ~sexps in new_sexp :: rest | Enclose _ :: _, Sexp.Atom atom :: _ -> unexpected_atom ~atom | Enclose xs :: diffs, Sexp.List ys :: sexps -> let%bind first = apply_list ~diffs:xs ~sexps:ys in let%map rest = apply_list ~diffs ~sexps in Sexp.List first :: rest | [], [] -> Ok [] | [], found -> expected_nothing ~found ;; let apply diff sexp = let result = apply_list ~diffs:[ diff ] ~sexps:[ sexp ] in Or_error.map result ~f:(function | [ x ] -> x | _ -> raise_s [%message "internal error in [Sexp_diff] while applying diff" (diff : t) (sexp : Sexp.t)]) ;; let apply_exn diff sexp = apply diff sexp |> Or_error.ok_exn