Skip to content

Commit

Permalink
add comparison function for Pp.Ast.t
Browse files Browse the repository at this point in the history
Signed-off-by: Ali Caglayan <[email protected]>
  • Loading branch information
Alizter committed Aug 22, 2023
1 parent 5316e9a commit fee774d
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 24 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
Unreleased
----------

- Add `Pp.compare` (#9, @Alizter)

1.1.2
-----

Expand Down
69 changes: 69 additions & 0 deletions src/pp.ml
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,72 @@ module O = struct
end

let of_fmt f x = Format (fun ppf -> f ppf x)

let compare compare_tag =
let compare_both (type a b) (f : a -> a -> int) (g : b -> b -> int) (a, b)
(c, d) =
let r = f a c in
if r <> 0 then
r
else
g b d
in
let rec compare x y =
match (x, y) with
| Nop, Nop -> 0
| Nop, _ -> -1
| _, Nop -> 1
| Seq (a, b), Seq (c, d) -> compare_both compare compare (a, b) (c, d)
| Seq _, _ -> -1
| _, Seq _ -> 1
| Concat (a, b), Concat (c, d) ->
compare_both compare (List.compare ~cmp:compare) (a, b) (c, d)
| Concat _, _ -> -1
| _, Concat _ -> 1
| Box (a, b), Box (c, d) -> compare_both Int.compare compare (a, b) (c, d)
| Box _, _ -> -1
| _, Box _ -> 1
| Vbox (a, b), Vbox (c, d) -> compare_both Int.compare compare (a, b) (c, d)
| Vbox _, _ -> -1
| _, Vbox _ -> 1
| Hbox a, Hbox b -> compare a b
| Hbox _, _ -> -1
| _, Hbox _ -> 1
| Hvbox (a, b), Hvbox (c, d) ->
compare_both Int.compare compare (a, b) (c, d)
| Hvbox _, _ -> -1
| _, Hvbox _ -> 1
| Hovbox (a, b), Hovbox (c, d) ->
compare_both Int.compare compare (a, b) (c, d)
| Hovbox _, _ -> -1
| _, Hovbox _ -> 1
| Verbatim a, Verbatim b -> String.compare a b
| Verbatim _, _ -> -1
| _, Verbatim _ -> 1
| Char a, Char b -> Char.compare a b
| Char _, _ -> -1
| _, Char _ -> 1
| Break (a, b), Break (c, d) ->
let compare (x, y, z) (a, b, c) =
compare_both String.compare
(compare_both Int.compare String.compare)
(x, (y, z))
(a, (b, c))
in
compare_both compare compare (a, b) (c, d)
| Break _, _ -> -1
| _, Break _ -> 1
| Newline, Newline -> 0
| Newline, _ -> -1
| _, Newline -> 1
| Text a, Text b -> String.compare a b
| Text _, _ -> -1
| _, Text _ -> 1
| Tag (a, b), Tag (c, d) -> compare_both compare_tag compare (a, b) (c, d)
| Format _, Format _ ->
raise
(Invalid_argument "[Pp.of_fmt] values not supported in [Pp.compare]")
| Format _, _ -> -1
| _, Format _ -> 1
in
compare
7 changes: 7 additions & 0 deletions src/pp.mli
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,10 @@ val of_ast : 'a Ast.t -> 'a t
(** [to_ast t] will try to convert [t] to [Ast.t]. When [t] contains values
constructed with [of_fmt], this function will fail and return [Error ()] *)
val to_ast : 'a t -> ('a Ast.t, unit) result

(** {1 Comparison} *)

(** [compare cmp x y] compares [x] and [y] using [cmp] to compare tags.
@raise Invalid_argument if two [of_fmt] values are compared. *)
val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
63 changes: 39 additions & 24 deletions test/tests.ml
Original file line number Diff line number Diff line change
Expand Up @@ -153,31 +153,33 @@ let%expect_test _ =
.....x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x
x x x x x x x x x x x x x x |}]

let error_example_1 =
Pp.vbox
(Pp.box (Pp.text "Error: something went wrong!")
++ Pp.cut
++ Pp.box (Pp.text "Here are a few things you can do:")
++ Pp.cut
++ Pp.enumerate
~f:(fun x -> x)
[ Pp.text
"read the documentation, double check the way you are using this \
software to make sure you are not doing something wrong, and \
hopefully fix the problem on your side and move on"
; Pp.text
"strace furiously the program to try and understand why exactly \
it is trying to do what it is doing"
; Pp.text "report an issue upstream"
; Pp.text "if all else fails"
++ Pp.cut
++ Pp.enumerate ~f:Pp.text
[ "scream loudly at your computer"
; "take a break from your keyboard"
; "clear your head and try again"
]
])

let%expect_test _ =
print
(Pp.vbox
(Pp.box (Pp.text "Error: something went wrong!")
++ Pp.cut
++ Pp.box (Pp.text "Here are a few things you can do:")
++ Pp.cut
++ Pp.enumerate
~f:(fun x -> x)
[ Pp.text
"read the documentation, double check the way you are using \
this software to make sure you are not doing something wrong, \
and hopefully fix the problem on your side and move on"
; Pp.text
"strace furiously the program to try and understand why \
exactly it is trying to do what it is doing"
; Pp.text "report an issue upstream"
; Pp.text "if all else fails"
++ Pp.cut
++ Pp.enumerate ~f:Pp.text
[ "scream loudly at your computer"
; "take a break from your keyboard"
; "clear your head and try again"
]
]));
print error_example_1;
[%expect
{|
Error: something went wrong!
Expand Down Expand Up @@ -219,3 +221,16 @@ let%expect_test _ =
(1,
2)
foo |}]

let%expect_test "comparison" =
let x = error_example_1
and y = Pp.hovbox ~indent:2 (xs 200) in
let print x = Printf.printf "comparison result: %d\n" x in
print (Pp.compare (fun _ _ -> 0) x y);
print (Pp.compare (fun _ _ -> 0) x x);
print (Pp.compare (fun _ _ -> 0) y x);
[%expect
{|
comparison result: -1
comparison result: 0
comparison result: 1 |}]

0 comments on commit fee774d

Please sign in to comment.